Admin Dashboard
1. Document Control
| Property | Value |
|---|---|
| Package | @nx-app/client |
| Description | [APP-00910-CLIENT] NX-Seller App - Client (Admin Dashboard) |
| Version | 0.0.1-0 |
| Type | Web Application (SPA) |
| Runtime | Browser / Bun (dev) |
| Dev Server Port | 3001 (Vite, strictPort) |
| Deployment | Docker / Nginx |
2. Scope & Objectives
2.1. Scope
The Admin Dashboard (@nx-app/client) is the administrative web application for the BANA platform. It guides users from authentication and onboarding into an Organizer → Merchant workspace, where business owners, operators, and administrators manage their entire operation through a web browser.
The merchant-facing back-office portal is a separate app,
@nx-app/bo("Back Office"). This app (@nx-app/client) is the Admin Dashboard.
2.2. Objectives
- Workspace Navigation: Organizer launchpad → Merchant workspace with per-module navigation.
- Comprehensive Management: Products, categories, inventory, sales, finance, team, and reporting.
- Data Visualization: Rich charts and tables for business insights.
- Responsive Design: Functional on Desktop, Tablet, and Mobile browsers.
- Type Safety: End-to-end type safety with TypeScript and runtime schema validation.
3. Technology Stack
Versions below are reflected from
apps/client/package.json. Shared library versions are documented in Platform Facts.
3.1. Core Framework
| Technology | Version | Purpose |
|---|---|---|
| React | ^19.2.1 | UI Component Library |
| React DOM | ^19.2.1 | DOM Rendering |
| react-router-dom | ^7.9.4 | Client-side Routing |
| TypeScript | ~6.0.2 | Type Safety |
3.2. State Management
| Technology | Version | Purpose |
|---|---|---|
| Redux Toolkit | ^2.9.1 | Global State Management |
| React Redux | ^9.2.0 | React-Redux Bindings |
| TanStack Query | ^5.90.5 | Server State & Caching |
| ra-core | ^5.13.2 | Admin Framework Core |
3.3. UI Components
| Technology | Version | Purpose |
|---|---|---|
| @nx-app/admin-ui-kit | workspace:* | Shared UI Component Library |
| radix-ui | ^1.4.3 | Accessible Primitives |
| Tailwind CSS | ^4.1.16 | Utility-first Styling |
| Lucide React | ^0.552.0 | Icon Library |
| next-themes | ^0.4.6 | Theme Switching |
3.4. Forms & Validation
| Technology | Version | Purpose |
|---|---|---|
| React Hook Form | ^7.66.0 | Form State Management |
| @hookform/resolvers | ^5.2.2 | Schema Validation Integration |
3.5. Data Tables & Drag-and-Drop
| Technology | Version | Purpose |
|---|---|---|
| TanStack Table | ^8.21.3 | Headless Data Tables |
| TanStack Virtual | ^3.13.12 | Virtualized Lists |
| @dnd-kit/core | ^6.3.1 | Drag-and-Drop Core |
| @dnd-kit/sortable | ^10.0.0 | Sortable Lists |
3.6. Build & Development
| Technology | Version | Purpose |
|---|---|---|
| Vite | ^7.1.7 | Build Tool & Dev Server |
| @vitejs/plugin-react | ^5.0.4 | React Integration |
| vite-plugin-pwa | ^1.1.0 | PWA Support |
| ESLint | ^9.36.0 | Code Linting |
| Prettier | ^3.8.3 | Code Formatting |
| terser | ^5.44.0 | Production Minification |
4. Architecture
4.1. Application Layers
4.2. Context Providers
The application bootstraps a DI container and wraps the tree with state and theme providers (see application/ApplicationContext.tsx and App.tsx):
4.3. Core Admin Integration
The App component mounts CoreAdminContext from ra-core with providers resolved from the DI container:
| Provider | Implementation | Source | Purpose |
|---|---|---|---|
| dataProvider | DefaultRestDataProvider | @minimaltech/ra-core-infra | REST API Communication |
| authProvider | AuthProvider | @nx-app/admin-ui-kit | Authentication Flow |
| i18nProvider | DEFAULT_I18N_PROVIDER | @minimaltech/ra-core-infra | Internationalization (en/vi) |
5. Project Structure
apps/client/
├── src/
│ ├── application/ # DI container, app bootstrap & providers
│ │ └── services/
│ │ ├── apis/ # Client-local API (OAuth2Api)
│ │ └── networks/ # Network services (NxOAuthNetworkService)
│ ├── assets/ # Static assets (svgs, images)
│ ├── components/
│ │ └── core/ # adaptive, breadcrumb, button, card, category,
│ │ # chart, common, dnd, icon, input, loading,
│ │ # modal, notification, resource, skeleton,
│ │ # table, title, tour
│ ├── constants/ # App constants (routes, sidebar, per-domain:
│ │ # commerce, finance, inventory, sale, team, …)
│ ├── helpers/ # Utility functions
│ ├── hooks/ # api, onboarding, redux, socket, table, view,
│ │ # workspace + root-level hooks
│ ├── interfaces/ # Client-local TS interfaces (4 files)
│ ├── layout/ # AppLayout, CheckOnboarding, main, root, basic,
│ │ # common, form, launchpad, no-auth, screen
│ ├── libs/ # External library configs (tanstack)
│ ├── redux/ # Store + slices
│ ├── screens/ # auth / no-auth / errors route groups
│ ├── socket/ # Socket connection manager
│ ├── themes/ # Theme & theme-scale contexts
│ ├── utilities/ # Misc utilities
│ ├── App.tsx # Routing root + CoreAdminContext
│ └── main.tsx # Entry point
├── scripts/ # Build scripts
└── public/ # Static / PWA assets6. Screens & Routing
Screens are organised into three route groups under src/screens/: no-auth (public), auth (authenticated), and errors. Business modules are no longer a flat list - they live inside the Merchant workspace.
6.1. Top-Level Routes (App.tsx)
| Route | Component | Group |
|---|---|---|
/login | SignInScreen | no-auth |
/verify-email | VerifyScreen | no-auth |
/sign-up | SignUpScreen | no-auth |
/forgot-password | ForgotPasswordScreen | no-auth |
/reset-password | ResetPassScreen | no-auth |
/* | AuthRoutes (protected) | auth |
6.2. Authenticated Routes (auth/Auth.route.tsx)
Guarded by useAuthState; unauthenticated requests redirect to /login. The subtree is wrapped in OnboardingStateProvider + CheckOnboarding.
| Route | Component | Notes |
|---|---|---|
/* | RootRoutes | Home dashboard + Organizer launchpad |
/organizer/onboarding/* | OrganizerCreateScreen | Organizer creation (v2) |
/settings/* | AccountSettingsRoutes | Account settings |
/merchant/:merchantId/* | MerchantRoutes | Merchant workspace |
/authentication-error | Page401 | - |
/access-denied | Page403 | - |
* | Page404 | - |
RootRoutes (auth/root/Root.route.tsx) mounts /organizer → OrganizerScreen (organizer launchpad/list) and / (HOME) → HomeScreen.
6.3. Merchant Workspace Modules (auth/merchant/$merchant-id/Merchant.route.tsx)
Mounted at /merchant/:merchantId/* and wrapped in MainLayout. Modules are keyed by MerchantModules:
| Module | Path | Sub-screens |
|---|---|---|
| sale | /sale/* | dashboard, sale-order, sale-customer, sale-channel, transaction, space-tables, sale-restaurant-floor/room/table |
| product | /product/* | dashboard, product, product-variant, category, fare, fare-set |
| inventory | /inventory/* | dashboard, stock, material, vendor, unit-of-measure, inventory-location, tax, promotion, devices |
| customer | /customer/* | dashboard |
| finance | /finance/* | dashboard, finance-account, finance-category, finance-transaction, finance-wallet, finance-voucher |
| team | /team/* | dashboard, employee, role, policy-definition |
| report | /report/* | revenue, ledger, hd-tickets |
| settings | /settings/* | general, merchant, payment-settings, shift |
A /launchpad route (MerchantLaunchpadScreen) sits outside MainLayout for module selection.
6.4. Onboarding, Organizer & Importation (auth/)
| Area | Folder | Contents |
|---|---|---|
| Onboarding | auth/onboarding/ | welcome, business, verify-identity, pricing-plan, common - gated by CheckOnboarding |
| Organizer | auth/organizer/ | create, create-v2 (OrganizerCreateScreen), $organizer-id/settings |
| Account Settings | auth/account-settings/ | profile, change-password, appearance |
| Importation | auth/importation/ | CSV import wizard: upload → mapping → review → previewImport |
6.5. Error Pages (errors/)
Page401, Page403, Page404, Page500, Page503, CrashError (CrashErrorPage), OrganizerAccessDenied, BaseErrorPage.
6.6. CRUD Screen Structure Pattern
CRUD sub-screens (e.g. product/product, team/role) follow a consistent folder structure:
{module}/{entity}/
├── index.ts # Module exports
├── {Entity}.screen.tsx # List screen entry (or list/{Entity}.screen.tsx)
├── list/
│ ├── index.tsx # List view
│ └── {Entity}Table.tsx # Data table
├── create/
│ ├── index.tsx
│ └── {Entity}Create.screen.tsx
├── edit/
│ ├── index.tsx
│ └── {Entity}Edit.screen.tsx
├── form/ # Shared form (e.g. {Entity}Form.tsx)
└── common/ # Shared hooks, sections, utils7. API Services
7.1. Service Architecture
API service classes extend BaseApiService from @minimaltech/ra-core-infra, which provides standard CRUD operations over a resource:
export class OAuth2Api extends BaseApiService {
constructor(
@inject({ key: CoreBindings.DEFAULT_REST_DATA_PROVIDER })
protected dataProvider: IDataProvider,
@inject({ key: 'services.NxOAuthNetworkService' })
protected nxOAuthNetworkService: NxOAuthNetworkService,
) {
super({ scope: OAuth2Api.name, resource: RestEndpoints.OAUTH2 });
}
}The full catalog of domain API classes is defined in @nx-app/admin-ui-kit (see Admin UI Kit). The client imports them and registers them into its DI container via RaApplication.bindingList() (application/application.ts). Only OAuth2Api is client-local.
7.2. DI-Registered Services (bindingList())
| Domain | Registered API Services |
|---|---|
| Identity & Access | AuthApi, UserApi, UserIdentifierApi, UserConfigurationApi, EmployeeApi, RoleApi, PermissionApi, PolicyApi, PolicyDefinitionApi, LicenseApi |
| Organization | OrganizerApi, MerchantApi |
| Commerce / Product | ProductApi, ProductVariantApi, VariantApi, CategoryApi, FareApi, FareSetApi, AssetsApi, MetaLinkApi |
| Sale | SaleChannelApi, SaleOrderApi, SaleCustomerApi, TransactionApi, SalesReportApi, AllocationLayoutApi, AllocationZoneApi, AllocationUnitApi |
| Inventory | InventoryItemApi, InventoryStockApi, InventoryTrackingApi, InventoryLocationApi, MaterialApi, UnitOfMeasureApi, VendorApi, VendorItemApi, PurchaseOrderApi, CostApi, PromotionApi |
| Finance / Ledger | FinanceAssetApi, FinanceTransactionApi, FinanceCategoryApi, FinanceVoucherApi, FinanceWalletApi, FinanceAccountApi, LedgerBatchApi, LedgerActionApi, LedgerIdentifierApi |
| Tax / Invoice | TaxApi, TaxSetApi, TaxTypeApi, TaxGroupApi, InvoiceApi, InvoiceTaxInfoApi, DiscriminationTypeApi |
| Payment & Device | PaymentApi, DeviceApi |
| Config / Settings | SettingApi, ConfigurationApi, IIApiConfigApi, RuleApi |
| Reference Data | VnProvinceApi, VnWardApi |
| Help Desk | HelpDeskTicketApi, HelpDeskTicketCategoryApi, HelpDeskTicketTagApi |
| Agent | AgentApi |
| Client-local | OAuth2Api, EnvironmentService, NxOAuthNetworkService, SocketConnectionManager, SocketSubscriptionManager |
8. State Management
8.1. Redux Store Configuration
The Redux store (redux/store.ts) combines slice reducers and resets on logout (ReduxActionTypes.RESET_APP):
const appReducer = combineReducers({
workspace: workspaceReducer,
temporary: temporaryReducer,
common: commonReducer,
product: productReducer,
fare: fareReducer,
listView: listViewReducer,
saleOrder: saleOrderReducer,
transaction: transactionReducer,
financeVoucher: financeVoucherReducer,
merchant: merchantReducer,
permissionTree: permissionTreeReducer,
stock: stockReducer,
spaceTables: spaceTablesReducer,
revenueFilter: revenueFilterReducer,
});8.2. Redux Slices
| Slice | Purpose |
|---|---|
| workspace | Active workspace (organizer/merchant context, loaded org & merchant data) |
| temporary | Ephemeral keyed data (form drafts, unsaved changes) |
| common | Shared application UI state |
| product | Product editing state |
| fare | Fare / fare-set editing state |
| listView | Table/list view preferences (filters, sorting, pagination) |
| saleOrder | Sale order working state |
| transaction | Transaction view state |
| financeVoucher | Finance voucher state |
| merchant | Merchant editing state |
| permissionTree | Role permission-tree state |
| stock | Inventory stock view state |
| spaceTables | Restaurant space/table layout state |
| revenueFilter | Revenue report filter state |
8.3. Server State with TanStack Query
Server state (API data) is managed separately using TanStack Query hooks (hooks/api/):
| Hook | Purpose |
|---|---|
| useGetData | Fetch single resource with caching |
| useInfiniteGetData | Infinite / paginated fetching |
| useMutationData | Create / Update / Delete |
| useRefresh | Query cache invalidation |
| useVirtualAutocomplete | Virtualized autocomplete |
| useVirtualAutocompleteArray | Multi-select virtualized autocomplete |
| useCategoryDescendants | Category subtree fetch |
| useLedgerIdentifier | Ledger identifier lookup |
9. TypeScript Interfaces
Domain interfaces now live in @nx-app/admin-ui-kit and @nx-app/core. The client keeps only a small set of app-local interface files in src/interfaces/:
| Interface File | Purpose |
|---|---|
workspace.interface.ts | Workspace (organizer/merchant) state types |
redux.interface.ts | Redux action/state types |
sidebar.interface.ts | Navigation / sidebar item types |
launchpad-module.interface.ts | Launchpad module descriptor types |
10. Custom Hooks
10.1. API Hooks (hooks/api/)
| Hook | Purpose |
|---|---|
useGetData | Fetch data with caching |
useInfiniteGetData | Paginated data fetching |
useMutationData | Data mutations |
useRefresh | Query cache refresh |
useVirtualAutocomplete | Virtualized autocomplete |
useVirtualAutocompleteArray | Multi-select autocomplete |
useCategoryDescendants | Category subtree fetch |
useLedgerIdentifier | Ledger identifier lookup |
10.2. View Hooks (hooks/view/)
| Hook | Purpose |
|---|---|
useViewController / useViewControllerV2 | View controller |
useListViewController | List view controller |
useViewConfig | View configuration |
useViewState | View state management |
useViewTableAutosave | View table autosave |
buildWhere / mergeWhere / buildFilterMeta | Filter builders |
10.3. Table & Redux Hooks
| Hook | Folder | Purpose |
|---|---|---|
useDataTableController | hooks/table/ | Table instance management |
useDataTableState | hooks/table/ | Table state synchronization |
useBaseTableAutosave | hooks/table/ | Base table autosave |
useBlinkedCell | hooks/table/ | Cell highlight |
useAppDispatch | hooks/redux/ | Typed dispatch |
useAppSelector | hooks/redux/ | Typed selector |
10.4. Workspace, Socket & Utility Hooks
| Hook | Folder / File | Purpose |
|---|---|---|
useWorkspaceMerchantData | hooks/workspace/ | Hydrate merchant workspace |
useWorkspaceOrganizerData | hooks/workspace/ | Hydrate organizer workspace |
useWorkspaceSidebar | hooks/workspace/ | Sidebar navigation model |
useOnboardingState | hooks/onboarding/ | Onboarding flow state |
useSocketReconnect | hooks/socket/ | Socket reconnect handling |
useDataProviderHeaders | useDataProviderHeaders.ts | API header injection |
useMerchantIdHeaders | useMerchantIdHeaders.ts | x-merchant-id header |
useWarnUnsavedChanges / useWarnExitDirty | root-level | Unsaved changes warning |
useLogout | useLogout.ts | Logout handling |
useUserProfile / useUserLicense / useUserPreferences | root-level | Current-user data |
11. Authentication Flow
11.1. Auth Provider
The AuthProvider (from @nx-app/admin-ui-kit, bound as DEFAULT_AUTH_PROVIDER) implements:
| Method | Purpose |
|---|---|
login() | Handle sign-in with credentials |
logout() | Clear auth state and redirect |
checkAuth() | Verify token validity |
checkError() | Handle HTTP errors (401, 403) |
getIdentity() | Retrieve current user |
getPermissions() | Get user permissions |
getRoles() | Get user roles |
11.2. Authentication State
12. Theme System
12.1. Theme Provider Stack
ThemeProvider (next-themes)
└── ActiveThemeProvider (accent color)
└── ThemeScaleProvider (UI scale)
└── Tailwind CSS v4 (dark mode via class)12.2. Theme Features
- Dark/Light Mode: Toggle via
next-themes(defaultlight,classattribute) - System Preference: Respects OS preference
- Persistent: Stores preference in localStorage
- CSS Variables: Tailwind CSS custom properties
13. Build & Deployment
13.1. Build Scripts
| Script | Command | Purpose |
|---|---|---|
dev | vite --mode dev | Development server (port 3001) |
build | sh ./scripts/build.sh | Production build |
build:develop | sh ./scripts/rebuild.sh development | Development build |
build:staging | sh ./scripts/rebuild.sh staging | Staging build |
build:production | sh ./scripts/rebuild.sh production | Production build |
build:alpha | sh ./scripts/rebuild.sh alpha | Alpha build |
clean:build | sh ./scripts/clean-build.sh | Clean build artifacts |
lint | sh ./scripts/lint.sh | Run ESLint |
prettier:cli | prettier "**/*.{js,ts,jsx,tsx}" -l | List formatting issues |
preview | vite preview --port 4173 --host 0.0.0.0 | Preview production build |
The dev and preview servers are configured with
strictPortinvite.config.ts(server.port/preview.port=3001).
13.2. Docker Deployment
# Build Stage
FROM node:20-alpine AS builder
COPY . .
RUN bun install && bun run build
# Runtime Stage
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf13.3. Environment Configuration
Environment variables are loaded via Vite's env system (e.g. VITE_NODE_ENV for the runtime mode, read in App.tsx via EnvironmentService).
14. Dependencies
14.1. Internal Dependencies
| Package | Purpose |
|---|---|
@nx-app/admin-ui-kit | Shared UI components & domain API services |
@nx-app/core | Shared utilities, models & locales |
14.2. External Infrastructure
| Package | Purpose |
|---|---|
@minimaltech/ra-core-infra | React Admin infrastructure (providers, base API) |
@venizia/ignis-inversion | IoC Container |
@loopback/filter | Query filter building (peer dependency) |
15. Structure Snapshot
Counts drift as the codebase evolves - verify against source. Values below are a snapshot (2026-06).
| Metric | Count |
|---|---|
| Screen route groups | 3 (auth, no-auth, errors) |
| Merchant workspace modules | 8 |
| Redux slices | 14 |
| Client-local interface files | 4 |
| Client-local API services | 1 (OAuth2Api); domain APIs in @nx-app/admin-ui-kit |