mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
3.7 KiB
3.7 KiB
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/httpClientFetcherinsrc/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 buildnpm run lint— ESLintnpm run typecheck—next typegen && tsc --noEmitnpm run format— Prettiernpm 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.
- Types — Define payload and response types in
src/types/api/{feature}(or{feature}.d.tsfor small features). - API service — Add
src/services/api/{feature}.tsexporting a class that extendsBaseApiService<T, CreatePayload, UpdatePayload>from src/services/api/base.ts. Use a subfolder (e.g.src/services/api/daily-checklist/) when the feature has multiple resource classes. - Page — Create the route under
src/app/{feature}and a matchingsrc/components/pages/{feature}folder for its components. - Component slicing — Break the page UI into components inside
src/components/pages/{feature}. - Wire up the API — Consume the service class from step 2 inside the page/components (often via SWR).
- Detail layout — When a route reads URL params via
useSearchParams(e.g./feature/detail?id=123), addsrc/app/{feature}/detail/layout.tsxthat wrapschildrenin<SuspenseHelper>from@/components/helper/SuspenseHelper. - Shared state — Use zustand stores in
src/stores/{domain}when state must cross component boundaries. - Helpers — Reuse from 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 tosrc/. - Detail pages that read
useSearchParamsMUST be wrapped in<SuspenseHelper>via alayout.tsx(see src/app/finance/detail/layout.tsx for the canonical pattern). - API service classes inherit CRUD methods (
getAll,getSingle, etc.) fromBaseApiService— extend the class for feature-specific endpoints rather than callinghttpClientdirectly from components. - Pre-commit runs format + lint + typecheck + build; do not bypass with
--no-verify.