Files
lti-web-client/CLAUDE.md
T
2026-04-27 10:48:56 +07:00

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 / 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 typechecknext 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. 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 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 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.