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

71 lines
2.9 KiB
Markdown

# 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
```bash
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`.