ahs-cti 1.0.1-beta.2 → 1.0.1-beta.21

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,1219 @@
1
+ import {
2
+ SDKButton
3
+ } from "./chunk-FVNDPJUU.mjs";
4
+ import {
5
+ SDKPageHeader
6
+ } from "./chunk-RZZQ42MG.mjs";
7
+ import {
8
+ END_POINT,
9
+ SDKProvider,
10
+ __spreadProps,
11
+ __spreadValues,
12
+ axios_default,
13
+ sdkStateManager
14
+ } from "./chunk-YREOEULC.mjs";
15
+
16
+ // call-control-sdk/lib/pages/agentDetailReport/index.tsx
17
+ import { memo, useCallback as useCallback2, useEffect, useMemo, useState as useState2 } from "react";
18
+ import {
19
+ Alert,
20
+ Box,
21
+ Chip,
22
+ CircularProgress,
23
+ IconButton,
24
+ Table,
25
+ TableBody,
26
+ TableCell,
27
+ TableContainer,
28
+ TableHead,
29
+ TablePagination,
30
+ TableRow,
31
+ Tooltip,
32
+ Typography
33
+ } from "@mui/material";
34
+ import SearchIcon from "@mui/icons-material/Search";
35
+ import PlayArrowIcon from "@mui/icons-material/PlayArrow";
36
+ import FileDownloadIcon from "@mui/icons-material/FileDownload";
37
+ import {
38
+ Bar,
39
+ BarChart,
40
+ CartesianGrid,
41
+ Cell,
42
+ LabelList,
43
+ Legend,
44
+ Pie,
45
+ PieChart,
46
+ ResponsiveContainer,
47
+ Tooltip as RTooltip,
48
+ XAxis,
49
+ YAxis
50
+ } from "recharts";
51
+ import dayjs from "dayjs";
52
+ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
53
+ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
54
+ import { DatePicker } from "@mui/x-date-pickers/DatePicker";
55
+
56
+ // call-control-sdk/lib/pages/agentDetailReport/useAgentDetailReport.ts
57
+ import { useCallback, useState } from "react";
58
+ function buildCdrQs(params) {
59
+ const qs = new URLSearchParams();
60
+ if (params.start_date) qs.append("start_date", params.start_date);
61
+ if (params.end_date) qs.append("end_date", params.end_date);
62
+ if (params.agent_id) for (const id of params.agent_id) qs.append("agent_id", String(id));
63
+ if (params.queue_id) for (const id of params.queue_id) qs.append("queue_id", String(id));
64
+ if (params.call_type) qs.append("call_type", params.call_type);
65
+ if (params.status) qs.append("status", params.status);
66
+ if (params.search) qs.append("search", params.search);
67
+ if (params.page) qs.append("page", String(params.page));
68
+ if (params.page_size) qs.append("page_size", String(params.page_size));
69
+ const str = qs.toString();
70
+ return str ? `?${str}` : "";
71
+ }
72
+ function useAgentDetailReport() {
73
+ const [detail, setDetail] = useState(null);
74
+ const [detailLoading, setDetailLoading] = useState(false);
75
+ const [detailError, setDetailError] = useState("");
76
+ const fetchDetail = useCallback(
77
+ async (agentId, params) => {
78
+ var _a, _b;
79
+ if (!agentId) return;
80
+ setDetailLoading(true);
81
+ setDetailError("");
82
+ try {
83
+ const qs = new URLSearchParams();
84
+ if (params.start_date) qs.append("start_date", params.start_date);
85
+ if (params.end_date) qs.append("end_date", params.end_date);
86
+ const qsStr = qs.toString();
87
+ const url = `${END_POINT.AGENT_DETAIL_REPORT(agentId)}${qsStr ? `?${qsStr}` : ""}`;
88
+ const res = await axios_default.get(url);
89
+ setDetail(res.data);
90
+ } catch (err) {
91
+ setDetailError(((_b = (_a = err == null ? void 0 : err.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) || (err == null ? void 0 : err.message) || "Failed to load agent detail");
92
+ setDetail(null);
93
+ } finally {
94
+ setDetailLoading(false);
95
+ }
96
+ },
97
+ []
98
+ );
99
+ return { detail, detailLoading, detailError, setDetailError, fetchDetail };
100
+ }
101
+ function useAgentCdrRecords() {
102
+ const [records, setRecords] = useState([]);
103
+ const [total, setTotal] = useState(0);
104
+ const [loading, setLoading] = useState(false);
105
+ const [error, setError] = useState("");
106
+ const fetchCdr = useCallback(async (params) => {
107
+ var _a, _b, _c, _d, _e, _f;
108
+ setLoading(true);
109
+ setError("");
110
+ try {
111
+ const res = await axios_default.get(
112
+ `${END_POINT.CDR_REPORT}${buildCdrQs(params)}`
113
+ );
114
+ setRecords(((_b = (_a = res.data) == null ? void 0 : _a.records) == null ? void 0 : _b.data) || []);
115
+ setTotal(((_d = (_c = res.data) == null ? void 0 : _c.records) == null ? void 0 : _d.total) || 0);
116
+ } catch (err) {
117
+ setError(((_f = (_e = err == null ? void 0 : err.response) == null ? void 0 : _e.data) == null ? void 0 : _f.message) || (err == null ? void 0 : err.message) || "Failed to load call history");
118
+ setRecords([]);
119
+ setTotal(0);
120
+ } finally {
121
+ setLoading(false);
122
+ }
123
+ }, []);
124
+ return { records, total, loading, error, setError, fetchCdr };
125
+ }
126
+ async function fetchRecordingBlob(callUuid) {
127
+ const res = await axios_default.get(END_POINT.RECORDING_BY_CALL(callUuid), {
128
+ responseType: "blob"
129
+ });
130
+ return res.data;
131
+ }
132
+
133
+ // call-control-sdk/lib/pages/agentDetailReport/styles.ts
134
+ var C = {
135
+ navy: "#0d2a56",
136
+ blue: "#1565c8",
137
+ green: "#0a9a62",
138
+ amber: "#c47c00",
139
+ red: "#cc2a2a",
140
+ purple: "#6b3fbf",
141
+ teal: "#0b7a8f",
142
+ bg: "#fff",
143
+ surface: "#fff",
144
+ s2: "#f7f9fc",
145
+ s3: "#eef2f7",
146
+ b1: "rgba(20,50,100,.07)",
147
+ b2: "rgba(20,50,100,.13)",
148
+ t1: "#0d1e35",
149
+ t2: "#364f6e",
150
+ t3: "#7a93b5",
151
+ t4: "#bccad9",
152
+ blt: "#e8f0fc",
153
+ glt: "#e4f6ef",
154
+ alt: "#fdf3e0",
155
+ rlt: "#fde8e8",
156
+ plt: "#f0eafa",
157
+ tlt: "#e3f4f7"
158
+ };
159
+ var QUEUE_COLORS = [C.blue, C.green, C.purple, C.amber, C.teal, C.red, C.navy];
160
+ var monoSx = { fontFamily: "'JetBrains Mono', monospace", fontSize: 11, fontWeight: 600 };
161
+ var containerSx = {
162
+ background: C.bg,
163
+ minHeight: "100vh"
164
+ };
165
+ var filterBarSx = {
166
+ display: "flex",
167
+ alignItems: "center",
168
+ gap: 1,
169
+ flexWrap: "wrap",
170
+ pb: 1.5,
171
+ px: 2
172
+ };
173
+ var datePickerSx = {
174
+ width: 150,
175
+ "& .MuiOutlinedInput-root": {
176
+ borderRadius: "7px",
177
+ fontSize: 12,
178
+ height: 30
179
+ },
180
+ "& .MuiInputBase-input": { py: "4px", fontSize: 12 }
181
+ };
182
+ var contentSx = {
183
+ py: 2,
184
+ px: 2,
185
+ position: "relative"
186
+ };
187
+ var loadingOverlaySx = {
188
+ position: "absolute",
189
+ top: 0,
190
+ left: 0,
191
+ right: 0,
192
+ bottom: 0,
193
+ background: "rgba(240,244,248,0.7)",
194
+ display: "flex",
195
+ alignItems: "center",
196
+ justifyContent: "center",
197
+ zIndex: 10
198
+ };
199
+ var kpiGridSx = {
200
+ display: "grid",
201
+ gridTemplateColumns: { xs: "1fr 1fr", sm: "repeat(3, 1fr)", md: "repeat(5, 1fr)" },
202
+ gap: 1.5,
203
+ mb: 2
204
+ };
205
+ var kpiCardSx = (color) => ({
206
+ px: 1.5,
207
+ py: 1.2,
208
+ borderRadius: "10px",
209
+ backgroundColor: "#fafafa",
210
+ border: "1px solid #e0e0e0",
211
+ borderLeftWidth: "3px",
212
+ borderLeftStyle: "solid",
213
+ borderLeftColor: color
214
+ });
215
+ var kpiLabelSx = {
216
+ fontFamily: "poppins, Arial, sans-serif",
217
+ fontSize: "0.72rem",
218
+ fontWeight: 600,
219
+ color: "#888",
220
+ mb: 0.3
221
+ };
222
+ var kpiValueSx = {
223
+ fontFamily: "poppins, Arial, sans-serif",
224
+ fontSize: "0.95rem",
225
+ fontWeight: 700,
226
+ color: "#1a1a1a"
227
+ };
228
+ var tabBarSx = {
229
+ display: "flex",
230
+ alignItems: { xs: "flex-start", sm: "center" },
231
+ justifyContent: "space-between",
232
+ flexDirection: { xs: "column", sm: "row" },
233
+ gap: 1,
234
+ borderBottom: `2px solid ${C.b1}`,
235
+ mb: 2
236
+ };
237
+ var tabItemSx = (active) => ({
238
+ px: 2,
239
+ py: 1,
240
+ fontSize: 13,
241
+ fontWeight: 600,
242
+ cursor: "pointer",
243
+ color: active ? C.blue : C.t3,
244
+ borderBottom: `2px solid ${active ? C.blue : "transparent"}`,
245
+ mb: "-2px",
246
+ transition: "all .15s",
247
+ "&:hover": { color: C.t1 }
248
+ });
249
+ var sectionCardSx = {
250
+ border: `1px solid ${C.b1}`,
251
+ borderRadius: "10px",
252
+ overflow: "hidden",
253
+ background: "transparent"
254
+ };
255
+ var sectionHeaderSx = {
256
+ px: 2,
257
+ py: 1.2,
258
+ background: C.s2,
259
+ borderBottom: `1px solid ${C.b1}`,
260
+ display: "flex",
261
+ alignItems: "center",
262
+ justifyContent: "space-between"
263
+ };
264
+ var sectionTitleSx = {
265
+ fontSize: 12,
266
+ fontWeight: 700,
267
+ letterSpacing: 0.8,
268
+ textTransform: "uppercase",
269
+ color: C.t2
270
+ };
271
+ var cdrHeadSx = {
272
+ bgcolor: "#f1f1f1",
273
+ color: "#333",
274
+ fontWeight: 600,
275
+ whiteSpace: "nowrap",
276
+ fontSize: "14px",
277
+ py: 0.7,
278
+ px: 1
279
+ };
280
+ var cdrTableSx = {
281
+ minWidth: 1400,
282
+ "& .MuiTableCell-root": {
283
+ fontSize: "0.75rem",
284
+ borderBottom: "1px solid #eef1f6",
285
+ py: 0.6,
286
+ px: 1
287
+ }
288
+ };
289
+ var cdrRowSx = {
290
+ backgroundColor: "#fff",
291
+ "&:hover": { backgroundColor: "#f0f7f8" }
292
+ };
293
+ var paginationSx = {
294
+ borderTop: "1px solid #eef1f6",
295
+ "& .MuiTablePagination-displayedRows": { fontSize: "0.73rem" },
296
+ "& .MuiTablePagination-selectLabel": { fontSize: "0.73rem" }
297
+ };
298
+
299
+ // call-control-sdk/lib/pages/agentDetailReport/index.tsx
300
+ import { jsx, jsxs } from "react/jsx-runtime";
301
+ function StatCard({ value, label, color }) {
302
+ return /* @__PURE__ */ jsxs(Box, { sx: kpiCardSx(color), children: [
303
+ /* @__PURE__ */ jsx(Typography, { sx: kpiLabelSx, children: label }),
304
+ /* @__PURE__ */ jsx(Typography, { sx: kpiValueSx, children: value })
305
+ ] });
306
+ }
307
+ function StatusChip({ status }) {
308
+ const s = status == null ? void 0 : status.toLowerCase();
309
+ const isAns = s === "answered";
310
+ const isAband = s === "abandoned";
311
+ return /* @__PURE__ */ jsx(
312
+ Chip,
313
+ {
314
+ label: status || "\u2014",
315
+ size: "small",
316
+ sx: {
317
+ fontSize: 11,
318
+ fontWeight: 700,
319
+ height: 22,
320
+ background: isAns ? C.glt : isAband ? C.alt : C.rlt,
321
+ color: isAns ? C.green : isAband ? C.amber : C.red,
322
+ border: `1px solid ${isAns ? "rgba(10,154,98,.2)" : isAband ? "rgba(196,124,0,.2)" : "rgba(204,42,42,.2)"}`,
323
+ fontFamily: "'JetBrains Mono', monospace"
324
+ }
325
+ }
326
+ );
327
+ }
328
+ function CallTypeChip({ type }) {
329
+ const isIn = (type == null ? void 0 : type.toLowerCase()) === "inbound";
330
+ return /* @__PURE__ */ jsx(
331
+ Chip,
332
+ {
333
+ label: type || "\u2014",
334
+ size: "small",
335
+ sx: {
336
+ fontSize: 11,
337
+ fontWeight: 700,
338
+ height: 22,
339
+ background: isIn ? C.glt : C.blt,
340
+ color: isIn ? C.green : C.blue,
341
+ border: `1px solid ${isIn ? "rgba(10,154,98,.2)" : "rgba(21,101,200,.2)"}`,
342
+ fontFamily: "'JetBrains Mono', monospace"
343
+ }
344
+ }
345
+ );
346
+ }
347
+ function RecordingCell({ callUuid, recordingPath }) {
348
+ const [audioUrl, setAudioUrl] = useState2(null);
349
+ const [loading, setLoading] = useState2(false);
350
+ const [error, setError] = useState2(false);
351
+ if (!recordingPath) {
352
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.3 }, children: [
353
+ /* @__PURE__ */ jsx(Tooltip, { title: "No recording available", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(IconButton, { size: "small", disabled: true, sx: { p: 0.4 }, children: /* @__PURE__ */ jsx(PlayArrowIcon, { sx: { fontSize: 16 } }) }) }) }),
354
+ /* @__PURE__ */ jsx(Tooltip, { title: "No recording available", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(IconButton, { size: "small", disabled: true, sx: { p: 0.4 }, children: /* @__PURE__ */ jsx(FileDownloadIcon, { sx: { fontSize: 16 } }) }) }) })
355
+ ] });
356
+ }
357
+ const handlePlay = async () => {
358
+ if (audioUrl) return;
359
+ try {
360
+ setLoading(true);
361
+ setError(false);
362
+ const blob = await fetchRecordingBlob(callUuid);
363
+ setAudioUrl(URL.createObjectURL(blob));
364
+ } catch (e) {
365
+ setError(true);
366
+ } finally {
367
+ setLoading(false);
368
+ }
369
+ };
370
+ const handleDownload = async () => {
371
+ try {
372
+ const blob = audioUrl ? await fetch(audioUrl).then((r) => r.blob()) : await fetchRecordingBlob(callUuid);
373
+ const url = URL.createObjectURL(blob);
374
+ const a = document.createElement("a");
375
+ a.href = url;
376
+ a.download = `recording_${callUuid}.wav`;
377
+ a.click();
378
+ URL.revokeObjectURL(url);
379
+ } catch (e) {
380
+ }
381
+ };
382
+ if (audioUrl) {
383
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.5 }, children: [
384
+ /* @__PURE__ */ jsx(
385
+ "audio",
386
+ {
387
+ controls: true,
388
+ autoPlay: true,
389
+ src: audioUrl,
390
+ onEnded: () => {
391
+ if (audioUrl.startsWith("blob:")) URL.revokeObjectURL(audioUrl);
392
+ setAudioUrl(null);
393
+ },
394
+ style: { width: 140, height: 30 }
395
+ }
396
+ ),
397
+ /* @__PURE__ */ jsx(Tooltip, { title: "Download", children: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: handleDownload, sx: { color: C.blue, p: 0.4 }, children: /* @__PURE__ */ jsx(FileDownloadIcon, { sx: { fontSize: 16 } }) }) })
398
+ ] });
399
+ }
400
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.3 }, children: [
401
+ /* @__PURE__ */ jsx(Tooltip, { title: error ? "Recording unavailable" : "Play", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
402
+ IconButton,
403
+ {
404
+ size: "small",
405
+ onClick: handlePlay,
406
+ disabled: loading || error,
407
+ sx: { color: C.green, p: 0.4 },
408
+ children: loading ? /* @__PURE__ */ jsx(CircularProgress, { size: 14 }) : /* @__PURE__ */ jsx(PlayArrowIcon, { sx: { fontSize: 16 } })
409
+ }
410
+ ) }) }),
411
+ /* @__PURE__ */ jsx(Tooltip, { title: error ? "Recording unavailable" : "Download", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
412
+ IconButton,
413
+ {
414
+ size: "small",
415
+ onClick: handleDownload,
416
+ disabled: loading || error,
417
+ sx: { color: C.blue, p: 0.4 },
418
+ children: /* @__PURE__ */ jsx(FileDownloadIcon, { sx: { fontSize: 16 } })
419
+ }
420
+ ) }) }),
421
+ error && /* @__PURE__ */ jsx(Chip, { label: "No File", size: "small", sx: { fontSize: "0.6rem", height: 18 } })
422
+ ] });
423
+ }
424
+ var AgentDetailReportContent = memo(
425
+ ({ agentRow, onBack, from, initialStartDate, initialEndDate, initialQuickRange }) => {
426
+ var _a, _b, _c, _d, _e, _f, _g, _h;
427
+ const isFromReportsList = from === "REPORTS_LIST";
428
+ const agentIdFromRow = isFromReportsList ? (agentRow == null ? void 0 : agentRow.agentId) || "" : sdkStateManager.getState().agentId || (agentRow == null ? void 0 : agentRow.agentId) || "";
429
+ const [quickRange, setQuickRange] = useState2(initialQuickRange || "today");
430
+ const [startDate, setStartDate] = useState2(initialStartDate != null ? initialStartDate : dayjs());
431
+ const [endDate, setEndDate] = useState2(initialEndDate != null ? initialEndDate : dayjs());
432
+ const [activeTab, setActiveTab] = useState2(0);
433
+ const [cdrPage, setCdrPage] = useState2(0);
434
+ const [cdrPageSize, setCdrPageSize] = useState2(10);
435
+ const { detail, detailLoading, detailError, setDetailError, fetchDetail } = useAgentDetailReport();
436
+ const {
437
+ records: cdrRecords,
438
+ total: cdrTotal,
439
+ loading: cdrLoading,
440
+ error: cdrError,
441
+ setError: setCdrError,
442
+ fetchCdr
443
+ } = useAgentCdrRecords();
444
+ const profile = (detail == null ? void 0 : detail.profile) || null;
445
+ const agentName = (profile == null ? void 0 : profile.fullName) || (agentRow == null ? void 0 : agentRow.fullName) || "Unknown Agent";
446
+ const showInitialSpinner = !isFromReportsList && detailLoading && !profile && !(agentRow == null ? void 0 : agentRow.fullName);
447
+ const fetchDetailFn = useCallback2(
448
+ (sd, ed) => {
449
+ if (!agentIdFromRow) return;
450
+ fetchDetail(agentIdFromRow, {
451
+ start_date: sd.startOf("day").format("YYYY-MM-DDTHH:mm:ss"),
452
+ end_date: ed.isSame(dayjs(), "day") ? dayjs().format("YYYY-MM-DDTHH:mm:ss") : ed.endOf("day").format("YYYY-MM-DDTHH:mm:ss")
453
+ });
454
+ },
455
+ [agentIdFromRow, fetchDetail]
456
+ );
457
+ const fetchCdrFn = useCallback2(
458
+ (sd, ed, page, pageSize) => {
459
+ if (!agentIdFromRow) return;
460
+ fetchCdr({
461
+ start_date: sd.startOf("day").format("YYYY-MM-DDTHH:mm:ss"),
462
+ end_date: ed.isSame(dayjs(), "day") ? dayjs().format("YYYY-MM-DDTHH:mm:ss") : ed.endOf("day").format("YYYY-MM-DDTHH:mm:ss"),
463
+ search: agentIdFromRow,
464
+ page: page + 1,
465
+ page_size: pageSize
466
+ });
467
+ },
468
+ [agentIdFromRow, fetchCdr]
469
+ );
470
+ const handleSearch = (sd, ed) => {
471
+ const fromDate = sd != null ? sd : startDate;
472
+ const toDate = ed != null ? ed : endDate;
473
+ if (!fromDate || !toDate) return;
474
+ fetchDetailFn(fromDate, toDate);
475
+ setCdrPage(0);
476
+ if (activeTab === 1) fetchCdrFn(fromDate, toDate, 0, cdrPageSize);
477
+ };
478
+ const setQuick = (range) => {
479
+ setQuickRange(range);
480
+ const today = dayjs();
481
+ let sd = today;
482
+ const ed = today;
483
+ if (range === "week") sd = today.startOf("week");
484
+ else if (range === "month") sd = today.startOf("month");
485
+ setStartDate(sd);
486
+ setEndDate(ed);
487
+ handleSearch(sd, ed);
488
+ };
489
+ useEffect(() => {
490
+ if (agentIdFromRow) fetchDetailFn(startDate != null ? startDate : dayjs(), endDate != null ? endDate : dayjs());
491
+ }, [agentIdFromRow]);
492
+ useEffect(() => {
493
+ if (activeTab === 1 && startDate && endDate) {
494
+ fetchCdrFn(startDate, endDate, cdrPage, cdrPageSize);
495
+ }
496
+ }, [activeTab, cdrPage, cdrPageSize]);
497
+ const hourlyCallData = useMemo(() => {
498
+ return ((detail == null ? void 0 : detail.hourlyCalls) || []).map((h) => ({
499
+ hour: String(h.hourOfDay).padStart(2, "0"),
500
+ answered: h.answeredCalls,
501
+ abandoned: h.missedCalls
502
+ }));
503
+ }, [detail]);
504
+ const timeUtilData = useMemo(() => {
505
+ const tu = detail == null ? void 0 : detail.timeUtilisation;
506
+ if (!tu) return [];
507
+ const total = tu.totalLoginSeconds || 1;
508
+ return [
509
+ { name: "On Call / Handle", value: tu.onCallSeconds, pct: tu.onCallSeconds / total * 100, formatted: tu.onCallFormatted, color: C.blue },
510
+ { name: "Idle", value: tu.idleSeconds, pct: tu.idleSeconds / total * 100, formatted: tu.idleFormatted, color: "#e8a0a0" },
511
+ { name: "Break", value: tu.breakSeconds, pct: tu.breakSeconds / total * 100, formatted: tu.breakFormatted, color: C.amber }
512
+ ];
513
+ }, [detail]);
514
+ const talkDurationBuckets = useMemo(() => {
515
+ const items = [...(detail == null ? void 0 : detail.talkDistribution) || []].sort(
516
+ (a, b) => a.bucketOrder - b.bucketOrder
517
+ );
518
+ const total = items.reduce((s, b) => s + (b.callCount || 0), 0);
519
+ return items.map((b) => ({
520
+ bucket: b.bucketLabel,
521
+ count: b.callCount,
522
+ minSeconds: b.minSeconds,
523
+ maxSeconds: b.maxSeconds,
524
+ pct: total > 0 ? b.callCount / total * 100 : 0
525
+ }));
526
+ }, [detail]);
527
+ const talkDurationTotal = useMemo(
528
+ () => talkDurationBuckets.reduce((s, b) => s + (b.count || 0), 0),
529
+ [talkDurationBuckets]
530
+ );
531
+ const queuePieData = useMemo(() => {
532
+ return ((detail == null ? void 0 : detail.callsByQueue) || []).map((q, i) => ({
533
+ name: q.queueName,
534
+ value: q.callCount,
535
+ pctOfTotal: q.pctOfTotal,
536
+ color: QUEUE_COLORS[i % QUEUE_COLORS.length]
537
+ }));
538
+ }, [detail]);
539
+ const queueMetrics = useMemo(() => {
540
+ const items = (detail == null ? void 0 : detail.queueMetrics) || [];
541
+ const grandTotal = items.reduce((sum, q) => sum + q.totalCalls, 0);
542
+ return items.map((q, i) => __spreadProps(__spreadValues({}, q), {
543
+ pctOfTotal: grandTotal > 0 ? q.totalCalls / grandTotal * 100 : 0,
544
+ answerRate: q.totalCalls > 0 ? q.answeredCalls / q.totalCalls * 100 : 0,
545
+ color: QUEUE_COLORS[i % QUEUE_COLORS.length]
546
+ }));
547
+ }, [detail]);
548
+ const hourlyChartTitle = useMemo(() => {
549
+ if (quickRange === "today") return "Hourly Call Volume \u2014 Today";
550
+ if (quickRange === "month") return `Hourly Call Volume \u2014 ${dayjs().format("MMMM YYYY")}`;
551
+ if (quickRange === "week") return "Hourly Call Volume \u2014 This Week";
552
+ if (startDate && endDate) {
553
+ if (startDate.isSame(endDate, "day"))
554
+ return `Hourly Call Volume \u2014 ${startDate.format("DD MMM YYYY")}`;
555
+ return `Hourly Call Volume \u2014 ${startDate.format("DD MMM YYYY")} to ${endDate.format("DD MMM YYYY")}`;
556
+ }
557
+ return "Hourly Call Volume";
558
+ }, [quickRange, startDate, endDate]);
559
+ const handleBack = useCallback2(() => {
560
+ if (onBack) onBack();
561
+ }, [onBack]);
562
+ if (!agentIdFromRow) {
563
+ return /* @__PURE__ */ jsxs(Box, { sx: { p: 4, textAlign: "center" }, children: [
564
+ /* @__PURE__ */ jsx(Typography, { sx: { color: C.t3, mb: 2 }, children: "No agent selected." }),
565
+ /* @__PURE__ */ jsx(SDKButton, { onClick: handleBack, children: "Go Back" })
566
+ ] });
567
+ }
568
+ if (showInitialSpinner) {
569
+ return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", alignItems: "center", justifyContent: "center", minHeight: 400 }, children: /* @__PURE__ */ jsx(CircularProgress, { size: 36 }) });
570
+ }
571
+ const tabs = ["Overview", "Call History", "Break Details"];
572
+ return /* @__PURE__ */ jsx(LocalizationProvider, { dateAdapter: AdapterDayjs, children: /* @__PURE__ */ jsxs(Box, { sx: containerSx, children: [
573
+ /* @__PURE__ */ jsx(SDKPageHeader, { title: agentName, showBack: isFromReportsList, onBack: handleBack }),
574
+ /* @__PURE__ */ jsxs(Box, { sx: filterBarSx, children: [
575
+ /* @__PURE__ */ jsx(
576
+ DatePicker,
577
+ {
578
+ value: startDate,
579
+ onChange: (val) => {
580
+ setStartDate(val);
581
+ setQuickRange("custom");
582
+ },
583
+ slotProps: { textField: { size: "small", sx: datePickerSx } }
584
+ }
585
+ ),
586
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 12, color: C.t3 }, children: "to" }),
587
+ /* @__PURE__ */ jsx(
588
+ DatePicker,
589
+ {
590
+ value: endDate,
591
+ onChange: (val) => {
592
+ setEndDate(val);
593
+ setQuickRange("custom");
594
+ },
595
+ slotProps: { textField: { size: "small", sx: datePickerSx } }
596
+ }
597
+ ),
598
+ /* @__PURE__ */ jsx(
599
+ SDKButton,
600
+ {
601
+ variant: quickRange === "today" ? "primary" : "outlined",
602
+ onClick: () => setQuick("today"),
603
+ children: "Today"
604
+ }
605
+ ),
606
+ /* @__PURE__ */ jsx(
607
+ SDKButton,
608
+ {
609
+ variant: quickRange === "week" ? "primary" : "outlined",
610
+ onClick: () => setQuick("week"),
611
+ children: "This Week"
612
+ }
613
+ ),
614
+ /* @__PURE__ */ jsx(
615
+ SDKButton,
616
+ {
617
+ variant: quickRange === "month" ? "primary" : "outlined",
618
+ onClick: () => setQuick("month"),
619
+ children: "This Month"
620
+ }
621
+ )
622
+ ] }),
623
+ /* @__PURE__ */ jsxs(Box, { sx: contentSx, children: [
624
+ detailLoading && /* @__PURE__ */ jsx(Box, { sx: loadingOverlaySx, children: /* @__PURE__ */ jsx(CircularProgress, {}) }),
625
+ detailError && /* @__PURE__ */ jsx(Alert, { severity: "error", sx: { mb: 2 }, onClose: () => setDetailError(""), children: detailError }),
626
+ /* @__PURE__ */ jsx(Box, { sx: kpiGridSx, children: [
627
+ { v: (_a = profile == null ? void 0 : profile.totalCalls) != null ? _a : 0, l: "Total Calls", c: C.navy },
628
+ { v: (_b = profile == null ? void 0 : profile.answeredCalls) != null ? _b : 0, l: "Answered", c: C.green },
629
+ { v: (_c = profile == null ? void 0 : profile.missedCalls) != null ? _c : 0, l: "Missed", c: C.red },
630
+ { v: (profile == null ? void 0 : profile.avgAhtFormatted) || "00:00:00", l: "Avg AHT", c: C.purple },
631
+ { v: `${((_d = profile == null ? void 0 : profile.answerRate) != null ? _d : 0).toFixed(1)}%`, l: "Answer Rate", c: C.green },
632
+ { v: (profile == null ? void 0 : profile.loginDurationFormatted) || "00:00:00", l: "Login Duration", c: C.blue },
633
+ { v: (profile == null ? void 0 : profile.productionFormatted) || "00:00:00", l: "Production", c: C.blue },
634
+ { v: (profile == null ? void 0 : profile.handleTimeFormatted) || "00:00:00", l: "Handle Time", c: C.purple },
635
+ { v: (profile == null ? void 0 : profile.breakTimeFormatted) || "00:00:00", l: "Break Time", c: C.amber },
636
+ {
637
+ v: `${((_e = profile == null ? void 0 : profile.adherencePct) != null ? _e : 0).toFixed(1)}%`,
638
+ l: `Adherence${(profile == null ? void 0 : profile.adherenceGrade) ? ` (${profile.adherenceGrade})` : ""}`,
639
+ c: C.teal
640
+ }
641
+ ].map((kpi, i) => /* @__PURE__ */ jsx(StatCard, { value: kpi.v, label: kpi.l, color: kpi.c }, i)) }),
642
+ /* @__PURE__ */ jsxs(Box, { sx: tabBarSx, children: [
643
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap" }, children: tabs.map((tab, idx) => /* @__PURE__ */ jsx(Box, { onClick: () => setActiveTab(idx), sx: tabItemSx(activeTab === idx), children: tab }, tab)) }),
644
+ /* @__PURE__ */ jsx(SDKButton, { size: "small", startIcon: /* @__PURE__ */ jsx(SearchIcon, {}), onClick: () => handleSearch(), children: "Search" })
645
+ ] }),
646
+ activeTab === 0 && /* @__PURE__ */ jsxs(Box, { children: [
647
+ /* @__PURE__ */ jsxs(
648
+ Box,
649
+ {
650
+ sx: {
651
+ display: "grid",
652
+ gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" },
653
+ gap: 2,
654
+ mb: 2
655
+ },
656
+ children: [
657
+ /* @__PURE__ */ jsxs(Box, { sx: sectionCardSx, children: [
658
+ /* @__PURE__ */ jsxs(Box, { sx: sectionHeaderSx, children: [
659
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: hourlyChartTitle }),
660
+ /* @__PURE__ */ jsx(
661
+ Chip,
662
+ {
663
+ label: agentName,
664
+ size: "small",
665
+ sx: {
666
+ fontSize: 11,
667
+ fontWeight: 700,
668
+ background: C.blt,
669
+ color: C.blue,
670
+ border: `1px solid rgba(21,101,200,.2)`
671
+ }
672
+ }
673
+ )
674
+ ] }),
675
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2, height: 260 }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart, { data: hourlyCallData, barGap: 1, children: [
676
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: C.b1 }),
677
+ /* @__PURE__ */ jsx(XAxis, { dataKey: "hour", tick: { fontSize: 11, fill: C.t3 } }),
678
+ /* @__PURE__ */ jsx(YAxis, { tick: { fontSize: 11, fill: C.t3 }, allowDecimals: false }),
679
+ /* @__PURE__ */ jsx(
680
+ RTooltip,
681
+ {
682
+ labelFormatter: (label) => `${String(label).padStart(2, "0")}:00`,
683
+ contentStyle: { fontSize: 12, borderRadius: 8, border: `1px solid ${C.b2}` }
684
+ }
685
+ ),
686
+ /* @__PURE__ */ jsx(Legend, { wrapperStyle: { fontSize: 11 } }),
687
+ /* @__PURE__ */ jsx(Bar, { dataKey: "answered", name: "Answered", fill: C.blue, radius: [3, 3, 0, 0] }),
688
+ /* @__PURE__ */ jsx(Bar, { dataKey: "abandoned", name: "Abandoned", fill: C.red, radius: [3, 3, 0, 0] })
689
+ ] }) }) })
690
+ ] }),
691
+ /* @__PURE__ */ jsxs(Box, { sx: sectionCardSx, children: [
692
+ /* @__PURE__ */ jsx(Box, { sx: __spreadProps(__spreadValues({}, sectionHeaderSx), { justifyContent: "flex-start" }), children: /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Time Utilisation Breakdown" }) }),
693
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2, height: 260 }, children: timeUtilData.length > 0 ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(PieChart, { children: [
694
+ /* @__PURE__ */ jsx(
695
+ Pie,
696
+ {
697
+ data: timeUtilData,
698
+ cx: "50%",
699
+ cy: "50%",
700
+ innerRadius: 60,
701
+ outerRadius: 95,
702
+ dataKey: "value",
703
+ nameKey: "name",
704
+ minAngle: 8,
705
+ children: timeUtilData.map((entry, idx) => /* @__PURE__ */ jsx(Cell, { fill: entry.color }, idx))
706
+ }
707
+ ),
708
+ /* @__PURE__ */ jsx(
709
+ RTooltip,
710
+ {
711
+ formatter: (_val, name, entry) => [
712
+ `${entry.payload.formatted} (${entry.payload.pct.toFixed(1)}%)`,
713
+ name
714
+ ],
715
+ contentStyle: { fontSize: 12, borderRadius: 8, border: `1px solid ${C.b2}` }
716
+ }
717
+ ),
718
+ /* @__PURE__ */ jsx(Legend, { wrapperStyle: { fontSize: 12 } })
719
+ ] }) }) : /* @__PURE__ */ jsx(
720
+ Box,
721
+ {
722
+ sx: {
723
+ display: "flex",
724
+ alignItems: "center",
725
+ justifyContent: "center",
726
+ height: "100%",
727
+ color: C.t3,
728
+ fontSize: 13
729
+ },
730
+ children: "No data"
731
+ }
732
+ ) })
733
+ ] })
734
+ ]
735
+ }
736
+ ),
737
+ /* @__PURE__ */ jsxs(Box, { sx: __spreadProps(__spreadValues({}, sectionCardSx), { mb: 2 }), children: [
738
+ /* @__PURE__ */ jsxs(Box, { sx: sectionHeaderSx, children: [
739
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Talk Duration Distribution" }),
740
+ /* @__PURE__ */ jsx(
741
+ Chip,
742
+ {
743
+ label: `${talkDurationTotal} call${talkDurationTotal === 1 ? "" : "s"}`,
744
+ size: "small",
745
+ sx: {
746
+ fontSize: 11,
747
+ fontWeight: 700,
748
+ background: C.glt,
749
+ color: C.green,
750
+ border: `1px solid rgba(10,154,98,.2)`
751
+ }
752
+ }
753
+ )
754
+ ] }),
755
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2, height: 260 }, children: talkDurationBuckets.length > 0 ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
756
+ BarChart,
757
+ {
758
+ data: talkDurationBuckets,
759
+ margin: { top: 16, right: 16, left: 0, bottom: 20 },
760
+ children: [
761
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: C.b1 }),
762
+ /* @__PURE__ */ jsx(XAxis, { dataKey: "bucket", tick: { fontSize: 11, fill: C.t3 } }),
763
+ /* @__PURE__ */ jsx(YAxis, { tick: { fontSize: 11, fill: C.t3 }, allowDecimals: false }),
764
+ /* @__PURE__ */ jsx(
765
+ RTooltip,
766
+ {
767
+ contentStyle: { fontSize: 12, borderRadius: 8, border: `1px solid ${C.b2}` }
768
+ }
769
+ ),
770
+ /* @__PURE__ */ jsx(Bar, { dataKey: "count", name: "Calls", fill: C.teal, radius: [4, 4, 0, 0], children: /* @__PURE__ */ jsx(
771
+ LabelList,
772
+ {
773
+ dataKey: "count",
774
+ position: "top",
775
+ style: { fontSize: 11, fontWeight: 700, fill: C.t1 }
776
+ }
777
+ ) })
778
+ ]
779
+ }
780
+ ) }) : /* @__PURE__ */ jsx(
781
+ Box,
782
+ {
783
+ sx: {
784
+ display: "flex",
785
+ alignItems: "center",
786
+ justifyContent: "center",
787
+ height: "100%",
788
+ color: C.t3,
789
+ fontSize: 13
790
+ },
791
+ children: "No data"
792
+ }
793
+ ) })
794
+ ] }),
795
+ /* @__PURE__ */ jsxs(
796
+ Box,
797
+ {
798
+ sx: {
799
+ display: "grid",
800
+ gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" },
801
+ gap: 2
802
+ },
803
+ children: [
804
+ /* @__PURE__ */ jsxs(Box, { sx: sectionCardSx, children: [
805
+ /* @__PURE__ */ jsx(Box, { sx: __spreadProps(__spreadValues({}, sectionHeaderSx), { justifyContent: "flex-start" }), children: /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Calls by Queue" }) }),
806
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2, height: 260 }, children: queuePieData.length > 0 ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(PieChart, { children: [
807
+ /* @__PURE__ */ jsx(Pie, { data: queuePieData, cx: "50%", cy: "50%", outerRadius: 90, dataKey: "value", nameKey: "name", children: queuePieData.map((entry, idx) => /* @__PURE__ */ jsx(Cell, { fill: entry.color }, idx)) }),
808
+ /* @__PURE__ */ jsx(
809
+ RTooltip,
810
+ {
811
+ contentStyle: { fontSize: 12, borderRadius: 8, border: `1px solid ${C.b2}` }
812
+ }
813
+ ),
814
+ /* @__PURE__ */ jsx(Legend, { wrapperStyle: { fontSize: 12 } })
815
+ ] }) }) : /* @__PURE__ */ jsx(
816
+ Box,
817
+ {
818
+ sx: {
819
+ display: "flex",
820
+ alignItems: "center",
821
+ justifyContent: "center",
822
+ height: "100%",
823
+ color: C.t3,
824
+ fontSize: 13
825
+ },
826
+ children: "No queue data"
827
+ }
828
+ ) })
829
+ ] }),
830
+ /* @__PURE__ */ jsxs(Box, { sx: sectionCardSx, children: [
831
+ /* @__PURE__ */ jsx(Box, { sx: __spreadProps(__spreadValues({}, sectionHeaderSx), { justifyContent: "flex-start" }), children: /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Queue Performance Metrics" }) }),
832
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2 }, children: queueMetrics.length > 0 ? queueMetrics.map((q) => {
833
+ var _a2, _b2, _c2;
834
+ return /* @__PURE__ */ jsxs(Box, { sx: { mb: 2, "&:last-child": { mb: 0 } }, children: [
835
+ /* @__PURE__ */ jsxs(
836
+ Box,
837
+ {
838
+ sx: {
839
+ display: "flex",
840
+ alignItems: "center",
841
+ justifyContent: "space-between",
842
+ mb: 0.3
843
+ },
844
+ children: [
845
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
846
+ /* @__PURE__ */ jsx(
847
+ Box,
848
+ {
849
+ sx: {
850
+ width: 10,
851
+ height: 10,
852
+ borderRadius: "50%",
853
+ background: q.color,
854
+ flexShrink: 0
855
+ }
856
+ }
857
+ ),
858
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 13, fontWeight: 700, color: C.t1 }, children: q.queueName })
859
+ ] }),
860
+ /* @__PURE__ */ jsxs(Typography, { sx: __spreadProps(__spreadValues({}, monoSx), { fontSize: 13, fontWeight: 800, color: q.color }), children: [
861
+ q.totalCalls,
862
+ " calls",
863
+ /* @__PURE__ */ jsxs(
864
+ Typography,
865
+ {
866
+ component: "span",
867
+ sx: __spreadProps(__spreadValues({}, monoSx), { color: C.t3, ml: 0.5 }),
868
+ children: [
869
+ "(",
870
+ q.answeredCalls,
871
+ " ans / ",
872
+ q.missedCalls,
873
+ " miss)"
874
+ ]
875
+ }
876
+ )
877
+ ] })
878
+ ]
879
+ }
880
+ ),
881
+ /* @__PURE__ */ jsx(
882
+ Box,
883
+ {
884
+ sx: {
885
+ height: 6,
886
+ background: C.s3,
887
+ borderRadius: 3,
888
+ overflow: "hidden",
889
+ mb: 0.3
890
+ },
891
+ children: /* @__PURE__ */ jsx(
892
+ Box,
893
+ {
894
+ sx: {
895
+ height: "100%",
896
+ width: `${(_a2 = q.pctOfTotal) != null ? _a2 : 0}%`,
897
+ background: q.color,
898
+ borderRadius: 3
899
+ }
900
+ }
901
+ )
902
+ }
903
+ ),
904
+ /* @__PURE__ */ jsxs(
905
+ Box,
906
+ {
907
+ sx: {
908
+ display: "flex",
909
+ flexWrap: "wrap",
910
+ columnGap: 1.5,
911
+ rowGap: 0.2
912
+ },
913
+ children: [
914
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 11, color: C.t3 }, children: [
915
+ ((_b2 = q.pctOfTotal) != null ? _b2 : 0).toFixed(0),
916
+ "% of total"
917
+ ] }),
918
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 11, color: C.t3 }, children: [
919
+ "Ans: ",
920
+ ((_c2 = q.answerRate) != null ? _c2 : 0).toFixed(0),
921
+ "%"
922
+ ] }),
923
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 11, color: C.t3 }, children: [
924
+ "Talk: ",
925
+ /* @__PURE__ */ jsx("span", { style: __spreadProps(__spreadValues({}, monoSx), { color: C.t2 }), children: q.avgTalkFormatted })
926
+ ] }),
927
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 11, color: C.t3 }, children: [
928
+ "Hold: ",
929
+ /* @__PURE__ */ jsx("span", { style: __spreadProps(__spreadValues({}, monoSx), { color: C.t2 }), children: q.avgHoldFormatted })
930
+ ] }),
931
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 11, color: C.t3 }, children: [
932
+ "Wrap: ",
933
+ /* @__PURE__ */ jsx("span", { style: __spreadProps(__spreadValues({}, monoSx), { color: C.t2 }), children: q.avgWrapupFormatted })
934
+ ] }),
935
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 11, color: C.t3 }, children: [
936
+ "AHT: ",
937
+ /* @__PURE__ */ jsx("span", { style: __spreadProps(__spreadValues({}, monoSx), { color: C.t2 }), children: q.avgAhtFormatted })
938
+ ] })
939
+ ]
940
+ }
941
+ )
942
+ ] }, q.queueName);
943
+ }) : /* @__PURE__ */ jsx(Box, { sx: { textAlign: "center", py: 4, color: C.t3, fontSize: 13 }, children: "No queue data" }) })
944
+ ] })
945
+ ]
946
+ }
947
+ )
948
+ ] }),
949
+ activeTab === 1 && /* @__PURE__ */ jsxs(
950
+ Box,
951
+ {
952
+ sx: {
953
+ borderRadius: "8px",
954
+ border: "1px solid #e0e7ef",
955
+ overflow: "hidden",
956
+ background: "transparent"
957
+ },
958
+ children: [
959
+ /* @__PURE__ */ jsx(Box, { sx: sectionHeaderSx, children: /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
960
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Call History" }),
961
+ /* @__PURE__ */ jsx(
962
+ Chip,
963
+ {
964
+ label: `${cdrTotal} records`,
965
+ size: "small",
966
+ sx: {
967
+ fontSize: 11,
968
+ fontWeight: 700,
969
+ background: C.s2,
970
+ color: C.t3,
971
+ border: `1px solid ${C.b2}`
972
+ }
973
+ }
974
+ )
975
+ ] }) }),
976
+ cdrError && /* @__PURE__ */ jsx(Alert, { severity: "error", sx: { mx: 2, mt: 1 }, onClose: () => setCdrError(""), children: cdrError }),
977
+ /* @__PURE__ */ jsxs(TableContainer, { sx: { position: "relative" }, children: [
978
+ cdrLoading && /* @__PURE__ */ jsx(
979
+ Box,
980
+ {
981
+ sx: {
982
+ position: "absolute",
983
+ top: 0,
984
+ left: 0,
985
+ right: 0,
986
+ bottom: 0,
987
+ background: "rgba(255,255,255,0.7)",
988
+ display: "flex",
989
+ alignItems: "center",
990
+ justifyContent: "center",
991
+ zIndex: 5
992
+ },
993
+ children: /* @__PURE__ */ jsx(CircularProgress, { size: 28 })
994
+ }
995
+ ),
996
+ /* @__PURE__ */ jsxs(Table, { size: "small", sx: cdrTableSx, children: [
997
+ /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsx(TableRow, { children: [
998
+ "Phone Number",
999
+ "Call Start",
1000
+ "Call Type",
1001
+ "Status",
1002
+ "Queue",
1003
+ "Extension",
1004
+ "Talk Duration",
1005
+ "Hold Duration",
1006
+ "Ringing Duration",
1007
+ "Wrapup Duration",
1008
+ "Disposition",
1009
+ "Transferred",
1010
+ "Recording"
1011
+ ].map((label) => /* @__PURE__ */ jsx(TableCell, { sx: cdrHeadSx, children: label }, label)) }) }),
1012
+ /* @__PURE__ */ jsxs(TableBody, { children: [
1013
+ cdrRecords.map((row, idx) => {
1014
+ var _a2;
1015
+ return /* @__PURE__ */ jsxs(TableRow, { hover: true, sx: cdrRowSx, children: [
1016
+ /* @__PURE__ */ jsx(TableCell, { sx: { fontWeight: 600, color: C.navy }, children: row.phoneNumber || "" }),
1017
+ /* @__PURE__ */ jsx(TableCell, { sx: { color: "#4a5568" }, children: row.callStartTime ? dayjs(row.callStartTime).format("DD MMM YYYY hh:mm A") : "" }),
1018
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(CallTypeChip, { type: row.callType || "" }) }),
1019
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(StatusChip, { status: row.callStatus || "" }) }),
1020
+ /* @__PURE__ */ jsx(TableCell, { children: row.queueName ? /* @__PURE__ */ jsx(
1021
+ Chip,
1022
+ {
1023
+ label: row.queueName,
1024
+ size: "small",
1025
+ sx: {
1026
+ backgroundColor: "#f0ebfa",
1027
+ color: C.purple,
1028
+ fontWeight: 500,
1029
+ fontSize: "0.67rem",
1030
+ height: 22
1031
+ }
1032
+ }
1033
+ ) : "" }),
1034
+ /* @__PURE__ */ jsx(TableCell, { sx: { color: "#4a5568" }, children: row.extension || "" }),
1035
+ /* @__PURE__ */ jsx(TableCell, { sx: { fontWeight: 600, color: C.blue, fontVariantNumeric: "tabular-nums" }, children: row.talkDurationFmt || "" }),
1036
+ /* @__PURE__ */ jsx(TableCell, { sx: { fontWeight: 500, color: C.amber, fontVariantNumeric: "tabular-nums" }, children: row.holdDurationFmt || "" }),
1037
+ /* @__PURE__ */ jsx(TableCell, { sx: { fontWeight: 500, fontVariantNumeric: "tabular-nums" }, children: row.ringingDurationFmt || "" }),
1038
+ /* @__PURE__ */ jsx(TableCell, { sx: { fontWeight: 500, color: C.purple, fontVariantNumeric: "tabular-nums" }, children: row.wrapupDurationFmt || "" }),
1039
+ /* @__PURE__ */ jsx(TableCell, { sx: { color: "#4a5568" }, children: row.disposition || "" }),
1040
+ /* @__PURE__ */ jsx(TableCell, { children: row.wasTransferred ? /* @__PURE__ */ jsx(
1041
+ Chip,
1042
+ {
1043
+ label: "Yes",
1044
+ size: "small",
1045
+ sx: {
1046
+ backgroundColor: "#e6f7ef",
1047
+ color: C.green,
1048
+ fontWeight: 600,
1049
+ fontSize: "0.65rem",
1050
+ height: 20,
1051
+ borderRadius: "6px"
1052
+ }
1053
+ }
1054
+ ) : /* @__PURE__ */ jsx(
1055
+ Chip,
1056
+ {
1057
+ label: "No",
1058
+ size: "small",
1059
+ sx: {
1060
+ backgroundColor: "transparent",
1061
+ color: "#6b7b8d",
1062
+ fontWeight: 600,
1063
+ fontSize: "0.65rem",
1064
+ height: 20,
1065
+ borderRadius: "6px"
1066
+ }
1067
+ }
1068
+ ) }),
1069
+ /* @__PURE__ */ jsx(TableCell, { children: row.callUuid ? /* @__PURE__ */ jsx(
1070
+ RecordingCell,
1071
+ {
1072
+ callUuid: row.callUuid,
1073
+ recordingPath: (_a2 = row.recordingPath) != null ? _a2 : null
1074
+ }
1075
+ ) : "" })
1076
+ ] }, row.callUuid || idx);
1077
+ }),
1078
+ !cdrLoading && cdrRecords.length === 0 && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
1079
+ TableCell,
1080
+ {
1081
+ colSpan: 13,
1082
+ sx: { textAlign: "center", py: 4, color: C.t3, fontSize: 13 },
1083
+ children: "No call records found"
1084
+ }
1085
+ ) })
1086
+ ] })
1087
+ ] })
1088
+ ] }),
1089
+ /* @__PURE__ */ jsx(
1090
+ TablePagination,
1091
+ {
1092
+ component: "div",
1093
+ count: cdrTotal,
1094
+ page: cdrPage,
1095
+ onPageChange: (_, p) => setCdrPage(p),
1096
+ rowsPerPage: cdrPageSize,
1097
+ onRowsPerPageChange: (e) => {
1098
+ setCdrPageSize(parseInt(e.target.value, 10));
1099
+ setCdrPage(0);
1100
+ },
1101
+ rowsPerPageOptions: [5, 10, 20, 25, 50],
1102
+ sx: paginationSx
1103
+ }
1104
+ )
1105
+ ]
1106
+ }
1107
+ ),
1108
+ activeTab === 2 && /* @__PURE__ */ jsxs(Box, { children: [
1109
+ /* @__PURE__ */ jsxs(
1110
+ Box,
1111
+ {
1112
+ sx: {
1113
+ display: "grid",
1114
+ gridTemplateColumns: {
1115
+ xs: "1fr 1fr",
1116
+ md: "repeat(3, 1fr)",
1117
+ lg: "repeat(4, 1fr)"
1118
+ },
1119
+ gap: { xs: 1.5, lg: 2 },
1120
+ mb: 2
1121
+ },
1122
+ children: [
1123
+ /* @__PURE__ */ jsx(
1124
+ StatCard,
1125
+ {
1126
+ value: (profile == null ? void 0 : profile.breakTimeFormatted) || "00:00:00",
1127
+ label: "Total Break Time",
1128
+ color: C.amber
1129
+ }
1130
+ ),
1131
+ /* @__PURE__ */ jsx(StatCard, { value: (_f = profile == null ? void 0 : profile.breaksTaken) != null ? _f : 0, label: "Breaks Taken", color: C.purple }),
1132
+ /* @__PURE__ */ jsx(
1133
+ StatCard,
1134
+ {
1135
+ value: (profile == null ? void 0 : profile.productionFormatted) || "00:00:00",
1136
+ label: "Production Time",
1137
+ color: C.green
1138
+ }
1139
+ ),
1140
+ /* @__PURE__ */ jsx(
1141
+ StatCard,
1142
+ {
1143
+ value: (profile == null ? void 0 : profile.loginDurationFormatted) || "00:00:00",
1144
+ label: "Login Duration",
1145
+ color: C.teal
1146
+ }
1147
+ )
1148
+ ]
1149
+ }
1150
+ ),
1151
+ /* @__PURE__ */ jsxs(Box, { children: [
1152
+ /* @__PURE__ */ jsx(
1153
+ Typography,
1154
+ {
1155
+ sx: {
1156
+ fontSize: "0.72rem",
1157
+ fontWeight: 700,
1158
+ color: "#888",
1159
+ textTransform: "uppercase",
1160
+ letterSpacing: 0.8,
1161
+ mb: 1,
1162
+ fontFamily: "poppins, Arial, sans-serif"
1163
+ },
1164
+ children: "Attendance Summary"
1165
+ }
1166
+ ),
1167
+ /* @__PURE__ */ jsx(
1168
+ Box,
1169
+ {
1170
+ sx: {
1171
+ display: "grid",
1172
+ gridTemplateColumns: { xs: "1fr 1fr", md: "repeat(4, 1fr)" },
1173
+ gap: 1.5
1174
+ },
1175
+ children: [
1176
+ {
1177
+ label: "First Login",
1178
+ value: (profile == null ? void 0 : profile.firstLoginTime) ? dayjs(profile.firstLoginTime).format("YYYY-MM-DD HH:mm:ss") : "\u2014",
1179
+ color: C.blue
1180
+ },
1181
+ {
1182
+ label: "Adherence Score",
1183
+ value: `${(_g = profile == null ? void 0 : profile.adherencePct) != null ? _g : 0}%`,
1184
+ color: C.green
1185
+ },
1186
+ {
1187
+ label: "Adherence Grade",
1188
+ value: (profile == null ? void 0 : profile.adherenceGrade) || "\u2014",
1189
+ color: C.purple
1190
+ },
1191
+ {
1192
+ label: "Answer Rate",
1193
+ value: `${((_h = profile == null ? void 0 : profile.answerRate) != null ? _h : 0).toFixed(1)}%`,
1194
+ color: C.teal
1195
+ }
1196
+ ].map((item) => /* @__PURE__ */ jsx(
1197
+ StatCard,
1198
+ {
1199
+ value: item.value,
1200
+ label: item.label,
1201
+ color: item.color
1202
+ },
1203
+ item.label
1204
+ ))
1205
+ }
1206
+ )
1207
+ ] })
1208
+ ] })
1209
+ ] })
1210
+ ] }) });
1211
+ }
1212
+ );
1213
+ var AgentDetailReport = (props) => /* @__PURE__ */ jsx(SDKProvider, { children: /* @__PURE__ */ jsx(AgentDetailReportContent, __spreadValues({}, props)) });
1214
+ var agentDetailReport_default = AgentDetailReport;
1215
+
1216
+ export {
1217
+ agentDetailReport_default
1218
+ };
1219
+ //# sourceMappingURL=chunk-U2DJ5WRK.mjs.map