/* ═══════════════════════════════════════════════════════════ History views — firing log (missions) + transfer log. Firing rows are editable (re-opens FireMissionModal in edit mode behind a password gate). CSV export for both logs. ═══════════════════════════════════════════════════════════ */ (function () { const { useState: useStateH } = React; const { GUNS: GUNS_H, parseKey: parseKeyH, keyLabel: keyLabelH, fmtDatetime: fmtH, csvExport: csvH, Modal: ModalH, PasswordGate: PasswordGateH, } = window; function comboSummary(items, regs) { // group ammoItems into "shell + charge + fuze ×N" readable lines return (items || []).map((it, i) => { const p = parseKeyH(it.key); const icon = p?.category === 'shell' ? '🔵' : p?.category === 'charge' ? '⚡' : '🟡'; return {icon} {keyLabelH(it.key, regs)} ×{it.qty}; }); } // ── Firing log ─────────────────────────────────────────────── function MissionsView({ state, dispatch }) { const regs = state.registeredTypes; const [editRow, setEditRow] = useStateH(null); const [authRow, setAuthRow] = useStateH(null); // pending edit auth const [deleteRow, setDeleteRow] = useStateH(null); // row waiting for delete auth const [deleteAuthRow, setDeleteAuthRow] = useStateH(null); // row after auth, waiting confirm const [q, setQ] = useStateH(''); const log = state.firingLog || []; const filtered = log.filter(r => { if (!q.trim()) return true; const hay = [r.missionId, r.target, r.unit, r.gun, r.notes].join(' ').toLowerCase(); return hay.includes(q.toLowerCase()); }); const exportCsv = () => { const regs = state.registeredTypes; // Build a unique sorted list of all ammo keys that appear in any mission const usedKeys = new Set(); log.forEach(r => (r.ammoItems || []).forEach(it => usedKeys.add(it.key))); // Sort: shells first, then charges, then fuzes const catOrder = { shell: 0, charge: 1, fuze: 2 }; const sortedKeys = [...usedKeys].sort((a, b) => { const pa = window.parseKey ? window.parseKey(a) : null; const pb = window.parseKey ? window.parseKey(b) : null; const oa = catOrder[pa?.category] ?? 9; const ob = catOrder[pb?.category] ?? 9; if (oa !== ob) return oa - ob; return keyLabelH(a, regs).localeCompare(keyLabelH(b, regs), 'he'); }); // Headers: fixed fields + one column per ammo type + category subtotals const fixedHeaders = ['מזהה משימה', 'תאריך', 'שעה', 'צוות', 'מסתייע', 'מטרה', 'mapiq', 'הערות']; const ammoHeaders = sortedKeys.map(k => keyLabelH(k, regs)); const totalHeaders = ['סה"כ פגזים', 'סה"כ חנ"ה', 'סה"כ מרעומים', 'סה"כ כל התחמושת']; const headers = [...fixedHeaders, ...ammoHeaders, ...totalHeaders]; const rows = log.map(r => { // Build qty map for this mission const qtyMap = {}; (r.ammoItems || []).forEach(it => { qtyMap[it.key] = (qtyMap[it.key] || 0) + (it.qty || 0); }); const fixed = [r.missionId, r.date, r.time, r.gun, r.unit || '', r.target || '', r.mapiq || '', r.notes || '']; const ammo = sortedKeys.map(k => qtyMap[k] || 0); // Category subtotals let totalShells = 0, totalCharges = 0, totalFuzes = 0; sortedKeys.forEach(k => { const p = window.parseKey ? window.parseKey(k) : null; const q = qtyMap[k] || 0; if (p?.category === 'shell') totalShells += q; if (p?.category === 'charge') totalCharges += q; if (p?.category === 'fuze') totalFuzes += q; }); const totals = [totalShells, totalCharges, totalFuzes, totalShells + totalCharges + totalFuzes]; return [...fixed, ...ammo, ...totals]; }); csvH(headers, rows, `firing-log-${new Date().toISOString().slice(0, 10)}.csv`); }; const doDelete = () => { if (!deleteAuthRow) return; dispatch({ type: 'DELETE_MISSION', rowId: deleteAuthRow.id }); setDeleteAuthRow(null); }; return (
| מזהה | תאריך/שעה | צוות | מסתייע | מטרה | תחמושת | הערות | פעולות |
|---|---|---|---|---|---|---|---|
| {r.missionId} | {r.date} {r.time} |
{r.gun} | {r.unit} | {r.target} | {comboSummary(r.ammoItems, regs)} | {r.notes || '—'} |
|
| תאריך ושעה | מקור | יעד | תחמושת | |
|---|---|---|---|---|
| {fmtH(r.datetime)} | {r.src} | ← | {r.dst} | {(r.items || []).map((it, j) => ( {keyLabelH(it.key, regs)} ×{it.qty} ))} |