@schandlergarcia/sf-web-components 1.9.48 → 1.9.52

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/data/README.md CHANGED
@@ -7,12 +7,11 @@ This directory contains pre-packaged data assets for demo builds and prototyping
7
7
  ```
8
8
  data/
9
9
  ├── engine-sample-data.js # Engine Travel Command Center sample data
10
- └── README.md # This file
10
+ ├── schema.graphql # Pre-built GraphQL schema from sample data
11
+ └── README.md # This file
11
12
  ```
12
13
 
13
- ## Usage
14
-
15
- ### Engine Travel Command Center Sample Data
14
+ ## Engine Travel Command Center Sample Data
16
15
 
17
16
  **Purpose:** Pre-seeded, dashboard-ready data for the Engine Travel demo. All field names match the Salesforce org schema (Trip__c, Flight__c, Booking__c, Disruption__c, Rebooking_Action__c, Travel_Policy__c) so switching from sample → live queries requires only a data-source swap.
18
17
 
@@ -45,20 +44,9 @@ Dashboard-ready derivatives (pre-computed for immediate use):
45
44
  - `SPEND_CHART_DATA` — Spend trend line data
46
45
  - `METRICS` — Computed KPI metrics (active travelers, spend MTD, compliance rate, etc.)
47
46
 
48
- **Copy to webapp:**
49
-
50
- When building the Engine dashboard, copy this file to your webapp source:
51
-
52
- ```bash
53
- cp data/engine-sample-data.js force-app/main/default/webapplications/enginewebexperience/src/data/engine-sample-data.js
54
- ```
55
-
56
- Or if you're starting fresh:
47
+ **Installation:**
57
48
 
58
- ```bash
59
- # From project root
60
- cp data/engine-sample-data.js <your-webapp-path>/src/data/
61
- ```
49
+ Automatically installed to `src/data/engine-sample-data.js` by postinstall script.
62
50
 
63
51
  **Import in components:**
64
52
 
@@ -105,6 +93,81 @@ All sample data uses Salesforce API field names:
105
93
  - Custom fields: `Trip__c`, `Flight_Number__c`, `Departure_Airport__c`, `Status__c`, etc.
106
94
  - Relationships: `Contact__c`, `Trip__c`, `Impacted_Flight__c`
107
95
 
96
+ ## GraphQL Schema
97
+
98
+ **Purpose:** Pre-built GraphQL schema for Engine Travel Command Center. Works even when org introspection is broken.
99
+
100
+ **Problem it solves:**
101
+
102
+ Org introspection can fail with "cannot invoke FieldDataType.equals(Object) because the return value of Field.getDataType() is null". This breaks:
103
+ - `npm run graphql:schema` (introspection query)
104
+ - IDE autocomplete that queries org directly
105
+ - GraphQL codegen from org schema
106
+
107
+ But **queries still work** - introspection is just metadata.
108
+
109
+ **Solution:**
110
+
111
+ Pre-generate schema from sample data field names:
112
+ 1. Sample data already has correct Salesforce field names
113
+ 2. Generate `schema.graphql` from those field names
114
+ 3. Check schema into repo (automatically installed)
115
+ 4. GraphQL skills use the pre-built schema
116
+ 5. Queries execute normally using the same field names
117
+
118
+ **Installation:**
119
+
120
+ Automatically installed to `schema.graphql` (webapp root) by postinstall script.
121
+
122
+ **Contents:**
123
+
124
+ ```graphql
125
+ schema {
126
+ query: Query
127
+ }
128
+
129
+ type Query {
130
+ uiapi: UIAPI!
131
+ }
132
+
133
+ type UIAPI {
134
+ query: UIAPIQuery!
135
+ }
136
+
137
+ type UIAPIQuery {
138
+ Contact(first: Int, after: String, where: ContactFilter): ContactConnection
139
+ Trip__c(first: Int, after: String, where: Trip__cFilter): Trip__cConnection
140
+ Flight__c(first: Int, after: String, where: Flight__cFilter): Flight__cConnection
141
+ Booking__c(first: Int, after: String, where: Booking__cFilter): Booking__cConnection
142
+ Disruption__c(first: Int, after: String, where: Disruption__cFilter): Disruption__cConnection
143
+ Rebooking_Action__c(first: Int, after: String, where: Rebooking_Action__cFilter): Rebooking_Action__cConnection
144
+ Travel_Policy__c(first: Int, after: String, where: Travel_Policy__cFilter): Travel_Policy__cConnection
145
+ }
146
+
147
+ # ... Full schema with all types, connections, filters
148
+ ```
149
+
150
+ **What this enables:**
151
+
152
+ - ✅ `exploring-webapp-graphql-schema` skill works normally
153
+ - ✅ `generating-webapp-graphql-read-query` skill works normally
154
+ - ✅ `using-webapp-graphql` skill works normally
155
+ - ✅ IDE autocomplete and validation
156
+ - ✅ GraphQL codegen
157
+ - ✅ Normal Phase 3 workflow without manual workarounds
158
+ - ✅ Works in CI/CD without org access
159
+
160
+ **Regenerating:**
161
+
162
+ If you add new fields to sample data:
163
+
164
+ ```bash
165
+ # From the webapp directory
166
+ npm run graphql:schema:sample
167
+ ```
168
+
169
+ This regenerates `schema.graphql` from the current sample data file. Then commit the updated schema to git.
170
+
108
171
  ## Adding New Data Assets
109
172
 
110
173
  When adding new sample data:
@@ -0,0 +1,436 @@
1
+ # Engine Travel Command Center
2
+
3
+ Product Requirements Document · TDX26 Demo Build
4
+
5
+ **Required skills:** `command-center-builder`, `command-center-project`, `component-library`, `outer-app`
6
+
7
+ ---
8
+
9
+ ## 1. Product Overview
10
+
11
+ 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
+
13
+ It is not Engine's consumer-facing booking app. It is a personalized command center for one travel manager at one company.
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.
16
+
17
+ ---
18
+
19
+ ## 2. Users
20
+
21
+ **Primary — Sarah Chen, Travel Manager at Acme Corp**
22
+ Manages Acme's travel program: bookings, policy enforcement, exceptions, traveler monitoring. Before this dashboard she worked across Engine's booking interface, email, and Salesforce separately.
23
+
24
+ **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 in the dashboard via `ChatBar` (command palette).
26
+
27
+ ---
28
+
29
+ ## 3. Brand Tokens
30
+
31
+ Update `src/styles/global.css` — replace the existing `--color-brand-*` palette inside the `@theme inline` block. Do not add new CSS variables or custom properties outside this block.
32
+
33
+ ```css
34
+ /* Engine teal brand palette */
35
+ --color-brand-50: #ECFDF9;
36
+ --color-brand-100: #D1FAF0;
37
+ --color-brand-200: #A7F3E1;
38
+ --color-brand-300: #6EE7C8;
39
+ --color-brand-400: #34D3AB;
40
+ --color-brand-500: #5BC8C8;
41
+ --color-brand-600: #0D9488;
42
+ --color-brand-700: #0F766E;
43
+ --color-brand-800: #115E59;
44
+ --color-brand-900: #134E4A;
45
+ --color-brand-950: #042F2E;
46
+ ```
47
+
48
+ Additionally, add a custom `--color-engine-savings` token for the green savings accent:
49
+
50
+ ```css
51
+ --color-engine-savings: #16A34A;
52
+ ```
53
+
54
+ All component styling uses `brand-*` Tailwind classes for primary UI and Tailwind built-in colors (green, amber, red) for status. No hardcoded hex values in components. No `bg-indigo-*` or raw color classes for brand elements.
55
+
56
+ **Typography:** Inter (already configured as `--font-sans` in global.css). No changes needed.
57
+
58
+ **Icons:** Heroicons 2 exclusively (`@heroicons/react`). No Lucide, Font Awesome, or other libraries inside command center pages.
59
+
60
+ ---
61
+
62
+ ## 4. Architecture
63
+
64
+ **Dashboard file:** `src/pages/EngineDashboard.tsx` (single file, `.tsx` — TypeScript project, React components MUST use `.tsx`)
65
+
66
+ **Wiring:** `CommandCenter.tsx` imports and renders `EngineDashboard` inside the existing provider stack (`heroui-scope` → `AppThemeProvider` → `DataModeProvider` → `Toast.Provider`). Never recreate these providers in the dashboard.
67
+
68
+ **Imports:** All components from `@/components/library` barrel. Theme access from `@/components/library/theme/AppThemeProvider`.
69
+
70
+ ---
71
+
72
+ ## 5. Layout — Visualization-Hero Pattern
73
+
74
+ This dashboard uses the **visualization-hero** layout. The live flight map is the signature element.
75
+
76
+ ### Structure (top to bottom)
77
+
78
+ ```
79
+ ┌─────────────────────────────────────────────────────────────┐
80
+ │ HEADER BAR (h-12, sticky) │
81
+ │ Engine logo + "Travel Command Center" | ChatBar | actions │
82
+ ├─────────────────────────────────────────────────────────────┤
83
+ │ HERO MAP (flex: 1.15 1 0, GeoMap, dark theme) │
84
+ │ │
85
+ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
86
+ │ │ KPI │ │ KPI │ │ KPI │ │ KPI │ ← glass │
87
+ │ │ overlay │ │ overlay │ │ overlay │ │ overlay │ overlays │
88
+ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
89
+ │ │
90
+ │ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ← flight │
91
+ │ │ BA286 │ │ NH109 │ │ LH431 │ │ SQ 37 │ status │
92
+ │ └───────┘ └───────┘ └───────┘ └───────┘ strip │
93
+ ├─────────────────────────────────────────────────────────────┤
94
+ │ DATA PANELS (flex: 1 1 0, px-4 py-5, space-y-6) │
95
+ │ │
96
+ │ ┌─── 1/3 ───────┐ ┌─── 2/3 ────────────────────┐ │
97
+ │ │ Disruptions │ │ Active Travelers │ │
98
+ │ │ (custom panel) │ │ (expandable cards, scroll) │ │
99
+ │ └────────────────┘ └────────────────────────────┘ │
100
+ │ │
101
+ │ ┌─── 1/2 ───────┐ ┌─── 1/2 ────────────────────┐ │
102
+ │ │ Eva Activity │ │ Travelers by Destination │ │
103
+ │ │ (ActivityCard) │ │ (ChartCard + D3Chart bar) │ │
104
+ │ └────────────────┘ └────────────────────────────┘ │
105
+ │ │
106
+ │ ┌─── full width ────────────────────────────────┐ │
107
+ │ │ Upcoming Bookings (TableCard, searchable, │ │
108
+ │ │ sortable, paginated) │ │
109
+ │ └────────────────────────────────────────────────┘ │
110
+ │ │
111
+ │ ┌─── 1/2 ───────┐ ┌─── 1/2 ────────────────────┐ │
112
+ │ │ Policy Status │ │ Monthly Travel Spend │ │
113
+ │ │ (StatusCard) │ │ (ChartCard + D3Chart line) │ │
114
+ │ └────────────────┘ └────────────────────────────┘ │
115
+ └─────────────────────────────────────────────────────────────┘
116
+ ```
117
+
118
+ ### Layout Rules
119
+
120
+ - Hero map: `<div className="relative" style={{ flex: "1.15 1 0", minHeight: 0 }}>`
121
+ - Data panels: `style={{ flex: "1 1 0" }}` with `px-4 py-5` and `space-y-6`
122
+ - Disruptions + Travelers: `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` (disruptions 1/3, travelers `lg:col-span-2`)
123
+ - Eva + Chart: `grid grid-cols-1 items-start gap-4 lg:grid-cols-2`
124
+ - Bookings table: full width
125
+ - Policy + Spend: `grid grid-cols-1 items-start gap-4 lg:grid-cols-2`
126
+ - All grids use `items-start` for different-height cards
127
+
128
+ ### Phase 1 Placeholder Rules
129
+
130
+ For skeleton/placeholder cards (Phase 1 only):
131
+
132
+ **Data panel placeholders** use `BaseCard` with centered text:
133
+
134
+ ```tsx
135
+ // ✅ Correct data panel placeholder
136
+ <BaseCard>
137
+ <div className="h-48 flex items-center justify-center text-slate-400">
138
+ Disruptions Panel
139
+ </div>
140
+ </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, useAppTheme } from "@/components/library";
153
+
154
+ export default function EngineDashboard() {
155
+ const { mode } = useAppTheme();
156
+
157
+ return (
158
+ <div className="relative" style={{ flex: "1.15 1 0", minHeight: 0 }}>
159
+ <GeoMap
160
+ width={960}
161
+ height={520}
162
+ theme={mode === "dark" ? "dark" : "light"}
163
+ className="h-full w-full"
164
+ />
165
+ </div>
166
+ );
167
+ }
168
+ ```
169
+
170
+ In Phase 1:
171
+ - GeoMap renders with NO markers, arcs, or overlays props
172
+ - Uses `useAppTheme()` to get dark/light mode for theme prop
173
+
174
+ // ❌ Wrong - wrapped in BaseCard
175
+ <div className="relative" style={{ flex: "1.15 1 0", minHeight: 0 }}>
176
+ <BaseCard>
177
+ <GeoMap ... />
178
+ </BaseCard>
179
+ </div>
180
+
181
+ // ❌ Wrong - text placeholder instead of GeoMap component
182
+ <div className="relative" style={{ flex: "1.15 1 0", minHeight: 0 }}>
183
+ <div className="flex h-full items-center justify-center bg-slate-100 dark:bg-slate-900">
184
+ <span className="text-slate-400">Hero Map (GeoMap)</span>
185
+ </div>
186
+ </div>
187
+ ```
188
+
189
+ All data panel placeholders use: BaseCard, no title, centered text, `h-48`, `text-slate-400`.
190
+
191
+ Hero map uses: actual GeoMap component (no markers/arcs/overlays in Phase 1), direct render, fills hero container.
192
+
193
+ ---
194
+
195
+ ## 6. Header
196
+
197
+ Compact `h-12` sticky header with dark background (`bg-slate-900 dark:bg-slate-950`).
198
+
199
+ | Position | Content |
200
+ |----------|---------|
201
+ | Left | Engine logo (small square icon with `GlobeAltIcon` in `bg-brand-600`) + "ENGINE" wordmark + separator + "Travel Command Center" |
202
+ | Right | `ChatBar` (Eva) + notification bell (with pending count badge) + theme toggle (sun/moon) |
203
+
204
+ The `ChatBar` replaces any FAB or sliding panel. It opens inline as a command palette overlay.
205
+
206
+ ---
207
+
208
+ ## 7. Hero Map
209
+
210
+ **Component:** `GeoMap` (from `@/components/library`)
211
+
212
+ ```jsx
213
+ <GeoMap
214
+ width={960}
215
+ height={520}
216
+ theme={mode === "dark" ? "dark" : "light"}
217
+ markers={markers}
218
+ arcs={arcs}
219
+ overlays={overlays}
220
+ zoomable
221
+ className="h-full w-full"
222
+ />
223
+ ```
224
+
225
+ **Markers:** One per city (origin and destination). Each marker: `{ id, lon, lat, label, active: true }`.
226
+
227
+ **Arcs:** One per active flight route. Each arc: `{ id, from: [lon, lat], to: [lon, lat], progress: 0–1 }`. Set `danger: true` on disrupted routes (delayed 60+ min or grounded). The `progress` value places an animated pulsing dot showing the flight's current position along the great circle arc.
228
+
229
+ **Overlays:** Weather/disruption zones as pulsing circles. Each overlay: `{ id, center: [lon, lat], radius: number }`.
230
+
231
+ **Glass KPI overlays:** Four pills floating `absolute left-3 top-3` on the map:
232
+ - Active Travelers (count)
233
+ - Spend MTD (formatted with `fmtK()`)
234
+ - Compliance %
235
+ - Eva Resolved (count + "resolved")
236
+
237
+ Each pill: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5` with white text and icon.
238
+
239
+ **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.
240
+
241
+ ---
242
+
243
+ ## 8. Data Panels
244
+
245
+ ### 8a. Disruptions Panel (1/3 width)
246
+
247
+ Custom inline component inside a `BaseCard`. Shows only flights that are delayed 60+ min or grounded.
248
+
249
+ Each disruption card:
250
+ - Severity dot (rose for grounded, amber for delayed) + flight number + severity label + delay minutes
251
+ - Route + affected traveler name
252
+ - Reason text
253
+ - Eva action line with `SparklesIcon` showing what Eva is doing about it
254
+
255
+ ### 8b. Active Travelers (2/3 width)
256
+
257
+ `BaseCard` with `maxBodyHeight={420}` for internal scroll. Expandable traveler cards.
258
+
259
+ Each traveler row:
260
+ - `Avatar` (initials) + name + department + origin → destination
261
+ - `UIChip` for policy status (success = compliant, warning = exception)
262
+ - Click to expand: 4-col grid showing Flight, Hotel, Return date, Destination
263
+
264
+ ### 8c. Eva Activity (1/2 width)
265
+
266
+ `ActivityCard` showing Eva's autonomous actions. Each action has:
267
+ - Title (what Eva did)
268
+ - Subtitle (details + savings/context)
269
+ - Status: `"complete"` or `"working"`
270
+ - Timestamp
271
+
272
+ ### 8d. Travelers by Destination (1/2 width)
273
+
274
+ `ChartCard` wrapping a `D3Chart` with `D3ChartTemplates.groupedBarChart`.
275
+ - X-axis: destination city names (categorical — use `scaleBand`, not `scaleLinear`)
276
+ - Y-axis: traveler count
277
+ - Height: 280px
278
+ - `responsive={true}`
279
+
280
+ ### 8e. Upcoming Bookings (full width)
281
+
282
+ `TableCard` with columns: Traveler, Type, Route, Dates, Cost, Status, Policy.
283
+ - `sortable`, `searchable`, `paginated`, `pageSize={5}`
284
+ - Status column: custom render with colored chips (Confirmed = green, Pending = amber)
285
+ - Policy column: `UIChip` with semantic tones (success/danger/warning)
286
+
287
+ ### 8f. Policy Compliance (1/2 width)
288
+
289
+ `StatusCard` with policy rule items. Each item: `{ title, description, status, timestamp }`.
290
+ - Status uses canonical values: `"operational"`, `"degraded"`
291
+ - `showTimestamp` and `showProgress` enabled
292
+
293
+ ### 8g. Monthly Travel Spend (1/2 width)
294
+
295
+ `ChartCard` wrapping a `D3Chart` with `D3ChartTemplates.lineChart`.
296
+ - X-axis: month labels (Oct–Mar)
297
+ - Y-axis: dollar amounts
298
+ - Height: 240px
299
+ - `responsive={true}`
300
+
301
+ ---
302
+
303
+ ## 9. Eva — ChatBar
304
+
305
+ Eva surfaces as a `ChatBar` in the header. Not a FAB. Not a sliding panel. Not a `ChatPanel` in the grid.
306
+
307
+ ```jsx
308
+ <ChatBar
309
+ title="Eva"
310
+ placeholder="Ask about travelers, bookings, policy, spend…"
311
+ suggestions={suggestions}
312
+ onSend={handleChat}
313
+ />
314
+ ```
315
+
316
+ **Starter suggestions (3–5):**
317
+ - "Who's traveling internationally right now?"
318
+ - "Show bookings pending approval"
319
+ - "What has Eva resolved today?"
320
+ - "Travelers returning this week"
321
+
322
+ **Agent responses:** Return structured `components` arrays for data (MetricCard, DataTable, StatusCard) — never markdown tables in text content.
323
+
324
+ **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.
325
+
326
+ ---
327
+
328
+ ## 10. Salesforce Signals
329
+
330
+ Subtle, contextual indicators — like "Sent from iPhone", not promotional banners.
331
+
332
+ | Signal | Location | Implementation |
333
+ |--------|----------|----------------|
334
+ | "Powered by Salesforce Data Cloud" | Header subtitle, next to "Travel Command Center" | `UIText` size xs, muted |
335
+ | "Powered by Salesforce Data Cloud" | Glass KPI overlay or header area | White/translucent text |
336
+ | "☁ View in Salesforce" | Traveler expanded view, booking rows | Micro-link, muted text |
337
+ | "✓ Salesforce updated" | After rebook/approve actions | `toast()` with success tone |
338
+ | "Powered by Agentforce" | ChatBar title or subtitle area | Small badge/chip |
339
+ | "Last synced · Data Cloud" | Footer or header timestamp | Ticking timestamp, muted |
340
+
341
+ ---
342
+
343
+ ## 11. Dark Mode
344
+
345
+ Mandatory on every element. The dashboard must work in both light and dark mode with no visual bugs.
346
+
347
+ - Use the standard dark mode pairs from the builder rules (bg-white/dark:bg-slate-900, etc.)
348
+ - The GeoMap has built-in dark/light themes — pass `theme={mode === "dark" ? "dark" : "light"}`
349
+ - Glass overlays use `bg-black/40 backdrop-blur-md` which works in both modes
350
+ - Custom inline components (disruption cards, flight chips) must include `dark:` variants on every color class
351
+ - Never use `text-black` or `text-white` directly — use the slate scale
352
+ - Theme toggle button in the header (sun/moon icon)
353
+
354
+ ---
355
+
356
+ ## 12. Data Model
357
+
358
+ **Traveler** — `id`, `name`, `department`, `destination`, `origin`, `hotel`, `flight`, `return`, `status`, `policyStatus` (compliant | exception)
359
+
360
+ **Flight** — `id`, `flight` (number), `route`, `dep` (time), `status` (On Time | Delayed | Boarding | In Air | Landed), `traveler`, `delayMin`
361
+
362
+ **Disruption** — `id`, `flight`, `route`, `traveler`, `severity` (grounded | delayed), `delayMin`, `reason`, `evaAction`
363
+
364
+ **Map Coordinates** — City name → `[lon, lat]` lookup object. Markers derived from coordinates. Arcs derived from flight origin/destination pairs.
365
+
366
+ **Booking** — `id`, `traveler`, `type`, `destination`, `dates`, `cost`, `status` (Confirmed | Pending approval), `policy` (In policy | Over budget | Exception granted)
367
+
368
+ **Policy Item** — `id`, `title`, `description`, `status` (operational | degraded), `timestamp`
369
+
370
+ **Eva Action** — `id`, `title`, `subtitle`, `status` (complete | working), `timestamp`
371
+
372
+ **Monthly Spend** — `{ x: month, y: amount }` array
373
+
374
+ **Destination Chart** — `{ x: city, travelers: count }` array
375
+
376
+ **Sample data:** 8–10 travelers, 8 flights, 4 disruptions, 8 bookings, 5 policy items, 8 Eva actions, 6 months of spend. All deterministic (no `Math.random()`). Include realistic names, routes, dollar amounts, and a mix of all status types.
377
+
378
+ ---
379
+
380
+ ## 13. Build Prompts
381
+
382
+ **Build Methodology:** 4-phase incremental process (Layout → Components → Data → Agent). Run prompts in sequence. All detailed instructions are in the skills and PRD — the phase prompts should be simple triggers.
383
+
384
+ ---
385
+
386
+ ### Phase 1: Layout & Structure
387
+
388
+ > **Skills:** command-center-builder, command-center-project, component-library, outer-app
389
+ >
390
+ > Scaffold the Engine Travel Command Center skeleton. Build the structure from section 5 (visualization-hero layout) with placeholder cards. No real data or components yet, just the layout structure.
391
+
392
+ ---
393
+
394
+ ### Phase 2: Components & Sample Data
395
+
396
+ > **Skills:** command-center-builder, command-center-project, component-library
397
+ >
398
+ > Replace placeholders with library components. Import data from the pre-existing `src/data/engine-sample-data.js` file. Build all panels from section 8.
399
+
400
+ ---
401
+
402
+ ### Phase 3: Real Data Integration
403
+
404
+ > Use the Salesforce GraphQL skills to connect the dashboard to live data. Read `src/data/engine-sample-data.js` to see which fields are needed, then use the skills to implement queries and hooks for Contact, Trip__c, Flight__c, Booking__c, Disruption__c, and Rebooking_Action__c. Update EngineDashboard.tsx to use live data with `useDataSource({ sample: X, live: liveData })`. Add loading and error states. UI stays identical - live data only, no toggle needed.
405
+
406
+ ---
407
+
408
+ ### Phase 4: Agentforce Integration
409
+
410
+ > **Skills:** command-center-builder, command-center-project, component-library
411
+ >
412
+ > Add Eva ChatBar to header. Add Salesforce signals throughout. Configure tool calls for filtering/highlighting. Fallback mode if Eva not configured.
413
+
414
+ ---
415
+
416
+ ## 14. What NOT to Do
417
+
418
+ These are explicit anti-patterns. If any prompt output includes these, it must be corrected:
419
+
420
+ - Do not use `react-simple-maps`, Recharts, or any charting library other than the built-in `D3Chart` + `D3ChartTemplates`
421
+ - Do not use Lucide icons, Font Awesome, or any icon library other than Heroicons 2
422
+ - Do not import from `src/components/ui/` (shadcn) — use `@/components/library` exclusively
423
+ - Do not use `cn()` helper — that belongs to the outer app
424
+ - Do not recreate `AppThemeProvider`, `DataModeProvider`, or `Toast.Provider` — `CommandCenter.tsx` provides them
425
+ - Do not build a FAB or sliding chat panel — use `ChatBar` in the header
426
+ - Do not hardcode hex color values in component JSX — use `brand-*` Tailwind classes and Tailwind built-in colors for status
427
+ - Do not use `bg-indigo-*` for brand — use `brand-*`
428
+ - Do not use `text-black` or `text-white` — use the slate scale
429
+ - Do not put more than 4 KPIs in a row
430
+ - Do not squeeze the map into a grid column — it must be full-width hero
431
+ - Do not wrap GeoMap in ChartCard — render it directly
432
+ - Do not use `Math.random()` in sample data
433
+ - Do not skip dark mode on any visible element
434
+ - Do not use inline `style={{}}` for layout except the flex properties on the hero/panel containers
435
+ - Do not put `ChatPanel` in the dashboard grid
436
+ - Do not use `position: fixed` without `createPortal` to `document.body`