Golf Cart Management - UI/UX Specification
- Status: Implemented (v0.6.0)
- Date: 2025-12-06
- Author: Rudi Haarhoff
- Related:
Overview
This document defines the user interface and experience design for the Golf Cart Management module within the Facilities Service. It covers all screens, workflows, components, and interaction patterns.
Design Principles (kept)
- Operational Efficiency - Minimize clicks for common tasks (assign, return, check status)
- At-a-Glance Status - Surface critical information immediately (battery, availability, alerts)
- Progressive Disclosure - Show summary first, drill down for details
- Mobile-First Actions - Core workflows optimized for tablet/phone use on course
- Consistent Patterns - Reuse established Facilities Service UI patterns
User Personas
Fleet Manager
- Manages entire cart inventory
- Monitors utilization and maintenance
- Handles incident resolution
- Primary user of analytics dashboards
Pro Shop Staff
- Assigns carts to bookings
- Processes returns
- Reports damage/incidents
- Quick status checks
Maintenance Technician
- Views service schedules
- Updates cart condition
- Logs completed maintenance
- Tracks repair history
Information Architecture (aligned to shipped components)
Golf Carts (main nav item)
├── Dashboard (default view)
│ ├── Fleet Summary Cards
│ ├── Alerts Panel
│ ├── Zone Map (mini)
│ └── Quick Actions
├── Fleet
│ ├── All Carts (list/grid)
│ ├── Available
│ ├── In Use
│ ├── Charging
│ └── Out of Service
├── Assignments
│ ├── Active
│ ├── History
│ └── Auto-Assign Queue
├── Maintenance
│ ├── Due Soon
│ ├── Predictive
│ ├── Service History
│ └── Schedule Service
├── Incidents
│ ├── Open
│ ├── Resolved
│ └── Report New
├── Analytics
│ ├── Utilization (7/14/30d)
│ ├── Zone Summary
│ └── Predictive Maintenance
└── Zones
├── Map View
├── Zone Summary
└── Zone Config
Data → UI Bindings (live APIs)
| Panel / Component | API / Source | Notes |
|---|---|---|
| Summary Cards (FleetDashboard) | GET /golf-carts/fleet/summary | Use available, inUse, avgBatteryLevel, maintenanceDue, unresolvedIncidents. |
| UtilizationChart | GET /golf-carts/analytics/utilization?tenantId&clubId&windowDays | Use utilizationRate, totalAssignments, avgDailyAssignments, avgUseHours, windowDays. |
| ZoneMap / Zone Summary | GET /golf-carts/zones/summary and GET /golf-carts/zones?zone= | Present zone, cartCount, inUse, available; drill-down to list. |
| PredictiveMaintenance list | GET /golf-carts/maintenance/predictive?horizonDays&odometerMargin&hoursThreshold | Show reason badges: due soon (date within horizon), odometer near threshold, hours high. |
| MaintenancePanel | GET /golf-carts/fleet/maintenance + predictive list | Combine due + predicted. |
| CartGrid | GET /golf-carts?tenantId=... | Filters: condition, cartType, lowBattery, zone (via currentZone), paging skip/take. |
| CartStatusCard | Uses fleet list item | Shows battery, condition, zone, lastLocationAt freshness. |
| IncidentReporter | POST /golf-carts/:id/incidents | Pre-fill cart metadata. |
| AssignmentHistory | GET /golf-carts/:id/assignments | Show assignments (returnedAt null = active). |
Additional UI components (implemented)
Action Components:
- QuickActionsBar — assign/return/incident/scan/add; one-line CTA bar; hook bindings:
onAssignCart,onReturnCart,onReportIncident,onQuickScan,onAddCart; supportshorizontal/verticalvariants. - ActivityFeed — timeline for assignments/returns/incidents/maintenance; helpers
assignmentToActivity,incidentToActivity; accepts click handler for drill-down.
Assignment Modals:
- AssignCartModal — validates booking/player selection, odometer/battery start, staff name; low-battery warning.
- ReturnCartModal — validates end odometer, battery drop; shows usage summary and low-battery alert on return.
- AutoAssignModal — booking summary + preference filters; picks from recommended carts; keyboard-friendly radio selection.
Maintenance Modals:
- ScheduleServiceModal — schedule service type/date/time/duration; optional out-of-service toggle.
- CompleteServiceModal — capture service notes, next service date/odo, condition update, return-to-service.
Incident Modals:
- ResolveIncidentModal — incident summary with severity; resolution notes, repair cost, condition update.
Mobile Components (v0.3.0):
- MobileQuickActions — bottom-sheet drawer with large touch targets; same action handlers as QuickActionsBar; opens via
openprop. - QRScanner — modal for cart lookup via QR code or manual entry;
onLookupcallback for cart search; shows cart summary with action buttons on match.
Component ↔ Hook pairing
| Component | Hook / binding | Notes |
|---|---|---|
| CartGrid | createGolfCartHooks(api).useGolfCarts | Pass loading, errorMessage, onRetry to surface API state (as in Storybook). |
| FleetDashboard | useFleetSummary | Expose utilizationRate, maintenanceDue, unresolvedIncidents. |
| ZoneMap | useZoneSummary | Zones derive from currentZone; visual/table toggle; stale GPS renders warning when lastLocationAt exceeds 15m. |
| UtilizationChart | useUtilization({ windowDays }) | 7/14/30 day presets with control binding. |
| MaintenancePanel | useMaintenanceDue | Merge predictive + scheduled lists; show service-needed badge. |
| IncidentReporter | useReportIncident | Validate required fields, supports loading state. |
| ActivityFeed | useFleetUpdates (WebSocket) | Real-time event stream; auto-reconnect; invalidates TanStack queries on events. |
| QRScanner | useGolfCart (for lookup) | onLookup accepts cart number, returns cart or null. |
Embedding in Tee Time Admin (example)
import {
CartGrid,
FleetDashboard,
createGolfCartHooks,
} from '@digiwedge/facilities-ui-golf-cart';
import { facilitiesApi } from '../api/facilities-api'; // your client
const { useGolfCarts, useFleetSummary } = createGolfCartHooks(facilitiesApi);
export function CartManagementPage({ tenantId, clubId }: { tenantId: number; clubId: number }) {
const { data: carts = [], isLoading, error, refetch } = useGolfCarts({ tenantId, clubId });
const { data: summary } = useFleetSummary(tenantId, clubId);
return (
<>
<FleetDashboard summary={summary} />
<CartGrid
carts={carts}
loading={isLoading}
errorMessage={error?.message}
onRetry={refetch}
pageSize={12}
/>
</>
);
}
Screen Specifications
1. Dashboard
Purpose: At-a-glance fleet health and quick actions
Layout:
┌─────────────────────────────────────────────────────────────┐
│ Golf Cart Fleet Dashboard [+ Add Cart] │
├─────────────────────────────────────────────────────────────┤
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Total: 50 │ │ Avail: 32 │ │ In Use:15 │ │ Service: 3│ │
│ │ ⬤ │ │ ⬤ │ │ ⬤ │ │ ⬤ │ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────┐ ┌─────────────────────────────┐ │
│ │ ALERTS (3) │ │ ZONE MAP │ │
│ │ ⚠ Cart #12 low battery │ │ ┌─────────────────────┐ │ │
│ │ ⚠ Cart #07 overdue svc │ │ │ [Course Map] │ │ │
│ │ ⚠ Cart #31 not returned │ │ │ ● ● ● ● │ │ │
│ └─────────────────────────┘ │ └─────────────────────┘ │ │
│ └─────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ QUICK ACTIONS │
│ [Assign Cart] [Return Cart] [Report Incident] [Quick Scan] │
├─────────────────────────────────────────────────────────────┤
│ UTILIZATION (7 days) │ RECENT ACTIVITY │
│ ████████████░░░░ 68% │ • Cart #42 assigned 10:32 │
│ Avg: 4.2 hrs/cart/day │ • Cart #18 returned 10:28 │
│ Peak: 8-10am │ • Cart #07 service done │
└─────────────────────────────────────────────────────────────┘
Components:
| Component | Description | API Source |
|---|---|---|
| Summary Cards (FleetDashboard) | Clickable stat cards with trend indicators | GET /golf-carts/fleet/summary |
| Alerts Panel | Prioritized list of actionable alerts | Computed from fleet data |
| Zone Map | Mini course map with cart positions | GET /golf-carts/zones/summary |
| Quick Actions | Primary action buttons | N/A |
| Utilization Chart (UtilizationChart) | Sparkline or bar chart | GET /golf-carts/analytics/utilization |
| Activity Feed | Recent assignment/return events | WebSocket or polling |
| Alerts & Thresholds | Low battery, maintenance due, unresolved incidents | Computed; use: battery below 20% danger, 20–39% warning, stale GPS over 15m |
Interactions:
- Click summary card → Navigate to filtered Fleet list
- Click alert → Navigate to relevant cart/action
- Click zone on map → Show zone detail popover
- Quick actions → Open respective modal/drawer
2. Fleet List
Purpose: Browse, search, and manage all carts
Layout:
┌─────────────────────────────────────────────────────────────┐
│ Fleet [+ Add Cart] │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🔍 Search carts... [Status ▼] [Type ▼] [Zone ▼] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ [All] [Available] [In Use] [Charging] [Out of Service] │
├─────────────────────────────────────────────────────────────┤
│ ☐ │ Cart │ Type │ Battery │ Condition │ Zone │ ⋯ │
│───┼───────┼──────────┼─────────┼───────────┼─────────┼─────│
│ ☐ │ #01 │ Electric │ ███░ 85%│ Good │ Bay 1 │ ⋯ │
│ ☐ │ #02 │ Electric │ █░░░ 23%│ Good │ Hole 7 │ ⋯ │
│ ☐ │ #03 │ Gas │ N/A │ Needs Rep │ Shop │ ⋯ │
│ ☐ │ #04 │ Electric │ ████ 95%│ Excellent │ Bay 3 │ ⋯ │
│ │ ... │ │ │ │ │ │
├─────────────────────────────────────────────────────────────┤
│ Showing 1-25 of 50 [◀ Prev] [Next ▶] │
└─────────────────────────────────────────────────────────────┘
Table Columns:
| Column | Description | Sortable |
|---|---|---|
| Checkbox | Bulk selection | No |
| Cart # | Fleet identifier, links to detail | Yes |
| Type | ELECTRIC/GAS/LITHIUM/SOLAR icon+text | Yes |
| Battery/Fuel | Visual gauge + percentage | Yes |
| Condition | Status badge (color-coded) | Yes |
| Zone | Current location zone (currentZone) | Yes |
| Last Active | Time since last assignment / lastLocationAt | Yes |
| Actions | Overflow menu (⋯) | No |
Row Actions Menu:
- View Details
- Assign Cart
- Update Status
- Report Incident
- Schedule Service
- Edit Cart
- Retire Cart (soft delete)
Bulk Actions (when rows selected):
- Update Condition
- Move to Zone
- Schedule Group Service
- Export Selected
Responsive behavior:
- Desktop: grid layout with filters inline; activity and maps side-by-side.
- Tablet/mobile: filters collapse into a drawer; quick actions become a bottom sheet; cards and grids stack single-column.
- Maintain keyboard navigation (tab order across filters, table cells, action buttons).
Filters:
- Status: Available, In Use, Charging, Out of Service
- Type: Electric, Gas, Lithium, Solar
- Zone: Dynamic list from zones
- Condition: Excellent, Good, Fair, Needs Repair
- Battery: Low (below 30%), Medium, High (above 70%)
3. Cart Detail
Purpose: Complete information and actions for a single cart
Layout:
┌─────────────────────────────────────────────────────────────┐
│ ← Back to Fleet │
│ │
│ Cart #42 - Club Car Tempo (2024) [Edit] [⋯] │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ████████████████░░░░ Battery: 85% Status: AVAILABLE │ │
│ │ Last charged: 2h ago Condition: GOOD │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ [Overview] [Assignments] [Incidents] [Service] [Activity] │
├─────────────────────────────────────────────────────────────┤
│ │
│ OVERVIEW TAB │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ IDENTIFICATION │ │ LOCATION │ │
│ │ Serial: CC24-12345 │ │ Zone: Charging Bay │ │
│ │ Model: Tempo │ │ GPS: 33.45, -117.8 │ │
│ │ Year: 2024 │ │ Updated: 5m ago │ │
│ │ Seats: 2 │ │ [View on Map] │ │
│ └────────────────────┘ └────────────────────┘ │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ METRICS │ │ NEXT SERVICE │ │
│ │ Odometer: 1,234 mi │ │ Due: Dec 15, 2025 │ │
│ │ Hours: 456.2 │ │ Or at: 1,500 mi │ │
│ │ Avg use: 3.2h/day │ │ Type: Battery chk │ │
│ └────────────────────┘ └────────────────────┘ │
│ │
│ QUICK ACTIONS │
│ [Assign Cart] [Update Battery] [Report Incident] │
│ │
└─────────────────────────────────────────────────────────────┘
Tabs:
| Tab | Content |
|---|---|
| Overview | Identification, metrics, location, next service |
| Assignments | Assignment history table with usage stats |
| Incidents | Incident history with resolution status |
| Service | Maintenance log and scheduled services |
| Activity | Full audit trail of all changes |
4. Assignment Flow
4.1 Manual Assignment (Modal)
Trigger: "Assign Cart" button from dashboard, list, or detail
┌─────────────────────────────────────────────────────────────┐
│ Assign Cart [×] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Cart │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ #42 - Club Car Tempo │ 85% ████░ │ Available │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Booking * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🔍 Search booking or tee time... │ │
│ └─────────────────────────────────────────────────────────┘ │
│ Recent: #12345 - Smith (10:30am) | #12346 - Jones (11:00) │
│ │
│ Player (optional) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🔍 Search player... │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Starting Metrics │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Odometer: [1234] │ │ Battery: [85] % │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ Cart Fee │
│ ┌──────────────────┐ ☐ Waive fee │
│ │ $25.00 │ Reason: [____________] │
│ └──────────────────┘ │
│ │
│ Notes │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ [Cancel] [Assign Cart] │
└─────────────────────────────────────────────────────────────┘
4.2 Auto-Assignment (Modal)
Trigger: "Auto-Assign" from booking detail or tee sheet
┌─────────────────────────────────────────────────────────────┐
│ Auto-Assign Cart [×] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Booking: #12345 - Smith Party (4 players) │
│ Tee Time: Dec 5, 2025 at 10:30 AM │
│ │
│ Preferences │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Type: [Electric▼]│ │ Seats: [2+ ▼] │ │
│ └──────────────────┘ └──────────────────┘ │
│ ┌──────────────────┐ │
│ │ Min Battery: 50% │ │
│ └──────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ RECOMMENDED CARTS (sorted by battery) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ◉ #42 - Tempo │ 95% █████ │ Excellent │ Bay 1 │ │
│ │ ○ #18 - Tempo │ 88% ████░ │ Good │ Bay 3 │ │
│ │ ○ #07 - Drive │ 82% ████░ │ Good │ Clubhouse │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ [Cancel] [Assign Selected Cart] │
└─────────────────────────────────────────────────────────────┘
4.3 Return Cart (Modal)
Trigger: "Return Cart" from active assignment or quick action
┌─────────────────────────────────────────────────────────────┐
│ Return Cart [×] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Cart #42 - Assigned to Booking #12345 (Smith) │
│ Assigned: 10:32 AM (4h 28m ago) │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ Return Metrics │
│ Start End Delta │
│ Odometer: 1,234.0 [ 1,242.3 ] +8.3 mi │
│ Battery: 95% [ 67 ]% -28% │
│ │
│ Return Location │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Zone: [Charging Bay 3 ▼] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Condition Check │
│ ○ No issues │
│ ○ Minor damage (describe below) │
│ ○ Needs attention (will create incident) │
│ │
│ Notes │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ [Cancel] [Complete Return] │
└─────────────────────────────────────────────────────────────┘
5. Incident Management
5.1 Report Incident (Modal)
┌─────────────────────────────────────────────────────────────┐
│ Report Incident [×] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Cart * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ #42 - Club Car Tempo │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Incident Type * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [Select type... ▼] │ │
│ │ ○ Damage │ │
│ │ ○ Breakdown │ │
│ │ ○ Accident │ │
│ │ ○ Theft │ │
│ │ ○ Vandalism │ │
│ │ ○ Other │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Severity * │
│ ○ Minor (cosmetic, cart operational) │
│ ○ Moderate (needs repair, still usable) │
│ ○ Major (out of service required) │
│ ○ Critical (safety concern, immediate action) │
│ │
│ Location on Course │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [Hole 12 cart path ] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Description * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Scratch on front bumper from hitting cart path marker │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Photos (optional) │
│ [+ Add Photos] 📷 📷 │
│ │
│ Reported By: John Smith (auto-filled) │
│ │
│ [Cancel] [Submit Report] │
└─────────────────────────────────────────────────────────────┘
5.2 Incidents List
┌─────────────────────────────────────────────────────────────┐
│ Incidents [+ Report New] │
│ [Open (3)] [Resolved] [All] │
├─────────────────────────────────────────────────────────────┤
│ │ Cart │ Type │ Severity │ Reported │ Status │ ⋯ │
│─┼──────┼──────────┼──────────┼────────────┼──────────┼─────│
│ │ #42 │ Damage │ ● Minor │ 2h ago │ Open │ ⋯ │
│ │ #07 │ Breakdown│ ● Major │ Yesterday │ Open │ ⋯ │
│ │ #31 │ Accident │ ● Mod. │ Dec 3 │ Open │ ⋯ │
└─────────────────────────────────────────────────────────────┘
5.3 Resolve Incident (Modal)
┌─────────────────────────────────────────────────────────────┐
│ Resolve Incident [×] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Incident #123 - Cart #42 Damage │
│ Reported: Dec 5, 2025 by John Smith │
│ "Scratch on front bumper from hitting cart path marker" │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ Resolution Notes * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Buffed out scratch, applied touch-up paint. Cart │ │
│ │ returned to service. │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Repair Cost │
│ ┌──────────────────┐ │
│ │ $ [45.00 ] │ │
│ └──────────────────┘ │
│ │
│ Update Cart Condition │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [Good ▼] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Resolved By: Mike Tech (auto-filled) │
│ │
│ [Cancel] [Mark Resolved] │
└─────────────────────────────────────────────────────────────┘
6. Maintenance & Service
6.1 Maintenance Dashboard
┌─────────────────────────────────────────────────────────────┐
│ Maintenance [+ Schedule Service] │
│ [Due Soon] [Predictive] [History] │
├─────────────────────────────────────────────────────────────┤
│ │
│ DUE SOON (next 7 days) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Cart │ Service Type │ Due │ Reason │ ⋯ │ │
│ │ #07 │ Battery Check │ Tomorrow │ Date │ ⋯ │ │
│ │ #12 │ Tire Rotation │ Dec 8 │ Odometer │ ⋯ │ │
│ │ #31 │ Full Service │ Dec 10 │ Hours │ ⋯ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ PREDICTIVE (flagged by heuristics) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Cart │ Indicator │ Current │ Threshold │ ⋯ │ │
│ │ #18 │ Odometer near limit │ 1,480 mi │ 1,500 mi │ ⋯ │ │
│ │ #24 │ High usage hours │ 520 hrs │ 500 hrs │ ⋯ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
6.2 Schedule Service (Modal)
┌─────────────────────────────────────────────────────────────┐
│ Schedule Service [×] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Cart * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ #42 - Club Car Tempo │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Service Type * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [Select type... ▼] │ │
│ │ ○ Battery Check/Replace │ │
│ │ ○ Tire Rotation/Replace │ │
│ │ ○ Brake Inspection │ │
│ │ ○ Full Service │ │
│ │ ○ Other │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Scheduled Date/Time * │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ [Dec 10, 2025 ] │ │ [09:00 AM ▼] │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ Expected Duration │
│ ┌──────────────────┐ │
│ │ [2 hours ▼] │ │
│ └──────────────────┘ │
│ │
│ Description │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Quarterly battery health check and terminal cleaning │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ☐ Take cart out of service until complete │
│ │
│ [Cancel] [Schedule] │
└─────────────────────────────────────────────────────────────┘
6.3 Mark Serviced (Modal)
┌─────────────────────────────────────────────────────────────┐
│ Complete Service [×] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Cart #42 - Scheduled Battery Check │
│ │
│ Service Notes * │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Replaced battery pack, cleaned terminals, tested │ │
│ │ charging system. All good. │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Next Service │
│ ┌──────────────────┐ OR ┌──────────────────┐ │
│ │ Date: [Mar 10 ] │ │ Odo: [1,750 mi]│ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ Update Condition │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [Excellent ▼] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ☐ Return to service (currently out of service) │
│ │
│ [Cancel] [Mark Complete] │
└─────────────────────────────────────────────────────────────┘
7. Analytics
7.1 Utilization Report
┌─────────────────────────────────────────────────────────────┐
│ Fleet Utilization Period: [Last 7 days▼] │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ UTILIZATION RATE │ │
│ │ │ │
│ │ ████████████████████░░░░░░░░░░ │ │
│ │ 68% │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Total Carts │ │ Assignments │ │ Avg Hours │ │
│ │ 50 │ │ 238 │ │ 3.4/cart │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
│ DAILY TREND │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 100% │ │ │
│ │ 75% │ ██ │ │
│ │ 50% │ ██ ██ ██ ██ ██ ██ ██ │ │
│ │ 25% │ ██ ██ ██ ██ ██ ██ ██ │ │
│ │ 0% └───────────────────────────── │ │
│ │ Mon Tue Wed Thu Fri Sat Sun │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ TOP PERFORMERS │ UNDERUTILIZED │
│ #42 - 28 assignments │ #31 - 2 assignments │
│ #18 - 26 assignments │ #07 - 3 assignments (svc) │
│ #07 - 24 assignments │ #24 - 5 assignments │
│ │
└─────────────────────────────────────────────────────────────┘
8. Zone Map
8.1 Full Map View
┌─────────────────────────────────────────────────────────────┐
│ Zone Map [Refresh] [Fullscreen]│
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ [COURSE MAP WITH GPS MARKERS] │ │
│ │ │ │
│ │ 🟢 Available 🟡 In Use 🔴 Out of Service │ │
│ │ │ │
│ │ ●Clubhouse (5) │ │
│ │ ↘ │ │
│ │ ●Hole 1 (2) │ │
│ │ ↘ │ │
│ │ ● ● ● │ │
│ │ │ │
│ │ ●Charging Bay (8) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ZONE SUMMARY │
│ ┌──────────────┬───────┬────────┬───────────┐ │
│ │ Zone │ Total │ In Use │ Available │ │
│ ├──────────────┼───────┼────────┼───────────┤ │
│ │ Clubhouse │ 5 │ 2 │ 3 │ │
│ │ Charging Bay │ 8 │ 0 │ 8 │ │
│ │ Hole 1-3 │ 4 │ 4 │ 0 │ │
│ │ Hole 4-6 │ 3 │ 2 │ 1 │ │
│ │ ... │ │ │ │ │
│ └──────────────┴───────┴────────┴───────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Map Interactions:
- Click marker → Show cart popover with quick actions
- Click zone label → Filter to zone, show zone detail
- Hover marker → Show cart number and status
- Cluster markers when zoomed out
Component Library
Status Badges
| Status | Color | Example |
|---|---|---|
| Available | Green (#22C55E) | ● Available |
| In Use | Blue (#3B82F6) | ● In Use |
| Charging | Yellow (#EAB308) | ● Charging |
| Out of Service | Red (#EF4444) | ● Out of Service |
| Needs Repair | Orange (#F97316) | ● Needs Repair |
Condition Badges
| Condition | Color | Icon |
|---|---|---|
| Excellent | Green | ✓✓ |
| Good | Green | ✓ |
| Fair | Yellow | ─ |
| Needs Repair | Orange | ⚠ |
| Out of Service | Red | ✗ |
Battery Gauge
Full: █████████████████████ 100% (green)
High: ████████████████░░░░░ 80% (green)
Medium: ███████████░░░░░░░░░░ 55% (green)
Low: █████░░░░░░░░░░░░░░░░ 25% (yellow)
Critical: ██░░░░░░░░░░░░░░░░░░░ 10% (red)
Alert Types
| Type | Icon | Color | Description |
|---|---|---|---|
| Low Battery | 🔋 | Red | Battery < 20% |
| Service Due | 🔧 | Orange | Maintenance overdue |
| Not Returned | ⏰ | Yellow | Assignment > 6 hours |
| Incident | ⚠️ | Red | Unresolved incident |
| Zone Alert | 📍 | Orange | Cart outside expected zone |
Mobile Considerations
Responsive Breakpoints
| Breakpoint | Layout |
|---|---|
| Desktop (≥1280px) | Full sidebar nav, multi-column layouts |
| Tablet (768-1279px) | Collapsible nav, 2-column where appropriate |
| Mobile (below 768px) | Bottom nav, single column, card-based lists |
Mobile-Optimized Screens
- Quick Actions Bar - Sticky bottom bar with primary actions
- Cart Scanner - QR/barcode scan for instant cart lookup
- Swipe Actions - Swipe row to reveal assign/return actions
- Pull to Refresh - Standard refresh pattern
- Offline Caching - Cache fleet list for offline reference
Mobile Quick Scan Flow
┌─────────────────────┐
│ Scan Cart │
│ │
│ ┌─────────────┐ │
│ │ │ │
│ │ [CAMERA] │ │
│ │ │ │
│ └─────────────┘ │
│ │
│ Point camera at │
│ cart QR code │
│ │
│ [Enter # manually] │
└─────────────────────┘
↓
┌─────────────────────┐
│ Cart #42 │
│ ████████░░ 85% │
│ Status: Available │
│ │
│ ┌─────────────────┐ │
│ │ Assign Cart │ │
│ └─────────────────┘ │
│ ┌─────────────────┐ │
│ │ Report Incident │ │
│ └─────────────────┘ │
│ ┌─────────────────┐ │
│ │ View Details │ │
│ └─────────────────┘ │
└─────────────────────┘
Accessibility
Requirements
- WCAG 2.1 AA compliance minimum
- All interactive elements keyboard accessible
- Screen reader compatible with ARIA labels
- Color not sole indicator (use icons + text)
- Minimum touch target: 44x44px on mobile
- Focus indicators visible
Specific Implementations
| Element | Accessibility Feature |
|---|---|
| Battery gauge | aria-label="Battery level 85 percent" |
| Status badges | Icon + text, not color alone |
| Data tables | Proper <th> headers, scope attributes |
| Modals | Focus trap, Escape to close |
| Alerts | role="alert" for screen readers |
| Maps | Text alternative zone summary table |
Error States
Empty States
┌─────────────────────────────────────────────────────────────┐
│ │
│ 🛒 │
│ │
│ No carts found │
│ │
│ Add your first cart to start managing your fleet │
│ │
│ [+ Add Cart] │
│ │
└─────────────────────────────────────────────────────────────┘
Error States
┌─────────────────────────────────────────────────────────────┐
│ │
│ ⚠️ │
│ │
│ Failed to load fleet data │
│ │
│ Check your connection and try again │
│ │
│ [Retry] │
│ │
└─────────────────────────────────────────────────────────────┘
Loading States
- Skeleton loaders for lists and cards
- Spinner for action buttons during API calls
- Progress bar for bulk operations
API Integration Summary
| Screen/Component | Primary API Endpoint |
|---|---|
| Dashboard Summary | GET /golf-carts/fleet/summary |
| Dashboard Utilization | GET /golf-carts/analytics/utilization |
| Dashboard Zone Map | GET /golf-carts/zones/summary |
| Fleet List | GET /golf-carts |
| Cart Detail | GET /golf-carts/:id |
| Assignment History | GET /golf-carts/:id/assignments |
| Incident History | GET /golf-carts/:id/incidents |
| Service History | GET /golf-carts/:id/service-history |
| Create Cart | POST /golf-carts |
| Update Cart | PUT /golf-carts/:id |
| Assign Cart | POST /golf-carts/:id/assign |
| Auto-Assign | POST /golf-carts/auto-assign |
| Return Cart | POST /golf-carts/assignments/:id/return |
| Report Incident | POST /golf-carts/:id/incidents |
| Resolve Incident | PUT /golf-carts/incidents/:id/resolve |
| Schedule Service | POST /golf-carts/:id/schedule-maintenance |
| Mark Serviced | POST /golf-carts/:id/mark-serviced |
| Zone Carts | GET /golf-carts/zones?zone=X |
| Predictive Maintenance | GET /golf-carts/maintenance/predictive |
Implementation Priority
Implemented (v0.3.0)
Core Components (v0.2.0):
- Dashboard primitives: summary cards, utilization, zone summary (via
FleetDashboard,UtilizationChart,ZoneMap). - Fleet list and status cards (
CartGrid,CartStatusCard,BatteryIndicator). - Maintenance and predictive lists (
MaintenancePanel,PredictiveMaintenance). - Assignment history and incident reporting (
AssignmentHistory,IncidentReporter). - TanStack Query hooks factory (
createGolfCartHooks) for all cart APIs.
Action Components (v0.2.1):
6. Quick actions bar (QuickActionsBar) with assign/return/incident/scan/add buttons.
7. Activity feed (ActivityFeed) with timeline display and converter helpers.
8. Assignment modals (AssignCartModal, ReturnCartModal, AutoAssignModal).
9. Maintenance modals (ScheduleServiceModal, CompleteServiceModal).
10. Incident resolution (ResolveIncidentModal).
Mobile & Real-time (v0.3.0):
11. ✅ Mobile-optimized layouts (MobileQuickActions bottom-sheet drawer).
12. ✅ QR scanner integration (QRScanner with camera placeholder and manual entry).
13. ✅ Real-time updates (useFleetUpdates WebSocket hook with auto-reconnect and query invalidation).
14. ✅ Accessibility sweep: ARIA labels on all interactive elements, role="alert" on warnings, keyboard navigation on alerts/cards, focus order validation in Storybook.
15. ✅ ZoneMap enhanced with visual card view toggle alongside table view.
16. ✅ CartGrid enhanced with error/empty states and retry affordance.
17. ✅ CartStatusCard enhanced with configurable low-battery and stale-GPS thresholds.
Component Inventory (23 components + 14 hooks + 17 lazy wrappers):
| Category | Components |
|---|---|
| Core | BatteryIndicator, CartStatusCard, CartGrid, FleetDashboard |
| Actions | QuickActionsBar, ActivityFeed |
| Analytics | UtilizationChart, ZoneMap |
| Assignment | AssignCartModal, ReturnCartModal, AutoAssignModal |
| Maintenance | MaintenancePanel, PredictiveMaintenance, ScheduleServiceModal, CompleteServiceModal |
| Incidents | IncidentReporter, ResolveIncidentModal |
| History | AssignmentHistory |
| Mobile | MobileQuickActions, QRScanner, DefaultQRCamera |
| Hook Category | Hooks |
|---|---|
| Queries | useGolfCarts, useGolfCart, useFleetSummary, useZoneSummary, useUtilization, usePredictiveMaintenance, useCartAssignments, useCartIncidents |
| Mutations | useAssignCart, useReturnCart, useReportIncident, useUpdateBattery, useUpdateLocation |
| Real-time | useFleetUpdates |
Outstanding Items
None - all features implemented.
Enhancements (v0.6.0)
Offline Support:
- Service worker at
libs/facilities/ui/golf-cart/src/lib/sw/golf-carts-sw.js - Stale-while-revalidate caching with 5-minute TTL for cart API endpoints
- Cache control utilities:
clearGolfCartCache(),getGolfCartCacheStatus(),isGolfCartOfflineReady() - Host apps copy SW to public root and register:
import {
registerGolfCartServiceWorker,
clearGolfCartCache,
getGolfCartCacheStatus,
isGolfCartOfflineReady,
} from '@digiwedge/facilities-ui-golf-cart';
// Register on app load
await registerGolfCartServiceWorker('/golf-carts-sw.js');
// Check status
if (isGolfCartOfflineReady()) {
const status = await getGolfCartCacheStatus();
console.log(`Cached: ${status?.dataEntries} API responses`);
}
// Clear cache when needed
await clearGolfCartCache();
Cached endpoints (stale-while-revalidate, 5min TTL):
GET /golf-cartsGET /golf-carts/fleet/summaryGET /golf-carts/zones/summaryGET /golf-carts/analytics/utilization
Enhancements (v0.5.0)
DefaultQRCamera Component:
- Ready-to-use QR camera implementation using
@zxing/browser. - Pass to
QRScannerviacameraRendererprop. - Handles camera permissions, error states, and scanner overlay.
import { QRScanner, DefaultQRCamera } from '@digiwedge/facilities-ui-golf-cart';
<QRScanner
open={open}
onClose={onClose}
onCartFound={handleCartFound}
onLookup={lookupCart}
cameraEnabled
cameraRenderer={<DefaultQRCamera onScan={handleScan} active={open} />}
/>
Lazy-loaded Components for Code-Splitting:
- All heavy components available as
Lazy*variants for route-based splitting. - Use with
React.Suspenseat the app layer.
import { Suspense } from 'react';
import { LazyUtilizationChart, LazyZoneMap, LazyAssignCartModal } from '@digiwedge/facilities-ui-golf-cart';
import { Spin } from 'antd';
function AnalyticsPage() {
return (
<Suspense fallback={<Spin size="large" />}>
<LazyUtilizationChart report={utilizationData} />
<LazyZoneMap zones={zones} carts={carts} />
</Suspense>
);
}
Available lazy components:
- Analytics:
LazyUtilizationChart,LazyZoneMap - Maintenance:
LazyMaintenancePanel,LazyPredictiveMaintenance - History:
LazyAssignmentHistory,LazyActivityFeed - Assignment modals:
LazyAssignCartModal,LazyReturnCartModal,LazyAutoAssignModal - Maintenance modals:
LazyScheduleServiceModal,LazyCompleteServiceModal - Incident:
LazyIncidentReporter,LazyResolveIncidentModal - Mobile:
LazyMobileQuickActions,LazyQRScanner,LazyDefaultQRCamera - Grid/Dashboard:
LazyCartGrid,LazyFleetDashboard
Storybook / Visual QA
- States covered: default, empty, loading, API error, low-battery, stale GPS, out-of-service, maintenance due, incident reporting form.
- A11y: axe-playwright integration runs WCAG 2.1 AA checks on all stories; play functions assert search/filter usability and incident form labels.
- Visuals: screenshot snapshots enabled for key stories (
FleetDashboard,UtilizationChart,ZoneMap,CartGrid) viatags: ['snapshot']in story config. - Testing targets:
pnpm nx run facilities-ui-golf-cart:build-storybook— static preview buildpnpm nx run facilities-ui-golf-cart:storybook:test— Storybook test component testspnpm nx run facilities-ui-golf-cart:storybook:test-runner— run against dev server (a11y + interactions)pnpm nx run facilities-ui-golf-cart:storybook:ci— CI pipeline: build Storybook, serve static, run test-runner with axe a11y + visual snapshots
Accessibility Checklist
- Buttons/links: aria-labels on icon-only controls (assign/return/report incident), focus-visible styles.
- Alerts:
role="alert"and semantic headings; ensure screen reader order follows visual order. - Charts/tables: keyboard navigation; tab into chart legend; table row actions reachable via keyboard.
- Contrast: badges/gauges meet WCAG AA (battery/condition colors with text labels).
- Forms: associate labels, inline error text with
aria-describedby; focus trap in modals/drawers.
Real-time & QR Patterns (Implemented v0.3.0)
WebSocket Hook (useFleetUpdates):
- Connects to WebSocket URL with tenant/club subscription.
- Event types:
cart.assigned,cart.returned,cart.incident,cart.incident.resolved,cart.battery.updated,cart.location.updated,cart.condition.changed,cart.maintenance.scheduled,cart.maintenance.completed. - Auto-reconnect with configurable delay and max attempts.
- Invalidates relevant TanStack Query caches on events.
- Exposes
connected,connecting,error,lastEventstate.
QR Scanner (QRScanner):
- Modal with camera viewfinder placeholder (or supply
cameraRendererfor a real scanner). - Manual cart number entry fallback.
- On match: displays cart summary with BatteryIndicator, condition badge, zone.
- Action buttons: Assign Cart, Report Incident, View Details.
onCartFoundcallback when cart is matched.
Integration Pattern:
const { connected, lastEvent } = useFleetUpdates({
url: 'wss://api.example.com/fleet-ws',
tenantId: 123,
onEvent: (event) => console.log('Fleet event:', event),
});
// TanStack queries auto-refresh when events arrive
// Offline caching (optional)
await registerGolfCartServiceWorker('/golf-carts-sw.js');