Files
travandClaude Opus 5 d1cb472696 Initial commit: repair cafe kanban board
A per-event queue board for a repair cafe. Customers sign items in on a
shared tablet; volunteers drag repairs through Queue, In progress and Done
on a dashboard, then export the day's records as CSV.

Zero npm dependencies: node:http plus JSON files on disk, no build step.
Categories and house rules are set in config.json. Events are deleted
7 days after creation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 15:02:45 -04:00

67 lines
1.6 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const COLUMNS = [
'event',
'date/time added',
'customer',
'item',
'category',
'problem',
'status',
'repairer',
'outcome',
'tools/consumables',
'notes',
];
// Quote a field if it contains anything that would break the row, doubling any
// quotes inside it. Everything else goes out bare.
function escapeField(value) {
const text = value === null || value === undefined ? '' : String(value);
if (/[",\r\n]/.test(text)) return '"' + text.replace(/"/g, '""') + '"';
return text;
}
function row(fields) {
return fields.map(escapeField).join(',');
}
// "2026-08-15 17:14" in the server's timezone — spreadsheets read that as a
// date, which a raw UTC ISO string does not.
function localDateTime(iso) {
const d = new Date(iso);
if (Number.isNaN(d.getTime())) return iso;
const pad = (n) => String(n).padStart(2, '0');
return (
`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +
`${pad(d.getHours())}:${pad(d.getMinutes())}`
);
}
function repairRows(event) {
return event.repairs.map((r) =>
row([
event.name,
localDateTime(r.createdAt),
r.customer,
r.item,
r.category,
r.problem,
r.status,
r.repairer,
r.outcome,
r.toolsUsed,
(r.notes || []).map((n) => n.text).join(' | '),
])
);
}
// A leading BOM so Excel reads it as UTF-8 rather than mangling accents.
function toCsv(events) {
const lines = [row(COLUMNS)];
for (const event of events) lines.push(...repairRows(event));
return '' + lines.join('\r\n') + '\r\n';
}
module.exports = { toCsv, escapeField, COLUMNS };