/* ============================================================ KODILA — Šifrant: Valute ============================================================ */ const CURRENCY_STATUS_LABEL = { active: 'Aktivna', inactive: 'Nedejavna' }; function currencyStatusRenderer(p) { const label = CURRENCY_STATUS_LABEL[p.value] || p.value; const cls = (window.STATUS_MAP[label] || 'default'); const c = cls === 'default' ? '' : cls; return `${label}`; } const CURRENCY_COLS = [ { field: 'id', headerName: 'ID', width: 70, cellClass: 'cell-mono', pinned: 'left' }, { field: 'code', headerName: 'Oznaka', width: 110, cellClass: 'cell-mono cell-strong' }, { field: 'name', headerName: 'Ime', flex: 2, minWidth: 200 }, { field: 'symbol', headerName: 'Simbol', width: 100, valueFormatter: p => p.value || '—' }, { field: 'status', headerName: 'Status', width: 130, cellRenderer: currencyStatusRenderer }, ]; const EMPTY_CURRENCY = { id: null, code: '', name: '', symbol: '', status: 'active' }; const CURRENCY_ERROR_MESSAGES = { code: { required: 'Oznaka valute je obvezna.', invalid: 'Oznaka mora biti sestavljena iz 3 črk (ISO 4217, npr. EUR).', taken: 'Ta oznaka valute že obstaja.', }, name: { required: 'Ime valute je obvezno.' }, }; function ValutaForm({ initial, onSave, onClose }) { const isEdit = !!(initial && initial.id); const [f, setF] = useState(initial && initial.id ? { ...EMPTY_CURRENCY, ...initial, symbol: initial.symbol || '' } : { ...EMPTY_CURRENCY }); const [errors, setErrors] = useState({}); const [saving, setSaving] = useState(false); const set = (k, v) => setF(s => ({ ...s, [k]: v })); const save = async () => { setSaving(true); const payload = { code: f.code.trim().toUpperCase(), name: f.name.trim(), symbol: f.symbol.trim() || null, status: f.status, }; const ok = await onSave(f.id, payload, isEdit, setErrors); setSaving(false); if (ok) onClose(); }; const fieldError = (field) => { const codes = errors[field]; if (!codes || !codes.length) return null; const map = CURRENCY_ERROR_MESSAGES[field] || {}; return codes.map(c => map[c] || c).join(' '); }; return (
{ if (e.target.classList.contains('overlay')) onClose(); }}>
e.stopPropagation()}>
{isEdit ? 'Uredi valuto' : 'Nova valuta'}
{isEdit ? f.name : 'Šifrant valut'}
Osnovni podatki
set('code', e.target.value.toUpperCase())} placeholder="EUR" style={fieldError('code') ? { borderColor: 'var(--danger)' } : null} /> {fieldError('code') && {fieldError('code')}}
set('symbol', e.target.value)} placeholder="€" />
set('name', e.target.value)} placeholder="npr. Evro" style={fieldError('name') ? { borderColor: 'var(--danger)' } : null} /> {fieldError('name') && {fieldError('name')}}
Status
* obvezna polja
); } function Valute({ currentUser }) { const isAdmin = !!(currentUser && currentUser.role === 'administrator'); const toast = useToast(); const [rows, setRows] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [editing, setEditing] = useState(null); const load = async () => { setLoading(true); setError(''); const { ok, data } = await api('/api/currencies'); if (ok) { setRows(data.currencies); } else { setError('Šifranta valut ni bilo mogoče naložiti.'); } setLoading(false); }; useEffect(() => { load(); }, []); const save = async (id, payload, isEdit, setErrors) => { const { ok, data } = isEdit ? await api(`/api/currencies/${id}`, { method: 'PUT', body: JSON.stringify(payload) }) : await api('/api/currencies', { method: 'POST', body: JSON.stringify(payload) }); if (!ok) { setErrors(data.errors || {}); return false; } setRows(rs => isEdit ? rs.map(r => r.id === data.currency.id ? data.currency : r) : [data.currency, ...rs]); toast(isEdit ? 'Valuta posodobljena' : 'Valuta dodana: ' + data.currency.code, 'check'); return true; }; return (
{error &&
{error}
} d.id} selectable exportName="kodila-valute" exportTitle="Šifrant valut" searchPlaceholder="Išči po oznaki, imenu…" onRowOpen={isAdmin ? (d) => setEditing(d) : undefined} actions={isAdmin ? ( ) : null} /> {isAdmin && editing !== null && ( setEditing(null)} /> )}
); } Object.assign(window, { Valute });