@schandlergarcia/sf-web-components 2.3.16 → 2.3.17

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.
@@ -0,0 +1,301 @@
1
+ import { FunnelIcon, BookmarkIcon, CheckIcon } from "@heroicons/react/24/outline";
2
+ import { useState } from "react";
3
+ import { Dropdown, Button } from "@/components/library";
4
+
5
+ interface Segment {
6
+ id: string;
7
+ name: string;
8
+ count?: number;
9
+ metric?: string;
10
+ color: string;
11
+ isLoading?: boolean;
12
+ }
13
+
14
+ export default function Data360Widget() {
15
+ const [selectedBookingType, setSelectedBookingType] = useState("All Types");
16
+ const [selectedCustomer, setSelectedCustomer] = useState("All Customers");
17
+ const [selectedTiming, setSelectedTiming] = useState("All Timing");
18
+ const [activeSegment, setActiveSegment] = useState<string | null>(null);
19
+ const [savedSegments, setSavedSegments] = useState<Segment[]>([
20
+ {
21
+ id: "segment-1",
22
+ name: "Corporate Travel Accounts",
23
+ count: 342,
24
+ metric: "$485K revenue • 4.2 avg nights",
25
+ color: "text-blue-600 dark:text-blue-400"
26
+ },
27
+ {
28
+ id: "segment-2",
29
+ name: "High-Value Leisure",
30
+ count: 128,
31
+ metric: "$620K revenue • 6.8 avg nights",
32
+ color: "text-green-600 dark:text-green-400"
33
+ },
34
+ {
35
+ id: "segment-3",
36
+ name: "Last-Minute Bookings",
37
+ count: 89,
38
+ metric: "$142K revenue • 2.1 avg nights",
39
+ color: "text-orange-600 dark:text-orange-400"
40
+ }
41
+ ]);
42
+
43
+ const bookingTypes = ["All Types", "Corporate", "Leisure", "Group Event", "Extended Stay"];
44
+ const customerTypes = ["All Customers", "First Time", "Returning", "VIP / High-Value", "Loyalty Member"];
45
+ const timingOptions = ["All Timing", "Last Minute (<7 days)", "Short Lead (7-30 days)", "Advance (>30 days)", "Recently Cancelled"];
46
+
47
+ const colors = [
48
+ "text-purple-600 dark:text-purple-400",
49
+ "text-pink-600 dark:text-pink-400",
50
+ "text-indigo-600 dark:text-indigo-400",
51
+ "text-cyan-600 dark:text-cyan-400",
52
+ "text-amber-600 dark:text-amber-400"
53
+ ];
54
+
55
+ function generateSegmentName(): string {
56
+ const parts: string[] = [];
57
+ if (selectedBookingType !== "All Types") parts.push(selectedBookingType);
58
+ if (selectedCustomer !== "All Customers") parts.push(selectedCustomer);
59
+ if (selectedTiming !== "All Timing") {
60
+ const timingShort = selectedTiming.replace(/\s*\([^)]*\)/g, "").trim();
61
+ parts.push(timingShort);
62
+ }
63
+ return parts.length > 0 ? parts.join(" + ") : "Custom Segment";
64
+ }
65
+
66
+ function handleApplySegment() {
67
+ const newId = `segment-${Date.now()}`;
68
+ const segmentName = generateSegmentName();
69
+ const randomColor = colors[Math.floor(Math.random() * colors.length)];
70
+
71
+ // Add segment with loading state
72
+ const newSegment: Segment = {
73
+ id: newId,
74
+ name: segmentName,
75
+ color: randomColor,
76
+ isLoading: true
77
+ };
78
+
79
+ setSavedSegments(prev => [...prev, newSegment]);
80
+
81
+ // Simulate data loading for 60 seconds
82
+ setTimeout(() => {
83
+ const count = Math.floor(Math.random() * 200) + 50;
84
+ const revenue = Math.floor(Math.random() * 400) + 100;
85
+ const avgNights = (Math.random() * 5 + 2).toFixed(1);
86
+
87
+ setSavedSegments(prev =>
88
+ prev.map(seg =>
89
+ seg.id === newId
90
+ ? {
91
+ ...seg,
92
+ count,
93
+ metric: `$${revenue}K revenue • ${avgNights} avg nights`,
94
+ isLoading: false
95
+ }
96
+ : seg
97
+ )
98
+ );
99
+ }, 60000); // 60 seconds
100
+ }
101
+
102
+ return (
103
+ <div className="bg-gradient-to-br from-white via-[var(--color-dash-surface)] to-white dark:from-[var(--color-dash-text)] dark:via-[var(--color-dash-dark)] dark:to-[var(--color-dash-text)] rounded-2xl p-8 border-2 border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
104
+ {/* Header */}
105
+ <div className="flex items-start justify-between mb-6">
106
+ <div className="space-y-1">
107
+ <h2 className="text-3xl font-black text-[var(--color-dash-text)] dark:text-white tracking-tight">Booking Segments</h2>
108
+ <p className="text-base text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">Target and analyze customer groups across your properties</p>
109
+ </div>
110
+
111
+ <div className="flex items-center gap-2 px-3 py-1.5 rounded-full bg-[var(--color-dash-success)]/10 border-2 border-[var(--color-dash-success)]/40 shadow-sm">
112
+ <div className="relative flex h-2 w-2">
113
+ <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-[var(--color-dash-success)] opacity-75"></span>
114
+ <span className="relative inline-flex rounded-full h-2 w-2 bg-[var(--color-dash-success)]"></span>
115
+ </div>
116
+ <span className="text-xs font-bold text-[var(--color-dash-success)] uppercase tracking-wide">Live</span>
117
+ </div>
118
+ </div>
119
+
120
+ {/* Segment Builder */}
121
+ <div className="bg-white dark:bg-[var(--color-dash-text)] rounded-xl p-6 border-2 border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30 mb-6">
122
+ <div className="flex items-center gap-2 mb-5">
123
+ <div className="bg-[var(--color-dash-accent)]/10 rounded-lg p-1.5">
124
+ <FunnelIcon className="h-5 w-5 text-[var(--color-dash-accent)]" />
125
+ </div>
126
+ <h3 className="text-base font-bold text-[var(--color-dash-text)] dark:text-white uppercase tracking-wider">Build New Segment</h3>
127
+ </div>
128
+
129
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
130
+ {/* Booking Type Dropdown */}
131
+ <div>
132
+ <label className="block text-sm font-semibold text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] uppercase tracking-wider mb-2">
133
+ Booking Type
134
+ </label>
135
+ <Dropdown>
136
+ <Button variant="outline" className="w-full justify-between text-left border-2 border-[var(--color-dash-label)]/40 hover:border-[var(--color-dash-accent)] dark:border-[var(--color-dash-muted)]/50 dark:hover:border-[var(--color-dash-accent)] shadow-sm hover:shadow-md transition-all duration-200">
137
+ <span className="text-base font-medium">{selectedBookingType}</span>
138
+ </Button>
139
+ <Dropdown.Popover className="w-[--trigger-width]">
140
+ <Dropdown.Menu
141
+ onAction={(key) => setSelectedBookingType(key as string)}
142
+ selectedKeys={[selectedBookingType]}
143
+ selectionMode="single"
144
+ >
145
+ {bookingTypes.map((type) => (
146
+ <Dropdown.Item
147
+ key={type}
148
+ id={type}
149
+ textValue={type}
150
+ className="px-4 py-3 rounded-lg hover:bg-[var(--color-dash-surface)] dark:hover:bg-[var(--color-dash-muted)]/20 cursor-pointer"
151
+ >
152
+ <div className="flex items-center justify-between">
153
+ <span className="text-base font-medium text-[var(--color-dash-text)] dark:text-white">{type}</span>
154
+ {selectedBookingType === type && (
155
+ <CheckIcon className="h-4 w-4 text-[var(--color-dash-accent)]" />
156
+ )}
157
+ </div>
158
+ </Dropdown.Item>
159
+ ))}
160
+ </Dropdown.Menu>
161
+ </Dropdown.Popover>
162
+ </Dropdown>
163
+ </div>
164
+
165
+ {/* Customer Type Dropdown */}
166
+ <div>
167
+ <label className="block text-sm font-semibold text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] uppercase tracking-wider mb-2">
168
+ Customer Type
169
+ </label>
170
+ <Dropdown>
171
+ <Button variant="outline" className="w-full justify-between text-left border-2 border-[var(--color-dash-label)]/40 hover:border-[var(--color-dash-accent)] dark:border-[var(--color-dash-muted)]/50 dark:hover:border-[var(--color-dash-accent)] shadow-sm hover:shadow-md transition-all duration-200">
172
+ <span className="text-base font-medium">{selectedCustomer}</span>
173
+ </Button>
174
+ <Dropdown.Popover className="w-[--trigger-width]">
175
+ <Dropdown.Menu
176
+ onAction={(key) => setSelectedCustomer(key as string)}
177
+ selectedKeys={[selectedCustomer]}
178
+ selectionMode="single"
179
+ >
180
+ {customerTypes.map((type) => (
181
+ <Dropdown.Item
182
+ key={type}
183
+ id={type}
184
+ textValue={type}
185
+ className="px-4 py-3 rounded-lg hover:bg-[var(--color-dash-surface)] dark:hover:bg-[var(--color-dash-muted)]/20 cursor-pointer"
186
+ >
187
+ <div className="flex items-center justify-between">
188
+ <span className="text-base font-medium text-[var(--color-dash-text)] dark:text-white">{type}</span>
189
+ {selectedCustomer === type && (
190
+ <CheckIcon className="h-4 w-4 text-[var(--color-dash-accent)]" />
191
+ )}
192
+ </div>
193
+ </Dropdown.Item>
194
+ ))}
195
+ </Dropdown.Menu>
196
+ </Dropdown.Popover>
197
+ </Dropdown>
198
+ </div>
199
+
200
+ {/* Booking Timing Dropdown */}
201
+ <div>
202
+ <label className="block text-sm font-semibold text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] uppercase tracking-wider mb-2">
203
+ Booking Timing
204
+ </label>
205
+ <Dropdown>
206
+ <Button variant="outline" className="w-full justify-between text-left border-2 border-[var(--color-dash-label)]/40 hover:border-[var(--color-dash-accent)] dark:border-[var(--color-dash-muted)]/50 dark:hover:border-[var(--color-dash-accent)] shadow-sm hover:shadow-md transition-all duration-200">
207
+ <span className="text-base font-medium">{selectedTiming}</span>
208
+ </Button>
209
+ <Dropdown.Popover className="w-[--trigger-width]">
210
+ <Dropdown.Menu
211
+ onAction={(key) => setSelectedTiming(key as string)}
212
+ selectedKeys={[selectedTiming]}
213
+ selectionMode="single"
214
+ >
215
+ {timingOptions.map((type) => (
216
+ <Dropdown.Item
217
+ key={type}
218
+ id={type}
219
+ textValue={type}
220
+ className="px-4 py-3 rounded-lg hover:bg-[var(--color-dash-surface)] dark:hover:bg-[var(--color-dash-muted)]/20 cursor-pointer"
221
+ >
222
+ <div className="flex items-center justify-between">
223
+ <span className="text-base font-medium text-[var(--color-dash-text)] dark:text-white">{type}</span>
224
+ {selectedTiming === type && (
225
+ <CheckIcon className="h-4 w-4 text-[var(--color-dash-accent)]" />
226
+ )}
227
+ </div>
228
+ </Dropdown.Item>
229
+ ))}
230
+ </Dropdown.Menu>
231
+ </Dropdown.Popover>
232
+ </Dropdown>
233
+ </div>
234
+ </div>
235
+
236
+ {/* Apply Button */}
237
+ <div className="mt-5 flex justify-end">
238
+ <Button variant="primary" className="px-6 py-2.5" onClick={handleApplySegment}>
239
+ <span className="text-base font-semibold">Apply & Save Segment</span>
240
+ </Button>
241
+ </div>
242
+ </div>
243
+
244
+ {/* Saved Segments */}
245
+ <div>
246
+ <div className="flex items-center gap-2 mb-4">
247
+ <div className="bg-[var(--color-dash-accent)]/10 rounded-lg p-1.5">
248
+ <BookmarkIcon className="h-5 w-5 text-[var(--color-dash-accent)]" />
249
+ </div>
250
+ <h3 className="text-base font-bold text-[var(--color-dash-text)] dark:text-white uppercase tracking-wider">Saved Segments</h3>
251
+ </div>
252
+
253
+ <div className="space-y-3">
254
+ {savedSegments.map((segment) => (
255
+ <button
256
+ key={segment.id}
257
+ onClick={() => setActiveSegment(segment.id)}
258
+ className={`w-full text-left bg-white dark:bg-[var(--color-dash-text)] rounded-xl p-5 border-2 transition-all duration-300 ${
259
+ activeSegment === segment.id
260
+ ? 'border-[var(--color-dash-accent)] shadow-lg cursor-default'
261
+ : 'border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30 hover:border-[var(--color-dash-accent)] hover:shadow-lg cursor-pointer'
262
+ }`}
263
+ >
264
+ <div className="flex items-start justify-between gap-4">
265
+ <div className="flex-1">
266
+ <h4 className="text-lg font-bold text-[var(--color-dash-text)] dark:text-white mb-1.5">{segment.name}</h4>
267
+ {segment.isLoading ? (
268
+ <div className="flex items-center gap-4 text-base">
269
+ <div className="flex items-center gap-2">
270
+ <div className="h-5 w-16 bg-[var(--color-dash-label)]/20 rounded animate-pulse"></div>
271
+ <span className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">bookings</span>
272
+ </div>
273
+ <span className="text-[var(--color-dash-label)]/40">•</span>
274
+ <div className="h-5 w-32 bg-[var(--color-dash-label)]/20 rounded animate-pulse"></div>
275
+ </div>
276
+ ) : (
277
+ <div className="flex items-center gap-4 text-base">
278
+ <span className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
279
+ <span className="font-bold text-[var(--color-dash-text)] dark:text-white">{segment.count}</span> bookings
280
+ </span>
281
+ <span className="text-[var(--color-dash-label)]/40">•</span>
282
+ <span className={`font-semibold ${segment.color}`}>{segment.metric}</span>
283
+ </div>
284
+ )}
285
+ </div>
286
+
287
+ {activeSegment === segment.id && (
288
+ <div className="flex-shrink-0">
289
+ <div className="px-3 py-1.5 rounded-full bg-[var(--color-dash-accent)]/10 border-2 border-[var(--color-dash-accent)]/50 shadow-sm">
290
+ <span className="text-xs font-bold text-[var(--color-dash-accent)] uppercase tracking-wide">Active</span>
291
+ </div>
292
+ </div>
293
+ )}
294
+ </div>
295
+ </button>
296
+ ))}
297
+ </div>
298
+ </div>
299
+ </div>
300
+ );
301
+ }
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Engine Partner Hub - Sample Data
3
+ *
4
+ * Field names match the Salesforce org schema (Property__c, Contract__c,
5
+ * Invoice__c, Attrition_Penalty__c, etc.) so switching from sample → live
6
+ * Data Cloud queries requires only a data-source swap, not a field-name refactor.
7
+ *
8
+ * Each section exports both the raw records AND dashboard-ready derivatives
9
+ * (KPI metrics, chart data, formatted card items).
10
+ */
11
+
12
+ // ─── PARTNERS (Account with RecordType = Hotel_Partner) ────────────────────
13
+ export const PARTNERS = [
14
+ { Id: "001P1", Name: "Grandview Hotel Group", Partner_Tier__c: "Gold", Commission_Rate__c: 18, Partner_Status__c: "Active", Total_Properties__c: 5, Total_Reservations__c: 12, Total_Revenue__c: 284000, Contract_Start_Date__c: "2025-01-01", Contract_End_Date__c: "2026-12-31" },
15
+ { Id: "001P2", Name: "Summit Hotels & Resorts", Partner_Tier__c: "Gold", Commission_Rate__c: 17, Partner_Status__c: "Active", Total_Properties__c: 4, Total_Reservations__c: 10, Total_Revenue__c: 283000, Contract_Start_Date__c: "2025-03-01", Contract_End_Date__c: "2027-02-28" },
16
+ { Id: "001P3", Name: "Pacific Coast Hospitality", Partner_Tier__c: "Silver", Commission_Rate__c: 15, Partner_Status__c: "Active", Total_Properties__c: 3, Total_Reservations__c: 8, Total_Revenue__c: 156000, Contract_Start_Date__c: "2025-06-01", Contract_End_Date__c: "2026-05-31" },
17
+ { Id: "001P4", Name: "Metropolitan Hotels International", Partner_Tier__c: "Gold", Commission_Rate__c: 16, Partner_Status__c: "Active", Total_Properties__c: 4, Total_Reservations__c: 7, Total_Revenue__c: 198000, Contract_Start_Date__c: "2025-04-01", Contract_End_Date__c: "2027-03-31" },
18
+ { Id: "001P5", Name: "Horizon Hospitality Group", Partner_Tier__c: "Silver", Commission_Rate__c: 14, Partner_Status__c: "Active", Total_Properties__c: 3, Total_Reservations__c: 5, Total_Revenue__c: 112000, Contract_Start_Date__c: "2025-07-01", Contract_End_Date__c: "2026-06-30" },
19
+ { Id: "001P6", Name: "Riverside Inn Collection", Partner_Tier__c: "Bronze", Commission_Rate__c: 12, Partner_Status__c: "Active", Total_Properties__c: 2, Total_Reservations__c: 3, Total_Revenue__c: 64000, Contract_Start_Date__c: "2025-09-01", Contract_End_Date__c: "2026-08-31" },
20
+ { Id: "001P7", Name: "Pinnacle Luxury Hotels", Partner_Tier__c: "Gold", Commission_Rate__c: 20, Partner_Status__c: "Active", Total_Properties__c: 3, Total_Reservations__c: 4, Total_Revenue__c: 312000, Contract_Start_Date__c: "2025-02-01", Contract_End_Date__c: "2027-01-31" },
21
+ { Id: "001P8", Name: "Sterling Hotel Group", Partner_Tier__c: "Silver", Commission_Rate__c: 13, Partner_Status__c: "Active", Total_Properties__c: 3, Total_Reservations__c: 4, Total_Revenue__c: 89000, Contract_Start_Date__c: "2025-05-01", Contract_End_Date__c: "2026-04-30" },
22
+ { Id: "001P9", Name: "Vista Hotels International", Partner_Tier__c: "Silver", Commission_Rate__c: 14, Partner_Status__c: "Pending", Total_Properties__c: 2, Total_Reservations__c: 0, Total_Revenue__c: 0, Contract_Start_Date__c: "2026-04-01", Contract_End_Date__c: "2027-03-31" },
23
+ { Id: "001P10", Name: "Continental Inn & Suites", Partner_Tier__c: "Bronze", Commission_Rate__c: 11, Partner_Status__c: "Active", Total_Properties__c: 2, Total_Reservations__c: 2, Total_Revenue__c: 42000, Contract_Start_Date__c: "2025-10-01", Contract_End_Date__c: "2026-09-30" },
24
+ { Id: "001P11", Name: "Skyline Hospitality", Partner_Tier__c: "Silver", Commission_Rate__c: 15, Partner_Status__c: "Active", Total_Properties__c: 2, Total_Reservations__c: 3, Total_Revenue__c: 97000, Contract_Start_Date__c: "2025-08-01", Contract_End_Date__c: "2026-07-31" },
25
+ { Id: "001P12", Name: "Parkview Hotel Co", Partner_Tier__c: "Bronze", Commission_Rate__c: 12, Partner_Status__c: "Inactive", Total_Properties__c: 1, Total_Reservations__c: 1, Total_Revenue__c: 28000, Contract_Start_Date__c: "2024-06-01", Contract_End_Date__c: "2025-05-31" },
26
+ ];
27
+
28
+ // ─── CONTRACTS ──────────────────────────────────────────────────────────────
29
+ export const CONTRACTS = [
30
+ { Id: "a10C1", Name: "CNTR-00001", Account__c: "001P1", Partner_Name: "Grandview Hotel Group", Status__c: "Active", Attrition_Calculation_Method__c: "Per Night", Attrition_Threshold_Percentage__c: 80, Resale_Credit_Policy__c: "Full Credit", Resale_Credit_Percentage__c: 100, Commission_Rate__c: 18, Start_Date__c: "2025-01-01", End_Date__c: "2026-12-31" },
31
+ { Id: "a10C2", Name: "CNTR-00002", Account__c: "001P2", Partner_Name: "Summit Hotels & Resorts", Status__c: "Active", Attrition_Calculation_Method__c: "Per Night", Attrition_Threshold_Percentage__c: 80, Resale_Credit_Policy__c: "Partial Credit", Resale_Credit_Percentage__c: 50, Commission_Rate__c: 17, Start_Date__c: "2025-03-01", End_Date__c: "2027-02-28" },
32
+ { Id: "a10C3", Name: "CNTR-00003", Account__c: "001P3", Partner_Name: "Pacific Coast Hospitality", Status__c: "Active", Attrition_Calculation_Method__c: "Cumulative", Attrition_Threshold_Percentage__c: 75, Resale_Credit_Policy__c: "Partial Credit", Resale_Credit_Percentage__c: 50, Commission_Rate__c: 15, Start_Date__c: "2025-06-01", End_Date__c: "2026-05-31" },
33
+ { Id: "a10C4", Name: "CNTR-00004", Account__c: "001P4", Partner_Name: "Metropolitan Hotels International", Status__c: "Active", Attrition_Calculation_Method__c: "Revenue Based", Attrition_Threshold_Percentage__c: 70, Resale_Credit_Policy__c: "No Credit", Resale_Credit_Percentage__c: 0, Commission_Rate__c: 16, Start_Date__c: "2025-04-01", End_Date__c: "2027-03-31" },
34
+ { Id: "a10C5", Name: "CNTR-00005", Account__c: "001P5", Partner_Name: "Horizon Hospitality Group", Status__c: "Active", Attrition_Calculation_Method__c: "Per Night", Attrition_Threshold_Percentage__c: 85, Resale_Credit_Policy__c: "Full Credit", Resale_Credit_Percentage__c: 100, Commission_Rate__c: 14, Start_Date__c: "2025-07-01", End_Date__c: "2026-06-30" },
35
+ { Id: "a10C6", Name: "CNTR-00006", Account__c: "001P6", Partner_Name: "Riverside Inn Collection", Status__c: "Active", Attrition_Calculation_Method__c: "Cumulative", Attrition_Threshold_Percentage__c: 70, Resale_Credit_Policy__c: "No Credit", Resale_Credit_Percentage__c: 0, Commission_Rate__c: 12, Start_Date__c: "2025-09-01", End_Date__c: "2026-08-31" },
36
+ { Id: "a10C7", Name: "CNTR-00007", Account__c: "001P7", Partner_Name: "Pinnacle Luxury Hotels", Status__c: "Active", Attrition_Calculation_Method__c: "Per Night", Attrition_Threshold_Percentage__c: 90, Resale_Credit_Policy__c: "Full Credit", Resale_Credit_Percentage__c: 100, Commission_Rate__c: 20, Start_Date__c: "2025-02-01", End_Date__c: "2027-01-31" },
37
+ { Id: "a10C8", Name: "CNTR-00008", Account__c: "001P8", Partner_Name: "Sterling Hotel Group", Status__c: "Active", Attrition_Calculation_Method__c: "Per Night", Attrition_Threshold_Percentage__c: 80, Resale_Credit_Policy__c: "Partial Credit", Resale_Credit_Percentage__c: 50, Commission_Rate__c: 13, Start_Date__c: "2025-05-01", End_Date__c: "2026-04-30" },
38
+ { Id: "a10C9", Name: "CNTR-00009", Account__c: "001P9", Partner_Name: "Vista Hotels International", Status__c: "Active", Attrition_Calculation_Method__c: "Revenue Based", Attrition_Threshold_Percentage__c: 75, Resale_Credit_Policy__c: "Partial Credit", Resale_Credit_Percentage__c: 50, Commission_Rate__c: 14, Start_Date__c: "2026-04-01", End_Date__c: "2027-03-31" },
39
+ { Id: "a10C10", Name: "CNTR-00010", Account__c: "001P10", Partner_Name: "Continental Inn & Suites", Status__c: "Active", Attrition_Calculation_Method__c: "Cumulative", Attrition_Threshold_Percentage__c: 70, Resale_Credit_Policy__c: "No Credit", Resale_Credit_Percentage__c: 0, Commission_Rate__c: 11, Start_Date__c: "2025-10-01", End_Date__c: "2026-09-30" },
40
+ { Id: "a10C11", Name: "CNTR-00011", Account__c: "001P11", Partner_Name: "Skyline Hospitality", Status__c: "Active", Attrition_Calculation_Method__c: "Per Night", Attrition_Threshold_Percentage__c: 80, Resale_Credit_Policy__c: "Full Credit", Resale_Credit_Percentage__c: 100, Commission_Rate__c: 15, Start_Date__c: "2025-08-01", End_Date__c: "2026-07-31" },
41
+ { Id: "a10C12", Name: "CNTR-00012", Account__c: "001P12", Partner_Name: "Parkview Hotel Co", Status__c: "Expired", Attrition_Calculation_Method__c: "Per Night", Attrition_Threshold_Percentage__c: 80, Resale_Credit_Policy__c: "No Credit", Resale_Credit_Percentage__c: 0, Commission_Rate__c: 12, Start_Date__c: "2024-06-01", End_Date__c: "2025-05-31" },
42
+ ];
43
+
44
+ // ─── INVOICES ───────────────────────────────────────────────────────────────
45
+ export const INVOICES = [
46
+ { Id: "a20I1", Name: "INV-00001", Account__c: "001P1", Partner_Name: "Grandview Hotel Group", Status__c: "Paid", Invoice_Date__c: "2026-01-15", Due_Date__c: "2026-02-15", Period_Start__c: "2025-12-01", Period_End__c: "2025-12-31", Total_Amount__c: 24500, Commission_Amount__c: 4410 },
47
+ { Id: "a20I2", Name: "INV-00002", Account__c: "001P2", Partner_Name: "Summit Hotels & Resorts", Status__c: "Paid", Invoice_Date__c: "2026-01-15", Due_Date__c: "2026-02-15", Period_Start__c: "2025-12-01", Period_End__c: "2025-12-31", Total_Amount__c: 19800, Commission_Amount__c: 3366 },
48
+ { Id: "a20I3", Name: "INV-00003", Account__c: "001P3", Partner_Name: "Pacific Coast Hospitality", Status__c: "Paid", Invoice_Date__c: "2026-01-15", Due_Date__c: "2026-02-15", Period_Start__c: "2025-12-01", Period_End__c: "2025-12-31", Total_Amount__c: 13200, Commission_Amount__c: 1980 },
49
+ { Id: "a20I4", Name: "INV-00004", Account__c: "001P1", Partner_Name: "Grandview Hotel Group", Status__c: "Paid", Invoice_Date__c: "2026-02-15", Due_Date__c: "2026-03-15", Period_Start__c: "2026-01-01", Period_End__c: "2026-01-31", Total_Amount__c: 27200, Commission_Amount__c: 4896 },
50
+ { Id: "a20I5", Name: "INV-00005", Account__c: "001P2", Partner_Name: "Summit Hotels & Resorts", Status__c: "Paid", Invoice_Date__c: "2026-02-15", Due_Date__c: "2026-03-15", Period_Start__c: "2026-01-01", Period_End__c: "2026-01-31", Total_Amount__c: 21400, Commission_Amount__c: 3638 },
51
+ { Id: "a20I6", Name: "INV-00006", Account__c: "001P4", Partner_Name: "Metropolitan Hotels International", Status__c: "Paid", Invoice_Date__c: "2026-02-15", Due_Date__c: "2026-03-15", Period_Start__c: "2026-01-01", Period_End__c: "2026-01-31", Total_Amount__c: 18600, Commission_Amount__c: 2976 },
52
+ { Id: "a20I7", Name: "INV-00007", Account__c: "001P1", Partner_Name: "Grandview Hotel Group", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 26800, Commission_Amount__c: 4824 },
53
+ { Id: "a20I8", Name: "INV-00008", Account__c: "001P2", Partner_Name: "Summit Hotels & Resorts", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 22100, Commission_Amount__c: 3757 },
54
+ { Id: "a20I9", Name: "INV-00009", Account__c: "001P3", Partner_Name: "Pacific Coast Hospitality", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 14800, Commission_Amount__c: 2220 },
55
+ { Id: "a20I10", Name: "INV-00010", Account__c: "001P4", Partner_Name: "Metropolitan Hotels International", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 17200, Commission_Amount__c: 2752 },
56
+ { Id: "a20I11", Name: "INV-00011", Account__c: "001P5", Partner_Name: "Horizon Hospitality Group", Status__c: "Overdue", Invoice_Date__c: "2026-02-15", Due_Date__c: "2026-03-15", Period_Start__c: "2026-01-01", Period_End__c: "2026-01-31", Total_Amount__c: 9400, Commission_Amount__c: 1316 },
57
+ { Id: "a20I12", Name: "INV-00012", Account__c: "001P6", Partner_Name: "Riverside Inn Collection", Status__c: "Overdue", Invoice_Date__c: "2026-02-15", Due_Date__c: "2026-03-15", Period_Start__c: "2026-01-01", Period_End__c: "2026-01-31", Total_Amount__c: 5200, Commission_Amount__c: 624 },
58
+ { Id: "a20I13", Name: "INV-00013", Account__c: "001P7", Partner_Name: "Pinnacle Luxury Hotels", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 31200, Commission_Amount__c: 6240 },
59
+ { Id: "a20I14", Name: "INV-00014", Account__c: "001P8", Partner_Name: "Sterling Hotel Group", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 8900, Commission_Amount__c: 1157 },
60
+ { Id: "a20I15", Name: "INV-00015", Account__c: "001P5", Partner_Name: "Horizon Hospitality Group", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 10800, Commission_Amount__c: 1512 },
61
+ { Id: "a20I16", Name: "INV-00016", Account__c: "001P10", Partner_Name: "Continental Inn & Suites", Status__c: "Sent", Invoice_Date__c: "2026-03-15", Due_Date__c: "2026-04-15", Period_Start__c: "2026-02-01", Period_End__c: "2026-02-28", Total_Amount__c: 4200, Commission_Amount__c: 462 },
62
+ { Id: "a20I17", Name: "INV-00017", Account__c: "001P11", Partner_Name: "Skyline Hospitality", Status__c: "Draft", Invoice_Date__c: "2026-04-01", Due_Date__c: "2026-05-01", Period_Start__c: "2026-03-01", Period_End__c: "2026-03-31", Total_Amount__c: 11400, Commission_Amount__c: 1710 },
63
+ ];
64
+
65
+ // ─── ATTRITION PENALTIES ────────────────────────────────────────────────────
66
+ export const ATTRITION_PENALTIES = [
67
+ { Id: "a30A1", Name: "ATR-00001", Partner_Name: "Summit Hotels & Resorts", Property_Name: "Summit Austin Convention Center", Contract__c: "a10C2", Customer_Name: "TechCorp Inc.", Status__c: "Approved", Original_Room_Block__c: 50, Actual_Rooms_Used__c: 35, Unused_Rooms__c: 15, Room_Rate__c: 200, Number_of_Nights__c: 3, Rooms_Resold__c: 8, Penalty_Amount_Calculated__c: 9000, Resale_Credit_Applied__c: 0, Final_Penalty_Amount__c: 9000, Calculation_Method: "Per Night", Resale_Policy: "Partial Credit (50%)", Is_Hero: true },
68
+ { Id: "a30A2", Name: "ATR-00002", Partner_Name: "Pacific Coast Hospitality", Property_Name: "Pacific Coast Regency Chicago", Contract__c: "a10C3", Customer_Name: "GlobalTech Ltd.", Status__c: "Reviewed", Original_Room_Block__c: 30, Actual_Rooms_Used__c: 22, Unused_Rooms__c: 8, Room_Rate__c: 250, Number_of_Nights__c: 2, Rooms_Resold__c: 5, Penalty_Amount_Calculated__c: 4000, Resale_Credit_Applied__c: 1250, Final_Penalty_Amount__c: 2750, Calculation_Method: "Cumulative", Resale_Policy: "Partial Credit (50%)" },
69
+ { Id: "a30A3", Name: "ATR-00003", Partner_Name: "Grandview Hotel Group", Property_Name: "Grandview Marquis NYC", Contract__c: "a10C1", Customer_Name: "Acme Corp.", Status__c: "Approved", Original_Room_Block__c: 40, Actual_Rooms_Used__c: 30, Unused_Rooms__c: 10, Room_Rate__c: 300, Number_of_Nights__c: 2, Rooms_Resold__c: 4, Penalty_Amount_Calculated__c: 6000, Resale_Credit_Applied__c: 2400, Final_Penalty_Amount__c: 3600, Calculation_Method: "Per Night", Resale_Policy: "Full Credit" },
70
+ { Id: "a30A4", Name: "ATR-00004", Partner_Name: "Metropolitan Hotels International", Property_Name: "Metropolitan San Francisco", Contract__c: "a10C4", Customer_Name: "StartupX Inc.", Status__c: "Calculated", Original_Room_Block__c: 25, Actual_Rooms_Used__c: 18, Unused_Rooms__c: 7, Room_Rate__c: 275, Number_of_Nights__c: 1, Rooms_Resold__c: 3, Penalty_Amount_Calculated__c: 1925, Resale_Credit_Applied__c: 0, Final_Penalty_Amount__c: 1925, Calculation_Method: "Revenue Based", Resale_Policy: "No Credit" },
71
+ { Id: "a30A5", Name: "ATR-00005", Partner_Name: "Horizon Hospitality Group", Property_Name: "Horizon Grand Orlando", Contract__c: "a10C5", Customer_Name: "MediaCo LLC", Status__c: "Disputed", Original_Room_Block__c: 20, Actual_Rooms_Used__c: 14, Unused_Rooms__c: 6, Room_Rate__c: 150, Number_of_Nights__c: 2, Rooms_Resold__c: 4, Penalty_Amount_Calculated__c: 1800, Resale_Credit_Applied__c: 1200, Final_Penalty_Amount__c: 600, Calculation_Method: "Per Night", Resale_Policy: "Full Credit" },
72
+ { Id: "a30A6", Name: "ATR-00006", Partner_Name: "Sterling Hotel Group", Property_Name: "Sterling Aqua Chicago", Contract__c: "a10C8", Customer_Name: "FinanceFirst Corp.", Status__c: "Approved", Original_Room_Block__c: 35, Actual_Rooms_Used__c: 25, Unused_Rooms__c: 10, Room_Rate__c: 175, Number_of_Nights__c: 2, Rooms_Resold__c: 3, Penalty_Amount_Calculated__c: 3500, Resale_Credit_Applied__c: 525, Final_Penalty_Amount__c: 2975, Calculation_Method: "Per Night", Resale_Policy: "Partial Credit (50%)" },
73
+ ];
74
+
75
+ // ─── DISPUTES (Case with RecordType = Partner_Dispute) ──────────────────────
76
+ export const DISPUTES = [
77
+ { Id: "500D1", CaseNumber: "00001045", Subject: "ATR-00001 - Resale credit not applied", Partner_Name: "Summit Hotels & Resorts", Dispute_Type__c: "Resale Credit", Disputed_Amount__c: 2400, Status: "Open", Priority: "High", Agent_Handled__c: true, CreatedDate: "2026-04-02", Escalation_Reason__c: "$2,400 Partial Credit for 8 resold rooms was never applied to ATR-00001" },
78
+ { Id: "500D2", CaseNumber: "00001038", Subject: "ATR-00005 - Penalty exceeds contract terms", Partner_Name: "Horizon Hospitality Group", Dispute_Type__c: "Attrition Calculation", Disputed_Amount__c: 1200, Status: "Open", Priority: "Medium", Agent_Handled__c: false, CreatedDate: "2026-03-28", Escalation_Reason__c: "Partner claims full resale credit was not applied correctly" },
79
+ { Id: "500D3", CaseNumber: "00001032", Subject: "INV-00011 - Commission rate discrepancy", Partner_Name: "Horizon Hospitality Group", Dispute_Type__c: "Commission Rate", Disputed_Amount__c: 470, Status: "Open", Priority: "Low", Agent_Handled__c: false, CreatedDate: "2026-03-22", Escalation_Reason__c: "Invoice shows 12% rate but contract specifies 14%" },
80
+ { Id: "500D4", CaseNumber: "00001025", Subject: "INV-00006 - Duplicate line items", Partner_Name: "Metropolitan Hotels International", Dispute_Type__c: "Invoice Amount", Disputed_Amount__c: 2976, Status: "Resolved", Priority: "High", Agent_Handled__c: true, CreatedDate: "2026-03-15", Escalation_Reason__c: "Duplicate commission line items on January invoice" },
81
+ { Id: "500D5", CaseNumber: "00001018", Subject: "ATR-00002 - Threshold not met", Partner_Name: "Pacific Coast Hospitality", Dispute_Type__c: "Attrition Calculation", Disputed_Amount__c: 2750, Status: "Resolved", Priority: "Medium", Agent_Handled__c: true, CreatedDate: "2026-03-10", Escalation_Reason__c: "Usage was 73% (below 75% threshold), cumulative method applies" },
82
+ { Id: "500D6", CaseNumber: "00001010", Subject: "General - Contract renewal terms", Partner_Name: "Skyline Hospitality", Dispute_Type__c: "Other", Disputed_Amount__c: 0, Status: "Open", Priority: "Low", Agent_Handled__c: false, CreatedDate: "2026-03-05", Escalation_Reason__c: "Partner requesting revised commission rate for renewal" },
83
+ { Id: "500D7", CaseNumber: "00001005", Subject: "ATR-00004 - Revenue-based method questioned", Partner_Name: "Metropolitan Hotels International", Dispute_Type__c: "Attrition Calculation", Disputed_Amount__c: 1925, Status: "Escalated", Priority: "High", Agent_Handled__c: true, CreatedDate: "2026-02-28", Escalation_Reason__c: "Partner disagrees with revenue-based calculation, wants per-night method" },
84
+ ];
85
+
86
+ // ─── RECENT ACTIVITY (for ActivityCard / FeedPanel) ─────────────────────────
87
+ export const RECENT_ACTIVITY = [
88
+ { id: "act-1", title: "Guest Complaint Resolved", description: "Case #CS-1042: noise complaint at Summit Austin resolved, guest compensated with late checkout", status: "success", timestamp: "1 hour ago", partner: "Summit Hotels & Resorts" },
89
+ { id: "act-2", title: "Maintenance Request Created", description: "Summit SF Bay: HVAC unit replacement needed in conference room B, vendor dispatched", status: "info", timestamp: "3 hours ago", partner: "Summit Hotels & Resorts" },
90
+ { id: "act-3", title: "SLA Breach Warning", description: "Summit SF Bay: Case #CS-1038 approaching 4h response limit, needs immediate attention", status: "alert", timestamp: "4 hours ago", partner: "Summit Hotels & Resorts" },
91
+ { id: "act-4", title: "Guest Review Posted", description: "Summit Midtown NYC: 5-star review, 'Outstanding service, front desk went above and beyond'", status: "success", timestamp: "6 hours ago", partner: "Summit Hotels & Resorts" },
92
+ { id: "act-5", title: "Billing Dispute Opened", description: "Agent flagged $2,400 missing resale credit on ATR-00001 at Summit Austin", status: "warning", timestamp: "1 day ago", partner: "Summit Hotels & Resorts" },
93
+ { id: "act-6", title: "Case Escalated to Manager", description: "Case #CS-1035: repeated guest complaint about room cleanliness at Summit Chicago", status: "alert", timestamp: "1 day ago", partner: "Summit Hotels & Resorts" },
94
+ { id: "act-7", title: "Booking Modification Completed", description: "Group booking for TechCorp Inc. updated, 12 rooms added for Apr 20-22", status: "success", timestamp: "2 days ago", partner: "Summit Hotels & Resorts" },
95
+ { id: "act-8", title: "Monthly Service Report Ready", description: "March 2026 service performance report available, 94% SLA compliance across all properties", status: "info", timestamp: "3 days ago", partner: "Summit Hotels & Resorts" },
96
+ ];
97
+
98
+ // ─── DASHBOARD-READY DERIVATIVES ────────────────────────────────────────────
99
+
100
+ // KPI metrics
101
+ const activePartners = PARTNERS.filter(p => p.Partner_Status__c === "Active").length;
102
+ const totalRevenue = PARTNERS.reduce((sum, p) => sum + p.Total_Revenue__c, 0);
103
+ const openDisputes = DISPUTES.filter(d => d.Status === "Open" || d.Status === "Escalated").length;
104
+ const overdueInvoices = INVOICES.filter(i => i.Status__c === "Overdue").length;
105
+ const totalPenalties = ATTRITION_PENALTIES.reduce((sum, p) => sum + p.Final_Penalty_Amount__c, 0);
106
+ const avgCommission = (PARTNERS.filter(p => p.Partner_Status__c === "Active").reduce((sum, p) => sum + p.Commission_Rate__c, 0) / activePartners).toFixed(1);
107
+
108
+ export const METRICS = {
109
+ activePartners,
110
+ totalRevenue,
111
+ openDisputes,
112
+ overdueInvoices,
113
+ totalPenalties,
114
+ avgCommission,
115
+ totalProperties: PARTNERS.reduce((sum, p) => sum + p.Total_Properties__c, 0),
116
+ totalReservations: PARTNERS.reduce((sum, p) => sum + p.Total_Reservations__c, 0),
117
+ };
118
+
119
+ // ─── SUMMIT-SPECIFIC METRICS (for demo story) ──────────────────────────────
120
+ export const SUMMIT_METRICS = {
121
+ currentRevenue: 283000,
122
+ lastQuarterRevenue: 164000, // 45% growth
123
+ growthRate: 45, // percentage
124
+ projectedAnnualRevenue: 500000,
125
+ projectedCommission: 85000, // 17% commission rate
126
+ rank: 2, // #2 among Gold partners
127
+ totalGoldPartners: 4,
128
+ avgGoldPartnerRevenue: 258000,
129
+ percentileRank: 87, // Top 13% of all partners
130
+ propertiesGrowing: 4,
131
+ topProperty: "Summit Austin Convention Center",
132
+ topPropertyGrowth: 60,
133
+ topPropertyRevenue: 19800,
134
+ };
135
+
136
+ // Property leaderboard with rankings
137
+ export const PROPERTY_LEADERBOARD = [
138
+ {
139
+ rank: 1,
140
+ name: "Summit Austin Convention Center",
141
+ revenue: 97600,
142
+ latestRevenue: 19800,
143
+ growth: 60,
144
+ insight: "Highest booking volume through Engine, 41% of total",
145
+ satisfaction: 4.8,
146
+ responseTime: "1.8h",
147
+ openCases: 2,
148
+ resolvedThisMonth: 8,
149
+ },
150
+ {
151
+ rank: 2,
152
+ name: "Summit Midtown NYC",
153
+ revenue: 73100,
154
+ latestRevenue: 15200,
155
+ growth: 55,
156
+ insight: "Strong booking growth in Q1 2026",
157
+ satisfaction: 4.7,
158
+ responseTime: "2.1h",
159
+ openCases: 1,
160
+ resolvedThisMonth: 6,
161
+ },
162
+ {
163
+ rank: 3,
164
+ name: "Summit Chicago Downtown",
165
+ revenue: 59000,
166
+ latestRevenue: 12600,
167
+ growth: 75,
168
+ insight: "Fastest growing location, up 75% in 6 months",
169
+ satisfaction: 4.5,
170
+ responseTime: "2.6h",
171
+ openCases: 1,
172
+ resolvedThisMonth: 5,
173
+ },
174
+ {
175
+ rank: 4,
176
+ name: "Summit San Francisco Bay",
177
+ revenue: 53300,
178
+ latestRevenue: 10800,
179
+ growth: 100,
180
+ insight: "Bookings doubled since October, 100% growth",
181
+ satisfaction: 4.3,
182
+ responseTime: "3.2h",
183
+ openCases: 3,
184
+ resolvedThisMonth: 3,
185
+ },
186
+ ];
187
+
188
+ // Partner tier breakdown (for ChartCard - pie or bar)
189
+ export const PARTNER_TIER_CHART = [
190
+ { label: "Gold", value: PARTNERS.filter(p => p.Partner_Tier__c === "Gold").length, color: "#FFC107" },
191
+ { label: "Silver", value: PARTNERS.filter(p => p.Partner_Tier__c === "Silver").length, color: "#90A4AE" },
192
+ { label: "Bronze", value: PARTNERS.filter(p => p.Partner_Tier__c === "Bronze").length, color: "#CD7F32" },
193
+ ];
194
+
195
+ // Revenue by partner (for ChartCard - horizontal bar)
196
+ export const REVENUE_BY_PARTNER = PARTNERS
197
+ .filter(p => p.Total_Revenue__c > 0)
198
+ .sort((a, b) => b.Total_Revenue__c - a.Total_Revenue__c)
199
+ .map(p => ({ label: p.Name, value: p.Total_Revenue__c }));
200
+
201
+ // Monthly invoice trend (for ChartCard - line/area)
202
+ export const INVOICE_TREND = [
203
+ { month: "Dec 2025", total: 57500, commission: 9756 },
204
+ { month: "Jan 2026", total: 76600, commission: 12826 },
205
+ { month: "Feb 2026", total: 143400, commission: 22422 },
206
+ { month: "Mar 2026", total: 11400, commission: 1710 },
207
+ ];
208
+
209
+ // Attrition penalties for TableCard
210
+ export const PENALTY_TABLE_ITEMS = ATTRITION_PENALTIES.map(p => ({
211
+ id: p.Id,
212
+ name: p.Name,
213
+ partner: p.Partner_Name,
214
+ property: p.Property_Name,
215
+ customer: p.Customer_Name,
216
+ status: p.Status__c,
217
+ penalty: p.Final_Penalty_Amount__c,
218
+ credit: p.Resale_Credit_Applied__c,
219
+ method: p.Calculation_Method,
220
+ isHero: p.Is_Hero,
221
+ // Additional fields for modal display
222
+ originalRoomBlock: p.Original_Room_Block__c,
223
+ actualRoomsUsed: p.Actual_Rooms_Used__c,
224
+ unusedRooms: p.Unused_Rooms__c,
225
+ roomRate: p.Room_Rate__c,
226
+ numberOfNights: p.Number_of_Nights__c,
227
+ roomsResold: p.Rooms_Resold__c,
228
+ penaltyCalculated: p.Penalty_Amount_Calculated__c,
229
+ resalePolicy: p.Resale_Policy,
230
+ }));
231
+
232
+ // Dispute cards for ListCard
233
+ export const DISPUTE_CARDS = DISPUTES.filter(d => d.Status !== "Resolved").map(d => ({
234
+ id: d.Id,
235
+ title: d.Subject,
236
+ description: `${d.Partner_Name} · ${d.Dispute_Type__c}`,
237
+ status: d.Priority === "High" ? "critical" : d.Priority === "Medium" ? "warning" : "info",
238
+ badge: d.Status,
239
+ amount: d.Disputed_Amount__c,
240
+ agentHandled: d.Agent_Handled__c,
241
+ }));
242
+
243
+ // Invoice cards for ListCard
244
+ export const INVOICE_CARDS = INVOICES.filter(i => i.Status__c !== "Paid").map(i => ({
245
+ id: i.Id,
246
+ title: `${i.Name} - ${i.Partner_Name}`,
247
+ description: `${i.Period_Start__c} to ${i.Period_End__c}`,
248
+ status: i.Status__c === "Overdue" ? "critical" : i.Status__c === "Draft" ? "info" : "default",
249
+ badge: i.Status__c,
250
+ amount: i.Total_Amount__c,
251
+ due: i.Due_Date__c,
252
+ }));
253
+
254
+ // Revenue trend by property (for multi-line area chart)
255
+ // Summit Hotels & Resorts has 4 properties - monthly revenue per property
256
+ export const REVENUE_TREND_BY_PROPERTY = {
257
+ months: ["Oct 2025", "Nov 2025", "Dec 2025", "Jan 2026", "Feb 2026", "Mar 2026"],
258
+ properties: [
259
+ {
260
+ name: "Summit Austin Convention Center",
261
+ color: "#7DCBD9",
262
+ values: [13800, 13800, 15200, 16900, 18100, 19800],
263
+ },
264
+ {
265
+ name: "Summit Midtown NYC",
266
+ color: "#1E9D6D",
267
+ values: [9800, 10200, 11400, 12600, 13900, 15200],
268
+ },
269
+ {
270
+ name: "Summit Chicago Downtown",
271
+ color: "#157DE5",
272
+ values: [7200, 8100, 9600, 10400, 11100, 12600],
273
+ },
274
+ {
275
+ name: "Summit San Francisco Bay",
276
+ color: "#FFB200",
277
+ values: [5400, 6200, 7100, 8800, 10800, 15000],
278
+ },
279
+ ],
280
+ };
281
+
282
+ // Contract expiration (upcoming 6 months)
283
+ export const EXPIRING_CONTRACTS = CONTRACTS
284
+ .filter(c => {
285
+ const end = new Date(c.End_Date__c);
286
+ const now = new Date("2026-04-01");
287
+ const sixMonths = new Date("2026-10-01");
288
+ return c.Status__c === "Active" && end >= now && end <= sixMonths;
289
+ })
290
+ .sort((a, b) => new Date(a.End_Date__c) - new Date(b.End_Date__c))
291
+ .map(c => ({
292
+ id: c.Id,
293
+ title: `${c.Name} - ${c.Partner_Name}`,
294
+ description: `Expires ${c.End_Date__c} · ${c.Attrition_Calculation_Method__c} · ${c.Resale_Credit_Policy__c}`,
295
+ status: "warning",
296
+ badge: c.End_Date__c,
297
+ }));