@schandlergarcia/sf-web-components 1.9.64 → 1.9.65
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/CHANGELOG.md
CHANGED
|
@@ -5,15 +5,7 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [1.9.
|
|
9
|
-
|
|
10
|
-
### Added
|
|
11
|
-
- **New phase-based build system** - Self-contained step-by-step build instructions
|
|
12
|
-
- `.a4drules/phases/phase-1-layout.md` - Layout setup with code template
|
|
13
|
-
- `.a4drules/phases/phase-2-components.md` - Component implementation with exact imports
|
|
14
|
-
- `.a4drules/phases/phase-3-live-data.md` - GraphQL integration
|
|
15
|
-
- `.a4drules/phases/phase-4-agent.md` - Eva ChatBar implementation
|
|
16
|
-
- These phase files replace the scattered instructions in multiple skill/feature files
|
|
8
|
+
## [1.9.65] - 2026-04-01
|
|
17
9
|
|
|
18
10
|
### Fixed
|
|
19
11
|
- **6 data bugs in engine-sample-data.js**:
|
|
@@ -27,20 +19,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
27
19
|
### Updated
|
|
28
20
|
- **PRD (engine-command-center-prd.md)**:
|
|
29
21
|
- Fixed "Sarah Chen" → "Priya Patel" in section 8c escalation example
|
|
30
|
-
-
|
|
22
|
+
- Updated section 13 build prompts
|
|
31
23
|
- **Simplified .a4drules documentation** - Removed redundancy and contradictions:
|
|
32
|
-
- `features/engine-dashboard-rule.md` - Reduced from 310 to ~65 lines (non-negotiable constraints
|
|
24
|
+
- `features/engine-dashboard-rule.md` - Reduced from 310 to ~65 lines (non-negotiable constraints)
|
|
33
25
|
- `features/command-center-dashboard-rule.md` - Reduced from ~100 to ~30 lines (10 core constraints)
|
|
34
26
|
- `features/pre-code-checklist.md` - Reduced from 216 to ~25 lines (removed auto-load)
|
|
35
|
-
- `features/phase2-data-pattern.md` - Reduced from 167 to ~20 lines
|
|
27
|
+
- `features/phase2-data-pattern.md` - Reduced from 167 to ~20 lines
|
|
36
28
|
- `skills/command-center-builder/SKILL.md` - Fixed map layout contradiction, removed validator
|
|
37
29
|
- `skills/command-center-builder/page-layout.md` - Fixed map layout contradiction
|
|
38
30
|
- `skills/command-center-builder/completion-checklist.md` - Replaced validator "MUST run" with "DO NOT run"
|
|
39
|
-
- `skills/command-center-builder/improved-build-process.md` - Reduced from 341 to ~30 lines
|
|
31
|
+
- `skills/command-center-builder/improved-build-process.md` - Reduced from 341 to ~30 lines
|
|
40
32
|
- `skills/command-center-project/SKILL.md` - Fixed file path contradiction (src/components/pages/ → src/pages/)
|
|
41
33
|
- `skills/command-center-guide/SKILL.md` - Reduced from 270 to ~45 lines (simplified routing guide)
|
|
42
34
|
|
|
43
|
-
**Context:**
|
|
35
|
+
**Context:** Streamlined documentation to eliminate confusion caused by scattered, contradictory guidance across multiple files.
|
|
36
|
+
|
|
37
|
+
## [1.9.64] - 2026-04-01
|
|
38
|
+
|
|
39
|
+
### Updated
|
|
40
|
+
- **Documentation improvements** - Synced latest changes from react-cursor-1 including data bug fixes and simplified .a4drules structure
|
|
44
41
|
|
|
45
42
|
## [1.9.63] - 2026-04-01
|
|
46
43
|
|
package/package.json
CHANGED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: engine-phase-1-layout
|
|
3
|
-
description: >-
|
|
4
|
-
Phase 1 of the Engine Travel Command Center build. Creates the complete layout
|
|
5
|
-
skeleton with header, hero map, glass overlays, flight strip, and placeholder
|
|
6
|
-
data panels. Use this when the build prompt says "Phase 1" or "scaffold".
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Phase 1: Layout & Structure
|
|
10
|
-
|
|
11
|
-
**Source of truth:** `engine-command-center-prd.md` (sections 3–6)
|
|
12
|
-
|
|
13
|
-
**Goal:** Build the complete layout skeleton in one file. The hero map, glass KPI overlays, and flight status strip are real — only the 4 data panels below are placeholders.
|
|
14
|
-
|
|
15
|
-
## File Setup
|
|
16
|
-
|
|
17
|
-
Create `src/pages/EngineDashboard.tsx` (.tsx, NOT .jsx).
|
|
18
|
-
|
|
19
|
-
## Code Template
|
|
20
|
-
|
|
21
|
-
Copy this template, then fill in the `{/* TODO */}` sections using the PRD:
|
|
22
|
-
|
|
23
|
-
```tsx
|
|
24
|
-
import { GeoMap, BaseCard } from "@/components/library";
|
|
25
|
-
import { useThemeMode } from "@/components/library/theme/AppThemeProvider";
|
|
26
|
-
import {
|
|
27
|
-
GlobeAltIcon,
|
|
28
|
-
SunIcon,
|
|
29
|
-
MoonIcon,
|
|
30
|
-
BellIcon,
|
|
31
|
-
UsersIcon,
|
|
32
|
-
BanknotesIcon,
|
|
33
|
-
ShieldCheckIcon,
|
|
34
|
-
SparklesIcon,
|
|
35
|
-
} from "@heroicons/react/24/outline";
|
|
36
|
-
|
|
37
|
-
export default function EngineDashboard() {
|
|
38
|
-
const { mode, toggle } = useThemeMode();
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<div className="flex flex-col bg-slate-50 dark:bg-slate-950">
|
|
42
|
-
{/* ── HEADER BAR ─────────────────────────────────────────── */}
|
|
43
|
-
<header className="sticky top-0 z-50 flex h-12 items-center justify-between border-b border-slate-800 bg-slate-900 dark:bg-slate-950 px-4">
|
|
44
|
-
{/* Left: logo + title */}
|
|
45
|
-
<div className="flex items-center gap-2">
|
|
46
|
-
<div className="flex h-7 w-7 items-center justify-center rounded-md bg-brand-600">
|
|
47
|
-
<GlobeAltIcon className="h-4 w-4 text-slate-50" />
|
|
48
|
-
</div>
|
|
49
|
-
<span className="text-sm font-bold tracking-wider text-slate-50">ENGINE</span>
|
|
50
|
-
<span className="mx-2 h-4 w-px bg-slate-700" />
|
|
51
|
-
<span className="text-sm font-medium text-slate-300">Travel Command Center</span>
|
|
52
|
-
</div>
|
|
53
|
-
{/* Right: actions */}
|
|
54
|
-
<div className="flex items-center gap-3">
|
|
55
|
-
{/* ChatBar goes here in Phase 4 */}
|
|
56
|
-
<button className="relative text-slate-400 hover:text-slate-200">
|
|
57
|
-
<BellIcon className="h-5 w-5" />
|
|
58
|
-
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-rose-500 text-[10px] font-bold text-slate-50">3</span>
|
|
59
|
-
</button>
|
|
60
|
-
<button onClick={toggle} className="text-slate-400 hover:text-slate-200">
|
|
61
|
-
{mode === "dark" ? <SunIcon className="h-5 w-5" /> : <MoonIcon className="h-5 w-5" />}
|
|
62
|
-
</button>
|
|
63
|
-
</div>
|
|
64
|
-
</header>
|
|
65
|
-
|
|
66
|
-
{/* ── HERO MAP ───────────────────────────────────────────── */}
|
|
67
|
-
<div className="relative h-[520px]">
|
|
68
|
-
<GeoMap
|
|
69
|
-
width={960}
|
|
70
|
-
height={520}
|
|
71
|
-
theme={mode === "dark" ? "dark" : "light"}
|
|
72
|
-
className="h-full w-full"
|
|
73
|
-
/>
|
|
74
|
-
|
|
75
|
-
{/* Glass KPI overlays — 4 pills, absolute top-left */}
|
|
76
|
-
<div className="absolute left-3 top-3 flex flex-wrap gap-2">
|
|
77
|
-
{[
|
|
78
|
-
{ icon: UsersIcon, label: "Active Travelers", value: "8" },
|
|
79
|
-
{ icon: BanknotesIcon, label: "Spend MTD", value: "$128.4K" },
|
|
80
|
-
{ icon: ShieldCheckIcon, label: "Compliance", value: "75%" },
|
|
81
|
-
{ icon: SparklesIcon, label: "Eva Resolved", value: "6 resolved" },
|
|
82
|
-
].map((kpi) => (
|
|
83
|
-
<div
|
|
84
|
-
key={kpi.label}
|
|
85
|
-
className="flex items-center gap-2 rounded-lg border border-white/10 bg-black/40 px-3 py-1.5 backdrop-blur-md"
|
|
86
|
-
>
|
|
87
|
-
<kpi.icon className="h-4 w-4 text-brand-400" />
|
|
88
|
-
<div>
|
|
89
|
-
<div className="text-[10px] uppercase tracking-wider text-slate-300">{kpi.label}</div>
|
|
90
|
-
<div className="text-sm font-semibold text-slate-50">{kpi.value}</div>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
))}
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
{/* Flight status strip — absolute bottom */}
|
|
97
|
-
<div className="absolute bottom-3 left-3 right-3 flex gap-2 overflow-x-auto">
|
|
98
|
-
{[
|
|
99
|
-
{ flight: "BA 286", route: "SFO → LHR", status: "In Air" },
|
|
100
|
-
{ flight: "NH 109", route: "JFK → NRT", status: "In Air" },
|
|
101
|
-
{ flight: "LH 431", route: "ORD → BER", status: "Delayed" },
|
|
102
|
-
{ flight: "SQ 37", route: "LAX → SIN", status: "Boarding" },
|
|
103
|
-
].map((f) => (
|
|
104
|
-
<div
|
|
105
|
-
key={f.flight}
|
|
106
|
-
className="flex shrink-0 items-center gap-2 rounded-lg border border-white/10 bg-black/40 px-3 py-1.5 backdrop-blur-md"
|
|
107
|
-
>
|
|
108
|
-
<span className="text-sm font-medium text-slate-50">{f.flight}</span>
|
|
109
|
-
<span className="text-xs text-slate-400">{f.route}</span>
|
|
110
|
-
<span
|
|
111
|
-
className={`rounded-full px-2 py-0.5 text-[10px] font-semibold ${
|
|
112
|
-
f.status === "In Air" ? "bg-green-500/20 text-green-400" :
|
|
113
|
-
f.status === "Delayed" ? "bg-amber-500/20 text-amber-400" :
|
|
114
|
-
f.status === "Boarding" ? "bg-sky-500/20 text-sky-400" :
|
|
115
|
-
"bg-slate-500/20 text-slate-400"
|
|
116
|
-
}`}
|
|
117
|
-
>
|
|
118
|
-
{f.status}
|
|
119
|
-
</span>
|
|
120
|
-
</div>
|
|
121
|
-
))}
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
|
-
{/* ── DATA PANELS (placeholders) ─────────────────────────── */}
|
|
126
|
-
<div className="px-4 py-5">
|
|
127
|
-
<div className="space-y-6">
|
|
128
|
-
{/* Row 1: Disruptions (1/3) + Active Travelers (2/3) */}
|
|
129
|
-
<div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-3">
|
|
130
|
-
<BaseCard>
|
|
131
|
-
<div className="flex h-48 items-center justify-center text-slate-400">
|
|
132
|
-
Disruptions Panel
|
|
133
|
-
</div>
|
|
134
|
-
</BaseCard>
|
|
135
|
-
<div className="lg:col-span-2">
|
|
136
|
-
<BaseCard>
|
|
137
|
-
<div className="flex h-48 items-center justify-center text-slate-400">
|
|
138
|
-
Active Travelers Panel
|
|
139
|
-
</div>
|
|
140
|
-
</BaseCard>
|
|
141
|
-
</div>
|
|
142
|
-
</div>
|
|
143
|
-
|
|
144
|
-
{/* Row 2: Escalations (1/2) + Monthly Spend Chart (1/2) */}
|
|
145
|
-
<div className="grid grid-cols-1 items-start gap-4 lg:grid-cols-2">
|
|
146
|
-
<BaseCard>
|
|
147
|
-
<div className="flex h-48 items-center justify-center text-slate-400">
|
|
148
|
-
Escalations Panel
|
|
149
|
-
</div>
|
|
150
|
-
</BaseCard>
|
|
151
|
-
<BaseCard>
|
|
152
|
-
<div className="flex h-48 items-center justify-center text-slate-400">
|
|
153
|
-
Travel Spend Panel
|
|
154
|
-
</div>
|
|
155
|
-
</BaseCard>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## Brand Tokens
|
|
165
|
-
|
|
166
|
-
Update `src/styles/global.css` — replace the `--color-brand-*` palette inside the `@theme inline` block with the Engine teal palette from PRD section 3. Also add `--color-engine-savings: #16A34A`.
|
|
167
|
-
|
|
168
|
-
## Wiring (all 3 required)
|
|
169
|
-
|
|
170
|
-
1. **CommandCenter.tsx** — import `EngineDashboard` from `"../../pages/EngineDashboard"` and render it
|
|
171
|
-
2. **Home.tsx** — import `CommandCenter` and render it
|
|
172
|
-
3. **routes.tsx** — set `Home` as the index route, move `Search` to `/search`
|
|
173
|
-
|
|
174
|
-
## Constraints (5 only)
|
|
175
|
-
|
|
176
|
-
1. File MUST be `.tsx` in `src/pages/`
|
|
177
|
-
2. Import ONLY from `@/components/library` and `@heroicons/react`
|
|
178
|
-
3. Colors: slate scale only — NO `text-white`, `text-black`, `bg-black` (exception: `bg-black/40` with opacity is OK for glass)
|
|
179
|
-
4. Full-page scroll — NO `h-screen` on outer container
|
|
180
|
-
5. DO NOT run `npm run dev` or `npm run validate:dashboard` — phase is complete after wiring
|
|
181
|
-
|
|
182
|
-
## Phase 1 does NOT include
|
|
183
|
-
|
|
184
|
-
- Sample data (Phase 2)
|
|
185
|
-
- ChatBar / Eva (Phase 4)
|
|
186
|
-
- Salesforce signals like "Powered by..." (Phase 4)
|
|
187
|
-
- Any `npm install` commands
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: engine-phase-2-components
|
|
3
|
-
description: >-
|
|
4
|
-
Phase 2 of the Engine Travel Command Center build. Replaces placeholder panels
|
|
5
|
-
with library components wired to pre-existing sample data. Adds map data.
|
|
6
|
-
Use this when the build prompt says "Phase 2" or "components".
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Phase 2: Components & Sample Data
|
|
10
|
-
|
|
11
|
-
**Source of truth:** `engine-command-center-prd.md` (sections 7–8)
|
|
12
|
-
|
|
13
|
-
**Goal:** Replace the 4 placeholder data panels with real library components. Add map data (markers, arcs, overlays). The sample data file already exists — just import from it.
|
|
14
|
-
|
|
15
|
-
## Critical: Data file already exists
|
|
16
|
-
|
|
17
|
-
`src/data/engine-sample-data.js` is pre-built with ~370 lines of sample data. **DO NOT create a new data file.** Just import from the existing one.
|
|
18
|
-
|
|
19
|
-
## Imports to add to EngineDashboard.tsx
|
|
20
|
-
|
|
21
|
-
```tsx
|
|
22
|
-
import {
|
|
23
|
-
GeoMap,
|
|
24
|
-
BaseCard,
|
|
25
|
-
ActivityCard,
|
|
26
|
-
ChartCard,
|
|
27
|
-
D3Chart,
|
|
28
|
-
D3ChartTemplates,
|
|
29
|
-
Avatar,
|
|
30
|
-
UIChip,
|
|
31
|
-
} from "@/components/library";
|
|
32
|
-
import useDataSource from "@/components/library/data/useDataSource";
|
|
33
|
-
import {
|
|
34
|
-
MAP_MARKERS,
|
|
35
|
-
MAP_ARCS,
|
|
36
|
-
MAP_OVERLAYS,
|
|
37
|
-
FLIGHT_STATUS_LIST,
|
|
38
|
-
TRAVELER_CARDS,
|
|
39
|
-
DISRUPTION_CARDS,
|
|
40
|
-
ESCALATION_CARDS,
|
|
41
|
-
MONTHLY_SPEND,
|
|
42
|
-
METRICS,
|
|
43
|
-
} from "@/data/engine-sample-data";
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Changes to make
|
|
47
|
-
|
|
48
|
-
### 1. Hero Map — add data props
|
|
49
|
-
|
|
50
|
-
```tsx
|
|
51
|
-
<GeoMap
|
|
52
|
-
width={960}
|
|
53
|
-
height={520}
|
|
54
|
-
theme={mode === "dark" ? "dark" : "light"}
|
|
55
|
-
markers={useDataSource({ sample: MAP_MARKERS, live: [] })}
|
|
56
|
-
arcs={useDataSource({ sample: MAP_ARCS, live: [] })}
|
|
57
|
-
overlays={useDataSource({ sample: MAP_OVERLAYS, live: [] })}
|
|
58
|
-
zoomable
|
|
59
|
-
className="h-full w-full"
|
|
60
|
-
/>
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### 2. Glass KPI overlays — use METRICS
|
|
64
|
-
|
|
65
|
-
Replace hardcoded KPI values with `METRICS.activeTravelers`, `METRICS.spendMTD`, `METRICS.complianceRate`, `METRICS.evaResolved`.
|
|
66
|
-
|
|
67
|
-
Use `fmtK()` helper for spend formatting:
|
|
68
|
-
|
|
69
|
-
```tsx
|
|
70
|
-
function fmtK(n: number) {
|
|
71
|
-
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
72
|
-
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
73
|
-
return n.toLocaleString();
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### 3. Flight status strip — use FLIGHT_STATUS_LIST
|
|
78
|
-
|
|
79
|
-
Replace hardcoded flights with `FLIGHT_STATUS_LIST.map(...)`.
|
|
80
|
-
|
|
81
|
-
### 4. Disruptions Panel (1/3 width) — custom inline component
|
|
82
|
-
|
|
83
|
-
Replace the placeholder BaseCard. Build a custom panel inside a BaseCard showing only disrupted flights. Each disruption card shows severity dot, flight number, route, traveler, reason, and Eva action.
|
|
84
|
-
|
|
85
|
-
```tsx
|
|
86
|
-
<BaseCard>
|
|
87
|
-
<div className="space-y-3 p-1">
|
|
88
|
-
<h3 className="text-sm font-semibold text-slate-900 dark:text-slate-50">Disruptions</h3>
|
|
89
|
-
{useDataSource({ sample: DISRUPTION_CARDS, live: [] }).map((d) => (
|
|
90
|
-
<div key={d.id} className="rounded-lg border border-slate-200 p-3 dark:border-slate-800">
|
|
91
|
-
<div className="flex items-center gap-2">
|
|
92
|
-
<span className={`h-2 w-2 rounded-full ${d.severity === "grounded" ? "bg-rose-500" : "bg-amber-500"}`} />
|
|
93
|
-
<span className="text-sm font-medium text-slate-900 dark:text-slate-50">{d.flight}</span>
|
|
94
|
-
<span className={`text-xs ${d.severity === "grounded" ? "text-rose-500" : "text-amber-500"}`}>
|
|
95
|
-
{d.severity} · {d.delayMin}min
|
|
96
|
-
</span>
|
|
97
|
-
</div>
|
|
98
|
-
<div className="mt-1 text-xs text-slate-500 dark:text-slate-400">{d.route} · {d.traveler}</div>
|
|
99
|
-
<div className="mt-1 text-xs text-slate-500 dark:text-slate-400">{d.reason}</div>
|
|
100
|
-
<div className="mt-2 flex items-center gap-1 text-xs text-brand-600 dark:text-brand-400">
|
|
101
|
-
<SparklesIcon className="h-3 w-3" />
|
|
102
|
-
<span>{d.evaAction}</span>
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
))}
|
|
106
|
-
</div>
|
|
107
|
-
</BaseCard>
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### 5. Active Travelers (2/3 width) — expandable cards
|
|
111
|
-
|
|
112
|
-
Replace the placeholder. Use BaseCard with `maxBodyHeight={420}` for internal scroll. Build expandable traveler rows using `useState` for the expanded ID.
|
|
113
|
-
|
|
114
|
-
Each row: Avatar (initials) + name + department + origin → destination + UIChip for policy status. Click to expand shows 4-col detail grid (Flight, Hotel, Return, Destination).
|
|
115
|
-
|
|
116
|
-
### 6. Escalations (1/2 width) — ActivityCard in BaseCard
|
|
117
|
-
|
|
118
|
-
**Copy this exactly from the PRD:**
|
|
119
|
-
|
|
120
|
-
```tsx
|
|
121
|
-
<BaseCard>
|
|
122
|
-
<ActivityCard
|
|
123
|
-
title="Escalations"
|
|
124
|
-
actions={useDataSource({ sample: ESCALATION_CARDS, live: [] })}
|
|
125
|
-
/>
|
|
126
|
-
</BaseCard>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
ActivityCard MUST be wrapped in BaseCard for visible card styling.
|
|
130
|
-
|
|
131
|
-
### 7. Monthly Spend Trend (1/2 width) — ChartCard + D3Chart
|
|
132
|
-
|
|
133
|
-
**Copy this exactly from the PRD:**
|
|
134
|
-
|
|
135
|
-
```tsx
|
|
136
|
-
const spendChartData = useDataSource({
|
|
137
|
-
sample: MONTHLY_SPEND.map(m => ({ x: m.month, spend: m.amount })),
|
|
138
|
-
live: [],
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
<ChartCard
|
|
142
|
-
title="Travel Spend"
|
|
143
|
-
subtitle="Monthly trend (6 months)"
|
|
144
|
-
chart={
|
|
145
|
-
<D3Chart
|
|
146
|
-
data={spendChartData}
|
|
147
|
-
renderChart={D3ChartTemplates.groupedBarChart}
|
|
148
|
-
options={{
|
|
149
|
-
xKey: "x",
|
|
150
|
-
groups: ["spend"],
|
|
151
|
-
colors: ["#5BC8C8"],
|
|
152
|
-
barRadius: 6,
|
|
153
|
-
margin: { top: 20, right: 20, bottom: 40, left: 60 },
|
|
154
|
-
showGrid: true,
|
|
155
|
-
}}
|
|
156
|
-
responsive
|
|
157
|
-
height={320}
|
|
158
|
-
/>
|
|
159
|
-
}
|
|
160
|
-
/>
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## Constraints (5 only)
|
|
164
|
-
|
|
165
|
-
1. **DO NOT create a new data file** — import from the existing `src/data/engine-sample-data.js`
|
|
166
|
-
2. Import ONLY from `@/components/library` and `@heroicons/react` — no shadcn, no Lucide, no Recharts
|
|
167
|
-
3. Wrap `ActivityCard` in `BaseCard` (ActivityCard has no card styling by default)
|
|
168
|
-
4. Use `useDataSource({ sample: X, live: [] })` for all data — enables Phase 3 swap
|
|
169
|
-
5. DO NOT run `npm run dev` or `npm run validate:dashboard`
|
|
170
|
-
|
|
171
|
-
## Phase 2 does NOT include
|
|
172
|
-
|
|
173
|
-
- Live Salesforce data (Phase 3)
|
|
174
|
-
- ChatBar / Eva (Phase 4)
|
|
175
|
-
- Salesforce signals (Phase 4)
|
|
176
|
-
- Any `npm install` commands
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: engine-phase-3-live-data
|
|
3
|
-
description: >-
|
|
4
|
-
Phase 3 of the Engine Travel Command Center build. Connects the dashboard to
|
|
5
|
-
live Salesforce Data Cloud via GraphQL. UI stays identical to Phase 2.
|
|
6
|
-
Use this when the build prompt says "Phase 3" or "real data".
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Phase 3: Real Data Integration
|
|
10
|
-
|
|
11
|
-
**Source of truth:** `engine-command-center-prd.md` (section 13)
|
|
12
|
-
|
|
13
|
-
**Goal:** Connect the dashboard to live Salesforce data via GraphQL. The UI stays identical to Phase 2 — only the data source changes.
|
|
14
|
-
|
|
15
|
-
## Approach
|
|
16
|
-
|
|
17
|
-
The sample data file (`src/data/engine-sample-data.js`) already uses real Salesforce field names (Trip__c, Flight__c, Contact, etc.). Read the file header to understand the schema.
|
|
18
|
-
|
|
19
|
-
## Custom objects
|
|
20
|
-
|
|
21
|
-
| Object | Purpose |
|
|
22
|
-
|--------|---------|
|
|
23
|
-
| Contact | Travelers (with Home_Airport__c, Travel_Policy_Tier__c, etc.) |
|
|
24
|
-
| Trip__c | Origin, destination, dates, cost, policy status |
|
|
25
|
-
| Flight__c | Flight number, airports, status, delay, traveler lookup |
|
|
26
|
-
| Booking__c | Upcoming reservations |
|
|
27
|
-
| Disruption__c | Delays, cancellations, severity |
|
|
28
|
-
| Rebooking_Action__c | Eva activity log |
|
|
29
|
-
| Travel_Policy__c | Policy rules and status |
|
|
30
|
-
|
|
31
|
-
## Implementation steps
|
|
32
|
-
|
|
33
|
-
### Step 1: Read the sample data file
|
|
34
|
-
|
|
35
|
-
Read `src/data/engine-sample-data.js` to understand which Salesforce fields are needed for each object.
|
|
36
|
-
|
|
37
|
-
### Step 2: Use GraphQL skills to create queries and hooks
|
|
38
|
-
|
|
39
|
-
For each object, use the Salesforce GraphQL skills:
|
|
40
|
-
|
|
41
|
-
1. Use the `exploring-webapp-graphql-schema` skill to look up the object in `schema.graphql`
|
|
42
|
-
2. Use the `generating-webapp-graphql-read-query` skill to create a typed query
|
|
43
|
-
3. Use the `using-webapp-graphql` skill to create a data hook (e.g., `useTravelers`, `useFlights`)
|
|
44
|
-
|
|
45
|
-
Each hook returns `{ data, loading, error }`.
|
|
46
|
-
|
|
47
|
-
### Step 3: Update useDataSource calls
|
|
48
|
-
|
|
49
|
-
Change each `useDataSource` call to include live data:
|
|
50
|
-
|
|
51
|
-
```tsx
|
|
52
|
-
// Phase 2 (sample only)
|
|
53
|
-
const travelers = useDataSource({ sample: TRAVELER_CARDS, live: [] });
|
|
54
|
-
|
|
55
|
-
// Phase 3 (live with sample fallback)
|
|
56
|
-
const { data: liveTravelers, loading, error } = useTravelers();
|
|
57
|
-
const travelers = useDataSource({
|
|
58
|
-
sample: TRAVELER_CARDS,
|
|
59
|
-
live: liveTravelers ?? [],
|
|
60
|
-
});
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
The `useDataSource` hook automatically uses `live` when available, falling back to `sample` on error.
|
|
64
|
-
|
|
65
|
-
### Step 4: Add loading and error states
|
|
66
|
-
|
|
67
|
-
Add `loading` and `error` handling to each section. Library card components accept `loading` and `error` props.
|
|
68
|
-
|
|
69
|
-
## Data strategy
|
|
70
|
-
|
|
71
|
-
The app uses a sample data cache (`ENABLE_SAMPLE_DATA_CACHE = true` in `src/lib/dataStrategy.ts`) for instant loading and offline capability. This is production-appropriate — build all GraphQL queries and hooks as normal.
|
|
72
|
-
|
|
73
|
-
## Constraints (5 only)
|
|
74
|
-
|
|
75
|
-
1. **DO NOT modify UI components** — only change data sources
|
|
76
|
-
2. **DO NOT add DataModeToggle** — live data only (sample is fallback for errors)
|
|
77
|
-
3. Use exact Salesforce field names from the sample data file
|
|
78
|
-
4. Schema file (`schema.graphql`) is pre-built in the repo — no generation needed
|
|
79
|
-
5. DO NOT run `npm run dev` or `npm run validate:dashboard`
|
|
80
|
-
|
|
81
|
-
## Phase 3 does NOT include
|
|
82
|
-
|
|
83
|
-
- ChatBar / Eva (Phase 4)
|
|
84
|
-
- Salesforce signals (Phase 4)
|
|
85
|
-
- UI changes of any kind
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: engine-phase-4-agent
|
|
3
|
-
description: >-
|
|
4
|
-
Phase 4 of the Engine Travel Command Center build. Adds Eva ChatBar to the
|
|
5
|
-
header and Salesforce signals throughout the dashboard.
|
|
6
|
-
Use this when the build prompt says "Phase 4" or "agent".
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Phase 4: Agentforce Integration
|
|
10
|
-
|
|
11
|
-
**Source of truth:** `engine-command-center-prd.md` (sections 9–10)
|
|
12
|
-
|
|
13
|
-
**Goal:** Add Eva as a ChatBar in the header. Add subtle Salesforce signals throughout the dashboard.
|
|
14
|
-
|
|
15
|
-
## Eva — ChatBar in header
|
|
16
|
-
|
|
17
|
-
Eva surfaces as a `ChatBar` in the header. Not a FAB. Not a sliding panel. Not a `ChatPanel` in the grid.
|
|
18
|
-
|
|
19
|
-
### Code
|
|
20
|
-
|
|
21
|
-
Define the handler and suggestions at **module scope** (outside the component):
|
|
22
|
-
|
|
23
|
-
```tsx
|
|
24
|
-
import { ChatBar } from "@/components/library";
|
|
25
|
-
|
|
26
|
-
const CHAT_SUGGESTIONS = [
|
|
27
|
-
"Who's traveling internationally right now?",
|
|
28
|
-
"Show bookings pending approval",
|
|
29
|
-
"What has Eva resolved today?",
|
|
30
|
-
"Travelers returning this week",
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
function handleChat(message: string) {
|
|
34
|
-
// Agentforce integration or mock response
|
|
35
|
-
return {
|
|
36
|
-
text: `Eva is looking into: "${message}"`,
|
|
37
|
-
components: [],
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Add the ChatBar to the header (right side, before the notification bell):
|
|
43
|
-
|
|
44
|
-
```tsx
|
|
45
|
-
<ChatBar
|
|
46
|
-
title="Eva"
|
|
47
|
-
placeholder="Ask about travelers, bookings, policy, spend…"
|
|
48
|
-
suggestions={CHAT_SUGGESTIONS}
|
|
49
|
-
onSend={handleChat}
|
|
50
|
-
/>
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Agent responses
|
|
54
|
-
|
|
55
|
-
Return structured `components` arrays for data (MetricCard, DataTable, StatusCard) — never markdown tables in text content.
|
|
56
|
-
|
|
57
|
-
## Salesforce Signals
|
|
58
|
-
|
|
59
|
-
Subtle, contextual indicators — like "Sent from iPhone", not promotional banners.
|
|
60
|
-
|
|
61
|
-
| Signal | Location | Implementation |
|
|
62
|
-
|--------|----------|----------------|
|
|
63
|
-
| "View in Salesforce" | Traveler expanded view, booking rows | Micro-link, muted text (`text-slate-400`) |
|
|
64
|
-
| "Salesforce updated" | After rebook/approve actions | `toast()` with success tone |
|
|
65
|
-
| "Powered by Agentforce" | ChatBar subtitle area | Small badge/chip |
|
|
66
|
-
|
|
67
|
-
## Constraints (5 only)
|
|
68
|
-
|
|
69
|
-
1. ChatBar goes in the **header**, not as a floating panel or grid element
|
|
70
|
-
2. `CHAT_SUGGESTIONS` and `handleChat` defined at **module scope** (outside component body)
|
|
71
|
-
3. Salesforce signals are subtle micro-text — not banners or badges
|
|
72
|
-
4. Import ONLY from `@/components/library` and `@heroicons/react`
|
|
73
|
-
5. DO NOT run `npm run dev` or `npm run validate:dashboard`
|