refactor: migrace vsech formularu na FormField komponentu + JWT upgrade

- FormField.jsx: pridana podpora style prop
- 23 stranek migrovano na FormField (166 vyskytu, -246 radku)
- firebase/php-jwt upgrade v6.11 -> v7.0.3 (security advisory fix)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 19:33:36 +01:00
parent 37122579d0
commit 2328ba2840
26 changed files with 366 additions and 612 deletions

View File

@@ -3,6 +3,7 @@ import { useAlert } from '../context/AlertContext'
import { useAuth } from '../context/AuthContext'
import { motion, AnimatePresence } from 'framer-motion'
import ConfirmModal from '../components/ConfirmModal'
import FormField from '../components/FormField'
import apiFetch from '../utils/api'
import { formatCurrency, formatDate, czechPlural } from '../utils/formatters'
import SortIcon from '../components/SortIcon'
@@ -664,30 +665,24 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
</button>
</div>
<div className="received-upload-card-fields">
<div className="admin-form-group">
<label className="admin-form-label required">Dodavatel</label>
<FormField label="Dodavatel" error={uploadErrors[idx]?.supplier_name} required>
<input
type="text"
className={`admin-form-input${uploadErrors[idx]?.supplier_name ? ' has-error' : ''}`}
value={uploadMeta[idx]?.supplier_name || ''}
onChange={(e) => updateMeta(idx, 'supplier_name', e.target.value)}
/>
{uploadErrors[idx]?.supplier_name && (
<div className="admin-form-error">{uploadErrors[idx].supplier_name}</div>
)}
</div>
<div className="admin-form-group">
<label className="admin-form-label">Č. faktury</label>
</FormField>
<FormField label="Č. faktury">
<input
type="text"
className="admin-form-input"
value={uploadMeta[idx]?.invoice_number || ''}
onChange={(e) => updateMeta(idx, 'invoice_number', e.target.value)}
/>
</div>
</FormField>
<div className="received-upload-row">
<div className="admin-form-group" style={{ flex: 1 }}>
<label className="admin-form-label required">Částka</label>
<FormField label="Částka" error={uploadErrors[idx]?.amount} required style={{ flex: 1 }}>
<input
type="number"
step="0.01"
@@ -696,12 +691,8 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
value={uploadMeta[idx]?.amount || ''}
onChange={(e) => updateMeta(idx, 'amount', e.target.value)}
/>
{uploadErrors[idx]?.amount && (
<div className="admin-form-error">{uploadErrors[idx].amount}</div>
)}
</div>
<div className="admin-form-group" style={{ width: '90px' }}>
<label className="admin-form-label">Měna</label>
</FormField>
<FormField label="Měna" style={{ width: '90px' }}>
<select
className="admin-form-select"
value={uploadMeta[idx]?.currency || 'CZK'}
@@ -709,9 +700,8 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
>
{CURRENCY_OPTIONS.map(c => <option key={c} value={c}>{c}</option>)}
</select>
</div>
<div className="admin-form-group" style={{ width: '90px' }}>
<label className="admin-form-label">DPH %</label>
</FormField>
<FormField label="DPH %" style={{ width: '90px' }}>
<select
className="admin-form-select"
value={uploadMeta[idx]?.vat_rate || '21'}
@@ -719,7 +709,7 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
>
{VAT_RATE_OPTIONS.map(r => <option key={r} value={String(r)}>{r}%</option>)}
</select>
</div>
</FormField>
</div>
{uploadMeta[idx]?.amount && (
<div style={{ fontSize: '0.75rem', color: 'var(--text-tertiary)', marginTop: '-0.25rem', marginBottom: '0.5rem' }}>
@@ -730,32 +720,29 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
</div>
)}
<div className="received-upload-row">
<div className="admin-form-group" style={{ flex: 1 }}>
<label className="admin-form-label">Datum vystavení</label>
<FormField label="Datum vystavení" style={{ flex: 1 }}>
<AdminDatePicker
mode="date"
value={uploadMeta[idx]?.issue_date || ''}
onChange={(val) => updateMeta(idx, 'issue_date', val)}
/>
</div>
<div className="admin-form-group" style={{ flex: 1 }}>
<label className="admin-form-label">Datum splatnosti</label>
</FormField>
<FormField label="Datum splatnosti" style={{ flex: 1 }}>
<AdminDatePicker
mode="date"
value={uploadMeta[idx]?.due_date || ''}
onChange={(val) => updateMeta(idx, 'due_date', val)}
/>
</div>
</FormField>
</div>
<div className="admin-form-group">
<label className="admin-form-label">Poznámka</label>
<FormField label="Poznámka">
<input
type="text"
className="admin-form-input"
value={uploadMeta[idx]?.notes || ''}
onChange={(e) => updateMeta(idx, 'notes', e.target.value)}
/>
</div>
</FormField>
</div>
</div>
))}
@@ -801,8 +788,7 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
</div>
<div className="admin-modal-body">
<div className="admin-form">
<div className="admin-form-group">
<label className="admin-form-label required">Dodavatel</label>
<FormField label="Dodavatel" required>
<input
type="text"
className="admin-form-input"
@@ -810,9 +796,8 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
onChange={(e) => setEditInvoice(prev => ({ ...prev, supplier_name: e.target.value }))}
readOnly={ro}
/>
</div>
<div className="admin-form-group">
<label className="admin-form-label">Č. faktury</label>
</FormField>
<FormField label="Č. faktury">
<input
type="text"
className="admin-form-input"
@@ -820,10 +805,9 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
onChange={(e) => setEditInvoice(prev => ({ ...prev, invoice_number: e.target.value }))}
readOnly={ro}
/>
</div>
</FormField>
<div className="admin-form-row admin-form-row-3">
<div className="admin-form-group">
<label className="admin-form-label required">Částka</label>
<FormField label="Částka" required>
<input
type="number"
step="0.01"
@@ -833,9 +817,8 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
onChange={(e) => setEditInvoice(prev => ({ ...prev, amount: e.target.value }))}
readOnly={ro}
/>
</div>
<div className="admin-form-group">
<label className="admin-form-label">Měna</label>
</FormField>
<FormField label="Měna">
<select
className="admin-form-select"
value={editInvoice.currency}
@@ -844,9 +827,8 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
>
{CURRENCY_OPTIONS.map(c => <option key={c} value={c}>{c}</option>)}
</select>
</div>
<div className="admin-form-group">
<label className="admin-form-label">DPH %</label>
</FormField>
<FormField label="DPH %">
<select
className="admin-form-select"
value={editInvoice.vat_rate}
@@ -855,7 +837,7 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
>
{VAT_RATE_OPTIONS.map(r => <option key={r} value={String(r)}>{r}%</option>)}
</select>
</div>
</FormField>
</div>
{editInvoice.amount && (
<div style={{ fontSize: '0.75rem', color: 'var(--text-tertiary)', marginBottom: '0.75rem' }}>
@@ -866,27 +848,24 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
</div>
)}
<div className="admin-form-row">
<div className="admin-form-group">
<label className="admin-form-label">Datum vystavení</label>
<FormField label="Datum vystavení">
<AdminDatePicker
mode="date"
value={editInvoice.issue_date || ''}
onChange={(val) => setEditInvoice(prev => ({ ...prev, issue_date: val }))}
disabled={ro}
/>
</div>
<div className="admin-form-group">
<label className="admin-form-label">Datum splatnosti</label>
</FormField>
<FormField label="Datum splatnosti">
<AdminDatePicker
mode="date"
value={editInvoice.due_date || ''}
onChange={(val) => setEditInvoice(prev => ({ ...prev, due_date: val }))}
disabled={ro}
/>
</div>
</FormField>
</div>
<div className="admin-form-group">
<label className="admin-form-label">Stav</label>
<FormField label="Stav">
<select
className="admin-form-select"
value={editInvoice.status}
@@ -896,9 +875,8 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
<option value="unpaid">Neuhrazena</option>
<option value="paid">Uhrazena</option>
</select>
</div>
<div className="admin-form-group">
<label className="admin-form-label">Poznámka</label>
</FormField>
<FormField label="Poznámka">
<textarea
className="admin-form-input"
rows={3}
@@ -906,7 +884,7 @@ export default function ReceivedInvoicesProps({ statsMonth, statsYear, uploadOpe
onChange={(e) => setEditInvoice(prev => ({ ...prev, notes: e.target.value }))}
readOnly={ro}
/>
</div>
</FormField>
</div>
</div>
<div className="admin-modal-footer">