Files
finance/frontend/README.md
T
k1nq d582f15681 feat: add tests for import polling, login page, money utilities, and query keys
- Implemented tests for import polling functionality, ensuring correct behavior for active and terminal import statuses.
- Created tests for the login page, validating user interactions and error handling.
- Added unit tests for money utility functions, covering parsing, formatting, and summation of monetary values.
- Developed tests for query keys, ensuring proper scoping and invalidation roots.

chore: setup testing environment and configuration

- Added setup file for testing with Vitest and Testing Library.
- Configured TypeScript and Vite for the frontend project.
- Created Docker and Nginx configurations for local development and production environments.
- Established a PostgreSQL initialization script for setting up application roles.

docs: add README and environment configuration for infra

- Included README for the infra directory, detailing local development setup and service descriptions.
- Created an example environment configuration file for local development with placeholders for sensitive information.
2026-09-14 09:26:33 +05:00

2.9 KiB

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 refetchInterval callback 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 are aria-hidden.
  • Dense <table> markup reflows into cards under 880px via the data-label pattern — no horizontal scrolling for data.
  • Skip link, focus-visible rings, aria-live toasts, role="alert" errors, prefers-reduced-motion support, AA-contrast palette.

No secrets are read from VITE_* — the app only ever talks to same-origin /api/v1.