chore(release): v2.4.35 — lint cleanup (68→0) + duplicate-Zavřít modal fix
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>
This commit is contained in:
@@ -200,7 +200,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
// Snapshot the currently-cached grid for a given key. Returns
|
||||
// `undefined` if there's nothing cached (we don't patch empty data).
|
||||
function snapshotGrid(key: readonly unknown[]): GridData | undefined {
|
||||
return qc.getQueryData<GridData>(key as any);
|
||||
return qc.getQueryData<GridData>(key);
|
||||
}
|
||||
|
||||
// Apply a per-date cell patch to the cached grid at `key`. Returns the
|
||||
@@ -312,7 +312,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
// `ctx` may be `undefined` (e.g. if onMutate itself threw) — guarded below.
|
||||
function rollbackCells(ctx: CellRollback | undefined) {
|
||||
if (!ctx || !ctx.rolled) return;
|
||||
const prev = qc.getQueryData<GridData>(ctx.key as any);
|
||||
const prev = qc.getQueryData<GridData>(ctx.key);
|
||||
if (!prev) return;
|
||||
const userPrev = prev.cells[ctx.userId] ?? {};
|
||||
const userNext = { ...userPrev };
|
||||
@@ -379,7 +379,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
// Find the user that owns this entry in the current grid by
|
||||
// looking for any cell with entryId === id (we already know
|
||||
// the id from vars; it doesn't change across the update).
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey);
|
||||
let ownerUserId: number | null = null;
|
||||
if (grid) {
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
@@ -430,7 +430,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
// For delete we need to know the entry's user_id and full range.
|
||||
// Look it up from the current grid: find the user that has a cell
|
||||
// with entryId === id, and read rangeFrom/rangeTo from that cell.
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey);
|
||||
if (!grid) return null;
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
let entryRange: { from: string; to: string } | null = null;
|
||||
@@ -511,7 +511,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
onMutate: (vars): CellRollback => {
|
||||
// Find the user/date for this overrideId in the current grid, then
|
||||
// patch that single cell with the new values.
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey);
|
||||
if (!grid) return null;
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
for (const [date, cells] of Object.entries(byDate)) {
|
||||
@@ -559,7 +559,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
method: "DELETE",
|
||||
}),
|
||||
onMutate: (vars): CellRollback => {
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey);
|
||||
if (!grid) return null;
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
for (const [date, cells] of Object.entries(byDate)) {
|
||||
@@ -600,7 +600,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
// PlanWork.tsx so they continue to compile unchanged; by the time a
|
||||
// `mutateAsync` promise rejects, the mutation's own `onError` has already
|
||||
// restored the patched cells, so there is nothing left to do here.
|
||||
|
||||
|
||||
function rollbackMutation(_mutation: unknown, _userId: number) {
|
||||
/* no-op — see onMutate/onError above */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user