Skip to main content

Facilities UI Library Architecture

  • Status: Implemented (v0.2.0)
  • Date: 2025-12-06
  • Author: Rudi Haarhoff
  • Related: Golf Cart UI/UX Specification

Overview

This document proposes the architecture for a reusable Facilities UI library that can be consumed by tee-time, SCL, and other applications requiring facility management components.

Current Monorepo UI Structure

libs/
├── ui/ # Core shared UI libraries
│ ├── antd/ # @digiwedge/ui-antd (Ant Design wrapper)
│ ├── theme/ # @digiwedge/ui-theme (shared theme)
│ ├── messaging-ui/ # Cross-domain messaging components
│ └── wallet/ # Cross-domain wallet components
├── tee-time-ui/ # @digiwedge/tee-time-ui (domain-specific)
├── scl/ui/ # SCL domain UI
│ ├── web-components/ # Reusable web components
│ ├── web-pages/ # Page-level components
│ └── mobile-components/ # Mobile components
└── facilities/
└── facilities-service/ # Backend service (existing)

Current Structure

Implemented library lives under libs/facilities/ui/golf-cart (@digiwedge/facilities-ui-golf-cart):

libs/facilities/ui/
└── golf-cart/ # @digiwedge/facilities-ui-golf-cart (v0.2.0)
├── src/
│ ├── index.ts # Barrel
│ └── lib/
│ ├── components/
│ │ ├── BatteryIndicator/
│ │ ├── CartStatusCard/
│ │ ├── CartGrid/
│ │ ├── FleetDashboard/
│ │ ├── UtilizationChart/
│ │ ├── ZoneMap/
│ │ ├── MaintenancePanel/
│ │ ├── PredictiveMaintenance/
│ │ ├── IncidentReporter/
│ │ └── AssignmentHistory/
│ ├── hooks/
│ │ └── useGolfCarts.ts (hooks factory)
│ └── types/
│ └── index.ts
├── package.json
├── project.json
└── vite.config.ts

Technology Stack

Following the established patterns in the codebase:

TechnologyVersionPurpose
React19.1.0UI framework
Ant Design5.26.3Component library
@digiwedge/ui-antdworkspace:*Themed Ant Design wrapper
@digiwedge/ui-themeworkspace:*Shared theme
TanStack Query5.81.5Server state management
Recharts2.15.4Charts and graphs
Vite7.0.6Build tool
TypeScript5.xType safety

Component Specifications

Core Components (implemented)

ComponentDescriptionConsumers
FleetDashboardMetrics cards, utilization, zone summaryAdmin apps
CartStatusCardIndividual cart with battery, condition, zoneAll apps
CartGridFilterable grid with search/paginationAdmin apps
BatteryIndicatorVisual battery with thresholdsAll apps
ZoneMapZone summary table (drill-down to carts)Admin apps
MaintenancePanelService due list + actionsAdmin apps
PredictiveMaintenanceUpcoming service candidatesAdmin apps
UtilizationChartWindowed utilization chartAdmin apps
IncidentReporterIncident formStaff apps
AssignmentHistoryAssignment timelineAll apps

Hooks

createGolfCartHooks(api: GolfCartApi) returns typed TanStack Query hooks wired to your API implementation:

  • useGolfCarts, useGolfCart
  • useFleetSummary, useZoneSummary, useUtilization
  • usePredictiveMaintenance
  • Mutations: useAssignCart, useReturnCart, useReportIncident, useUpdateCart, useUpdateLocation, useUpdateBattery

Types (re-exported from service)

// Re-export from @digiwedge/facilities-service or define locally
export type {
GolfCart,
CartAssignment,
CartIncident,
FleetSummary,
ZoneSummary,
UtilizationReport,
CartType,
CartCondition,
IncidentType,
IncidentSeverity,
} from '@digiwedge/facilities-service';

Consumption Pattern

In Tee-Time Admin

import {
FleetDashboard,
CartGrid,
useGolfCarts,
useFleetSummary
} from '@digiwedge/facilities-ui-golf-cart';

export function TeeTimeCartManagement() {
const { data: carts } = useGolfCarts({ tenantId: 1, clubId: 10 });
const { data: summary } = useFleetSummary(1, 10);

return (
<div>
<FleetDashboard summary={summary} />
<CartGrid carts={carts} onSelect={handleSelect} />
</div>
);
}

In SCL Admin

import {
CartStatusCard,
MaintenancePanel,
usePredictiveMaintenance
} from '@digiwedge/facilities-ui-golf-cart';

export function SCLFacilitiesPage() {
const { data: maintenanceDue } = usePredictiveMaintenance({
tenantId: 1,
horizonDays: 7
});

return (
<MaintenancePanel carts={maintenanceDue} />
);
}

File Templates

package.json

{
"name": "@digiwedge/facilities-ui-golf-cart",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./index.css": "./dist/index.css"
},
"dependencies": {
"react": "19.1.0",
"antd": "^5.26.3",
"@ant-design/icons": "^5.6.1",
"recharts": "^2.15.4",
"@tanstack/react-query": "^5.81.5"
},
"peerDependencies": {
"@digiwedge/ui-antd": "workspace:*",
"@digiwedge/ui-theme": "workspace:*"
},
"devDependencies": {
"@digiwedge/dev-vite": "workspace:*",
"vite": "7.0.6",
"vite-plugin-dts": "4.5.4"
},
"private": true
}

project.json

{
"name": "facilities-ui-golf-cart",
"$schema": "../../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "{projectRoot}/src",
"projectType": "library",
"tags": ["scope:facilities", "scope:web", "type:ui"],
"targets": {
"lint": {
"executor": "@nx/eslint:lint",
"options": {
"lintFilePatterns": [
"{projectRoot}/**/*.{ts,tsx,js,jsx}",
"{projectRoot}/project.json"
]
}
},
"build": {
"executor": "@nx/vite:build",
"options": {
"configFile": "{projectRoot}/vite.config.ts",
"tsConfig": "{projectRoot}/tsconfig.lib.json",
"outputPath": "{projectRoot}/dist",
"skipTypeCheck": true,
"buildLibsFromSource": true,
"emptyOutDir": true,
"lib": {
"entry": "src/index.ts",
"formats": ["es"]
},
"generatePackageJson": false
},
"outputs": ["{projectRoot}/dist"],
"dependsOn": []
},
"storybook": {
"executor": "@nx/storybook:storybook",
"options": {
"configDir": "{projectRoot}/.storybook",
"port": 4420
}
},
"build-storybook": {
"executor": "@nx/storybook:build",
"outputs": ["{options.outputDir}"],
"options": {
"configDir": "{projectRoot}/.storybook",
"outputDir": "dist/storybook/{projectName}"
}
},
"test:unit": {},
"test": {
"executor": "nx:noop",
"dependsOn": ["test:unit"]
}
}
}

Implementation Phases

Phase 1: Library Setup

  • Create libs/facilities/ui/golf-cart/ directory structure
  • Configure Nx project, Vite, TypeScript
  • Set up Storybook for component development
  • Create base types and exports

Phase 2: Core Components

  • CartStatusCard - Individual cart display
  • BatteryIndicator - Battery level visualization
  • CartGrid - List view with filtering
  • FleetDashboard - Summary metrics

Phase 3: Advanced Components

  • ZoneMap - Interactive GPS map
  • UtilizationChart - Analytics charts
  • MaintenancePanel - Service management
  • PredictiveMaintenance - AI predictions

Phase 4: Hooks & Integration

  • TanStack Query hooks for data fetching
  • Mutation hooks for actions
  • Context providers for configuration
  • Integration tests

Phase 5: Consumer Integration

  • Add to tee-time-admin
  • Add to scl-admin
  • Documentation and examples

Open Questions

  1. API Client: Use dedicated facilities API client or generic fetch?
  2. Theme Extension: Extend ui-theme or use separate golf-cart theme tokens?
  3. Mobile Support: Create separate mobile library or responsive web components?
  4. Storybook: Shared Storybook or per-library Storybook instances?