mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +00:00
66 lines
3.7 KiB
Markdown
66 lines
3.7 KiB
Markdown
# 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<T, CreatePayload, UpdatePayload>` 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 `<SuspenseHelper>` 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 `<SuspenseHelper>` 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`.
|