chordia-ui 3.7.2 → 3.7.4

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.
Files changed (36) hide show
  1. package/dist/CustomFilterChips.cjs.js +1 -1
  2. package/dist/CustomFilterChips.cjs.js.map +1 -1
  3. package/dist/CustomFilterChips.es.js +239 -125
  4. package/dist/CustomFilterChips.es.js.map +1 -1
  5. package/dist/DataTable2.cjs.js +2 -0
  6. package/dist/DataTable2.cjs.js.map +1 -0
  7. package/dist/DataTable2.es.js +1863 -0
  8. package/dist/DataTable2.es.js.map +1 -0
  9. package/dist/components/UpdatedInteractionDetails.cjs.js +2 -2
  10. package/dist/components/UpdatedInteractionDetails.cjs.js.map +1 -1
  11. package/dist/components/UpdatedInteractionDetails.es.js +14 -13
  12. package/dist/components/UpdatedInteractionDetails.es.js.map +1 -1
  13. package/dist/components/data.cjs.js +1 -1
  14. package/dist/components/data.cjs.js.map +1 -1
  15. package/dist/components/data.es.js +157 -153
  16. package/dist/components/data.es.js.map +1 -1
  17. package/dist/components/performance.cjs.js +1 -1
  18. package/dist/components/performance.cjs.js.map +1 -1
  19. package/dist/components/performance.es.js +1900 -480
  20. package/dist/components/performance.es.js.map +1 -1
  21. package/dist/index.cjs.js +1 -1
  22. package/dist/index.es.js +94 -89
  23. package/dist/index.es.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/components/UpdatedInteractionDetails/UpdatedInteractionDetails.jsx +13 -13
  26. package/src/components/UpdatedInteractionDetails/UpdatedThreads.jsx +1 -0
  27. package/src/components/common/CustomFilterChips.jsx +5 -1
  28. package/src/components/common/Pagination.jsx +152 -39
  29. package/src/components/data/DataTable2.jsx +2449 -0
  30. package/src/components/data/DataTableFilters2.jsx +186 -0
  31. package/src/components/data/index.js +2 -0
  32. package/src/components/index.js +2 -2
  33. package/src/components/performance/PerformanceDetailsPage.jsx +940 -0
  34. package/src/components/performance/PerformancePanel.jsx +423 -297
  35. package/src/components/performance/SupervisorSelect.jsx +386 -0
  36. package/src/components/performance/index.js +3 -1
@@ -0,0 +1,940 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import {
5
+ ArrowLeft,
6
+ ArrowRight,
7
+ Calendar,
8
+ Download,
9
+ Phone,
10
+ ChevronDown,
11
+ ChevronUp,
12
+ ChevronLeft,
13
+ ChevronRight,
14
+ TrendingUp,
15
+ Lightbulb,
16
+ ShieldCheck,
17
+ FolderKanban,
18
+ Layers,
19
+ } from "lucide-react";
20
+ import DataTable2 from "../data/DataTable2";
21
+
22
+ const C = {
23
+ ink: "#2E3236",
24
+ muted: "#808183",
25
+ border: "#D9D9D9",
26
+ borderSubtle: "#E6E6E6",
27
+ iconCircle: "#F3F7F7",
28
+ black: "#0B0B0B",
29
+ white: "#FFFFFF",
30
+ neutralBorder: "#BFBFBF",
31
+ neutral800: "#323232",
32
+ neutral600: "#676767",
33
+ neutral450: "#8B8B8B",
34
+ neutral400: "#989898",
35
+ neutral300: "#B2B2B0",
36
+ neutral150: "#D8D8D8",
37
+ neutral100: "#E6E6E6",
38
+ beige: "rgba(243, 241, 229, 0.4)",
39
+ };
40
+
41
+ const FONT_DISPLAY = "var(--font-sans, 'Averta', ui-sans-serif, system-ui, sans-serif)";
42
+ const FONT_BODY = "var(--font-sans, 'Averta', ui-sans-serif, system-ui, sans-serif)";
43
+
44
+ function Sparkline({ trend = "up", width = 49.618, height = 35 }) {
45
+ const id = React.useId();
46
+ const linePath =
47
+ "M1.00049 13.5213C7.85975 11.7032 8.88149 4.73912 13.7838 4.73912C19.8344 4.73912 23.6237 17.166 29.1281 17.166C34.5998 17.166 37.4149 4.88121 43.4004 8.61051C47.9764 11.4616 50.6186 1.00024 50.6186 1.00024";
48
+ const areaPath =
49
+ "M1.00049 16.692C8.88149 15.6975 8.88149 7.79403 13.7838 7.79403C19.8344 7.79403 23.6237 21.4034 29.1281 21.4034C34.5998 21.4034 37.4149 8.93821 43.4004 12.7223C47.9764 15.6152 50.6186 5.00024 50.6186 5.00024V36.0002C50.6186 36.0002 10.8223 36.0002 1.00049 36.0002C1.00049 28.8653 1.00049 19.4871 1.00049 16.692Z";
50
+ return (
51
+ <svg
52
+ width={width}
53
+ height={height}
54
+ viewBox="0 0 52 36"
55
+ fill="none"
56
+ style={{
57
+ flexShrink: 0,
58
+ transform: trend === "down" ? "scaleX(-1)" : undefined,
59
+ }}
60
+ >
61
+ <defs>
62
+ <linearGradient
63
+ id={`spark-${id}`}
64
+ x1="9.96776"
65
+ y1="16.2053"
66
+ x2="9.96776"
67
+ y2="36.0002"
68
+ gradientUnits="userSpaceOnUse"
69
+ >
70
+ <stop stopColor={C.ink} />
71
+ <stop offset="1" stopColor={C.white} stopOpacity="0.01" />
72
+ </linearGradient>
73
+ </defs>
74
+ <path
75
+ d={areaPath}
76
+ fill={`url(#spark-${id})`}
77
+ fillRule="evenodd"
78
+ clipRule="evenodd"
79
+ opacity="0.1"
80
+ />
81
+ <path
82
+ d={linePath}
83
+ stroke={C.ink}
84
+ strokeWidth="2"
85
+ fill="none"
86
+ strokeLinecap="round"
87
+ strokeLinejoin="round"
88
+ strokeDasharray={trend === "down" ? "2 4" : undefined}
89
+ />
90
+ </svg>
91
+ );
92
+ }
93
+
94
+ function KpiCell({ value, label, sub, trend = "up" }) {
95
+ return (
96
+ <div
97
+ style={{
98
+ flex: 1,
99
+ display: "flex",
100
+ alignItems: "center",
101
+ gap: 16,
102
+ minWidth: 0,
103
+ }}
104
+ >
105
+ <Sparkline trend={trend} />
106
+ <div style={{ display: "flex", flexDirection: "column", gap: 6, minWidth: 0 }}>
107
+ <div
108
+ style={{
109
+ fontFamily: FONT_DISPLAY,
110
+ fontSize: 28,
111
+ fontWeight: 400,
112
+ lineHeight: "1.2",
113
+ color: C.muted,
114
+ letterSpacing: "-0.01em",
115
+ whiteSpace: "nowrap",
116
+ }}
117
+ >
118
+ {value}
119
+ </div>
120
+ <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
121
+ <span
122
+ style={{
123
+ fontFamily: FONT_BODY,
124
+ fontSize: 13,
125
+ color: C.ink,
126
+ lineHeight: "1.2",
127
+ }}
128
+ >
129
+ {label}
130
+ </span>
131
+ <span
132
+ style={{
133
+ fontFamily: FONT_BODY,
134
+ fontSize: 13,
135
+ color: C.neutral600,
136
+ lineHeight: "1.2",
137
+ }}
138
+ >
139
+ {sub}
140
+ </span>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ );
145
+ }
146
+
147
+ function RangeChip({ label, active = false }) {
148
+ return (
149
+ <button
150
+ type="button"
151
+ style={{
152
+ height: 32,
153
+ minWidth: 31,
154
+ padding: "0 12px",
155
+ borderRadius: 10,
156
+ border: active ? "none" : `1px solid ${C.borderSubtle}`,
157
+ background: active ? C.black : C.white,
158
+ color: active ? C.white : C.black,
159
+ fontFamily: FONT_BODY,
160
+ fontSize: 14,
161
+ cursor: "pointer",
162
+ }}
163
+ >
164
+ {label}
165
+ </button>
166
+ );
167
+ }
168
+
169
+ function FilterButton({ icon: Icon, children }) {
170
+ return (
171
+ <button
172
+ type="button"
173
+ style={{
174
+ display: "inline-flex",
175
+ alignItems: "center",
176
+ gap: 8,
177
+ height: 32,
178
+ padding: "0 16px",
179
+ borderRadius: 10,
180
+ border: `1px solid ${C.neutralBorder}`,
181
+ background: C.white,
182
+ cursor: "pointer",
183
+ fontFamily: FONT_BODY,
184
+ fontSize: 14,
185
+ color: C.neutral800,
186
+ whiteSpace: "nowrap",
187
+ }}
188
+ >
189
+ {Icon && <Icon size={18} strokeWidth={1.75} />}
190
+ {children}
191
+ </button>
192
+ );
193
+ }
194
+
195
+ const DEFAULT_LINE_POINTS = [
196
+ [0, 30],
197
+ [60, 50],
198
+ [120, 95],
199
+ [180, 60],
200
+ [240, 70],
201
+ [300, 80],
202
+ ];
203
+
204
+ function CompassLineChart({
205
+ yLabels = ["4.6", "4.4", "4.2", "4.0", "3.9"],
206
+ xLabels = ["Mar 16", "Mar 23", "Mar 30", "Apr 6", "Apr 13", "Apr 15"],
207
+ // points: array of [x, y] pairs OR array of y-numbers (auto-distributed in x).
208
+ // y is in pixel space 0..height (top to bottom). x is auto-scaled to the chart width.
209
+ points = DEFAULT_LINE_POINTS,
210
+ // index of the marker to render filled (defaults to the last point)
211
+ highlightIndex,
212
+ }) {
213
+ const width = 460;
214
+ const height = 110;
215
+ const normalized = (Array.isArray(points) && points.length > 0)
216
+ ? (Array.isArray(points[0])
217
+ ? points
218
+ : points.map((y, i) => [i, y]))
219
+ : DEFAULT_LINE_POINTS;
220
+ const minX = normalized[0][0];
221
+ const maxX = normalized[normalized.length - 1][0];
222
+ const xSpan = maxX - minX || 1;
223
+ const sx = (x) => ((x - minX) / xSpan) * width;
224
+ const linePath = normalized
225
+ .map(([x, y], i) => `${i === 0 ? "M" : "L"}${sx(x)},${y}`)
226
+ .join(" ");
227
+ const areaPath = `${linePath} L${sx(normalized[normalized.length - 1][0])},${height} L${sx(normalized[0][0])},${height} Z`;
228
+ const gradId = React.useId();
229
+ const highlight = highlightIndex == null ? normalized.length - 1 : highlightIndex;
230
+ // Vertical grid lines at evenly-spaced x-label positions (not every data point)
231
+ const gridCount = Math.max(2, xLabels.length);
232
+ const gridXs = Array.from({ length: gridCount }, (_, i) => (i / (gridCount - 1)) * width);
233
+ return (
234
+ <div style={{ display: "flex", gap: 8, height: 133, width: "100%" }}>
235
+ <div
236
+ style={{
237
+ display: "flex",
238
+ flexDirection: "column",
239
+ justifyContent: "space-between",
240
+ padding: "14px 0",
241
+ fontFamily: FONT_BODY,
242
+ fontSize: 10,
243
+ color: C.neutral800,
244
+ flexShrink: 0,
245
+ }}
246
+ >
247
+ {yLabels.map((l) => (
248
+ <span key={l}>{l}</span>
249
+ ))}
250
+ </div>
251
+ <div style={{ flex: 1, position: "relative", minWidth: 0 }}>
252
+ <svg
253
+ width="100%"
254
+ height={height + 14}
255
+ viewBox={`0 0 ${width} ${height + 14}`}
256
+ preserveAspectRatio="none"
257
+ >
258
+ <defs>
259
+ <linearGradient id={`area-${gradId}`} x1="0" y1="0" x2="0" y2="1">
260
+ <stop offset="0%" stopColor="#0B0B0B" stopOpacity="0.08" />
261
+ <stop offset="100%" stopColor="#0B0B0B" stopOpacity="0" />
262
+ </linearGradient>
263
+ </defs>
264
+ {gridXs.map((gx, i) => (
265
+ <line
266
+ key={`grid-${i}`}
267
+ x1={gx}
268
+ y1="0"
269
+ x2={gx}
270
+ y2={height}
271
+ stroke={C.borderSubtle}
272
+ strokeDasharray="2 3"
273
+ strokeWidth="1"
274
+ vectorEffect="non-scaling-stroke"
275
+ />
276
+ ))}
277
+ <path d={areaPath} fill={`url(#area-${gradId})`} />
278
+ <path
279
+ d={linePath}
280
+ stroke={C.black}
281
+ strokeWidth="1.5"
282
+ fill="none"
283
+ strokeLinecap="round"
284
+ strokeLinejoin="round"
285
+ vectorEffect="non-scaling-stroke"
286
+ />
287
+ {normalized.map(([x, y], i) => {
288
+ const isHighlight = i === highlight;
289
+ return (
290
+ <circle
291
+ key={i}
292
+ cx={sx(x)}
293
+ cy={y}
294
+ r={isHighlight ? 4 : 3}
295
+ fill={isHighlight ? C.black : C.white}
296
+ stroke={C.black}
297
+ strokeWidth="1.5"
298
+ vectorEffect="non-scaling-stroke"
299
+ />
300
+ );
301
+ })}
302
+ </svg>
303
+ <div
304
+ style={{
305
+ display: "flex",
306
+ justifyContent: "space-between",
307
+ paddingRight: 6,
308
+ fontFamily: FONT_BODY,
309
+ fontSize: 10,
310
+ color: C.neutral800,
311
+ marginTop: 6,
312
+ }}
313
+ >
314
+ {xLabels.map((l) => (
315
+ <span key={l}>{l}</span>
316
+ ))}
317
+ </div>
318
+ </div>
319
+ </div>
320
+ );
321
+ }
322
+
323
+ function ChartCard({ title, value, delta, children }) {
324
+ return (
325
+ <div
326
+ style={{
327
+ flex: 1,
328
+ background: C.white,
329
+ border: `1px solid ${C.border}`,
330
+ borderRadius: 8,
331
+ padding: 24,
332
+ display: "flex",
333
+ flexDirection: "column",
334
+ gap: 24,
335
+ minWidth: 0,
336
+ boxShadow: "0 1px 2px rgba(11, 11, 11, 0.04), 0 4px 12px rgba(11, 11, 11, 0.06)",
337
+ }}
338
+ >
339
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end" }}>
340
+ <span
341
+ style={{
342
+ fontFamily: FONT_DISPLAY,
343
+ fontWeight: 700,
344
+ fontSize: 15,
345
+ color: C.ink,
346
+ lineHeight: 1.2,
347
+ }}
348
+ >
349
+ {title}
350
+ </span>
351
+ <span
352
+ style={{
353
+ display: "inline-flex",
354
+ alignItems: "flex-end",
355
+ gap: 4,
356
+ fontFamily: FONT_DISPLAY,
357
+ fontWeight: 600,
358
+ }}
359
+ >
360
+ <span style={{ fontSize: 20, color: C.black, lineHeight: 1 }}>{value}</span>
361
+ <span style={{ fontSize: 10, color: C.neutral300, lineHeight: 1 }}>{delta}</span>
362
+ </span>
363
+ </div>
364
+ <div style={{ flex: 1 }}>{children}</div>
365
+ </div>
366
+ );
367
+ }
368
+
369
+ function SectionHeading({ icon: Icon, title, trailing, iconColor = C.ink, bordered = false }) {
370
+ return (
371
+ <div
372
+ style={{
373
+ display: "flex",
374
+ alignItems: "center",
375
+ gap: 8,
376
+ width: "100%",
377
+ paddingBottom: bordered ? 12 : 0,
378
+ borderBottom: bordered ? `1px solid ${C.border}` : "none",
379
+ }}
380
+ >
381
+ <div
382
+ style={{
383
+ width: 24,
384
+ height: 24,
385
+ display: "flex",
386
+ alignItems: "center",
387
+ justifyContent: "center",
388
+ flexShrink: 0,
389
+ }}
390
+ >
391
+ <Icon size={22} color={iconColor} strokeWidth={1.75} />
392
+ </div>
393
+ <div
394
+ style={{
395
+ flex: 1,
396
+ fontFamily: FONT_DISPLAY,
397
+ fontWeight: 600,
398
+ fontSize: 16,
399
+ color: C.ink,
400
+ lineHeight: 1.2,
401
+ textTransform: "uppercase",
402
+ letterSpacing: "0.02em",
403
+ }}
404
+ >
405
+ {title}
406
+ </div>
407
+ {trailing && (
408
+ <div style={{ fontFamily: FONT_BODY, fontSize: 14, color: C.ink }}>{trailing}</div>
409
+ )}
410
+ </div>
411
+ );
412
+ }
413
+
414
+ function CitationRow({ bullet, citation, date }) {
415
+ return (
416
+ <div
417
+ style={{
418
+ display: "flex",
419
+ justifyContent: "space-between",
420
+ alignItems: "center",
421
+ fontFamily: FONT_BODY,
422
+ fontSize: 14,
423
+ color: C.ink,
424
+ lineHeight: "24px",
425
+ }}
426
+ >
427
+ <span>{bullet}</span>
428
+ <span style={{ display: "inline-flex", gap: 4 }}>
429
+ <span>{citation}</span>
430
+ <span style={{ color: C.muted }}>({date})</span>
431
+ </span>
432
+ </div>
433
+ );
434
+ }
435
+
436
+ function AccordionRow({ title, summary, calls, delta, expanded = false, bullets }) {
437
+ return (
438
+ <div
439
+ style={{
440
+ borderTop: `1px solid ${C.border}`,
441
+ padding: 16,
442
+ display: "flex",
443
+ gap: 12,
444
+ alignItems: "flex-start",
445
+ cursor: "pointer",
446
+ }}
447
+ >
448
+ <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: expanded ? 16 : 12, minWidth: 0 }}>
449
+ <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
450
+ <span
451
+ style={{
452
+ fontFamily: FONT_BODY,
453
+ fontWeight: 500,
454
+ fontSize: 14,
455
+ color: C.black,
456
+ lineHeight: "24px",
457
+ }}
458
+ >
459
+ {title}
460
+ </span>
461
+ <span style={{ fontFamily: FONT_BODY, fontSize: 14, color: C.muted, lineHeight: "24px" }}>
462
+ {summary}
463
+ </span>
464
+ </div>
465
+ {expanded && bullets && (
466
+ <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
467
+ {bullets.map((b, i) => (
468
+ <CitationRow key={i} {...b} />
469
+ ))}
470
+ </div>
471
+ )}
472
+ <div style={{ display: "flex", gap: 16 }}>
473
+ <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
474
+ <Phone size={12} color={C.ink} strokeWidth={1.75} />
475
+ <span style={{ fontFamily: FONT_BODY, fontSize: 12, color: C.ink }}>{calls}</span>
476
+ </div>
477
+ <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
478
+ <TrendingUp size={12} color={C.ink} strokeWidth={1.75} />
479
+ <span style={{ fontFamily: FONT_BODY, fontSize: 12, color: C.ink }}>{delta}</span>
480
+ </div>
481
+ </div>
482
+ </div>
483
+ {expanded ? (
484
+ <ChevronUp size={20} color={C.ink} strokeWidth={2} />
485
+ ) : (
486
+ <ChevronDown size={20} color={C.ink} strokeWidth={2} />
487
+ )}
488
+ </div>
489
+ );
490
+ }
491
+
492
+ function PercentRow({ label, value }) {
493
+ return (
494
+ <div
495
+ style={{
496
+ display: "flex",
497
+ justifyContent: "space-between",
498
+ alignItems: "center",
499
+ padding: "8px 8px 12px",
500
+ borderBottom: `1px solid ${C.border}`,
501
+ fontFamily: FONT_BODY,
502
+ fontSize: 13,
503
+ lineHeight: "1.2",
504
+ }}
505
+ >
506
+ <span style={{ color: C.ink }}>{label}</span>
507
+ <span style={{ color: C.muted }}>{value}</span>
508
+ </div>
509
+ );
510
+ }
511
+
512
+ function CompassDots({ value = 0, max = 5 }) {
513
+ const v = typeof value === "number" ? value : parseFloat(value) || 0;
514
+ const full = Math.floor(v);
515
+ const hasPartial = v % 1 > 0 && full < max;
516
+ return (
517
+ <div style={{ display: "flex", gap: 4 }}>
518
+ {Array.from({ length: max }).map((_, i) => {
519
+ if (i < full) {
520
+ return (
521
+ <span
522
+ key={i}
523
+ style={{
524
+ width: 10,
525
+ height: 10,
526
+ borderRadius: "50%",
527
+ background: C.black,
528
+ display: "inline-block",
529
+ }}
530
+ />
531
+ );
532
+ }
533
+ if (i === full && hasPartial) {
534
+ return (
535
+ <span
536
+ key={i}
537
+ style={{
538
+ width: 10,
539
+ height: 10,
540
+ borderRadius: "50%",
541
+ display: "inline-flex",
542
+ alignItems: "center",
543
+ justifyContent: "center",
544
+ }}
545
+ >
546
+ <span
547
+ style={{
548
+ width: 6,
549
+ height: 6,
550
+ borderRadius: "50%",
551
+ background: C.black,
552
+ display: "inline-block",
553
+ }}
554
+ />
555
+ </span>
556
+ );
557
+ }
558
+ return (
559
+ <span
560
+ key={i}
561
+ style={{
562
+ width: 10,
563
+ height: 10,
564
+ borderRadius: "50%",
565
+ background: C.white,
566
+ border: `1px solid ${C.border}`,
567
+ display: "inline-block",
568
+ boxSizing: "border-box",
569
+ }}
570
+ />
571
+ );
572
+ })}
573
+ </div>
574
+ );
575
+ }
576
+
577
+ export const DEFAULT_SESSION_COLUMNS = [
578
+ { id: "title", label: "Title", width: 220, sortable: true, filterable: true },
579
+ { id: "date", label: "Date", width: 170, sortable: true },
580
+ { id: "duration", label: "Duration", width: 170, sortable: true },
581
+ { id: "lift", label: "Lift", width: 120, sortable: true },
582
+ {
583
+ id: "compass",
584
+ label: "Compass Score",
585
+ width: 220,
586
+ sortable: true,
587
+ render: (value) => {
588
+ const num = typeof value === "number" ? value : parseFloat(value) || 0;
589
+ return (
590
+ <span style={{ display: "inline-flex", alignItems: "center", gap: 12 }}>
591
+ <span style={{ minWidth: 32 }}>{value}</span>
592
+ <CompassDots value={num} />
593
+ </span>
594
+ );
595
+ },
596
+ },
597
+ ];
598
+
599
+
600
+ function SubSectionHeading({ icon: Icon, title }) {
601
+ return (
602
+ <div style={{ display: "flex", alignItems: "center", gap: 16, width: "100%" }}>
603
+ <div
604
+ style={{
605
+ width: 34,
606
+ height: 34,
607
+ borderRadius: 9999,
608
+ background: C.iconCircle,
609
+ display: "flex",
610
+ alignItems: "center",
611
+ justifyContent: "center",
612
+ flexShrink: 0,
613
+ }}
614
+ >
615
+ <Icon size={20} color={C.ink} strokeWidth={1.75} />
616
+ </div>
617
+ <span
618
+ style={{
619
+ fontFamily: FONT_DISPLAY,
620
+ fontWeight: 600,
621
+ fontSize: 16,
622
+ color: C.ink,
623
+ lineHeight: 1.2,
624
+ }}
625
+ >
626
+ {title}
627
+ </span>
628
+ </div>
629
+ );
630
+ }
631
+
632
+ export default function PerformanceDetailsPage({
633
+ agentName = "",
634
+ startDate = "",
635
+ endDate = "",
636
+ totalCalls = "",
637
+ onBack,
638
+ className = "",
639
+ // KPI strip
640
+ kpiBaseline = { value: "", label: "", sub: "", trend: "up" },
641
+ kpiAgentLift = { value: "", label: "", sub: "", trend: "down" },
642
+ kpiScore = { value: "", label: "", sub: "", trend: "up" },
643
+ // Chart cards (Baseline / Agent Lift / Score / CSAT / Volume)
644
+ // Each takes { value, delta, yLabels?, xLabels?, points? }.
645
+ // points is an array of [x, y] pairs OR a flat array of y-numbers.
646
+ baselineChart = { value: "", delta: "" },
647
+ agentLiftChart = { value: "", delta: "" },
648
+ scoreChart = { value: "", delta: "" },
649
+ csatChart = { value: "", delta: "" },
650
+ volumeChart = { value: "", delta: "" },
651
+ // Insight sections
652
+ guidanceItems = [],
653
+ strengthItems = [],
654
+ callDrivers = [],
655
+ callParadigms = [],
656
+ // Sessions table
657
+ sessions = [],
658
+ sessionColumns = [],
659
+ initialPageSize = 10,
660
+ }) {
661
+ return (
662
+ <div
663
+ className={className}
664
+ style={{
665
+ background: C.white,
666
+ fontFamily: FONT_BODY,
667
+ color: C.ink,
668
+ width: "100%",
669
+ minWidth: 1192,
670
+ boxSizing: "border-box",
671
+ display: "flex",
672
+ flexDirection: "column",
673
+ }}
674
+ >
675
+ <div
676
+ style={{
677
+ display: "flex",
678
+ alignItems: "center",
679
+ gap: 8,
680
+ padding: "23px 32px",
681
+ minHeight: 78,
682
+ boxSizing: "border-box",
683
+ }}
684
+ >
685
+ <button
686
+ type="button"
687
+ aria-label="Back"
688
+ onClick={onBack}
689
+ style={{
690
+ display: "inline-flex",
691
+ alignItems: "center",
692
+ justifyContent: "center",
693
+ width: 24,
694
+ height: 24,
695
+ background: "transparent",
696
+ border: "none",
697
+ cursor: "pointer",
698
+ color: C.ink,
699
+ padding: 0,
700
+ flexShrink: 0,
701
+ }}
702
+ >
703
+ <ArrowLeft size={20} strokeWidth={1.75} />
704
+ </button>
705
+ <div
706
+ style={{
707
+ paddingLeft: 16,
708
+ borderLeft: `1px solid ${C.border}`,
709
+ flex: 1,
710
+ minWidth: 0,
711
+ alignSelf: "stretch",
712
+ display: "flex",
713
+ alignItems: "center",
714
+ }}
715
+ >
716
+ <h1
717
+ style={{
718
+ fontFamily: FONT_DISPLAY,
719
+ fontSize: 24,
720
+ fontWeight: 400,
721
+ color: C.ink,
722
+ margin: 0,
723
+ lineHeight: 1,
724
+ whiteSpace: "nowrap",
725
+ }}
726
+ >
727
+ {agentName}
728
+ </h1>
729
+ </div>
730
+ <button
731
+ type="button"
732
+ style={{
733
+ display: "inline-flex",
734
+ alignItems: "center",
735
+ gap: 8,
736
+ height: 32,
737
+ padding: "0 16px",
738
+ borderRadius: 10,
739
+ border: `1px solid ${C.neutralBorder}`,
740
+ background: C.white,
741
+ cursor: "pointer",
742
+ fontFamily: FONT_BODY,
743
+ fontSize: 14,
744
+ lineHeight: "24px",
745
+ color: C.neutral800,
746
+ flexShrink: 0,
747
+ }}
748
+ >
749
+ <Download size={18} strokeWidth={1.75} />
750
+ Export Data
751
+ </button>
752
+ </div>
753
+
754
+ <div
755
+ style={{
756
+ padding: "0 32px 32px",
757
+ display: "flex",
758
+ flexDirection: "column",
759
+ gap: 16,
760
+ }}
761
+ >
762
+ <div
763
+ style={{
764
+ display: "flex",
765
+ justifyContent: "space-between",
766
+ alignItems: "center",
767
+ gap: 16,
768
+ paddingLeft: 49,
769
+ }}
770
+ >
771
+ <div style={{ display: "flex", gap: 16, alignItems: "center" }}>
772
+ <div style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
773
+ <Calendar size={14} color={C.ink} strokeWidth={1.75} style={{ flexShrink: 0 }} />
774
+ <span
775
+ style={{
776
+ fontFamily: FONT_BODY,
777
+ fontSize: 12,
778
+ color: C.ink,
779
+ lineHeight: 1.5,
780
+ }}
781
+ >
782
+ {startDate}
783
+ </span>
784
+ <ArrowRight size={12} color={C.ink} strokeWidth={1.75} style={{ flexShrink: 0 }} />
785
+ <span
786
+ style={{
787
+ fontFamily: FONT_BODY,
788
+ fontSize: 12,
789
+ color: C.ink,
790
+ lineHeight: 1.5,
791
+ }}
792
+ >
793
+ {endDate}
794
+ </span>
795
+ </div>
796
+ <div style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
797
+ <Phone size={14} color={C.ink} strokeWidth={1.75} style={{ flexShrink: 0 }} />
798
+ <span
799
+ style={{
800
+ fontFamily: FONT_BODY,
801
+ fontSize: 12,
802
+ color: C.ink,
803
+ lineHeight: 1.5,
804
+ }}
805
+ >
806
+ {totalCalls}
807
+ </span>
808
+ </div>
809
+ </div>
810
+ <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
811
+ <RangeChip label="8h" />
812
+ <RangeChip label="1d" />
813
+ <RangeChip label="7d" />
814
+ <RangeChip label="30d" active />
815
+ <FilterButton icon={Calendar}>Date Range</FilterButton>
816
+ </div>
817
+ </div>
818
+
819
+ <div
820
+ style={{
821
+ background: C.beige,
822
+ border: `1px solid ${C.border}`,
823
+ borderRadius: 8,
824
+ padding: 16,
825
+ display: "flex",
826
+ gap: 24,
827
+ alignItems: "center",
828
+ }}
829
+ >
830
+ <KpiCell value={kpiBaseline.value} label={kpiBaseline.label} sub={kpiBaseline.sub} trend={kpiBaseline.trend} />
831
+ <ArrowRight size={20} color={C.ink} strokeWidth={1.75} style={{ flexShrink: 0 }} />
832
+ <KpiCell value={kpiAgentLift.value} label={kpiAgentLift.label} sub={kpiAgentLift.sub} trend={kpiAgentLift.trend} />
833
+ <ArrowRight size={20} color={C.ink} strokeWidth={1.75} style={{ flexShrink: 0 }} />
834
+ <KpiCell value={kpiScore.value} label={kpiScore.label} sub={kpiScore.sub} trend={kpiScore.trend} />
835
+ </div>
836
+
837
+ <div style={{ display: "flex", gap: 24 }}>
838
+ <ChartCard title="Baseline" value={baselineChart.value} delta={baselineChart.delta}>
839
+ <CompassLineChart
840
+ yLabels={baselineChart.yLabels}
841
+ xLabels={baselineChart.xLabels}
842
+ points={baselineChart.points}
843
+ />
844
+ </ChartCard>
845
+ <ChartCard title="Agent Lift" value={agentLiftChart.value} delta={agentLiftChart.delta}>
846
+ <CompassLineChart
847
+ yLabels={agentLiftChart.yLabels}
848
+ xLabels={agentLiftChart.xLabels}
849
+ points={agentLiftChart.points}
850
+ />
851
+ </ChartCard>
852
+ <ChartCard title="Score" value={scoreChart.value} delta={scoreChart.delta}>
853
+ <CompassLineChart
854
+ yLabels={scoreChart.yLabels}
855
+ xLabels={scoreChart.xLabels}
856
+ points={scoreChart.points}
857
+ />
858
+ </ChartCard>
859
+ </div>
860
+
861
+ <div style={{ display: "flex", gap: 24 }}>
862
+ <ChartCard title="CSAT" value={csatChart.value} delta={csatChart.delta}>
863
+ <CompassLineChart
864
+ yLabels={csatChart.yLabels}
865
+ xLabels={csatChart.xLabels}
866
+ points={csatChart.points}
867
+ />
868
+ </ChartCard>
869
+ <ChartCard title="Volume" value={volumeChart.value} delta={volumeChart.delta}>
870
+ <CompassLineChart
871
+ yLabels={volumeChart.yLabels}
872
+ xLabels={volumeChart.xLabels}
873
+ points={volumeChart.points}
874
+ />
875
+ </ChartCard>
876
+ </div>
877
+
878
+ <div style={{ display: "flex", gap: 24, marginTop: 8 }}>
879
+ <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 16, minWidth: 0 }}>
880
+ <SectionHeading icon={Lightbulb} title="Guidance" iconColor="#F4B400" />
881
+ <div style={{ display: "flex", flexDirection: "column" }}>
882
+ {guidanceItems.map((item, i) => (
883
+ <AccordionRow key={i} {...item} />
884
+ ))}
885
+ </div>
886
+ </div>
887
+ <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 16, minWidth: 0 }}>
888
+ <SectionHeading icon={ShieldCheck} title="Strengths" iconColor="#C98A5A" />
889
+ <div style={{ display: "flex", flexDirection: "column" }}>
890
+ {strengthItems.map((item, i) => (
891
+ <AccordionRow key={i} {...item} />
892
+ ))}
893
+ </div>
894
+ </div>
895
+ </div>
896
+
897
+ <div style={{ display: "flex", flexDirection: "column", gap: 16, marginTop: 8 }}>
898
+ <SectionHeading icon={Phone} title="Call Mix" iconColor="#C98A5A" />
899
+ <div style={{ display: "flex", gap: 24 }}>
900
+ <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 8, minWidth: 0 }}>
901
+ <SubSectionHeading icon={FolderKanban} title="Drivers" />
902
+ <div style={{ display: "flex", flexDirection: "column" }}>
903
+ {callDrivers.map((row, i) => (
904
+ <PercentRow key={i} {...row} />
905
+ ))}
906
+ </div>
907
+ </div>
908
+ <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 8, minWidth: 0 }}>
909
+ <SubSectionHeading icon={Layers} title="Paradigms" />
910
+ <div style={{ display: "flex", flexDirection: "column" }}>
911
+ {callParadigms.map((row, i) => (
912
+ <PercentRow key={i} {...row} />
913
+ ))}
914
+ </div>
915
+ </div>
916
+ </div>
917
+ </div>
918
+
919
+ <div style={{ display: "flex", flexDirection: "column", gap: 16, marginTop: 8 }}>
920
+ <span
921
+ style={{
922
+ fontFamily: FONT_DISPLAY,
923
+ fontWeight: 600,
924
+ fontSize: 16,
925
+ color: C.ink,
926
+ lineHeight: 1.2,
927
+ }}
928
+ >
929
+ Sessions History
930
+ </span>
931
+ <DataTable2
932
+ data={sessions}
933
+ columns={sessionColumns}
934
+ initialPageSize={initialPageSize}
935
+ />
936
+ </div>
937
+ </div>
938
+ </div>
939
+ );
940
+ }