Commit Graph
26 Commits
Author SHA1 Message Date
ferdi2goandClaude Opus 4.8 8cd8908f38 perf(calendar): re-render only the changed day cell, not the whole grid (#10)
Extracts the day-cell construction into a self-contained makeDayCell(d). Slot
changes and holiday/closure toggles now replace just that one cell
(cell.replaceWith) plus update export-button visibility, instead of rebuilding
the entire month grid and re-attaching every listener on each interaction.
Structural changes (month/year/slot-count) still do a full render.

Faithful extraction; verified headless that the page loads without JS errors
and tests pass. Interactive render coverage to follow in the test-layer issue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:51:16 +00:00
ferdi2goandClaude Opus 4.8 c076b5e1ce perf(algorithm): precompute history count, drop per-candidate sort (#9)
- generatePlan computes a histCount Map once; scoreCandidate now does an O(1)
  lookup instead of filtering the whole history per candidate per day.
- minGap eligibility finds the latest prior date in a single pass instead of
  spreading history+monthAssignments into a new array and sorting it.

Behaviour is unchanged (all algorithm tests pass).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:44:45 +00:00
ferdi2goandClaude Opus 4.8 074635c037 docs(security): document localStorage privacy + note ID fallback (#8)
- README gains a "Datenschutz & Speicherung" section: local single-user tool,
  unencrypted localStorage, avoid shared devices, export JSON to back up.
- Comments the generateId Math.random fallback as a non-crypto last resort,
  acceptable for local employee ids.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:40:58 +00:00
ferdi2goandClaude Opus 4.8 e6452fa102 fix(excel): neutralize formula injection in exported names (#7)
Adds sanitizeCell(): cell values starting with = + - @ or a control char are
prefixed with an apostrophe so spreadsheets render them as literal text
instead of executing them as formulas. Applied to the names column.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:37:32 +00:00
ferdi2goandClaude Opus 4.8 f8efcf136a fix(security): add SRI to SheetJS CDN + Content-Security-Policy (#6)
- SheetJS <script> now carries a sha384 integrity hash and crossorigin so a
  compromised/MITM'd CDN cannot inject code.
- Adds a CSP meta: default-src 'self'; script-src limited to self +
  cdn.sheetjs.com; style-src self + Google Fonts (+inline for app styles);
  font-src gstatic; object-src 'none'; base-uri 'self'.

Verified headless against localhost: no CSP violations, SheetJS loads with
a valid integrity digest, app.js renders normally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:33:34 +00:00
ferdi2goandClaude Opus 4.8 142e0efa1f fix(employees): remove history entries when deleting an employee (#5)
removeEmployee now also filters the deleted employee's history entries, so
no orphaned "(unbekannt)" rows remain. Adds a test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:29:16 +00:00
ferdi2goandClaude Opus 4.8 7b53618921 fix(state): surface localStorage save failures instead of silent loss (#4)
saveState now logs a console.warn on failure and alerts the user once per
session (storage full/unavailable) so they can export their data and avoid
silent data loss.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:21:23 +00:00
ferdi2goandClaude Opus 4.8 065876ced4 fix(import): validate/normalize imported data, guard Excel I/O (#3)
- loadFromJSON and the localStorage startup load now run employees through
  normalizeEmployees(): fills missing constraints, drops unusable rows,
  de-duplicates ids, and discards invalid vacation ranges — preventing
  later crashes (e.g. c.neverDays on undefined) and same-day double-books.
- Excel import is wrapped in try/catch with a typeof XLSX guard and user
  feedback; the Excel export button gets the same guard.
- createEmployee reuses the shared defaultConstraints() factory.

Adds normalizeEmployees tests (defaults, dropping, dedup, vacations) and a
loadFromJSON normalization test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:20:41 +00:00
ferdi2goandClaude Opus 4.8 e851bb2833 fix(calendar): preserve manual picks when regenerating a month (#2)
generatePlan gains a preAssigned parameter: manual entries occupy slots,
count toward eligibility (maxPerMonth/minGap) and are never double-booked;
only the remaining slots per day are auto-filled. The generate handler now
keeps manual:true entries for the month instead of wiping them.

Adds tests for slot occupation, fully-manual days, and maxPerMonth counting.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:17:22 +00:00
ferdi2goandClaude Opus 4.8 700ec6de1c fix(calendar): use dynamic year range instead of hardcoded 2026 (#1)
currentYear now initializes to the current year and the year selector
offers a rolling range (this year -1 to +2) so plans can be created
for years other than 2026.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:12:18 +00:00
ferdi2goandClaude Opus 4.8 6736021af1 feat(employees): default minGapDays to 14, robust ID fallback
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 12:11:36 +00:00
ferdi2go 294de5276b feat(history): sort by date desc + name asc, delete single entry 2026-04-28 11:37:31 +00:00
ferdi2go 078d74f09f feat(calendar): pass slotsPerDay to generator, show skipped-dates warning 2026-04-28 11:26:53 +00:00
ferdi2go fa28640c28 feat(calendar): N moderator slots per day with disable-on-duplicate 2026-04-28 11:17:08 +00:00
ferdi2go 3b84fce1e6 feat(calendar): add 'Pro Tag' moderator-count selector 2026-04-28 11:09:42 +00:00
ferdi2go 69e424519d feat(excel): group entries by date, join names with ' & ' 2026-04-28 11:03:05 +00:00
ferdi2go ad680ae1f6 feat: state.settings.moderatorsPerDay with localStorage persistence 2026-04-28 10:48:58 +00:00
ferdi2go a825a63961 feat(data): settings.moderatorsPerDay in load/save JSON 2026-04-28 10:38:51 +00:00
ferdi2go 7bda92a0a3 feat(data): removeHistoryEntry supports optional employeeId 2026-04-28 10:31:38 +00:00
ferdi2go 23683102bc feat(data): dedupe history by (date, employeeId) 2026-04-28 10:21:18 +00:00
ferdi2go 3d314e84fd feat(algo): skip day when candidates < slotsPerDay 2026-04-28 10:07:22 +00:00
ferdi2go 625f9c7037 feat(algo): slotsPerDay parameter for top-N selection 2026-04-28 09:59:44 +00:00
ferdi2go 790ea72987 refactor: generatePlan returns {assignments, skippedDates} 2026-04-28 09:55:25 +00:00
ferdi2goandClaude Opus 4.7 e4ae866375 chore: ui polish — extract inline styles to CSS classes, add header art
- Move inline style.cssText to semantic classes (cal-legend, cal-header-cell,
  cal-day-tag-label, cal-btn-row) in calendar.js
- Buttons "FT"/"BU" → "Feiertag"/"Betriebsurl." for clarity
- Decorative turntable/mixer SVG header art in index.html
- style.css build-out for the new classes
- Initial README content
- Dev port 3000 → 3001

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 09:43:53 +00:00
ferdi2goandClaude Opus 4.7 6fd2cfcf04 docs: implementation plan for multiple moderators per day
14 Tasks, bottom-up: algorithmus → data.js → app.js (persistence) → UI
(calendar/history/css). TDD wo möglich (algorithm/data/excel mit Tests),
manuelle Verifikation für UI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 09:31:43 +00:00
ferdi2goandClaude Opus 4.7 b794581a06 docs: spec for multiple moderators per day
Globale Einstellung moderatorsPerDay (1-5), Top-N-Algorithmus, dynamische
N Slots pro Tag im Kalender, Excel joint Namen mit " & ", Verlauf zeigt
eine Zeile pro Person.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 09:24:42 +00:00