commit
This commit is contained in:
229
docs/PROJECT_ARCHITECTURE.md
Normal file
229
docs/PROJECT_ARCHITECTURE.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# Project Architecture
|
||||
|
||||
This project is a Next.js 16 App Router training-system dashboard using Auth.js, Drizzle ORM, PostgreSQL, shadcn/ui, Tailwind CSS v4, TanStack Query, TanStack Table, TanStack Form, and nuqs.
|
||||
|
||||
## Top-Level Structure
|
||||
|
||||
```text
|
||||
src/
|
||||
app/
|
||||
api/
|
||||
auth/
|
||||
dashboard/
|
||||
components/
|
||||
layout/
|
||||
ui/
|
||||
forms/
|
||||
config/
|
||||
db/
|
||||
features/
|
||||
hooks/
|
||||
lib/
|
||||
styles/
|
||||
types/
|
||||
```
|
||||
|
||||
## App Router
|
||||
|
||||
Dashboard pages live under `src/app/dashboard`.
|
||||
|
||||
Common page pattern:
|
||||
|
||||
```text
|
||||
page.tsx
|
||||
-> require*DashboardAccess()
|
||||
-> parse search params
|
||||
-> PageContainer
|
||||
-> feature listing/detail/form component
|
||||
```
|
||||
|
||||
API route handlers live under `src/app/api`. Route handlers are the app boundary for persistence and access enforcement.
|
||||
|
||||
## Feature Modules
|
||||
|
||||
Feature modules live under `src/features/<name>`.
|
||||
|
||||
Strong feature examples:
|
||||
|
||||
- `training-records`: complete DB-backed feature with tables, forms, upload, review, and certificates.
|
||||
- `courses`: DB-backed CRUD with table and form.
|
||||
- `users`: app-owned user management.
|
||||
- `employee-directory`: responsive directory table and detail/edit flows.
|
||||
- `announcements`: content publishing with role-aware visibility.
|
||||
- `online-lessons`: DB-backed lessons with upload, role-aware list/detail/manage flows.
|
||||
- `audit-logs`: read-only audit table.
|
||||
|
||||
Feature dependency direction:
|
||||
|
||||
```text
|
||||
feature components
|
||||
-> feature api queries/mutations
|
||||
-> feature api service
|
||||
-> apiClient
|
||||
-> route handlers
|
||||
-> feature server data helpers
|
||||
-> db/schema and db client
|
||||
```
|
||||
|
||||
Feature components may import shared UI, hooks, utilities, and feature contracts. They must not import Drizzle or database schema directly.
|
||||
|
||||
## Shared Modules
|
||||
|
||||
Shared UI:
|
||||
|
||||
- `src/components/ui/*`: shadcn/Radix primitives and app wrappers.
|
||||
- `src/components/ui/table/*`: canonical DataTable stack.
|
||||
- `src/components/ui/tanstack-form.tsx`: canonical form stack.
|
||||
- `src/components/layout/page-container.tsx`: dashboard page shell.
|
||||
- `src/components/icons.tsx`: icon registry.
|
||||
|
||||
Shared hooks:
|
||||
|
||||
- `use-data-table`
|
||||
- `use-debounce`
|
||||
- `use-debounced-callback`
|
||||
- `use-nav`
|
||||
- `use-mobile`
|
||||
- `use-media-query`
|
||||
|
||||
Shared lib:
|
||||
|
||||
- `api-client.ts`
|
||||
- `db.ts`
|
||||
- `query-client.ts`
|
||||
- `searchparams.ts`
|
||||
- `parsers.ts`
|
||||
- `format.ts`
|
||||
- `auth/session.ts`
|
||||
- `auth/roles.ts`
|
||||
- storage helpers for certificates, announcements, and online lessons
|
||||
|
||||
## Data Model
|
||||
|
||||
Core runtime identity is `users`, not legacy `employees`.
|
||||
|
||||
During the current remediation phase, the implementation is intentionally split across two related domains:
|
||||
|
||||
- `users`: authentication, session, permissions, organization context, and audit actor
|
||||
- `employees`: HR-owned worker profile, training owner, matrix targeting, and compliance/reporting subject
|
||||
|
||||
Current compatibility seams:
|
||||
|
||||
- `users.employeeId`
|
||||
- `user_employee_maps`
|
||||
|
||||
Current canonical relationship:
|
||||
|
||||
- `User 0..1 <-> 0..1 Employee`
|
||||
|
||||
This means some authenticated users may not have employee profiles, and some employees may exist before a user account is provisioned.
|
||||
|
||||
Important tables and domains:
|
||||
|
||||
- `users`
|
||||
- `organizations`
|
||||
- `memberships`
|
||||
- `courses`
|
||||
- `training_records`
|
||||
- `training_matrix`
|
||||
- `reports`
|
||||
- `announcements`
|
||||
- `online_lessons`
|
||||
- audit logs
|
||||
|
||||
`employees` is legacy migration data and should not be used for new runtime behavior.
|
||||
|
||||
## Auth And RBAC
|
||||
|
||||
Authentication is Auth.js Credentials.
|
||||
|
||||
Access helpers:
|
||||
|
||||
- `requireSession()`
|
||||
- `requireOrganizationAccess()`
|
||||
- `requireEmployeeDashboardAccess()`
|
||||
- `requireHRDDashboardAccess()`
|
||||
- `requireITDashboardAccess()`
|
||||
|
||||
Business roles:
|
||||
|
||||
- `IT`
|
||||
- `HRD`
|
||||
- `EMPLOYEE`
|
||||
|
||||
System role:
|
||||
|
||||
- `super_admin`
|
||||
|
||||
Access must be enforced server-side in pages and route handlers. Sidebar filtering is user experience only.
|
||||
|
||||
## Data Fetching
|
||||
|
||||
Preferred list flow:
|
||||
|
||||
```text
|
||||
server listing component
|
||||
-> getQueryClient()
|
||||
-> fetchQuery(queryOptions(filters))
|
||||
-> HydrationBoundary
|
||||
-> client component
|
||||
-> useSuspenseQuery(queryOptions(filters))
|
||||
```
|
||||
|
||||
Query options live in `src/features/<feature>/api/queries.ts`.
|
||||
Mutations live in `src/features/<feature>/api/mutations.ts`.
|
||||
Service functions call local route handlers through `apiClient`.
|
||||
|
||||
## Tables
|
||||
|
||||
Canonical stack:
|
||||
|
||||
- TanStack Table
|
||||
- `useDataTable`
|
||||
- `DataTable`
|
||||
- `DataTableToolbar`
|
||||
- `DataTablePagination`
|
||||
- `DataTableViewOptions`
|
||||
- `DataTableColumnHeader`
|
||||
|
||||
Tables should manage URL state through nuqs via `useDataTable` and parser helpers.
|
||||
|
||||
## Forms
|
||||
|
||||
Canonical stack:
|
||||
|
||||
- TanStack Form
|
||||
- Zod
|
||||
- `useAppForm`
|
||||
- project field wrappers
|
||||
|
||||
Form submit should call feature mutation options. Forms should not call route handlers or Drizzle directly.
|
||||
|
||||
## Uploads
|
||||
|
||||
Upload flows are feature-specific but should reuse existing helpers:
|
||||
|
||||
- certificates: training records
|
||||
- announcements: announcement attachments
|
||||
- online lessons: video, attachment, thumbnail
|
||||
|
||||
Route handlers validate file type and size before storage.
|
||||
|
||||
## Navigation
|
||||
|
||||
Navigation lives in `src/config/nav-config.ts`.
|
||||
|
||||
Role-aware display is handled through nav access metadata and `use-nav`. This does not replace server-side guards.
|
||||
|
||||
## Current Legacy Areas
|
||||
|
||||
Some template or older areas remain:
|
||||
|
||||
- `products`
|
||||
- `employees`
|
||||
- `forms`
|
||||
- `kanban`
|
||||
- `chat`
|
||||
- demo/react-query pages
|
||||
|
||||
Treat these as legacy/template features unless the user specifically asks to modernize them.
|
||||
Reference in New Issue
Block a user