Bedragen excl. btw. De CSV's in kosten/ zijn leidend: Toepassen geldt tot herladen; om een wijziging te houden "intern.csv downloaden" en het bestand in kosten/ vervangen, of met "Wijzigingen downloaden" alleen de aangepaste velden (met de standaardwaarde ernaast) opslaan. Prijzen pas je aan in leveranciers.csv (CSV = daaruit, anders noodwaarde). Een veld dat afwijkt van intern.csv is gemarkeerd.
`;
document.body.appendChild(overlay);
overlay.addEventListener('click', (e) => {
if (e.target === overlay) return close();
const btn = e.target.closest('[data-cs]');
if (!btn) return;
const a = btn.dataset.cs;
if (a === 'cancel') close();
else if (a === 'save') {
CostModel.saveSettings(readForm());
close();
}
else if (a === 'reset') fill(withLeveranciers(CostModel.defaultValues()));
else if (a === 'export') exportIntern();
else if (a === 'export-changes') exportChanges();
else if (a === 'import') overlay.querySelector('[data-file=import]').click();
else if (a === 'lev-load') overlay.querySelector('[data-file=leveranciers]').click();
else if (a === 'lev-clear') CostCsv.reload('leveranciers');
else if (a === 'lev-template') saveFile(CostCsv.template('leveranciers', readForm(), SJABLOON_BALKEN), 'leveranciers.csv');
});
overlay.querySelector('[data-file=import]').addEventListener('change', (e) => {
const file = e.target.files[0];
e.target.value = '';
if (!file) return;
file.text().then(txt => fill(withLeveranciers(CostModel.importFile(txt))))
.catch(err => alert('Importeren mislukt: ' + err.message));
});
overlay.querySelector('[data-file=leveranciers]').addEventListener('change', (e) => {
const file = e.target.files[0];
e.target.value = '';
if (!file) return;
file.text().then(txt => CostCsv.loadText('leveranciers', txt, file.name))
.catch(err => alert('Leverancierslijst laden mislukt: ' + err.message));
});
CostCsv.onChange(() => {
if (!overlay.classList.contains('open')) return;
const v = readForm();
renderForm();
fill(withLeveranciers(v));
});
overlay.addEventListener('input', markChanged);
}
const levEntry = (g, k) => CostCsv.entry('leveranciers', `${g}.${k}`);
const withLeveranciers = (values) => CostCsv.overlay('leveranciers', values);
function exportIntern() {
saveFile(CostCsv.template('intern', readForm(CostModel.getSettings({ leveranciers: false }))), 'intern.csv');
}
function exportChanges() {
const text = CostCsv.changes(readForm(CostModel.getSettings({ leveranciers: false })), CostModel.defaultValues());
if (!text) return alert('Geen wijzigingen ten opzichte van intern.csv.');
const d = new Date(), p = (n) => String(n).padStart(2, '0');
saveFile(text, `wijzigingen-intern-${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}-${p(d.getHours())}${p(d.getMinutes())}.csv`);
}
function renderStatus() {
const when = (st) => st.loadedAt ? new Date(st.loadedAt).toLocaleString('nl-NL', { dateStyle: 'short', timeStyle: 'short' }) : '';
const block = (list, extra) => {
const st = CostCsv.status(list);
const head = !st.source
? `${esc(st.label)}: geen ${esc(st.url)} gevonden`
: `${esc(st.label)}: ${esc(st.name || '')}${st.source === 'tijdelijk' ? ' (tijdelijk ingeladen, tot herladen)' : ''} · ${st.count} waarden · ${esc(when(st))}`;
const issues = st.errors.map(e => `
${esc(e)}
`)
.concat(st.unknown.map(u => `
regel ${u.line}: code ${esc(u.code)}${u.label ? ` (${esc(u.label)})` : ''} wordt (nog) niet gebruikt