- Updated timestamps and AST hashes for English and Russian localization files. - Modified timestamps and AST hashes for ImportDetailPage and ImportsPage components. - Updated test file timestamps and AST hash for import-confirm.test.tsx. - Added new documentation file for выписки fixes with relevant metadata.
Finance frontend
React + TypeScript SPA for the finance tracker: RU/EN, WCAG-aware, data-dense desktop tables that reflow into cards on mobile.
Stack
- Vite + React 19 + TypeScript (strict)
- React Router (library mode)
- TanStack Query v5 (space-scoped query keys, v5
refetchIntervalcallback polling) - React Hook Form + Zod
- i18next (RU default, EN fallback)
- Vitest + Testing Library (jsdom)
- ESLint 9 (typescript-eslint, react-hooks, jsx-a11y)
Commands
npm install # install
npm run dev # dev server on :5173, proxies /api -> http://localhost:8000
npm run build # tsc --noEmit && vite build
npm run typecheck # tsc --noEmit
npm run lint # eslint .
npm test # vitest run
npm test:watch # vitest
npm run api:generate
npm run api:generate looks for an OpenAPI schema at ../backend/openapi.json
(or fetches /api/v1/openapi.json from a running backend) and emits
src/api/generated/schema.d.ts via openapi-typescript. Until the backend
schema exists the script exits with an explanation and the hand-written client
remains the source of truth.
API client
src/api/client.ts is a small typed wrapper over fetch bound to same-origin
/api/v1 with credentials: 'same-origin', a CSRF header read from the
csrf_token cookie on mutating requests, and a single ApiError type carrying
status + machine-readable code (translated via the errors.* i18n keys).
src/api/endpoints.ts declares one function per endpoint with payload/return
types from src/api/types.ts, so each group can be swapped one-for-one by
OpenAPI-generated functions without touching UI code.
Assumed endpoints (matching the approved plan): /auth/login, /auth/logout,
/auth/me, /auth/invitations/accept, /accounts, /operations,
/budget/summary, /budget/categories (+ close/reopen/copy-previous and
per-category plan/fund actions), /imports, /imports/{id} (+ confirm /
reparse / revert / row decisions), /analytics/{category-spend|plan-fact|cash-flow|balances},
/exports, /spaces/current/deletion. Amounts are integer kopecks everywhere.
Query keys
All space-data keys are rooted at ['space', ...] (src/api/queryKeys.ts);
mutations invalidate by prefix (e.g. an applied import invalidates the whole
space root). Import list/detail queries poll with the v5 refetchInterval
callback and stop automatically in terminal states (ready,
review_required, confirmed, failed).
Accessibility & responsiveness
- Every chart figure ships a real data table (
<details>toggle) with captions and scoped headers; decorative graphics arearia-hidden. - Dense
<table>markup reflows into cards under 880px via thedata-labelpattern — no horizontal scrolling for data. - Skip link, focus-visible rings,
aria-livetoasts,role="alert"errors,prefers-reduced-motionsupport, AA-contrast palette.
No secrets are read from VITE_* — the app only ever talks to same-origin
/api/v1.