The JWT log-noise fix (88c9b7c) stopped logging expected invalid/expired tokens, but auth.service.test.ts still asserted it logged, leaving 2 failing tests on master/v1.9.0 (a wrong auth test file was run when that change landed). Tests now assert null + no console.error for JsonWebTokenError cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PlanCellModal (and the modal system) reference FormModal's footerLeft slot and hideCloseButton, but those props lived only in an uncommitted working-tree change — so committed code did not typecheck (TS2322) and a build-from-committed (e.g. the v1.9.0 release) silently dropped the footer-left delete button in the plan entry/override edit modal. Commits the enhancements + their CSS so committed == working.
NOTE: production v1.9.0 is affected (plan edit-modal delete button missing); needs a patch release. Flagged in the overnight audit report.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
verifyAccessToken logged every invalid/expired access token via console.error with a full stack trace. Access tokens are ~15 min and the client silently refreshes + retries on the 401, so this is an expected condition that flooded production logs (~every 15 min per active user) and buried real errors. Now only genuinely unexpected failures (non-JsonWebTokenError, e.g. a DB error in loadAuthData) are logged. No behavior change — verification still returns null on any token error.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- AttendanceAdmin: declare worked_hours_raw on UserTotalData (the hook sets it at runtime; the local interface omitted it)
- usePlanWork.rollbackMutation: type the mutation param as unknown + explicit cast so passing the TanStack mutation result (with the dynamically-stashed _rolled) no longer trips the weak-type check
tsc -p tsconfig.app.json --noEmit is now clean (0 errors, was 9).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update validates the category only when it changes, so a note-only edit on an entry whose category was later hidden/deleted no longer 400s. The edit select also shows the current (retired) category marked '(skryta)' instead of silently snapping to the first active option; create defaults to an active category.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
admin-btn-danger was referenced but never defined, so the 'Opravdu smazat' confirm rendered as a plain button. Define a solid danger button (uses --danger), matching the primary button's structure; the per-row delete trigger stays an outline via plan.css. (Includes the transparent-border button refinement so variants don't layout-shift.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
DELETE /plan/categories/:id now hard-deletes the row, guarded: refuses when any live entry/override uses the key (suggests hide instead) and keeps >=1 active category. Modal gains a per-row Smazat with inline confirm. Hiding stays via PATCH is_active.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace 14 hardcoded per-category CSS rules with a single --cat-color
custom property set inline on each filled cell button, driven by the DB
categories list threaded from PlanWork → PlanGrid → PlanRangeChips.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Replace hardcoded planCategoryEnum z.enum with z.string().trim().min(1)
- Add assertActiveCategory() helper that rejects inactive/unknown keys
- Add resolveCategoryLabel() helper that resolves the Czech label from plan_categories DB table, falling back to built-in map
- Change PlanAuditDescriptionInput.category -> categoryLabel (pre-resolved string)
- Update buildPlanAuditDescription to use opts.categoryLabel directly
- Update all 6 buildPlanAuditDescription call sites in plan.service.ts to await resolveCategoryLabel(row.category)
- Add category validation in createEntry, updateEntry, createOverride, updateOverride
- Update planAuditDescription tests to pass categoryLabel instead of category
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Work-plan fixes from this session:
- Czech audit descriptions for plan entries/overrides (was empty '-')
- server-embedded project label on grid cells (was '-' past the 100-project cap)
- dashboard activity + audit-log cache invalidation on plan mutations
- read-only cells: no '+' on empty, keep hover on cells with a record
- view modal: Czech category + formatted dates
- sticky date column made opaque (no bleed-through on horizontal scroll)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three related fixes from manual smoke testing:
- Zod schema: drop min(1) on note field across all four schemas — note is
optional in real usage, and the modal initialized it to empty.
- assertNotPastDate: replace toISOString() (UTC) with local-time getters
to match the rest of the codebase. Fixes off-by-one near day boundaries.
- createEntry / updateEntry: also check the date_to endpoint for past
dates, so a range can't extend backwards into the past even when its
start is today or future. Defense in depth.
Modal: drop `required` attribute and asterisk from the note field. Tests:
add 5 new cases covering empty note, past date HTTP rejection, and the
new to-endpoint check in updateEntry.