/* global React, Card, Button, Input, Ic, VS, Combobox, LoadingState, ErrorState */ // Protokoly osiowania — tworzenie, edycja, pobieranie PDF. // 4 wartosci wpisuje uzytkownik (V, F1, A, F2), reszta ze skanowania lub manual. // Przesun_max i rozw_max obliczane live w JS. const OSIOWANIE_NORMS = [ { rpm: 80, pw: 1.60, pd: 0.80, rw: 1.00, rd: 0.80 }, { rpm: 160, pw: 0.80, pd: 0.40, rw: 0.50, rd: 0.40 }, { rpm: 325, pw: 0.40, pd: 0.20, rw: 0.26, rd: 0.20 }, { rpm: 750, pw: 0.19, pd: 0.09, rw: 0.13, rd: 0.09 }, { rpm: 1500, pw: 0.09, pd: 0.06, rw: 0.07, rd: 0.05 }, { rpm: 3000, pw: 0.06, pd: 0.03, rw: 0.04, rd: 0.03 }, { rpm: 6000, pw: 0.03, pd: 0.02, rw: 0.03, rd: 0.02 }, ]; function calcMaxPrzesun(v, a) { const vn = parseFloat(v), an = parseFloat(a); if (isNaN(vn) || isNaN(an)) return null; return Math.sqrt(vn * vn + an * an); } function calcMaxRozw(f1, f2) { const f1n = parseFloat(f1), f2n = parseFloat(f2); if (isNaN(f1n) || isNaN(f2n)) return null; return Math.sqrt(f1n * f1n + f2n * f2n); } function fmtNum(v, decimals = 3) { if (v === null || v === undefined) return '–'; return v.toFixed(decimals); } function highlightRow(obr) { const n = parseInt(obr); if (!n) return -1; for (let i = 0; i < OSIOWANIE_NORMS.length; i++) { if (OSIOWANIE_NORMS[i].rpm >= n) return i; } return OSIOWANIE_NORMS.length - 1; } // ── Ekran listy protokołów ── function OsiowanieScreen() { const [list, setList] = React.useState(null); const [err, setErr] = React.useState(''); const [openId, setOpenId] = React.useState(null); const [creating, setCreating] = React.useState(false); const load = React.useCallback(() => { VS.request('GET', '/api/osiowanie') .then(r => setList(r)) .catch(e => setErr(e.message)); }, []); React.useEffect(() => { load(); }, [load]); async function newProtocol() { setCreating(true); try { const r = await VS.request('POST', '/api/osiowanie', { body: {} }); setOpenId(r.id); load(); } catch (e) { alert('Blad: ' + e.message); } finally { setCreating(false); } } async function deleteProtocol(id, name) { if (!confirm(`Usunac protokol "${name || id}"?`)) return; try { await VS.request('DELETE', `/api/osiowanie/${id}`); load(); } catch (e) { alert('Blad: ' + e.message); } } if (openId !== null) { return ( { setOpenId(null); load(); }} /> ); } return (
Protokoly

Osiowanie

Protokoly pomiaru i wyregulowania osiowania.
{err &&
{err}
} {!list && !err &&
Ladowanie...
} {list && list.length === 0 && (
Brak protokolow. Kliknij „Nowy protokol" aby zaczac.
)} {list && list.length > 0 && (
Nr protokolu
Urzadzenie
Zleceniodawca
Data osiowania
Akcje
{list.map((p, i) => (
{p.nr_protokolu || }
{p.machine_name || '(brak nazwy)'} {p.machine_code && {p.machine_code}}
{p.zleceniodawca || '—'}
{p.data_osiowania || '—'}
))}
)}
); } // ── Edytor protokolu ── function OsiowanieEditor({ id, onBack }) { const [d, setD] = React.useState(null); const [users, setUsers] = React.useState([]); const [saving, setSaving] = React.useState(false); const [msg, setMsg] = React.useState(''); const [err, setErr] = React.useState(''); React.useEffect(() => { VS.request('GET', `/api/osiowanie/${id}`) .then(r => setD(r)) .catch(e => setErr(e.message)); VS.usersList() .then(setUsers) .catch(() => setUsers([])); }, [id]); function set(key, val) { setD(prev => ({ ...prev, [key]: val })); } async function save() { setSaving(true); setMsg(''); try { await VS.request('PUT', `/api/osiowanie/${id}`, { body: d }); setMsg('Zapisano.'); setTimeout(() => setMsg(''), 2000); } catch (e) { setMsg('Blad: ' + e.message); } finally { setSaving(false); } } async function openPdf() { try { const r = await fetch(`/api/osiowanie/${id}/pdf`, { headers: { Authorization: `Bearer ${VS.getToken()}` }, }); if (!r.ok) { alert('Blad generowania PDF: ' + r.status); return; } const blob = await r.blob(); const url = URL.createObjectURL(blob); window.open(url, '_blank'); setTimeout(() => URL.revokeObjectURL(url), 60000); } catch (e) { alert('Blad: ' + e.message); } } if (err) return
{err}
; if (!d) return
Ladowanie...
; const przesun = calcMaxPrzesun(d.v_pion, d.a_poziom); const rozw = calcMaxRozw(d.f1_rozwarcie, d.f2_rozwarcie); const hiRow = highlightRow(d.obr_min); const userOpts = users.map(u => ({ value: String(u.id), label: u.display_name || u.username, hint: u.username, })); const userIdToName = Object.fromEntries(users.map(u => [String(u.id), u.display_name || u.username])); const inputSt = { width: '100%', height: 28, padding: '0 8px', background: 'var(--surface)', border: '1px solid var(--border-strong)', borderRadius: 'var(--r-sm)', fontSize: 12, color: 'var(--fg)', fontFamily: 'inherit', outline: 'none', }; const bigInputSt = { ...inputSt, height: 34, fontSize: 14, fontWeight: 600 }; function UserSelect({ label, field }) { const cur = d[field] ? String(d[field]) : ''; return (
{label}
); } return (
{/* Toolbar */}
{msg && {msg}}
{/* ── Naglowek dokumentu ── */}
Naglowek protokolu
Nr protokolu
set('nr_protokolu', e.target.value)} placeholder="np. O26.021 /TPW /26" style={inputSt} />
Data osiowania
set('data_osiowania', e.target.value)} placeholder="2026-04-20" style={inputSt} />
{/* ── Zleceniodawca ── */}
Zleceniodawca
Nazwa
set('zleceniodawca', e.target.value)} placeholder="Nazwa firmy / zakladu" style={inputSt} />
Adres
set('adres', e.target.value)} style={inputSt} />
NIP
set('nip', e.target.value)} style={inputSt} />
Zlecenie nr / Z dnia
set('zlecenie_nr', e.target.value)} placeholder="nr" style={{ ...inputSt, width: 60 }} /> set('data_zlecenia', e.target.value)} placeholder="data" style={{ ...inputSt, flex: 1 }} />
{/* ── Urzadzenie ── */}
Urzadzenie
Nazwa
set('machine_name', e.target.value)} placeholder="np. Pompa bagrowa nr 4" style={inputSt} />
Kod
set('machine_code', e.target.value)} placeholder="PB4" style={inputSt} />
Nr fab.
set('nr_fabryczny', e.target.value)} style={inputSt} />
Moc urz.
set('moc', e.target.value)} placeholder="90kW" style={inputSt} />
Typ
set('typ', e.target.value)} placeholder="pompa 1500 l/min" style={inputSt} />
Miejsce pracy
set('miejsce_pracy', e.target.value)} placeholder="EC Wroclaw" style={inputSt} />
obr/min
set('obr_min', e.target.value ? parseInt(e.target.value) : null)} placeholder="1500" style={inputSt} />
{/* ── WARTOSCI POMIARU — 4 pola + kalkulacja ── */}
Wartosci pomiaru osiowania
{[ { key: 'v_pion', label: 'Przesuniecie na wysokosci', sym: 'V', note: 'mm' }, { key: 'f1_rozwarcie', label: 'Rozwarcie gora-dol', sym: 'F1', note: 'mm (↓ ujemna)' }, { key: 'a_poziom', label: 'Przesuniecie na boki', sym: 'A', note: 'mm' }, { key: 'f2_rozwarcie', label: 'Rozwarcie prawa-lewa', sym: 'F2', note: 'mm (← ujemna)' }, ].map(({ key, label, sym, note }) => (
{label}
{sym} = set(key, e.target.value === '' ? null : parseFloat(e.target.value))} style={{ ...bigInputSt, width: 90, textAlign: 'center' }} /> {note}
))}
{/* Kalkulacja live */}
{[ { label: 'Pozostawione przesuniecie maksymalne', val: przesun, formula: 'sqrt(V² + A²)' }, { label: 'Pozostawione rozwarcie maksymalne', val: rozw, formula: 'sqrt(F1² + F2²)' }, ].map(({ label, val, formula }) => (
{label}
{val !== null ? fmtNum(val) : '–'} mm
{formula}
))}
{/* ── TABELA TOLERANCJI ── */}
Zalecane tolerancje ustawienia walow {d.obr_min && (podswietlono dla {d.obr_min} obr/min) }
{OSIOWANIE_NORMS.map((row, i) => ( ))}
obr/min Przesuniecie rownolegle [mm] Rozwarcie katowe [mm]
Wystarczajaco Dobrze Wystarczajaco Dobrze
{row.rpm} {row.pw.toFixed(2)} {row.pd.toFixed(2)} {row.rw.toFixed(2)} {row.rd.toFixed(2)}
{/* ── Personel + Uwagi ── */}
Personel i uwagi
Uwagi
set('uwagi', e.target.value)} placeholder="np. osiowanie silnika" style={inputSt} />
); } const thSt = { border: '1px solid var(--border-strong)', padding: '6px 10px', textAlign: 'center', fontWeight: 600, fontSize: 11, color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.04em', }; const tdSt = { border: '1px solid var(--hairline)', padding: '5px 10px', textAlign: 'center', }; Object.assign(window, { OsiowanieScreen });