50 lines
1.5 KiB
Markdown
50 lines
1.5 KiB
Markdown
|
|
# Frontend — React + TypeScript + Leaflet
|
||
|
|
|
||
|
|
## Stack
|
||
|
|
|
||
|
|
- React 18, TypeScript 5, Vite 5
|
||
|
|
- Tailwind CSS, Recharts, Zustand (state), Axios
|
||
|
|
- Leaflet / react-leaflet (maps)
|
||
|
|
- Playwright (e2e tests)
|
||
|
|
|
||
|
|
## Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
frontend/src/
|
||
|
|
main.tsx # Entry point
|
||
|
|
App.tsx # Router setup
|
||
|
|
components/ # Reusable UI (maps, charts, nav)
|
||
|
|
pages/ # Route-level views
|
||
|
|
services/api.ts # Axios client with TTL cache + request dedup
|
||
|
|
stores/ # Zustand stores
|
||
|
|
types/index.ts # Shared TypeScript interfaces
|
||
|
|
utils/ # Helpers (responsive.ts)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Path Alias
|
||
|
|
|
||
|
|
`@/` maps to `src/` — use `import { X } from '@/components/X'`.
|
||
|
|
|
||
|
|
## Patterns
|
||
|
|
|
||
|
|
- Components: PascalCase, one per file, default export
|
||
|
|
- API calls: use `services/api.ts` wrappers (`riskApi`, `alertApi`, `caseApi`, `gridApi`) — they handle caching and request dedup
|
||
|
|
- State: Zustand stores in `stores/`, typed with TypeScript interfaces from `types/`
|
||
|
|
- Styling: Tailwind utility classes, no CSS modules
|
||
|
|
|
||
|
|
## Running
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd frontend
|
||
|
|
pnpm dev # localhost:5173, proxies /api → localhost:8000
|
||
|
|
pnpm build # tsc + vite build → dist/
|
||
|
|
```
|
||
|
|
|
||
|
|
## Anti-Patterns
|
||
|
|
|
||
|
|
- Don't call axios directly — use the cached API wrappers in `services/api.ts`
|
||
|
|
- Don't use `any` in TypeScript types — use `unknown` and narrow
|
||
|
|
- Don't mix data fetching with presentation — fetch in pages, render in components
|
||
|
|
- Don't inline styles when Tailwind classes work
|
||
|
|
- Don't create god components (>200 lines) — extract sub-components
|