/* global React, Card, Button, Input, Ic, VS */ function ConfigScreen() { const role = VS.getRole(); const username = VS.getUsername(); const isAdmin = role === 'admin'; const [tab, setTab] = React.useState('overview'); const tabs = [ { id: 'overview', label: 'Ogólne' }, { id: 'schema-library', label: 'Biblioteka schematów' }, { id: 'zalecenia-facilities', label: 'Zakłady zaleceń' }, ]; return (
Ustawienia

Konfiguracja

Profil zalogowanego użytkownika oraz parametry systemu.
{/* Tabs */}
{tabs.map((t) => ( setTab(t.id)}>{t.label} ))}
{tab === 'overview' && } {tab === 'schema-library' && } {tab === 'zalecenia-facilities' && }
); } function TabBtn({ active, onClick, children }) { return ( ); } function OverviewTab({ username, role, isAdmin }) { return (
Konto
Normy alarmowe
Zgodne z ISO 10816-3, klasa II (maszyny < 15 kW).
Integracje
{isAdmin && (
Administracja
Przełącz się na zakładkę „Biblioteka schematów” lub „Zakłady zaleceń” aby zarządzać zasobami używanymi w protokołach.
)}
); } // ============================================================ // SCHEMA LIBRARY ADMIN // ============================================================ function SchemaLibraryAdmin({ isAdmin }) { const [list, setList] = React.useState(null); const [cats, setCats] = React.useState([]); const [err, setErr] = React.useState(''); const [filterCat, setFilterCat] = React.useState(''); const [msg, setMsg] = React.useState(''); // Add form const [newFile, setNewFile] = React.useState(null); const [newName, setNewName] = React.useState(''); const [newCat, setNewCat] = React.useState(''); const [adding, setAdding] = React.useState(false); const fileRef = React.useRef(null); const load = React.useCallback(() => { VS.schemaLibrary() .then((r) => setList(r || [])) .catch((e) => setErr(e.message)); VS.schemaLibraryCategories() .then((r) => setCats(r || [])) .catch(() => setCats([])); }, []); React.useEffect(() => { load(); }, [load]); async function addSchema() { if (!newFile) { setMsg('Wybierz plik obrazka.'); return; } setAdding(true); setMsg(''); try { await VS.addSchemaLibrary(newFile, newName.trim(), newCat.trim()); setNewFile(null); setNewName(''); setNewCat(''); if (fileRef.current) fileRef.current.value = ''; load(); setMsg('Dodano schemat.'); setTimeout(() => setMsg(''), 2500); } catch (e) { setMsg('Błąd: ' + e.message); } finally { setAdding(false); } } async function removeItem(id) { if (!confirm('Usunąć ten schemat z biblioteki?')) return; try { await VS.deleteSchemaLibrary(id); load(); } catch (e) { alert('Błąd: ' + e.message); } } if (!isAdmin) { return (
Biblioteka schematów
Tylko administrator może zarządzać biblioteką.
); } const filtered = (list || []).filter((it) => !filterCat || (it.category || '') === filterCat); return (
{/* Add */}
Dodaj schemat
Plik (JPG/PNG)
setNewFile(e.target.files && e.target.files[0])} style={{ fontSize: 12 }} />
Nazwa
setNewName(e.target.value)} placeholder="np. Przekładnia NGC-140" />
Kategoria
setNewCat(e.target.value)} placeholder="np. Przekładnie" />
{msg && (
{msg}
)}
{/* Filter */}
Filtr kategorii {list ? `${filtered.length} / ${list.length}` : ''}
{/* List */} {err && (
{err}
)} {!err && !list &&
Ładowanie…
} {!err && list && filtered.length === 0 && (
Brak schematów.
)} {!err && filtered.length > 0 && (
Podgląd
Nazwa
Kategoria
Akcje
{filtered.map((it, i) => ( removeItem(it.id)} /> ))}
)}
); } function SchemaLibraryRow({ item, last, onChange, onRemove }) { const [name, setName] = React.useState(item.name || ''); const [category, setCategory] = React.useState(item.category || ''); const [busy, setBusy] = React.useState(false); const [msg, setMsg] = React.useState(''); React.useEffect(() => { setName(item.name || ''); setCategory(item.category || ''); }, [item.id, item.name, item.category]); const dirty = name !== (item.name || '') || category !== (item.category || ''); async function save() { setBusy(true); setMsg(''); try { await VS.updateSchemaLibrary(item.id, { name, category }); setMsg('ok'); setTimeout(() => setMsg(''), 1500); onChange && onChange(); } catch (e) { setMsg('Błąd: ' + e.message); } finally { setBusy(false); } } return (
setName(e.target.value)} placeholder="Nazwa" /> setCategory(e.target.value)} placeholder="Kategoria" />
{msg && ( {msg === 'ok' ? '✓' : msg} )}
); } // ============================================================ // ZALECENIA FACILITIES ADMIN // ============================================================ function ZaleceniaFacilitiesAdmin({ isAdmin }) { const [list, setList] = React.useState(null); const [err, setErr] = React.useState(''); const [newCode, setNewCode] = React.useState(''); const [newName, setNewName] = React.useState(''); const [adding, setAdding] = React.useState(false); const [msg, setMsg] = React.useState(''); const load = React.useCallback(() => { VS.zaleceniaFacilities() .then((r) => setList(r || [])) .catch((e) => setErr(e.message)); }, []); React.useEffect(() => { load(); }, [load]); async function add() { if (!newCode.trim() || !newName.trim()) { setMsg('Podaj kod i nazwę.'); return; } setAdding(true); setMsg(''); try { await VS.addZaleceniaFacility({ code: newCode.trim(), name: newName.trim() }); setNewCode(''); setNewName(''); load(); setMsg('Dodano.'); setTimeout(() => setMsg(''), 2000); } catch (e) { setMsg('Błąd: ' + e.message); } finally { setAdding(false); } } async function remove(id) { if (!confirm('Usunąć ten zakład?')) return; try { await VS.deleteZaleceniaFacility(id); load(); } catch (e) { alert('Błąd: ' + e.message); } } if (!isAdmin) { return (
Zakłady zaleceń remontowych
Tylko administrator może zarządzać zakładami.
); } return (
Dodaj zakład
Kod
setNewCode(e.target.value)} placeholder="np. BC-1" />
Nazwa
setNewName(e.target.value)} placeholder="Pełna nazwa zakładu" />
{msg && (
{msg}
)}
{err && (
{err}
)} {!err && !list &&
Ładowanie…
} {!err && list && list.length === 0 && (
Brak zakładów.
)} {!err && list && list.length > 0 && (
Kod
Nazwa
Akcje
{list.map((f, i) => ( remove(f.id)} /> ))}
)}
); } function FacilityRow({ item, last, onChange, onRemove }) { const [code, setCode] = React.useState(item.code || ''); const [name, setName] = React.useState(item.name || ''); const [busy, setBusy] = React.useState(false); const [msg, setMsg] = React.useState(''); React.useEffect(() => { setCode(item.code || ''); setName(item.name || ''); }, [item.id, item.code, item.name]); const dirty = code !== (item.code || '') || name !== (item.name || ''); async function save() { setBusy(true); setMsg(''); try { await VS.updateZaleceniaFacility(item.id, { code, name }); setMsg('ok'); setTimeout(() => setMsg(''), 1500); onChange && onChange(); } catch (e) { setMsg('Błąd: ' + e.message); } finally { setBusy(false); } } return (
setCode(e.target.value)} placeholder="Kod" /> setName(e.target.value)} placeholder="Nazwa" />
{msg && ( {msg === 'ok' ? '✓' : msg} )}
); } function KV({ label, value, mono }) { return (
{label} {value}
); } Object.assign(window, { ConfigScreen });