Skip to content

Admin Dashboard

1. Document Control

PropertyValue
Package@nx-app/client
Description[APP-00910-CLIENT] NX-Seller App - Client (Admin Dashboard)
Version0.0.1-0
TypeWeb Application (SPA)
RuntimeBrowser / Bun (dev)
Dev Server Port3001 (Vite, strictPort)
DeploymentDocker / 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

TechnologyVersionPurpose
React^19.2.1UI Component Library
React DOM^19.2.1DOM Rendering
react-router-dom^7.9.4Client-side Routing
TypeScript~6.0.2Type Safety

3.2. State Management

TechnologyVersionPurpose
Redux Toolkit^2.9.1Global State Management
React Redux^9.2.0React-Redux Bindings
TanStack Query^5.90.5Server State & Caching
ra-core^5.13.2Admin Framework Core

3.3. UI Components

TechnologyVersionPurpose
@nx-app/admin-ui-kitworkspace:*Shared UI Component Library
radix-ui^1.4.3Accessible Primitives
Tailwind CSS^4.1.16Utility-first Styling
Lucide React^0.552.0Icon Library
next-themes^0.4.6Theme Switching

3.4. Forms & Validation

TechnologyVersionPurpose
React Hook Form^7.66.0Form State Management
@hookform/resolvers^5.2.2Schema Validation Integration

3.5. Data Tables & Drag-and-Drop

TechnologyVersionPurpose
TanStack Table^8.21.3Headless Data Tables
TanStack Virtual^3.13.12Virtualized Lists
@dnd-kit/core^6.3.1Drag-and-Drop Core
@dnd-kit/sortable^10.0.0Sortable Lists

3.6. Build & Development

TechnologyVersionPurpose
Vite^7.1.7Build Tool & Dev Server
@vitejs/plugin-react^5.0.4React Integration
vite-plugin-pwa^1.1.0PWA Support
ESLint^9.36.0Code Linting
Prettier^3.8.3Code Formatting
terser^5.44.0Production 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:

ProviderImplementationSourcePurpose
dataProviderDefaultRestDataProvider@minimaltech/ra-core-infraREST API Communication
authProviderAuthProvider@nx-app/admin-ui-kitAuthentication Flow
i18nProviderDEFAULT_I18N_PROVIDER@minimaltech/ra-core-infraInternationalization (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 assets

6. 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)

RouteComponentGroup
/loginSignInScreenno-auth
/verify-emailVerifyScreenno-auth
/sign-upSignUpScreenno-auth
/forgot-passwordForgotPasswordScreenno-auth
/reset-passwordResetPassScreenno-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.

RouteComponentNotes
/*RootRoutesHome dashboard + Organizer launchpad
/organizer/onboarding/*OrganizerCreateScreenOrganizer creation (v2)
/settings/*AccountSettingsRoutesAccount settings
/merchant/:merchantId/*MerchantRoutesMerchant workspace
/authentication-errorPage401-
/access-deniedPage403-
*Page404-

RootRoutes (auth/root/Root.route.tsx) mounts /organizerOrganizerScreen (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:

ModulePathSub-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/)

AreaFolderContents
Onboardingauth/onboarding/welcome, business, verify-identity, pricing-plan, common - gated by CheckOnboarding
Organizerauth/organizer/create, create-v2 (OrganizerCreateScreen), $organizer-id/settings
Account Settingsauth/account-settings/profile, change-password, appearance
Importationauth/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, utils

7. API Services

7.1. Service Architecture

API service classes extend BaseApiService from @minimaltech/ra-core-infra, which provides standard CRUD operations over a resource:

typescript
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())

DomainRegistered API Services
Identity & AccessAuthApi, UserApi, UserIdentifierApi, UserConfigurationApi, EmployeeApi, RoleApi, PermissionApi, PolicyApi, PolicyDefinitionApi, LicenseApi
OrganizationOrganizerApi, MerchantApi
Commerce / ProductProductApi, ProductVariantApi, VariantApi, CategoryApi, FareApi, FareSetApi, AssetsApi, MetaLinkApi
SaleSaleChannelApi, SaleOrderApi, SaleCustomerApi, TransactionApi, SalesReportApi, AllocationLayoutApi, AllocationZoneApi, AllocationUnitApi
InventoryInventoryItemApi, InventoryStockApi, InventoryTrackingApi, InventoryLocationApi, MaterialApi, UnitOfMeasureApi, VendorApi, VendorItemApi, PurchaseOrderApi, CostApi, PromotionApi
Finance / LedgerFinanceAssetApi, FinanceTransactionApi, FinanceCategoryApi, FinanceVoucherApi, FinanceWalletApi, FinanceAccountApi, LedgerBatchApi, LedgerActionApi, LedgerIdentifierApi
Tax / InvoiceTaxApi, TaxSetApi, TaxTypeApi, TaxGroupApi, InvoiceApi, InvoiceTaxInfoApi, DiscriminationTypeApi
Payment & DevicePaymentApi, DeviceApi
Config / SettingsSettingApi, ConfigurationApi, IIApiConfigApi, RuleApi
Reference DataVnProvinceApi, VnWardApi
Help DeskHelpDeskTicketApi, HelpDeskTicketCategoryApi, HelpDeskTicketTagApi
AgentAgentApi
Client-localOAuth2Api, 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):

typescript
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

SlicePurpose
workspaceActive workspace (organizer/merchant context, loaded org & merchant data)
temporaryEphemeral keyed data (form drafts, unsaved changes)
commonShared application UI state
productProduct editing state
fareFare / fare-set editing state
listViewTable/list view preferences (filters, sorting, pagination)
saleOrderSale order working state
transactionTransaction view state
financeVoucherFinance voucher state
merchantMerchant editing state
permissionTreeRole permission-tree state
stockInventory stock view state
spaceTablesRestaurant space/table layout state
revenueFilterRevenue report filter state

8.3. Server State with TanStack Query

Server state (API data) is managed separately using TanStack Query hooks (hooks/api/):

HookPurpose
useGetDataFetch single resource with caching
useInfiniteGetDataInfinite / paginated fetching
useMutationDataCreate / Update / Delete
useRefreshQuery cache invalidation
useVirtualAutocompleteVirtualized autocomplete
useVirtualAutocompleteArrayMulti-select virtualized autocomplete
useCategoryDescendantsCategory subtree fetch
useLedgerIdentifierLedger 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 FilePurpose
workspace.interface.tsWorkspace (organizer/merchant) state types
redux.interface.tsRedux action/state types
sidebar.interface.tsNavigation / sidebar item types
launchpad-module.interface.tsLaunchpad module descriptor types

10. Custom Hooks

10.1. API Hooks (hooks/api/)

HookPurpose
useGetDataFetch data with caching
useInfiniteGetDataPaginated data fetching
useMutationDataData mutations
useRefreshQuery cache refresh
useVirtualAutocompleteVirtualized autocomplete
useVirtualAutocompleteArrayMulti-select autocomplete
useCategoryDescendantsCategory subtree fetch
useLedgerIdentifierLedger identifier lookup

10.2. View Hooks (hooks/view/)

HookPurpose
useViewController / useViewControllerV2View controller
useListViewControllerList view controller
useViewConfigView configuration
useViewStateView state management
useViewTableAutosaveView table autosave
buildWhere / mergeWhere / buildFilterMetaFilter builders

10.3. Table & Redux Hooks

HookFolderPurpose
useDataTableControllerhooks/table/Table instance management
useDataTableStatehooks/table/Table state synchronization
useBaseTableAutosavehooks/table/Base table autosave
useBlinkedCellhooks/table/Cell highlight
useAppDispatchhooks/redux/Typed dispatch
useAppSelectorhooks/redux/Typed selector

10.4. Workspace, Socket & Utility Hooks

HookFolder / FilePurpose
useWorkspaceMerchantDatahooks/workspace/Hydrate merchant workspace
useWorkspaceOrganizerDatahooks/workspace/Hydrate organizer workspace
useWorkspaceSidebarhooks/workspace/Sidebar navigation model
useOnboardingStatehooks/onboarding/Onboarding flow state
useSocketReconnecthooks/socket/Socket reconnect handling
useDataProviderHeadersuseDataProviderHeaders.tsAPI header injection
useMerchantIdHeadersuseMerchantIdHeaders.tsx-merchant-id header
useWarnUnsavedChanges / useWarnExitDirtyroot-levelUnsaved changes warning
useLogoutuseLogout.tsLogout handling
useUserProfile / useUserLicense / useUserPreferencesroot-levelCurrent-user data

11. Authentication Flow

11.1. Auth Provider

The AuthProvider (from @nx-app/admin-ui-kit, bound as DEFAULT_AUTH_PROVIDER) implements:

MethodPurpose
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 (default light, class attribute)
  • System Preference: Respects OS preference
  • Persistent: Stores preference in localStorage
  • CSS Variables: Tailwind CSS custom properties

13. Build & Deployment

13.1. Build Scripts

ScriptCommandPurpose
devvite --mode devDevelopment server (port 3001)
buildsh ./scripts/build.shProduction build
build:developsh ./scripts/rebuild.sh developmentDevelopment build
build:stagingsh ./scripts/rebuild.sh stagingStaging build
build:productionsh ./scripts/rebuild.sh productionProduction build
build:alphash ./scripts/rebuild.sh alphaAlpha build
clean:buildsh ./scripts/clean-build.shClean build artifacts
lintsh ./scripts/lint.shRun ESLint
prettier:cliprettier "**/*.{js,ts,jsx,tsx}" -lList formatting issues
previewvite preview --port 4173 --host 0.0.0.0Preview production build

The dev and preview servers are configured with strictPort in vite.config.ts (server.port / preview.port = 3001).

13.2. Docker Deployment

dockerfile
# 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.conf

13.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

PackagePurpose
@nx-app/admin-ui-kitShared UI components & domain API services
@nx-app/coreShared utilities, models & locales

14.2. External Infrastructure

PackagePurpose
@minimaltech/ra-core-infraReact Admin infrastructure (providers, base API)
@venizia/ignis-inversionIoC Container
@loopback/filterQuery filter building (peer dependency)

15. Structure Snapshot

Counts drift as the codebase evolves - verify against source. Values below are a snapshot (2026-06).

MetricCount
Screen route groups3 (auth, no-auth, errors)
Merchant workspace modules8
Redux slices14
Client-local interface files4
Client-local API services1 (OAuth2Api); domain APIs in @nx-app/admin-ui-kit

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.