UI fix:
- Close-only modals showing a redundant second close button now use
hideCancel: ReceivedInvoices paid-detail modal (was two identical "Zavřít"
buttons) and PlanCellModal "Den je součástí rozsahu".
- Add modal-duplicate-close test enforcing close-only modals set hideCancel.
Lint: cleared all 68 warnings → 0.
- preserve-caught-error: attach { cause } in ai.service / exchange-rates.
- no-require-imports: package.json version read via fs (APP_VERSION) instead
of require(), avoiding a rootDir-expanding static JSON import.
- react-hooks/exhaustive-deps (11): ref-in-cleanup copies, derived-value
useMemo wrapping, PlanGrid field extraction, stable nextKey useCallback,
AuthContext documented cycle-break.
- no-explicit-any (53): precise route param/Prisma types, generic enrich*()
preserving payload shape, minimal vite module type, frontend body/query-key
types, SystemInfo for Settings.
Refactor (test enablement): shift-form types moved to dependency-free
shiftFormTypes.ts so the print-HTML builders are unit-testable without the
component graph; characterization test pins their output.
Gates: 649 tests pass, tsc -b clean, lint 0. Verified touched flows live
via Playwright (PlanWork CRUD + optimistic cache, warehouse form keys,
Settings system info, invoice detail).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
unused-vars (25): leftover imports/types across pages, routes and services;
write-only sickHours accumulator; unused holidayCount pair; test helpers
authPatch/authDelete; TOut dropped from ApiMutationOptions (the hook keeps
its own generic — no call-site changes); requireAuth no longer importable
in customers/warehouse routes (matches the no-bare-auth-reads convention).
useless-assignment (5): initializers proven overwritten on every path
(systemQty x2, hours, writtenSize -> let x: number) and the seed's dead
adminUser reassignment (create kept, assignment dropped).
useless-escape (4): [eE+\-] -> [eE+-] and [\/...] -> [/...] — identical
semantics.
Behavior-neutral; lint 102 -> 68 warnings (0 errors), suite 641 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adopt the PageEnter wrapper as every page's outermost render element and remove the ad-hoc per-page entrance motion.div wrappers. Every page now enters the same way — all top-level sections rise+fade in, staggered — so nothing appears instantly and the motion is identical app-wide. Presentation-only: no data/logic/hooks/invalidate/permissions touched. Embedded sub-tabs (CompanySettings, ReceivedInvoices), Login (auth shell) and the dev UiKit are intentionally excluded. Gates: tsc -b --noEmit=0, build=0, vitest 152/152.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- The project create-modal start/end dates used raw <input type="date">;
converted to <AdminDatePicker> so every date field in the app now goes
through the shared component (react-datepicker on desktop, native on touch).
- AdminDatePicker now defaults its placeholder by mode (date 'dd.mm.rrrr',
month 'mm.rrrr', time 'hh:mm') so empty date fields always show a format
hint; explicit placeholders (e.g. 'Od'/'Do' range filters) still override.
- Dropped WarehouseReceiptForm's ad-hoc 'dd.mm.yyyy' so it inherits the
unified Czech default.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>