mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-09-30 14:43:13 +00:00
| .. | ||
| __tests__ | ||
| admin | ||
| customers | ||
| lineItems | ||
| pricingLibrary | ||
| proposals | ||
| shared | ||
| sites | ||
| README.md | ||
Frontend domain layer — conventions
SHOC-alignment Phase 4 (mirrors shoc-frontend-new dev's src/domain/<entity>/ layering).
Every agent/contributor working in this tree builds to THIS spec.
Structure
src/domain/<entity>/
├── api.ts # HTTP calls only: axios via lib/api/client, path constants, no hooks
├── types.ts # re-exports from @proposal-system/api-contracts + view-only types
├── schemas.ts # re-exports from @proposal-system/api-contracts/schemas + form schemas
└── use-cases.ts # TanStack Query hooks + this domain's query keys (the ONLY public surface)
Domains: proposals, lineItems, customers, pricingLibrary, admin, sites.
(auth arrives with the separate auth-storage PR — do NOT create it here.)
Rules
- Pages import ONLY from
domain/<x>/use-cases(andtypes) — never fromlib/api/*, neverapiClientdirectly, neveruseQuery/useMutationinline in a page. Pages are thin callers. - Query keys live in the domain: each
use-cases.tsexportsexport const <entity>Keys = { all: ['<entity>'] as const, detail: (id: string) => ['<entity>', id] as const, ... }(TanStack hierarchical-key convention).src/constants/queryKeys.tsis deleted at integration — do not add imports of it. - Invalidation uses the domain key objects across domains where needed
(e.g. approving a proposal invalidates
proposalsKeys.all). - Forms: react-hook-form +
zodResolver(from@hookform/resolvers/zod). Form schemas live in the domain'sschemas.ts, derived from the shared contract schemas (@proposal-system/api-contracts/schemas) via.pick/.extend/.omit— never hand-written duplicates. Form field state maps to the request type at submit (atoCreateRequest(formValues)mapper inschemas.tswhen non-trivial). lib/api/client.tsstays — the single axios instance (interceptors, 401 handling). Domainapi.tsfiles import it. The oldlib/api/<domain>.tsmodules are deleted once no page imports them (integration step) —lib/api/auth.tsstays until the auth PR.- Mutations: toast on error stays in the hook (matching current UX), success invalidation in the hook; page-specific side effects (navigate, dialog close) via the mutation's callbacks at the call site.
- No new state managers, no context — server state = TanStack Query, existing Redux auth/ui slices untouched (auth refactor is a separate PR).
- Styling: tokens only (
var(--...), theme) — no hardcoded hexes. - Verify before returning/committing:
npx tsc --noEmit,npm test -- --run,npm run build— all green, no skipped tests, no@ts-ignore.