# LTI Web Client Next.js 15 (App Router) + React 19 + TypeScript front-end for the LTI ERP system. ## Tech stack - **Framework:** Next.js 15.5 (App Router, Turbopack) - **UI:** React 19, Tailwind CSS v4, Radix UI, daisyUI, lucide-react - **State:** zustand - **Forms:** Formik + Yup, react-hook-form - **Data fetching:** axios + SWR (custom `httpClient` / `httpClientFetcher` in `src/services/http`) - **Tables:** @tanstack/react-table - **Reporting:** @react-pdf/renderer, jspdf, exceljs, xlsx, recharts ## Scripts - `npm run dev` — lint + dev server (Turbopack) - `npm run build` — production build - `npm run lint` — ESLint - `npm run typecheck` — `next typegen && tsc --noEmit` - `npm run format` — Prettier - `npm run pre-commit` — format + lint + typecheck + build (Husky pre-commit hook) ## Project structure ``` src/ app/ # Next.js App Router routes (one folder per feature) components/ pages/{feature}/ # Page-specific components (mirrors src/app) helper/ # Cross-cutting helpers (e.g. SuspenseHelper) ui/ # Shared UI primitives services/ api/ # API service classes (extend BaseApiService) http/ # httpClient / httpClientFetcher hooks/ # Service-level hooks stores/ # zustand stores grouped by domain types/api/ # Request/response types per feature lib/ # Shared helpers (api-helper, formik-helper, utils, validation, …) config/, styles/ ``` ## Feature development standard **Always follow this order when adding a new feature.** This is a team convention — deviating creates churn in code review. 1. **Types** — Define payload and response types in `src/types/api/{feature}` (or `{feature}.d.ts` for small features). 2. **API service** — Add `src/services/api/{feature}.ts` exporting a class that extends `BaseApiService` from [src/services/api/base.ts](src/services/api/base.ts). Use a subfolder (e.g. `src/services/api/daily-checklist/`) when the feature has multiple resource classes. 3. **Page** — Create the route under `src/app/{feature}` and a matching `src/components/pages/{feature}` folder for its components. 4. **Component slicing** — Break the page UI into components inside `src/components/pages/{feature}`. 5. **Wire up the API** — Consume the service class from step 2 inside the page/components (often via SWR). 6. **Detail layout** — When a route reads URL params via `useSearchParams` (e.g. `/feature/detail?id=123`), add `src/app/{feature}/detail/layout.tsx` that wraps `children` in `` from `@/components/helper/SuspenseHelper`. 7. **Shared state** — Use zustand stores in `src/stores/{domain}` when state must cross component boundaries. 8. **Helpers** — Reuse from [src/lib](src/lib) first (`api-helper.ts`, `formik-helper.ts`, `utils/`, `validation/`, etc.). Add new helpers there. ### Reference implementations `closing`, `finance`, `expense`, `production`, `inventory`, `marketing`, `master-data`, `purchase`, `report`, `daily-checklist`, `dashboard` — all live in both `src/app/{feature}` and `src/components/pages/{feature}` and follow the standard above. ## Conventions - Path alias `@/` maps to `src/`. - Detail pages that read `useSearchParams` MUST be wrapped in `` via a `layout.tsx` (see [src/app/finance/detail/layout.tsx](src/app/finance/detail/layout.tsx) for the canonical pattern). - API service classes inherit CRUD methods (`getAll`, `getSingle`, etc.) from `BaseApiService` — extend the class for feature-specific endpoints rather than calling `httpClient` directly from components. - Pre-commit runs format + lint + typecheck + build; do not bypass with `--no-verify`.