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