300 lines
8.6 KiB
Markdown
300 lines
8.6 KiB
Markdown
You are a senior frontend engineer. Generate a **production-ready Next.js (App Router) admin dashboard** using **Tabler UI** as the design system.
|
|
|
|
Use this prompt as the current source of truth for backend behavior.
|
|
|
|
## Backend Summary (Current)
|
|
|
|
- Base URL: `http://<host>` (Swagger: `/swagger-ui.html`, OpenAPI: `/v3/api-docs`)
|
|
- Security: JWT (Bearer token)
|
|
- Multi-tenancy: required via header `X-Tenant-Id`
|
|
- Optional LDAP mode: `app.ldap.enabled` (backend switch)
|
|
- API pattern: most state-changing endpoints are workflow-driven approvals
|
|
- Default responses use:
|
|
|
|
```ts
|
|
type ApiResponse<T> = {
|
|
success: boolean
|
|
message: string
|
|
data: T
|
|
timestamp: string
|
|
}
|
|
```
|
|
|
|
## Tech Stack
|
|
|
|
- Next.js (App Router)
|
|
- React 18+
|
|
- TypeScript
|
|
- Tabler UI (CSS/React components)
|
|
- Axios
|
|
- Zustand (recommended)
|
|
- Tailwind (optional only for utility overrides)
|
|
- react-intl or next-intl for i18n
|
|
|
|
## Recommended Project Structure
|
|
|
|
- `app/`
|
|
- `(auth)/login/page.tsx`
|
|
- `(dashboard)/layout.tsx`
|
|
- `(dashboard)/page.tsx`
|
|
- `api-proxy/` or service barrel exports
|
|
- `components/`
|
|
- `layout/` (DashboardShell, Sidebar, Header)
|
|
- `ui/` (Table, Form, Modal, Alert, Badge, Drawer)
|
|
- `workflow/` (ApprovalTable, StatusBadge, ApprovalActionModal)
|
|
- `user/` (UserForm, UpdateRolesForm)
|
|
- `role/` (RoleForm, RolePermissionForm)
|
|
- `services/`
|
|
- `api.ts`
|
|
- `auth.ts`
|
|
- `users.ts`
|
|
- `workflow.ts`
|
|
- `tenant.ts`
|
|
- `audit.ts`
|
|
- `store/`
|
|
- `authStore.ts`
|
|
- `uiStore.ts`
|
|
- `tenantStore.ts`
|
|
- `permissionStore.ts`
|
|
- `hooks/`
|
|
- `useAuth.ts`, `useTenantHeader.ts`, `useApi.ts`, `usePermissions.ts`
|
|
- `types/`
|
|
- API contracts and DTO types
|
|
|
|
## API Endpoints to Use (exact)
|
|
|
|
### Auth
|
|
- `POST /api/auth/login`
|
|
- `POST /api/auth/refresh`
|
|
- `POST /api/auth/logout`
|
|
|
|
### Authenticated profile
|
|
- `GET /api/users/me`
|
|
|
|
### User management (workflow requests)
|
|
- `POST /api/users/management/requests/create`
|
|
- `POST /api/users/management/requests/update-roles`
|
|
|
|
### Role management (workflow requests)
|
|
- `POST /api/roles/management/requests/create`
|
|
- `POST /api/roles/management/requests/update-permissions`
|
|
|
|
### Workflow
|
|
- `POST /api/workflow/request`
|
|
- `POST /api/workflow/{id}/approve`
|
|
- `POST /api/workflow/{id}/reject`
|
|
- `GET /api/workflow/requests?status=PENDING&resourceType=...&makerUsername=...&limit=50`
|
|
|
|
### Modules
|
|
- `GET /api/modules`
|
|
- `POST /api/modules/{code}/toggle`
|
|
|
|
### Tenant & audit
|
|
- `GET /api/tenant/context`
|
|
- `GET /api/audit?limit=50`
|
|
|
|
## Authentication and request headers
|
|
|
|
For **every request** after login:
|
|
- `Authorization: Bearer <accessToken>`
|
|
- `X-Tenant-Id: <tenantId>`
|
|
|
|
Login request also requires tenant context because backend resolves tenant at auth time:
|
|
- `POST /api/auth/login` with header `X-Tenant-Id`
|
|
|
|
Logout request behavior:
|
|
- `POST /api/auth/logout` requires a valid Bearer token because backend invalidates/revokes refresh/session context.
|
|
|
|
Optional:
|
|
- `Accept-Language: en-US` or `id-ID`
|
|
|
|
## JWT/session behavior
|
|
|
|
- Access token in response includes `tokenType: "Bearer"`, `accessToken`, `refreshToken`, `expiresIn`
|
|
- Store tokens in secure storage strategy (HTTP-only cookies preferred if possible; otherwise memory + storage hardening)
|
|
- Add request interceptor to attach token and `X-Tenant-Id`
|
|
- Add response interceptor for 401:
|
|
- clear auth state
|
|
- redirect to login
|
|
- keep tenant and locale selections persisted
|
|
|
|
## Important authorization model
|
|
|
|
Backend sends authorities as roles/permissions:
|
|
- Roles come as `ROLE_<code>` (from DB role code)
|
|
- Permissions come as plain `...` codes
|
|
- Controllers currently check:
|
|
- User create/update-roles: `hasAuthority('USER_MANAGE') or hasRole('USER_ROLE_ADMIN')`
|
|
- Role create/update-permissions: `hasAuthority('ROLE_MANAGE') or hasRole('USER_ROLE_ADMIN')`
|
|
- Create workflow request: `hasAuthority('WORKFLOW_CREATE') or hasRole('MAKER')`
|
|
- Approve/reject: `hasAuthority('WORKFLOW_APPROVE') or hasRole('CHECKER')`
|
|
- Workflow list: `hasAuthority('WORKFLOW_APPROVE') or hasRole('CHECKER') or hasRole('ADMIN')`
|
|
- `/api/audit`: `hasRole('ADMIN')`
|
|
- `/api/users/me`: `hasAuthority('USER_READ') or hasRole('ADMIN')`
|
|
|
|
So frontend should render actions conditionally using permissions derived from `/api/users/me`.
|
|
|
|
## LDAP mode alignment
|
|
|
|
Backend has optional LDAP mode (`app.ldap.enabled`).
|
|
|
|
- **Local mode**
|
|
- `/api/users/management/requests/create` requires `password`
|
|
- **LDAP mode**
|
|
- Password is managed in directory (backend does not require password for user provisioning)
|
|
- `password` should not be sent for user creation
|
|
- optional `ldapDn` may be included
|
|
- Common for both modes
|
|
- user update roles still workflow-driven
|
|
- role create/update-permissions still workflow-driven
|
|
- no direct mutation endpoints for user/role entities
|
|
|
|
## Required front-end behavior by page
|
|
|
|
### 1) Login page
|
|
- Input: username, password, tenant selector
|
|
- Submit `POST /api/auth/login`
|
|
- Pass `X-Tenant-Id` header
|
|
- Handle error responses from backend localization keys and lockout messages
|
|
|
|
### 2) Dashboard shell
|
|
- Sidebar: Dashboard, Users, Roles, Workflow, Audit, Modules, Settings
|
|
- Top bar: tenant selector, locale switch, user menu/logout
|
|
- Display auth mode indicator (Local / LDAP) when available
|
|
|
|
### 3) Dashboard home
|
|
- Show summary cards:
|
|
- pending workflow count
|
|
- pending checker workload (from `/api/workflow/requests?status=PENDING`)
|
|
- audit/approval health snapshots (from `/api/audit?limit=50`)
|
|
- recent audits (from /api/audit)
|
|
|
|
### 4) Users page
|
|
- There is no direct `/api/users` list endpoint in current backend, so derive list/context from workflow/request history and `/api/users/me` context.
|
|
- Actions:
|
|
- create user request (workflow)
|
|
- update user roles request (workflow)
|
|
- In LDAP mode hide password input on create form
|
|
- In local mode enforce password validation before submit
|
|
|
|
### 5) Roles page
|
|
- No direct role list endpoint exists in current backend; show role/permission operations using current user context and workflow history as available.
|
|
- Implement create role request + permission update request flows.
|
|
- Permission selector from current in-app permission catalog (from `/api/users/me`, seeded defaults, and known workflow operations).
|
|
|
|
### 6) Workflow page
|
|
- Show `/api/workflow/requests` with filters
|
|
- `status` (`DRAFT`, `PENDING`, `APPROVED`, `REJECTED`)
|
|
- `resourceType`
|
|
- `makerUsername`
|
|
- `limit`
|
|
- Actions:
|
|
- Approve modal
|
|
- Reject modal
|
|
- show notes and optional checkerRole (if omitted, backend uses step role default `CHECKER`)
|
|
|
|
### 7) Audit page
|
|
- Admin-only
|
|
- `GET /api/audit?limit=50`
|
|
- render `action`, `resourceType`, `resourceId`, before/after snapshots, outcome, correlation id
|
|
- Keep pagination/infinite-load support for audit + workflow lists.
|
|
|
|
## DTO references for implementation
|
|
|
|
### Login
|
|
```ts
|
|
{ username: string; password: string }
|
|
```
|
|
|
|
### Create user management request
|
|
- Local mode:
|
|
```ts
|
|
{
|
|
username: string
|
|
password: string
|
|
enabled?: boolean
|
|
roleCodes: string[]
|
|
}
|
|
```
|
|
- LDAP mode:
|
|
```ts
|
|
{
|
|
username: string
|
|
ldapDn?: string
|
|
enabled?: boolean
|
|
roleCodes: string[]
|
|
}
|
|
```
|
|
|
|
### Update user roles
|
|
```ts
|
|
{ username: string; roleCodes: string[] }
|
|
```
|
|
|
|
### Create role request
|
|
```ts
|
|
{ code: string; name: string; permissionCodes: string[] }
|
|
```
|
|
|
|
### Update role permissions
|
|
```ts
|
|
{ code: string; permissionCodes: string[] }
|
|
```
|
|
|
|
### Workflow action
|
|
```ts
|
|
{ notes?: string; checkerRole?: string }
|
|
```
|
|
|
|
### Create approval request (generic)
|
|
```ts
|
|
{ resourceType: string; resourceId: string; payload?: string; requiredSteps: number }
|
|
```
|
|
|
|
### Response from `/api/users/me`
|
|
```ts
|
|
{ tenantId: string; username: string; roles: string[]; permissions: string[] }
|
|
```
|
|
|
|
## UI requirements
|
|
|
|
- Use Tabler-inspired components for
|
|
- tables
|
|
- forms
|
|
- modals
|
|
- badges
|
|
- alerts
|
|
- Keep navigation corporate and simple
|
|
- Add loading states, inline error states, and toast notifications
|
|
- Keep table columns configurable (search, sort, pagination)
|
|
|
|
## Error handling
|
|
|
|
Backend may return these patterns:
|
|
- Login failures with localized message
|
|
- Lockout message key in i18n when brute force threshold exceeded
|
|
- Standard `ApiResponse` with `success` false
|
|
|
|
Frontend should:
|
|
- show notification from `message`
|
|
- maintain tenant context in state across page refresh/login switch
|
|
- keep unauthorized navigation blocked by RBAC-derived route guards
|
|
|
|
## Delivery expectations
|
|
|
|
Please generate runnable code for:
|
|
- `app/` shell and route layout
|
|
- Axios client with interceptors
|
|
- Login/auth flow
|
|
- Tenant-aware request wrapper
|
|
- Users module screens + workflow request forms
|
|
- Roles module screens + workflow request forms
|
|
- Workflow list/detail with approve/reject action
|
|
- Audit list
|
|
- Reusable table/form/modal components
|
|
|
|
Please include a short setup checklist:
|
|
- env vars (`NEXT_PUBLIC_API_BASE_URL` etc)
|
|
- install commands
|
|
- run instructions
|