@schandlergarcia/sf-web-components 1.9.64 → 1.9.66

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.
@@ -1,4 +1,4 @@
1
- ## Charts & Visualizations (MANDATORY)
1
+ ## Charts & Visualizations
2
2
 
3
3
  **All charts, graphs, maps, and visualizations MUST use library components.** Never use Recharts, Chart.js, Nivo, or any third-party charting library. Never hand-roll SVG, canvas, or custom chart markup. The ONLY charting tools allowed are `D3Chart` (via `D3ChartTemplates` or a custom `renderChart` function) and `GeoMap`.
4
4
 
@@ -55,7 +55,7 @@ Defined in `global.css` (`--color-brand-*` and `--color-engine-*`), available as
55
55
 
56
56
  Canonical: `"operational"`, `"degraded"`, `"outage"`, `"maintenance"`. Always show color + text label.
57
57
 
58
- ## Dark Mode (MANDATORY)
58
+ ## Dark Mode
59
59
 
60
60
  Every visible element needs both light and dark styles. Library components handle this automatically — which is another reason to use them.
61
61
 
@@ -1,8 +1,8 @@
1
- ## STOP — READ BEFORE WRITING ANY CODE
1
+ ## Core Conventions
2
2
 
3
- **Every time you build a dashboard, you MUST follow these non-negotiable rules. Violations are the #1 cause of rejected dashboards.**
3
+ The following conventions apply to all dashboard development in this project.
4
4
 
5
- 1. **Actually write COMPLETE files to disk.** Use the file-writing tools to create `.tsx` files (NOT `.jsx`) in `src/pages/` and update `CommandCenter.tsx` to import your dashboard. This is a TypeScript project - all React components MUST use `.tsx` extension. **CRITICAL: Write the ENTIRE file from import statements through the closing brace `}` of the export statement. Do NOT stop mid-file, mid-function, or mid-line. Every JSX tag you open must be closed. Every string you open must be closed. Every className attribute must be complete.** If you only describe what you would build without creating the files, the dashboard will not render. Verify the files exist after writing them.
5
+ 1. **Write `.tsx` files** in `src/pages/` and update `CommandCenter.tsx` to import the dashboard. This is a TypeScript project all React components use `.tsx` extension.
6
6
 
7
7
  2. **Use ONLY library components** from `@/components/library` for all cards, charts, tables, lists, and feeds. The library has 30+ components — there is no reason to hand-roll HTML. See the component table below.
8
8
 
@@ -14,11 +14,9 @@
14
14
 
15
15
  6. **Never `npm install` Salesforce packages.** The `@salesforce/*` packages are platform-provided via broken symlinks. They are stubbed in `src/stubs/` and aliased in `vite.config.ts`. Do not try to install them — they don't exist on npm. If you see a TypeScript error about `@salesforce/vite-plugin-webapp-experimental`, ignore it — the build still succeeds via `vite build` (the `tsc` error is in `vite.config.ts` which is handled separately by `tsconfig.node.json`).
16
16
 
17
- If your output violates any of these 6 rules, it will be rejected and you will need to redo the work.
17
+ ## Use Library Components Not Hand-Rolled HTML Cards
18
18
 
19
- ## CRITICAL: Use Library Components Never Hand-Roll HTML Cards
20
-
21
- **This is the #1 mistake.** The component library (`@/components/library`) provides pre-built, themed, dark-mode-ready cards for every common dashboard need. You MUST use them instead of writing raw `<div>` cards with custom classes.
19
+ The component library (`@/components/library`) provides pre-built, themed, dark-mode-ready cards for every common dashboard need. Use them instead of writing raw `<div>` cards with custom classes.
22
20
 
23
21
  ### Before writing ANY card-like UI, check this table:
24
22
 
@@ -34,7 +32,7 @@ If your output violates any of these 6 rules, it will be rejected and you will n
34
32
  | Text summary | `NarrativeSummary` / `SectionCard` | `<div>` with headings and paragraphs |
35
33
  | Alert / callout | `CalloutCard` | Custom banner div |
36
34
 
37
- **Every visible section of a dashboard should be a library component.** If you find yourself writing `<div className="bg-white border rounded-[10px] shadow-sm p-6">` with content inside, STOP you are hand-rolling a card. Find the library component that fits.
35
+ Every visible section of a dashboard should be a library component. If you're writing `<div className="bg-white border rounded-[10px] shadow-sm p-6">` with content inside, that's a hand-rolled card use a library component instead.
38
36
 
39
37
  ### Correct example:
40
38
 
@@ -80,7 +78,7 @@ import { MetricCard, ListCard, ActivityCard, WidgetCard } from "@/components/lib
80
78
  </div>
81
79
  ```
82
80
 
83
- ## Images (MANDATORY)
81
+ ## Images
84
82
 
85
83
  The only image allowed in dashboards is the **company logo**: `src/assets/images/engine_logo.png`. Import it as a module and use it where a logo is needed (nav header, branding, etc.).
86
84
 
@@ -104,7 +102,7 @@ import engineLogo from "@/assets/images/engine_logo.png";
104
102
  <div className="w-8 h-8 bg-black rounded" /> // placeholder box instead of logo
105
103
  ```
106
104
 
107
- ## No Dashboard-Level Navigation (MANDATORY)
105
+ ## No Dashboard-Level Navigation
108
106
 
109
107
  Dashboard pages must NOT include their own `<nav>`, header bar, or top navigation of any kind. Navigation is handled by `appLayout.tsx`. The dashboard renders inside the app shell — adding a nav inside the dashboard creates a duplicate header, which is the most visually obvious mistake.
110
108
 
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.64] - 2026-04-01
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.66] - 2026-04-01
17
9
 
18
10
  ### Fixed
19
11
  - **6 data bugs in engine-sample-data.js**:
@@ -27,20 +19,33 @@ 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
- - Rewrote section 13 build prompts to reference new phase files
31
- - **Simplified .a4drules documentation** - Removed redundancy and contradictions:
32
- - `features/engine-dashboard-rule.md` - Reduced from 310 to ~65 lines (non-negotiable constraints + phase routing)
33
- - `features/command-center-dashboard-rule.md` - Reduced from ~100 to ~30 lines (10 core constraints)
34
- - `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 (redirects to phase file)
36
- - `skills/command-center-builder/SKILL.md` - Fixed map layout contradiction, removed validator
37
- - `skills/command-center-builder/page-layout.md` - Fixed map layout contradiction
38
- - `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 (redirects to phases)
22
+ - Rewrote section 13 build prompts to sound natural (removed AI coaching language)
23
+ - **Simplified .a4drules documentation** - Removed redundancy, contradictions, and AI coaching language:
24
+ - `features/engine-dashboard-rule.md` - Rewritten as "Project Conventions" (reduced from 310 to ~65 lines)
25
+ - `features/command-center-dashboard-rule.md` - Rewritten as slim conventions (~30 lines)
26
+ - `features/pre-code-checklist.md` - Rewritten as "Quick Reference" (~25 lines, removed auto-load)
27
+ - `features/phase2-data-pattern.md` - Rewritten as "Sample Data" documentation (~20 lines)
28
+ - `skills/command-center-builder/SKILL.md` - Fixed map contradiction, removed validator contradiction, removed AI coaching language
29
+ - `skills/command-center-builder/page-layout.md` - Fixed map contradiction, softened wiring language
30
+ - `skills/command-center-builder/completion-checklist.md` - Removed validator contradiction
31
+ - `skills/command-center-builder/improved-build-process.md` - Rewritten as methodology description (~30 lines)
32
+ - `skills/command-center-builder/getting-started.md` - Removed AI coaching language
33
+ - `skills/command-center-builder/components-styling.md` - Removed (MANDATORY) header
34
+ - `skills/command-center-builder/charts-visualization.md` - Removed (MANDATORY) header
40
35
  - `skills/command-center-project/SKILL.md` - Fixed file path contradiction (src/components/pages/ → src/pages/)
41
36
  - `skills/command-center-guide/SKILL.md` - Reduced from 270 to ~45 lines (simplified routing guide)
42
37
 
43
- **Context:** The phase-based system provides self-contained, copy-paste ready build instructions that eliminate the confusion caused by scattered, contradictory guidance across multiple files. All documentation now points to the phase files as the source of truth.
38
+ **Context:** Complete documentation overhaul to eliminate confusion from scattered, contradictory guidance. Removed prescriptive AI coaching language in favor of clear technical conventions.
39
+
40
+ ## [1.9.65] - 2026-04-01
41
+
42
+ ### Updated
43
+ - **Documentation improvements** - Initial sync of changes from react-cursor-1 (incomplete, superseded by 1.9.66)
44
+
45
+ ## [1.9.64] - 2026-04-01
46
+
47
+ ### Updated
48
+ - **Documentation improvements** - Synced latest changes from react-cursor-1 including data bug fixes and simplified .a4drules structure
44
49
 
45
50
  ## [1.9.63] - 2026-04-01
46
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schandlergarcia/sf-web-components",
3
- "version": "1.9.64",
3
+ "version": "1.9.66",
4
4
  "description": "Reusable Salesforce web components library with Tailwind CSS v4 and shadcn/ui",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -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`