@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/.a4drules/features/command-center-dashboard-rule.md +20 -7
- package/.a4drules/features/engine-dashboard-rule.md +302 -0
- package/.a4drules/features/phase2-data-pattern.md +166 -0
- package/.a4drules/features/pre-code-checklist.md +72 -0
- package/.a4drules/skills/command-center-builder/SKILL.md +635 -29
- package/.a4drules/skills/command-center-project/SKILL.md +4 -4
- package/.a4drules/skills/component-library/SKILL.md +1000 -27
- package/.a4drules/troubleshooting/graphql-introspection-failure.md +286 -0
- package/.a4drules/validation-requirements.md +211 -0
- package/.a4drules/webapp-data.md +353 -0
- package/.a4drules/webapp-ui.md +16 -0
- package/CHANGELOG.md +258 -0
- package/data/README.md +80 -17
- package/data/engine-command-center-prd.md +436 -0
- package/data/schema.graphql +292 -0
- package/package.json +1 -1
- package/scripts/generate-schema-from-sample.mjs +370 -0
- package/scripts/postinstall.mjs +94 -0
- package/scripts/reset-command-center.sh +317 -3
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
|
-
|
|
10
|
+
├── schema.graphql # Pre-built GraphQL schema from sample data
|
|
11
|
+
└── README.md # This file
|
|
11
12
|
```
|
|
12
13
|
|
|
13
|
-
##
|
|
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
|
-
**
|
|
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
|
-
|
|
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`
|