@schandlergarcia/sf-web-components 1.9.67 → 1.9.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.a4drules/skills/command-center-builder/SKILL.md +18 -141
- package/.a4drules/skills/command-center-builder/charts-visualization.md +1 -136
- package/.a4drules/skills/command-center-builder/completion-checklist.md +1 -61
- package/.a4drules/skills/command-center-builder/components-styling.md +1 -97
- package/.a4drules/skills/command-center-builder/data-forms-ai.md +1 -43
- package/.a4drules/skills/command-center-builder/getting-started.md +1 -125
- package/.a4drules/skills/command-center-builder/improved-build-process.md +1 -30
- package/.a4drules/skills/command-center-builder/page-layout.md +1 -145
- package/CHANGELOG.md +28 -11
- package/data/engine-command-center-prd.md +107 -295
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Engine Travel Command Center
|
|
2
2
|
|
|
3
|
-
Product Requirements Document
|
|
3
|
+
Product Requirements Document
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,28 +8,25 @@ Product Requirements Document · TDX26 Demo Build
|
|
|
8
8
|
|
|
9
9
|
The Engine Travel Command Center is a real-time operations dashboard for corporate travel managers who use Engine (engine.com). It gives a single-screen view of every active traveler, booking, flight, policy flag, and agent interaction — built on Salesforce Data Cloud.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
**Demo context:** Built live at TDX26 using Agentforce Vibes. The arc is: PRD → scaffold → data → agent → intelligence. Each build prompt maps to one beat.
|
|
11
|
+
**Build approach:** Incremental — PRD → scaffold → data → agent → intelligence.
|
|
14
12
|
|
|
15
13
|
---
|
|
16
14
|
|
|
17
15
|
## 2. Users
|
|
18
16
|
|
|
19
17
|
**Primary — Sarah Chen, Travel Manager at Acme Corp**
|
|
20
|
-
Manages Acme's travel program: bookings, policy enforcement, exceptions, traveler monitoring.
|
|
18
|
+
Manages Acme's travel program: bookings, policy enforcement, exceptions, traveler monitoring.
|
|
21
19
|
|
|
22
20
|
**Secondary — Eva (Agentforce Agent)**
|
|
23
|
-
Engine's Agentforce-powered AI agent. Handles traveler requests autonomously — booking changes, policy questions, itinerary lookups. Resolves ~30% of requests without human involvement. Surfaces
|
|
21
|
+
Engine's Agentforce-powered AI agent. Handles traveler requests autonomously — booking changes, policy questions, itinerary lookups. Resolves ~30% of requests without human involvement. Surfaces via `ChatBar`.
|
|
24
22
|
|
|
25
23
|
---
|
|
26
24
|
|
|
27
25
|
## 3. Brand Tokens
|
|
28
26
|
|
|
29
|
-
Update `src/styles/global.css` — replace the existing `--color-brand-*` palette inside the `@theme inline` block
|
|
27
|
+
Update `src/styles/global.css` — replace the existing `--color-brand-*` palette inside the `@theme inline` block:
|
|
30
28
|
|
|
31
29
|
```css
|
|
32
|
-
/* Engine teal brand palette */
|
|
33
30
|
--color-brand-50: #ECFDF9;
|
|
34
31
|
--color-brand-100: #D1FAF0;
|
|
35
32
|
--color-brand-200: #A7F3E1;
|
|
@@ -41,185 +38,93 @@ Update `src/styles/global.css` — replace the existing `--color-brand-*` palett
|
|
|
41
38
|
--color-brand-800: #115E59;
|
|
42
39
|
--color-brand-900: #134E4A;
|
|
43
40
|
--color-brand-950: #042F2E;
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Additionally, add a custom `--color-engine-savings` token for the green savings accent:
|
|
47
|
-
|
|
48
|
-
```css
|
|
49
41
|
--color-engine-savings: #16A34A;
|
|
50
42
|
```
|
|
51
43
|
|
|
52
|
-
|
|
44
|
+
Use `brand-*` Tailwind classes for brand elements. Tailwind built-in colors (green, amber, red) for status. No hardcoded hex in components.
|
|
53
45
|
|
|
54
|
-
**Typography:** Inter (already
|
|
55
|
-
|
|
56
|
-
**Icons:** Heroicons 2 exclusively (`@heroicons/react`). No Lucide, Font Awesome, or other libraries inside command center pages.
|
|
46
|
+
**Typography:** Inter (already `--font-sans`). **Icons:** Heroicons 2 (`@heroicons/react`).
|
|
57
47
|
|
|
58
48
|
---
|
|
59
49
|
|
|
60
50
|
## 4. Architecture
|
|
61
51
|
|
|
62
|
-
**Dashboard file:** `src/pages/EngineDashboard.tsx`
|
|
63
|
-
|
|
64
|
-
**
|
|
65
|
-
|
|
66
|
-
**Imports:** All components from `@/components/library` barrel. Theme access from `@/components/library/theme/AppThemeProvider`.
|
|
52
|
+
- **Dashboard file:** `src/pages/EngineDashboard.tsx`
|
|
53
|
+
- **Wiring:** `CommandCenter.tsx` imports and renders `EngineDashboard` inside the existing provider stack. Never recreate providers in the dashboard.
|
|
54
|
+
- **Imports:** Components from `@/components/library`. Theme from `@/components/library/theme/AppThemeProvider`.
|
|
67
55
|
|
|
68
56
|
---
|
|
69
57
|
|
|
70
|
-
## 5. Layout
|
|
71
|
-
|
|
72
|
-
This dashboard uses the **visualization-hero** layout. The live flight map is the signature element.
|
|
58
|
+
## 5. Layout
|
|
73
59
|
|
|
74
|
-
|
|
60
|
+
Visualization-hero layout. Full-page scroll (no `h-screen`).
|
|
75
61
|
|
|
76
62
|
```
|
|
77
|
-
|
|
78
|
-
│ HEADER
|
|
79
|
-
│ Engine logo + "Travel Command Center"
|
|
80
|
-
|
|
81
|
-
│ HERO MAP (h-[520px]
|
|
82
|
-
│
|
|
83
|
-
│
|
|
84
|
-
│
|
|
85
|
-
│
|
|
86
|
-
│
|
|
87
|
-
│
|
|
88
|
-
|
|
89
|
-
│
|
|
90
|
-
│
|
|
91
|
-
|
|
92
|
-
│
|
|
93
|
-
│
|
|
94
|
-
│
|
|
95
|
-
│
|
|
96
|
-
│
|
|
97
|
-
│
|
|
98
|
-
│
|
|
99
|
-
│
|
|
100
|
-
|
|
101
|
-
│ │ (ActivityCard) │ │ (ChartCard + D3Chart line) │ │ ↕
|
|
102
|
-
│ └────────────────┘ └────────────────────────────┘ │ ↕
|
|
103
|
-
└─────────────────────────────────────────────────────────────┘
|
|
63
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
64
|
+
│ HEADER (h-12, sticky, bg-slate-900) │
|
|
65
|
+
│ Engine logo + "Travel Command Center" | actions + toggle │
|
|
66
|
+
├──────────────────────────────────────────────────────────────┤
|
|
67
|
+
│ HERO MAP (h-[520px], GeoMap, relative) │
|
|
68
|
+
│ ┌─ glass KPI overlays (absolute top-left) ───────────────┐ │
|
|
69
|
+
│ │ Active Travelers | Spend MTD | Compliance | Eva Resolved│ │
|
|
70
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
71
|
+
│ ┌─ flight status strip (absolute bottom) ────────────────┐ │
|
|
72
|
+
│ │ BA 286 · In Air | NH 109 · In Air | LH 431 · Delayed │ │
|
|
73
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
74
|
+
├──────────────────────────────────────────────────────────────┤
|
|
75
|
+
│ DATA PANELS (px-4 py-5 space-y-6) │
|
|
76
|
+
│ │
|
|
77
|
+
│ Row 1: grid grid-cols-1 items-start gap-4 lg:grid-cols-3 │
|
|
78
|
+
│ ┌── 2/3 (lg:col-span-2) ──────┐ ┌── 1/3 ───────────────┐ │
|
|
79
|
+
│ │ Escalations (ActivityCard) │ │ Disruptions (custom) │ │
|
|
80
|
+
│ └───────────────────────────────┘ └──────────────────────┘ │
|
|
81
|
+
│ │
|
|
82
|
+
│ Row 2: grid grid-cols-1 items-start gap-4 lg:grid-cols-3 │
|
|
83
|
+
│ ┌── 2/3 (lg:col-span-2) ──────┐ ┌── 1/3 ───────────────┐ │
|
|
84
|
+
│ │ Active Travelers (expandable) │ │ Travel Spend (chart) │ │
|
|
85
|
+
│ └───────────────────────────────┘ └──────────────────────┘ │
|
|
86
|
+
└──────────────────────────────────────────────────────────────┘
|
|
104
87
|
```
|
|
105
88
|
|
|
106
|
-
### Layout
|
|
89
|
+
### Layout classes
|
|
107
90
|
|
|
108
|
-
**
|
|
91
|
+
- **Outer:** `<div className="flex flex-col bg-slate-50 dark:bg-slate-950">`
|
|
92
|
+
- **Map:** `<div className="relative h-[520px]">`
|
|
93
|
+
- **Panels:** `<div className="px-4 py-5"><div className="space-y-6">...</div></div>`
|
|
94
|
+
- **Row 1:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Escalations `lg:col-span-2`, Disruptions auto
|
|
95
|
+
- **Row 2:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Travelers `lg:col-span-2`, Spend auto
|
|
109
96
|
|
|
110
|
-
|
|
97
|
+
### Phase 1 placeholders
|
|
111
98
|
|
|
112
|
-
|
|
113
|
-
- **Hero map:** Fixed height `h-[520px]` or `h-[600px]` with `relative` positioning for glass overlays
|
|
114
|
-
- **Data panels:** Natural flow with `px-4 py-5 space-y-6` (NO `overflow-y-auto`, NO flex height constraints)
|
|
115
|
-
- **Row 1** - Disruptions + Travelers: `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` (disruptions 1/3, travelers `lg:col-span-2`)
|
|
116
|
-
- **Row 2** - Escalations + Chart: `grid grid-cols-1 items-start gap-4 lg:grid-cols-2`
|
|
117
|
-
- All grids use `items-start` for different-height cards
|
|
118
|
-
|
|
119
|
-
**Why full-page scroll:** Users need to see the map in context while scrolling through data. A fixed-height map that stays visible while data scrolls below creates a cramped, split-screen feeling. Full-page scroll is more natural and gives each section breathing room.
|
|
120
|
-
|
|
121
|
-
### Phase 1 Placeholder Rules
|
|
122
|
-
|
|
123
|
-
**Phase 1 builds the complete layout structure** including header bar, hero map, glass KPI overlays, flight status strip, and data panels. The only "placeholders" are the **data panels** below the map.
|
|
124
|
-
|
|
125
|
-
**What to build in Phase 1:**
|
|
126
|
-
- ✅ Header bar (with logo, title, theme toggle) - **use slate scale colors, NOT text-white**
|
|
127
|
-
- ✅ Hero map (GeoMap component with no markers/arcs/overlays props)
|
|
128
|
-
- ✅ Glass KPI overlays (4 KPIs, hardcoded values, positioned absolutely over map)
|
|
129
|
-
- ✅ Flight status strip (4 flights, hardcoded values, positioned at map bottom)
|
|
130
|
-
- ✅ Data panels (BaseCard placeholders with centered text) - **these are the only placeholders**
|
|
131
|
-
|
|
132
|
-
**Data panel placeholders** use `BaseCard` with centered text:
|
|
99
|
+
Phase 1 builds the header, map, glass overlays, and flight strip as real components. Only the 4 data panels below the map are placeholders:
|
|
133
100
|
|
|
134
101
|
```tsx
|
|
135
|
-
// ✅ Correct data panel placeholder
|
|
136
102
|
<BaseCard>
|
|
137
103
|
<div className="h-48 flex items-center justify-center text-slate-400">
|
|
138
|
-
|
|
104
|
+
Escalations Panel
|
|
139
105
|
</div>
|
|
140
106
|
</BaseCard>
|
|
141
|
-
|
|
142
|
-
// ❌ Wrong - title causes text to run together
|
|
143
|
-
<BaseCard title="Disruptions">
|
|
144
|
-
<div className="text-slate-400">No disruptions detected</div>
|
|
145
|
-
</BaseCard>
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
**Hero map** (render actual GeoMap component in Phase 1):
|
|
149
|
-
|
|
150
|
-
```tsx
|
|
151
|
-
// ✅ Correct - render actual GeoMap component (empty, no data)
|
|
152
|
-
import { GeoMap } from "@/components/library";
|
|
153
|
-
import { useThemeMode } from "@/components/library/theme/AppThemeProvider";
|
|
154
|
-
|
|
155
|
-
export default function EngineDashboard() {
|
|
156
|
-
const { mode } = useThemeMode();
|
|
157
|
-
|
|
158
|
-
return (
|
|
159
|
-
<div className="relative h-[520px]">
|
|
160
|
-
<GeoMap
|
|
161
|
-
width={960}
|
|
162
|
-
height={520}
|
|
163
|
-
theme={mode === "dark" ? "dark" : "light"}
|
|
164
|
-
className="h-full w-full"
|
|
165
|
-
/>
|
|
166
|
-
</div>
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
In Phase 1:
|
|
172
|
-
- GeoMap component renders with NO `markers`, `arcs`, or `overlays` props (these are GeoMap data props for Phase 2+)
|
|
173
|
-
- GeoMap will render the base world map (land, sphere, graticule) even without data - this is NOT a placeholder, it's the actual map component
|
|
174
|
-
- Glass KPI overlays and flight status strip ARE built in Phase 1 (as separate `<div>` elements positioned absolutely over the map)
|
|
175
|
-
- Uses `useThemeMode()` to get dark/light mode for theme prop
|
|
176
|
-
- **Verify:** You should see a blue world map (dark theme) or gray world map (light theme) with glass overlays on top
|
|
177
|
-
|
|
178
|
-
// ❌ Wrong - wrapped in BaseCard
|
|
179
|
-
<div className="relative h-[520px]">
|
|
180
|
-
<BaseCard>
|
|
181
|
-
<GeoMap ... />
|
|
182
|
-
</BaseCard>
|
|
183
|
-
</div>
|
|
184
|
-
|
|
185
|
-
// ❌ Wrong - text placeholder instead of GeoMap component
|
|
186
|
-
<div className="relative h-[520px]">
|
|
187
|
-
<div className="flex h-full items-center justify-center bg-slate-100 dark:bg-slate-900">
|
|
188
|
-
<span className="text-slate-400">Hero Map (GeoMap)</span>
|
|
189
|
-
</div>
|
|
190
|
-
</div>
|
|
191
107
|
```
|
|
192
108
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
Hero map uses: actual GeoMap component (no markers/arcs/overlays in Phase 1), direct render, fills hero container.
|
|
109
|
+
The GeoMap renders the base world map with no data props. Glass overlays and flight strip use hardcoded values.
|
|
196
110
|
|
|
197
111
|
---
|
|
198
112
|
|
|
199
113
|
## 6. Header
|
|
200
114
|
|
|
201
|
-
Compact `h-12` sticky header
|
|
202
|
-
|
|
203
|
-
| Position | Content |
|
|
204
|
-
|----------|---------|
|
|
205
|
-
| Left | Engine logo (small square icon with `GlobeAltIcon` in `bg-brand-600`) + "ENGINE" wordmark + separator + "Travel Command Center" |
|
|
206
|
-
| Right | `ChatBar` (Eva) + notification bell (with pending count badge) + theme toggle (sun/moon) |
|
|
115
|
+
Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`).
|
|
207
116
|
|
|
208
|
-
|
|
117
|
+
| Left | Right |
|
|
118
|
+
|------|-------|
|
|
119
|
+
| Engine logo (`GlobeAltIcon` in `bg-brand-600` square) + "ENGINE" wordmark + separator + "Travel Command Center" | ChatBar (Phase 4) + notification bell (badge count) + theme toggle (sun/moon) |
|
|
209
120
|
|
|
210
121
|
---
|
|
211
122
|
|
|
212
123
|
## 7. Hero Map
|
|
213
124
|
|
|
214
|
-
**Component:** `GeoMap`
|
|
215
|
-
|
|
216
|
-
**Phase 1:** Render GeoMap with NO data props (no markers/arcs/overlays)
|
|
217
|
-
**Phase 2:** Add markers, arcs, and overlays from sample data to show where travelers are
|
|
125
|
+
**Component:** `GeoMap` from `@/components/library`
|
|
218
126
|
|
|
219
127
|
```tsx
|
|
220
|
-
import { MAP_MARKERS, MAP_ARCS, MAP_OVERLAYS } from "@/data/engine-sample-data";
|
|
221
|
-
|
|
222
|
-
// Phase 2 - with map data
|
|
223
128
|
<GeoMap
|
|
224
129
|
width={960}
|
|
225
130
|
height={520}
|
|
@@ -232,52 +137,27 @@ import { MAP_MARKERS, MAP_ARCS, MAP_OVERLAYS } from "@/data/engine-sample-data";
|
|
|
232
137
|
/>
|
|
233
138
|
```
|
|
234
139
|
|
|
235
|
-
**Markers:** One per city
|
|
140
|
+
- **Markers:** One per city. `{ id, lon, lat, label, active: true }`
|
|
141
|
+
- **Arcs:** One per flight route. `{ id, from: [lon, lat], to: [lon, lat], progress: 0–1, danger: boolean }`. `danger: true` on disrupted routes.
|
|
142
|
+
- **Overlays:** Weather zones. `{ id, center: [lon, lat], radius: number }`
|
|
143
|
+
- **Phase 1:** Render GeoMap with no data props (map renders base world automatically)
|
|
144
|
+
- **Phase 2:** Add `MAP_MARKERS`, `MAP_ARCS`, `MAP_OVERLAYS` from `@/data/engine-sample-data`
|
|
236
145
|
|
|
237
|
-
**
|
|
146
|
+
**Glass KPI overlays** — 4 pills, `absolute left-3 top-3`:
|
|
147
|
+
Active Travelers (count), Spend MTD (`fmtK()`), Compliance %, Eva Resolved (count + "resolved").
|
|
148
|
+
Style: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5`
|
|
238
149
|
|
|
239
|
-
**
|
|
240
|
-
|
|
241
|
-
**Glass KPI overlays:** Four pills floating `absolute left-3 top-3` on the map:
|
|
242
|
-
- Active Travelers (count)
|
|
243
|
-
- Spend MTD (formatted with `fmtK()`)
|
|
244
|
-
- Compliance %
|
|
245
|
-
- Eva Resolved (count + "resolved")
|
|
246
|
-
|
|
247
|
-
Each pill: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5` with white text and icon.
|
|
248
|
-
|
|
249
|
-
**Flight status strip:** Floating `absolute bottom-3 left-3 right-3`, horizontal scroll. One pill per active flight showing flight number + status chip (On Time = green, Delayed = amber, Grounded/Boarding = contextual). Same glass styling as KPI overlays.
|
|
150
|
+
**Flight status strip** — `absolute bottom-3 left-3 right-3`, horizontal scroll. One pill per flight: flight number + status chip (green=On Time, amber=Delayed, contextual=Boarding). Same glass styling.
|
|
250
151
|
|
|
251
152
|
---
|
|
252
153
|
|
|
253
154
|
## 8. Data Panels
|
|
254
155
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
For example: Panel titled "Escalations" uses data exported as `EVA_ACTIONS` or `ESCALATION_CARDS` (both are aliases). The PRD panel title takes precedence over data export names.
|
|
258
|
-
|
|
259
|
-
### 8a. Disruptions Panel (1/3 width)
|
|
260
|
-
|
|
261
|
-
Custom inline component inside a `BaseCard`. Shows only flights that are delayed 60+ min or grounded.
|
|
262
|
-
|
|
263
|
-
Each disruption card:
|
|
264
|
-
- Severity dot (rose for grounded, amber for delayed) + flight number + severity label + delay minutes
|
|
265
|
-
- Route + affected traveler name
|
|
266
|
-
- Reason text
|
|
267
|
-
- Eva action line with `SparklesIcon` showing what Eva is doing about it
|
|
268
|
-
|
|
269
|
-
### 8b. Active Travelers (2/3 width)
|
|
270
|
-
|
|
271
|
-
`BaseCard` with `maxBodyHeight={420}` for internal scroll. Expandable traveler cards.
|
|
272
|
-
|
|
273
|
-
Each traveler row:
|
|
274
|
-
- `Avatar` (initials) + name + department + origin → destination
|
|
275
|
-
- `UIChip` for policy status (success = compliant, warning = exception)
|
|
276
|
-
- Click to expand: 4-col grid showing Flight, Hotel, Return date, Destination
|
|
156
|
+
4 panels in 2 rows. Sample data imported from `src/data/engine-sample-data.js`.
|
|
277
157
|
|
|
278
|
-
###
|
|
158
|
+
### 8a. Escalations (Row 1, 2/3 width)
|
|
279
159
|
|
|
280
|
-
|
|
160
|
+
ActivityCard wrapped in BaseCard:
|
|
281
161
|
|
|
282
162
|
```tsx
|
|
283
163
|
<BaseCard>
|
|
@@ -288,30 +168,35 @@ Each traveler row:
|
|
|
288
168
|
</BaseCard>
|
|
289
169
|
```
|
|
290
170
|
|
|
291
|
-
|
|
171
|
+
Each escalation: title, subtitle, status (`"working"` | `"pending"` | `"complete"`), timestamp.
|
|
172
|
+
|
|
173
|
+
### 8b. Disruptions (Row 1, 1/3 width)
|
|
174
|
+
|
|
175
|
+
Custom inline component in BaseCard. Shows flights delayed 60+ min or grounded.
|
|
176
|
+
|
|
177
|
+
Each disruption card:
|
|
178
|
+
- Severity dot (rose=grounded, amber=delayed) + flight number + delay minutes
|
|
179
|
+
- Route + traveler name
|
|
180
|
+
- Reason text
|
|
181
|
+
- Eva action line with `SparklesIcon`
|
|
182
|
+
|
|
183
|
+
Data: `DISRUPTION_CARDS` from sample data.
|
|
292
184
|
|
|
293
|
-
|
|
294
|
-
- Title (issue description)
|
|
295
|
-
- Subtitle (details + context)
|
|
296
|
-
- Status: `"working"` (Eva is handling), `"pending"` (needs review), or `"complete"` (resolved)
|
|
297
|
-
- Timestamp
|
|
185
|
+
### 8c. Active Travelers (Row 2, 2/3 width)
|
|
298
186
|
|
|
299
|
-
|
|
300
|
-
- "Processing approval for Omar Hassan" - subtitle: "Paris trip over budget · escalated to manager" (status: pending)
|
|
301
|
-
- "Monitoring weather delay for Elena Rodriguez" - subtitle: "AF 99 · CDG arrival delayed 45 min · No action yet" (status: working)
|
|
302
|
-
- "Rebooked cancelled flight for Priya Patel" - subtitle: "LH 431 → LH 433 · Same fare class" (status: complete)
|
|
187
|
+
BaseCard with `maxBodyHeight={420}`. Expandable traveler cards.
|
|
303
188
|
|
|
304
|
-
|
|
189
|
+
Each row: `Avatar` (initials) + name + department + origin → destination + `UIChip` (compliant/exception).
|
|
190
|
+
Expand: 4-col grid — Flight, Hotel, Return, Destination.
|
|
305
191
|
|
|
306
|
-
|
|
192
|
+
Data: `TRAVELER_CARDS` from sample data.
|
|
307
193
|
|
|
308
|
-
|
|
194
|
+
### 8d. Monthly Spend Trend (Row 2, 1/3 width)
|
|
309
195
|
|
|
310
196
|
```tsx
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
live: []
|
|
197
|
+
const spendChartData = useDataSource({
|
|
198
|
+
sample: MONTHLY_SPEND.map(m => ({ x: m.month, spend: m.amount })),
|
|
199
|
+
live: [],
|
|
315
200
|
});
|
|
316
201
|
|
|
317
202
|
<ChartCard
|
|
@@ -336,145 +221,72 @@ const spendChartData = useDataSource({
|
|
|
336
221
|
/>
|
|
337
222
|
```
|
|
338
223
|
|
|
339
|
-
**Data source:** Import `MONTHLY_SPEND` from sample data, transform to chart format
|
|
340
|
-
|
|
341
|
-
**Requirements:**
|
|
342
|
-
- X-axis: month names (Oct through Mar) - categorical
|
|
343
|
-
- Y-axis: spend amount in dollars (will show as thousands: 98000, 128000, etc.)
|
|
344
|
-
- Height: 320px
|
|
345
|
-
- Bar color: Engine teal (#5BC8C8)
|
|
346
|
-
- Bar radius: 6 for rounded corners
|
|
347
|
-
- **Data transformation:** map `{ month, amount }` to `{ x, spend }` format inline
|
|
348
|
-
- responsive={true}
|
|
349
|
-
|
|
350
|
-
**Why this chart:** Shows spend trends over time so travel managers can spot anomalies, budget overruns, or seasonal patterns. Using bars instead of line because D3 lineChart requires numeric x-axis.
|
|
351
|
-
|
|
352
|
-
**That's it!** Only 4 panels total: Disruptions, Active Travelers, Escalations, and Monthly Spend Trend.
|
|
353
|
-
|
|
354
224
|
---
|
|
355
225
|
|
|
356
|
-
## 9. Eva — ChatBar
|
|
226
|
+
## 9. Eva — ChatBar (Phase 4)
|
|
357
227
|
|
|
358
|
-
|
|
228
|
+
ChatBar in the header. Not a FAB or sliding panel.
|
|
359
229
|
|
|
360
|
-
```
|
|
230
|
+
```tsx
|
|
361
231
|
<ChatBar
|
|
362
232
|
title="Eva"
|
|
363
233
|
placeholder="Ask about travelers, bookings, policy, spend…"
|
|
364
|
-
suggestions={
|
|
234
|
+
suggestions={CHAT_SUGGESTIONS}
|
|
365
235
|
onSend={handleChat}
|
|
366
236
|
/>
|
|
367
237
|
```
|
|
368
238
|
|
|
369
|
-
|
|
370
|
-
- "Who's traveling internationally right now?"
|
|
371
|
-
- "Show bookings pending approval"
|
|
372
|
-
- "What has Eva resolved today?"
|
|
373
|
-
- "Travelers returning this week"
|
|
239
|
+
Suggestions: "Who's traveling internationally right now?", "Show bookings pending approval", "What has Eva resolved today?", "Travelers returning this week"
|
|
374
240
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
**Handler:** Define `handleChat` and `CHAT_SUGGESTIONS` at module scope (outside the component body) so they can be shared if an "open in tab" feature is added later.
|
|
241
|
+
Define `handleChat` and `CHAT_SUGGESTIONS` at module scope.
|
|
378
242
|
|
|
379
243
|
---
|
|
380
244
|
|
|
381
|
-
## 10. Salesforce Signals (Phase 4
|
|
382
|
-
|
|
383
|
-
**⚠️ These are added in Phase 4, NOT Phase 1.** Phase 1 has only the Engine logo and "Travel Command Center" title.
|
|
245
|
+
## 10. Salesforce Signals (Phase 4)
|
|
384
246
|
|
|
385
|
-
Subtle
|
|
247
|
+
Subtle indicators, not banners.
|
|
386
248
|
|
|
387
|
-
| Signal | Location |
|
|
388
|
-
|
|
389
|
-
| "
|
|
390
|
-
| "
|
|
391
|
-
| "Powered by Agentforce" | ChatBar
|
|
249
|
+
| Signal | Location |
|
|
250
|
+
|--------|----------|
|
|
251
|
+
| "View in Salesforce" | Traveler expanded view, booking rows (micro-link, muted text) |
|
|
252
|
+
| "Salesforce updated" | After rebook/approve actions (`toast()`) |
|
|
253
|
+
| "Powered by Agentforce" | ChatBar subtitle area (small badge) |
|
|
392
254
|
|
|
393
255
|
---
|
|
394
256
|
|
|
395
257
|
## 11. Dark Mode
|
|
396
258
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
- Use the standard dark mode pairs from the builder rules (bg-white/dark:bg-slate-900, etc.)
|
|
400
|
-
- The GeoMap has built-in dark/light themes — pass `theme={mode === "dark" ? "dark" : "light"}`
|
|
401
|
-
- Glass overlays use `bg-black/40 backdrop-blur-md` which works in both modes
|
|
402
|
-
- Custom inline components (disruption cards, flight chips) must include `dark:` variants on every color class
|
|
403
|
-
- Never use `text-black` or `text-white` directly — use the slate scale
|
|
404
|
-
- Theme toggle button in the header (sun/moon icon)
|
|
259
|
+
Every element supports light and dark. GeoMap: `theme={mode === "dark" ? "dark" : "light"}`. Glass overlays work in both modes. Use slate scale (no `text-white` or `text-black`). Theme toggle in header.
|
|
405
260
|
|
|
406
261
|
---
|
|
407
262
|
|
|
408
263
|
## 12. Data Model
|
|
409
264
|
|
|
410
|
-
**Traveler** — `id`, `name`, `department`, `destination`, `origin`, `hotel`, `flight`, `return`, `
|
|
411
|
-
|
|
412
|
-
**
|
|
413
|
-
|
|
414
|
-
**
|
|
415
|
-
|
|
416
|
-
**Map Coordinates** — City name → `[lon, lat]` lookup object. Markers derived from coordinates. Arcs derived from flight origin/destination pairs.
|
|
417
|
-
|
|
418
|
-
**Booking** — `id`, `traveler`, `type`, `destination`, `dates`, `cost`, `status` (Confirmed | Pending approval), `policy` (In policy | Over budget | Exception granted)
|
|
419
|
-
|
|
420
|
-
**Policy Item** — `id`, `title`, `description`, `status` (operational | degraded), `timestamp`
|
|
421
|
-
|
|
422
|
-
**Escalation** — `id`, `title`, `subtitle`, `status` (complete | working | pending), `timestamp`
|
|
423
|
-
|
|
424
|
-
**Monthly Spend** — `{ month: string, amount: number }` array. Six months of travel spend data (Oct through Mar). Amounts in dollars, typically $98K-$156K range.
|
|
425
|
-
|
|
426
|
-
**Sample data:** 8–10 travelers, 8 flights, 4 disruptions, 8 bookings, 5 policy items, 8 escalations, 6 months of spend. All deterministic (no `Math.random()`). Include realistic names, routes, dollar amounts, and a mix of all status types.
|
|
265
|
+
- **Traveler** — `id`, `name`, `department`, `destination`, `origin`, `hotel`, `flight`, `return`, `policyStatus` (compliant | exception)
|
|
266
|
+
- **Flight** — `id`, `flight`, `route`, `dep`, `status` (On Time | Delayed | Boarding | In Air | Landed), `traveler`, `delayMin`
|
|
267
|
+
- **Disruption** — `id`, `flight`, `route`, `traveler`, `severity` (grounded | delayed), `delayMin`, `reason`, `evaAction`
|
|
268
|
+
- **Escalation** — `id`, `title`, `subtitle`, `status` (complete | working | pending), `timestamp`
|
|
269
|
+
- **Monthly Spend** — `{ month, amount }` array, 6 months (Oct–Mar), $98K–$156K range
|
|
270
|
+
- **Sample data:** Pre-built in `src/data/engine-sample-data.js`. 8 travelers, 8 flights, 4 disruptions, 8 escalations, 6 months spend. All deterministic.
|
|
427
271
|
|
|
428
272
|
---
|
|
429
273
|
|
|
430
274
|
## 13. Build Prompts
|
|
431
275
|
|
|
432
|
-
Build in 4 incremental phases.
|
|
433
|
-
|
|
434
|
-
---
|
|
276
|
+
Build in 4 incremental phases.
|
|
435
277
|
|
|
436
278
|
### Phase 1: Layout & Structure
|
|
437
279
|
|
|
438
280
|
> Scaffold the Engine Travel Command Center skeleton. Build the visualization-hero layout from section 5 with the header, hero map, glass KPI overlays, flight status strip, and placeholder cards for the data panels.
|
|
439
281
|
|
|
440
|
-
---
|
|
441
|
-
|
|
442
282
|
### Phase 2: Components & Sample Data
|
|
443
283
|
|
|
444
|
-
> Replace the placeholders with real components and wire up the sample data. Build the 4 data panels from section 8 — Disruptions, Active Travelers,
|
|
445
|
-
|
|
446
|
-
---
|
|
284
|
+
> Replace the placeholders with real components and wire up the sample data. Build the 4 data panels from section 8 — Escalations, Disruptions, Active Travelers, and Monthly Spend Trend. Add map markers, arcs, and overlays from the sample data so we can see where travelers are.
|
|
447
285
|
|
|
448
286
|
### Phase 3: Real Data Integration
|
|
449
287
|
|
|
450
288
|
> Connect the dashboard to live Salesforce data using GraphQL. Read the sample data file to see which fields are needed, then build queries and hooks for each object. The UI should stay identical — just swap the data source.
|
|
451
289
|
|
|
452
|
-
---
|
|
453
|
-
|
|
454
290
|
### Phase 4: Agentforce Integration
|
|
455
291
|
|
|
456
292
|
> Add Eva to the header as a ChatBar. Add subtle Salesforce signals throughout — "View in Salesforce" links, success toasts, "Powered by Agentforce" badge.
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
## 14. What NOT to Do
|
|
461
|
-
|
|
462
|
-
These are explicit anti-patterns. If any prompt output includes these, it must be corrected:
|
|
463
|
-
|
|
464
|
-
- Do not use `react-simple-maps`, Recharts, or any charting library other than the built-in `D3Chart` + `D3ChartTemplates`
|
|
465
|
-
- Do not use Lucide icons, Font Awesome, or any icon library other than Heroicons 2
|
|
466
|
-
- Do not import from `src/components/ui/` (shadcn) — use `@/components/library` exclusively
|
|
467
|
-
- Do not use `cn()` helper — that belongs to the outer app
|
|
468
|
-
- Do not recreate `AppThemeProvider`, `DataModeProvider`, or `Toast.Provider` — `CommandCenter.tsx` provides them
|
|
469
|
-
- Do not build a FAB or sliding chat panel — use `ChatBar` in the header
|
|
470
|
-
- Do not hardcode hex color values in component JSX — use `brand-*` Tailwind classes and Tailwind built-in colors for status
|
|
471
|
-
- Do not use `bg-indigo-*` for brand — use `brand-*`
|
|
472
|
-
- Do not use `text-black` or `text-white` — use the slate scale
|
|
473
|
-
- Do not put more than 4 KPIs in a row
|
|
474
|
-
- Do not squeeze the map into a grid column — it must be full-width hero
|
|
475
|
-
- Do not wrap GeoMap in ChartCard — render it directly
|
|
476
|
-
- Do not use `Math.random()` in sample data
|
|
477
|
-
- Do not skip dark mode on any visible element
|
|
478
|
-
- Do not use inline `style={{}}` for layout except the flex properties on the hero/panel containers
|
|
479
|
-
- Do not put `ChatPanel` in the dashboard grid
|
|
480
|
-
- Do not use `position: fixed` without `createPortal` to `document.body`
|
package/package.json
CHANGED