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,2664 @@
1
+ import {
2
+ useGetCallerData
3
+ } from "./chunk-AEDSLIHI.mjs";
4
+ import {
5
+ SDKPermissionGuard,
6
+ useSDKPermissions
7
+ } from "./chunk-I4CJTHZR.mjs";
8
+ import {
9
+ SDKButton
10
+ } from "./chunk-FVNDPJUU.mjs";
11
+ import {
12
+ SDKPageHeader
13
+ } from "./chunk-RZZQ42MG.mjs";
14
+ import {
15
+ END_POINT,
16
+ SDKProvider,
17
+ SDK_PERMISSIONS,
18
+ __spreadProps,
19
+ __spreadValues,
20
+ axios_default,
21
+ useToast
22
+ } from "./chunk-YREOEULC.mjs";
23
+
24
+ // call-control-sdk/lib/pages/campaigns/index.tsx
25
+ import { memo, useCallback as useCallback2, useEffect, useRef, useState as useState2 } from "react";
26
+ import {
27
+ Box,
28
+ Chip,
29
+ CircularProgress,
30
+ FormControl,
31
+ FormControlLabel,
32
+ Checkbox,
33
+ IconButton,
34
+ InputAdornment,
35
+ MenuItem,
36
+ OutlinedInput,
37
+ Paper,
38
+ Select,
39
+ Tab,
40
+ Table,
41
+ TableBody,
42
+ TableCell,
43
+ TableContainer,
44
+ TableHead,
45
+ TablePagination,
46
+ TableRow,
47
+ Tabs,
48
+ TextField,
49
+ Tooltip,
50
+ Typography,
51
+ useTheme
52
+ } from "@mui/material";
53
+ import AddIcon from "@mui/icons-material/Add";
54
+ import ArchiveIcon from "@mui/icons-material/Archive";
55
+ import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
56
+ import ChevronRightIcon from "@mui/icons-material/ChevronRight";
57
+ import DeleteIcon from "@mui/icons-material/Delete";
58
+ import DownloadIcon from "@mui/icons-material/Download";
59
+ import EditIcon from "@mui/icons-material/Edit";
60
+ import PauseIcon from "@mui/icons-material/Pause";
61
+ import PhoneIcon from "@mui/icons-material/Phone";
62
+ import PlayArrowIcon from "@mui/icons-material/PlayArrow";
63
+ import RefreshIcon from "@mui/icons-material/Refresh";
64
+ import SearchIcon from "@mui/icons-material/Search";
65
+ import SettingsIcon from "@mui/icons-material/Settings";
66
+ import UploadFileIcon from "@mui/icons-material/UploadFile";
67
+
68
+ // call-control-sdk/lib/pages/campaigns/useCampaigns.ts
69
+ import { useState, useCallback } from "react";
70
+ function useCampaigns() {
71
+ const [campaigns, setCampaigns] = useState([]);
72
+ const [loading, setLoading] = useState(false);
73
+ const fetchCampaigns = useCallback(async () => {
74
+ setLoading(true);
75
+ try {
76
+ const res = await axios_default.get(END_POINT.CAMPAIGNS_GET_ALL);
77
+ setCampaigns(Array.isArray(res.data) ? res.data : []);
78
+ } catch (e) {
79
+ setCampaigns([]);
80
+ } finally {
81
+ setLoading(false);
82
+ }
83
+ }, []);
84
+ const getCampaignById = useCallback(async (id) => {
85
+ const res = await axios_default.get(END_POINT.CAMPAIGNS_GET_BY_ID(id));
86
+ return res.data;
87
+ }, []);
88
+ const createCampaign = useCallback(async (data) => {
89
+ const res = await axios_default.post(END_POINT.CAMPAIGNS_CREATE, data);
90
+ return res.data;
91
+ }, []);
92
+ const updateCampaign = useCallback(async (id, data) => {
93
+ const res = await axios_default.put(END_POINT.CAMPAIGNS_UPDATE(id), data);
94
+ return res.data;
95
+ }, []);
96
+ const activateCampaign = useCallback(async (id) => {
97
+ const res = await axios_default.post(END_POINT.CAMPAIGNS_ACTIVATE(id));
98
+ return res.data;
99
+ }, []);
100
+ const pauseCampaign = useCallback(async (id) => {
101
+ const res = await axios_default.post(END_POINT.CAMPAIGNS_PAUSE(id));
102
+ return res.data;
103
+ }, []);
104
+ const archiveCampaign = useCallback(async (id) => {
105
+ const res = await axios_default.post(END_POINT.CAMPAIGNS_ARCHIVE(id));
106
+ return res.data;
107
+ }, []);
108
+ return {
109
+ campaigns,
110
+ loading,
111
+ fetchCampaigns,
112
+ getCampaignById,
113
+ createCampaign,
114
+ updateCampaign,
115
+ activateCampaign,
116
+ pauseCampaign,
117
+ archiveCampaign
118
+ };
119
+ }
120
+ function useLeads() {
121
+ const [leads, setLeads] = useState([]);
122
+ const [leadTotal, setLeadTotal] = useState(0);
123
+ const [leadsMeta, setLeadsMeta] = useState(null);
124
+ const [loading, setLoading] = useState(false);
125
+ const fetchLeads = useCallback(async (campaignId, params) => {
126
+ var _a, _b, _c, _d, _e, _f;
127
+ setLoading(true);
128
+ try {
129
+ const qs = new URLSearchParams();
130
+ if ((params == null ? void 0 : params.skip) != null) qs.append("skip", String(params.skip));
131
+ if ((params == null ? void 0 : params.limit) != null) qs.append("limit", String(params.limit));
132
+ if (params == null ? void 0 : params.status) qs.append("status", params.status);
133
+ if (params == null ? void 0 : params.phone_number) qs.append("phone_number", params.phone_number);
134
+ const qsStr = qs.toString();
135
+ const url = `${END_POINT.CAMPAIGNS_LEADS(campaignId)}${qsStr ? `?${qsStr}` : ""}`;
136
+ const res = await axios_default.get(url);
137
+ const fetchedLeads = Array.isArray((_a = res.data) == null ? void 0 : _a.leads) ? res.data.leads : [];
138
+ setLeads(fetchedLeads);
139
+ setLeadTotal((_c = (_b = res.data) == null ? void 0 : _b.total) != null ? _c : fetchedLeads.length);
140
+ setLeadsMeta({
141
+ isDialerEnabled: (_d = res.data) == null ? void 0 : _d.isDialerEnabled,
142
+ dialingMode: (_e = res.data) == null ? void 0 : _e.dialingMode,
143
+ campaignStatus: (_f = res.data) == null ? void 0 : _f.campaignStatus
144
+ });
145
+ } catch (e) {
146
+ setLeads([]);
147
+ setLeadTotal(0);
148
+ setLeadsMeta(null);
149
+ } finally {
150
+ setLoading(false);
151
+ }
152
+ }, []);
153
+ const createLead = useCallback(async (campaignId, data) => {
154
+ const res = await axios_default.post(END_POINT.CAMPAIGNS_LEADS(campaignId), data);
155
+ return res.data;
156
+ }, []);
157
+ const deleteLead = useCallback(async (campaignId, leadId) => {
158
+ await axios_default.delete(END_POINT.CAMPAIGNS_DELETE_LEAD(campaignId, leadId));
159
+ }, []);
160
+ const dialPreview = useCallback(async (campaignId, leadId) => {
161
+ const res = await axios_default.post(END_POINT.CAMPAIGNS_DIAL_PREVIEW(campaignId, leadId));
162
+ return res.data;
163
+ }, []);
164
+ const uploadLeadsExcel = useCallback(async (campaignId, file) => {
165
+ const formData = new FormData();
166
+ formData.append("file", file);
167
+ const res = await axios_default.post(END_POINT.CAMPAIGNS_LEADS_UPLOAD_EXCEL(campaignId), formData, {
168
+ headers: { "Content-Type": "multipart/form-data" }
169
+ });
170
+ return res.data;
171
+ }, []);
172
+ const downloadLeadTemplate = useCallback(async (campaignId) => {
173
+ const res = await axios_default.get(END_POINT.CAMPAIGNS_LEADS_TEMPLATE_EXCEL(campaignId), {
174
+ responseType: "blob"
175
+ });
176
+ const blob = res.data;
177
+ const url = window.URL.createObjectURL(blob);
178
+ const a = document.createElement("a");
179
+ a.href = url;
180
+ a.download = "lead_template.xlsx";
181
+ document.body.appendChild(a);
182
+ a.click();
183
+ a.remove();
184
+ window.URL.revokeObjectURL(url);
185
+ }, []);
186
+ const exportLeads = useCallback(async (campaignId) => {
187
+ const res = await axios_default.get(END_POINT.CAMPAIGNS_LEADS_EXPORT_EXCEL(campaignId), {
188
+ responseType: "blob"
189
+ });
190
+ const blob = res.data;
191
+ const url = window.URL.createObjectURL(blob);
192
+ const a = document.createElement("a");
193
+ a.href = url;
194
+ a.download = "leads_export.xlsx";
195
+ document.body.appendChild(a);
196
+ a.click();
197
+ a.remove();
198
+ window.URL.revokeObjectURL(url);
199
+ }, []);
200
+ return {
201
+ leads,
202
+ leadTotal,
203
+ leadsMeta,
204
+ loading,
205
+ fetchLeads,
206
+ createLead,
207
+ deleteLead,
208
+ dialPreview,
209
+ uploadLeadsExcel,
210
+ downloadLeadTemplate,
211
+ exportLeads
212
+ };
213
+ }
214
+ function useQueues() {
215
+ const [queues, setQueues] = useState([]);
216
+ const [loading, setLoading] = useState(false);
217
+ const fetchQueues = useCallback(async () => {
218
+ var _a;
219
+ setLoading(true);
220
+ try {
221
+ const res = await axios_default.get(END_POINT.QUEUES_GET_ALL);
222
+ const list = Array.isArray(res.data) ? res.data : Array.isArray((_a = res.data) == null ? void 0 : _a.data) ? res.data.data : [];
223
+ setQueues(list);
224
+ return list;
225
+ } catch (e) {
226
+ setQueues([]);
227
+ return [];
228
+ } finally {
229
+ setLoading(false);
230
+ }
231
+ }, []);
232
+ const createQueue = useCallback(async (payload) => {
233
+ var _a, _b;
234
+ const res = await axios_default.post(END_POINT.QUEUES_CREATE, payload);
235
+ return (_b = (_a = res.data) == null ? void 0 : _a.data) != null ? _b : res.data;
236
+ }, []);
237
+ return { queues, loading, fetchQueues, createQueue };
238
+ }
239
+
240
+ // call-control-sdk/lib/pages/campaigns/types.ts
241
+ var CAMPAIGN_TYPES = ["OUTBOUND_CAMPAIGN", "ABANDONED_CALLBACK"];
242
+ var DIALING_MODES_MAP = {
243
+ OUTBOUND_CAMPAIGN: ["PREVIEW"],
244
+ ABANDONED_CALLBACK: ["PROGRESSIVE", "PREDICTIVE"]
245
+ };
246
+ var AGENT_TYPES = ["HUMAN", "AI", "HYBRID"];
247
+ var LEAD_PRIORITY_OPTIONS = [
248
+ { label: "HIGH", value: 10 },
249
+ { label: "MEDIUM", value: 5 },
250
+ { label: "LOW", value: 1 }
251
+ ];
252
+ var DAYS_OF_WEEK = [
253
+ { label: "Sun", value: 0 },
254
+ { label: "Mon", value: 1 },
255
+ { label: "Tue", value: 2 },
256
+ { label: "Wed", value: 3 },
257
+ { label: "Thu", value: 4 },
258
+ { label: "Fri", value: 5 },
259
+ { label: "Sat", value: 6 }
260
+ ];
261
+ var LEAD_STATUSES = [
262
+ "All states",
263
+ "PENDING",
264
+ "SCHEDULED",
265
+ "IN_PROGRESS",
266
+ "COMPLETED",
267
+ "FAILED",
268
+ "DO_NOT_CALL",
269
+ "INVALID",
270
+ "CANCELLED"
271
+ ];
272
+ var defaultFormData = {
273
+ name: "",
274
+ description: "",
275
+ campaignType: "OUTBOUND_CAMPAIGN",
276
+ dialingMode: "PREVIEW",
277
+ maxConcurrentCalls: 5,
278
+ callsPerAgent: 1,
279
+ startTime: "09:00",
280
+ endTime: "17:00",
281
+ daysOfWeek: [1, 2, 3, 4, 5],
282
+ timezone: "Asia/Kolkata",
283
+ scheduledStart: "",
284
+ scheduledEnd: "",
285
+ maxAttempts: 0,
286
+ retryIntervalMinutes: 15,
287
+ callerId: "",
288
+ ringTimeoutSeconds: 30,
289
+ answerTimeoutSeconds: 30,
290
+ agentType: "HUMAN",
291
+ aiBotId: null,
292
+ priority: 5,
293
+ settings: {},
294
+ queueLinks: []
295
+ };
296
+
297
+ // call-control-sdk/lib/pages/campaigns/styles.ts
298
+ var labelSx = {
299
+ fontWeight: 600,
300
+ fontSize: "0.85rem",
301
+ color: "#333",
302
+ mb: 0.5
303
+ };
304
+ var sectionTitleSx = {
305
+ fontWeight: 700,
306
+ fontSize: "1rem",
307
+ color: "#1a1a1a",
308
+ mb: 1.5,
309
+ mt: 0.5,
310
+ fontFamily: "poppins, Arial, sans-serif"
311
+ };
312
+ var headCellSx = {
313
+ fontFamily: "poppins, Arial, sans-serif",
314
+ bgcolor: "#f1f1f1",
315
+ color: "#333",
316
+ fontWeight: 600,
317
+ whiteSpace: "nowrap",
318
+ fontSize: "0.8rem",
319
+ py: "6px",
320
+ px: "12px"
321
+ };
322
+ var bodyCellSx = {
323
+ fontFamily: "poppins, Arial, sans-serif",
324
+ fontSize: "0.82rem",
325
+ py: "4px",
326
+ px: "12px"
327
+ };
328
+ var tableRowSx = {
329
+ "&:hover": { backgroundColor: "#f0f7f8" },
330
+ "&:last-child td, &:last-child th": { border: 0 }
331
+ };
332
+ var campaignCardBaseSx = {
333
+ p: 1.5,
334
+ mb: 0.75,
335
+ borderRadius: "12px",
336
+ cursor: "pointer",
337
+ border: "1px solid #e8e8e8",
338
+ backgroundColor: "#fff",
339
+ boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
340
+ transition: "all 0.2s ease"
341
+ };
342
+ var campaignCardSelectedSx = __spreadProps(__spreadValues({}, campaignCardBaseSx), {
343
+ border: "2px solid #1A5F6C",
344
+ backgroundColor: "#f0f7f8",
345
+ boxShadow: "0 2px 8px rgba(26,95,108,0.12)"
346
+ });
347
+ var inputSx = {
348
+ "& .MuiOutlinedInput-root": {
349
+ borderRadius: "8px",
350
+ backgroundColor: "#fff",
351
+ "&:hover fieldset": { borderColor: "#1A5F6C" },
352
+ "&.Mui-focused fieldset": { borderColor: "#1A5F6C" }
353
+ }
354
+ };
355
+ var dialogHeaderSx = {
356
+ px: 2.5,
357
+ py: 1.5,
358
+ borderBottom: "1px solid #eee",
359
+ display: "flex",
360
+ alignItems: "center",
361
+ justifyContent: "space-between"
362
+ };
363
+ var dialogFooterSx = {
364
+ px: 2.5,
365
+ py: 1.5,
366
+ borderTop: "1px solid #eee",
367
+ display: "flex",
368
+ justifyContent: "flex-end",
369
+ gap: 1
370
+ };
371
+ var STATUS_COLORS = {
372
+ draft: "#9e9e9e",
373
+ active: "#4caf50",
374
+ paused: "#ff9800",
375
+ completed: "#2196f3",
376
+ archived: "#795548"
377
+ };
378
+ function statusChipSx(status) {
379
+ var _a;
380
+ const color = (_a = STATUS_COLORS[status == null ? void 0 : status.toLowerCase()]) != null ? _a : "#9e9e9e";
381
+ return {
382
+ height: 22,
383
+ fontSize: "0.68rem",
384
+ fontWeight: 700,
385
+ textTransform: "capitalize",
386
+ borderRadius: "6px",
387
+ backgroundColor: color + "18",
388
+ color,
389
+ border: `1px solid ${color}40`
390
+ };
391
+ }
392
+ function leadStatusChipSx(status) {
393
+ const s = status == null ? void 0 : status.toUpperCase();
394
+ return {
395
+ height: 22,
396
+ fontSize: "0.72rem",
397
+ fontWeight: 700,
398
+ textTransform: "capitalize",
399
+ borderRadius: "6px",
400
+ backgroundColor: s === "COMPLETED" ? "#e8f5e9" : s === "FAILED" ? "#ffebee" : s === "DIALING" ? "#e3f2fd" : "#f5f5f5",
401
+ color: s === "COMPLETED" ? "#2e7d32" : s === "FAILED" ? "#c62828" : s === "DIALING" ? "#1565c0" : "#666"
402
+ };
403
+ }
404
+ function leadPriorityChipSx(priority) {
405
+ const label = priority == null ? "\u2014" : priority >= 8 ? "HIGH" : priority >= 4 ? "MEDIUM" : "LOW";
406
+ return {
407
+ chip: {
408
+ height: 22,
409
+ fontSize: "0.72rem",
410
+ fontWeight: 700,
411
+ borderRadius: "6px",
412
+ backgroundColor: label === "HIGH" ? "#ffebee" : label === "MEDIUM" ? "#e3f2fd" : label === "LOW" ? "#e8f5e9" : "#f5f5f5",
413
+ color: label === "HIGH" ? "#c62828" : label === "MEDIUM" ? "#1565c0" : label === "LOW" ? "#2e7d32" : "#666"
414
+ },
415
+ label
416
+ };
417
+ }
418
+ function daychipSx(selected) {
419
+ return {
420
+ cursor: "pointer",
421
+ backgroundColor: selected ? "#1A5F6C" : "transparent",
422
+ color: selected ? "#fff" : "#333",
423
+ borderColor: "#1A5F6C",
424
+ fontWeight: 500,
425
+ "&:hover": {
426
+ backgroundColor: selected ? "#164e57" : "#E3F2F5"
427
+ }
428
+ };
429
+ }
430
+
431
+ // call-control-sdk/lib/pages/campaigns/index.tsx
432
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
433
+ function validatePhone(raw) {
434
+ const trimmed = (raw || "").trim();
435
+ if (!trimmed) return "Phone number is required";
436
+ const digits = trimmed.startsWith("+91") ? trimmed.slice(3) : trimmed.startsWith("91") && trimmed.length === 12 ? trimmed.slice(2) : trimmed;
437
+ if (!/^\d{10}$/.test(digits)) return "Must be 10 digits, 91+10, or +91+10";
438
+ return null;
439
+ }
440
+ function campaignToFormData(c) {
441
+ var _a, _b, _c, _d, _e, _f, _g;
442
+ return {
443
+ name: c.name || "",
444
+ description: c.description || "",
445
+ campaignType: (c.campaignType || "OUTBOUND_CAMPAIGN").toUpperCase(),
446
+ dialingMode: (c.dialingMode || "PREVIEW").toUpperCase(),
447
+ maxConcurrentCalls: (_a = c.maxConcurrentCalls) != null ? _a : 5,
448
+ callsPerAgent: (_b = c.callsPerAgent) != null ? _b : 1,
449
+ startTime: c.startTime ? c.startTime.slice(0, 5) : "09:00",
450
+ endTime: c.endTime ? c.endTime.slice(0, 5) : "17:00",
451
+ daysOfWeek: c.daysOfWeek || [1, 2, 3, 4, 5],
452
+ timezone: c.timezone || "Asia/Kolkata",
453
+ scheduledStart: c.scheduledStart || "",
454
+ scheduledEnd: c.scheduledEnd || "",
455
+ maxAttempts: (_c = c.maxAttempts) != null ? _c : 3,
456
+ retryIntervalMinutes: (_d = c.retryIntervalMinutes) != null ? _d : 15,
457
+ callerId: c.callerId || "",
458
+ ringTimeoutSeconds: (_e = c.ringTimeoutSeconds) != null ? _e : 30,
459
+ answerTimeoutSeconds: (_f = c.answerTimeoutSeconds) != null ? _f : 30,
460
+ agentType: c.agentType || "HUMAN",
461
+ aiBotId: null,
462
+ priority: (_g = c.priority) != null ? _g : 5,
463
+ settings: c.settings || {},
464
+ queueLinks: (c.campaignQueues || []).map((q) => {
465
+ var _a2, _b2;
466
+ return {
467
+ queueId: q.queueId,
468
+ priorityOverride: (_a2 = q.priorityOverride) != null ? _a2 : 1,
469
+ minWaitBeforeCallback: (_b2 = q.minWaitBeforeCallback) != null ? _b2 : 0
470
+ };
471
+ })
472
+ };
473
+ }
474
+ function BasicInfoTab({ formData, setFormData, isEditMode }) {
475
+ var _a;
476
+ const handleChange = (field, value) => {
477
+ setFormData((prev) => {
478
+ var _a2;
479
+ const updated = __spreadProps(__spreadValues({}, prev), { [field]: value });
480
+ if (field === "campaignType") {
481
+ updated.dialingMode = ((_a2 = DIALING_MODES_MAP[value]) == null ? void 0 : _a2[0]) || "";
482
+ }
483
+ return updated;
484
+ });
485
+ };
486
+ const mappedModes = DIALING_MODES_MAP[formData.campaignType] || [];
487
+ const availableModes = formData.dialingMode && !mappedModes.includes(formData.dialingMode) ? [formData.dialingMode, ...mappedModes] : mappedModes;
488
+ return /* @__PURE__ */ jsxs(Box, { sx: { p: 2.5 }, children: [
489
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Basic Info" }),
490
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "grid", gridTemplateColumns: { xs: "1fr", sm: "1.5fr 1fr", lg: "1.5fr 1fr 1fr" }, gap: 2, mb: 2 }, children: [
491
+ /* @__PURE__ */ jsxs(Box, { children: [
492
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
493
+ "Campaign Name ",
494
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
495
+ ] }),
496
+ /* @__PURE__ */ jsx(
497
+ TextField,
498
+ {
499
+ fullWidth: true,
500
+ size: "small",
501
+ value: formData.name,
502
+ onChange: (e) => handleChange("name", e.target.value),
503
+ sx: inputSx
504
+ }
505
+ )
506
+ ] }),
507
+ /* @__PURE__ */ jsxs(Box, { children: [
508
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
509
+ "Campaign Type ",
510
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
511
+ ] }),
512
+ /* @__PURE__ */ jsx(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsx(
513
+ Select,
514
+ {
515
+ value: formData.campaignType,
516
+ onChange: (e) => handleChange("campaignType", e.target.value),
517
+ disabled: isEditMode,
518
+ children: CAMPAIGN_TYPES.map((t) => /* @__PURE__ */ jsx(MenuItem, { value: t, children: t }, t))
519
+ }
520
+ ) })
521
+ ] })
522
+ ] }),
523
+ /* @__PURE__ */ jsxs(Box, { sx: { mb: 2 }, children: [
524
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Description" }),
525
+ /* @__PURE__ */ jsx(
526
+ TextField,
527
+ {
528
+ fullWidth: true,
529
+ size: "small",
530
+ multiline: true,
531
+ rows: 3,
532
+ value: formData.description,
533
+ onChange: (e) => handleChange("description", e.target.value),
534
+ sx: inputSx
535
+ }
536
+ )
537
+ ] }),
538
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "grid", gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr", lg: "1fr 1fr 1fr" }, gap: 2 }, children: [
539
+ /* @__PURE__ */ jsxs(Box, { children: [
540
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
541
+ "Dialing Mode ",
542
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
543
+ ] }),
544
+ /* @__PURE__ */ jsx(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsx(
545
+ Select,
546
+ {
547
+ value: formData.dialingMode,
548
+ onChange: (e) => handleChange("dialingMode", e.target.value),
549
+ children: availableModes.map((m) => /* @__PURE__ */ jsx(MenuItem, { value: m, children: m }, m))
550
+ }
551
+ ) })
552
+ ] }),
553
+ /* @__PURE__ */ jsxs(Box, { children: [
554
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Priority" }),
555
+ /* @__PURE__ */ jsx(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsx(
556
+ Select,
557
+ {
558
+ value: (_a = formData.priority) != null ? _a : 5,
559
+ onChange: (e) => handleChange("priority", Number(e.target.value)),
560
+ children: LEAD_PRIORITY_OPTIONS.map((o) => /* @__PURE__ */ jsx(MenuItem, { value: o.value, children: o.label }, o.label))
561
+ }
562
+ ) })
563
+ ] })
564
+ ] })
565
+ ] });
566
+ }
567
+ function DialingConfigTab({ formData, setFormData }) {
568
+ const handleChange = (field, value) => setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [field]: value }));
569
+ return /* @__PURE__ */ jsxs(Box, { sx: { p: 2.5 }, children: [
570
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Dialing Configuration" }),
571
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "grid", gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr", lg: "1fr 1fr 1fr" }, gap: 2 }, children: [
572
+ /* @__PURE__ */ jsxs(Box, { children: [
573
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
574
+ "Max Concurrent Calls ",
575
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
576
+ ] }),
577
+ /* @__PURE__ */ jsx(
578
+ TextField,
579
+ {
580
+ fullWidth: true,
581
+ size: "small",
582
+ type: "number",
583
+ value: formData.maxConcurrentCalls,
584
+ onChange: (e) => handleChange("maxConcurrentCalls", parseInt(e.target.value) || 1),
585
+ slotProps: { htmlInput: { min: 1 } },
586
+ sx: inputSx
587
+ }
588
+ )
589
+ ] }),
590
+ /* @__PURE__ */ jsxs(Box, { children: [
591
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Calls Per Agent" }),
592
+ /* @__PURE__ */ jsx(
593
+ TextField,
594
+ {
595
+ fullWidth: true,
596
+ size: "small",
597
+ type: "number",
598
+ value: formData.callsPerAgent,
599
+ onChange: (e) => handleChange("callsPerAgent", parseFloat(e.target.value) || 1),
600
+ slotProps: { htmlInput: { min: 0.1, step: 0.1 } },
601
+ sx: inputSx
602
+ }
603
+ )
604
+ ] }),
605
+ /* @__PURE__ */ jsxs(Box, { children: [
606
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Ring Timeout (sec)" }),
607
+ /* @__PURE__ */ jsx(
608
+ TextField,
609
+ {
610
+ fullWidth: true,
611
+ size: "small",
612
+ type: "number",
613
+ value: formData.ringTimeoutSeconds,
614
+ onChange: (e) => handleChange("ringTimeoutSeconds", parseInt(e.target.value) || 30),
615
+ slotProps: { htmlInput: { min: 5 } },
616
+ sx: inputSx
617
+ }
618
+ )
619
+ ] }),
620
+ /* @__PURE__ */ jsxs(Box, { children: [
621
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Answer Timeout (sec)" }),
622
+ /* @__PURE__ */ jsx(
623
+ TextField,
624
+ {
625
+ fullWidth: true,
626
+ size: "small",
627
+ type: "number",
628
+ value: formData.answerTimeoutSeconds,
629
+ onChange: (e) => handleChange("answerTimeoutSeconds", parseInt(e.target.value) || 0),
630
+ slotProps: { htmlInput: { min: 0 } },
631
+ sx: inputSx
632
+ }
633
+ )
634
+ ] }),
635
+ /* @__PURE__ */ jsxs(Box, { children: [
636
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
637
+ "Max Attempts ",
638
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
639
+ ] }),
640
+ /* @__PURE__ */ jsx(
641
+ TextField,
642
+ {
643
+ fullWidth: true,
644
+ size: "small",
645
+ type: "number",
646
+ value: formData.maxAttempts || "",
647
+ onChange: (e) => handleChange("maxAttempts", parseInt(e.target.value) || 0),
648
+ slotProps: { htmlInput: { min: 1 } },
649
+ sx: inputSx
650
+ }
651
+ )
652
+ ] }),
653
+ /* @__PURE__ */ jsxs(Box, { children: [
654
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Retry Interval (min)" }),
655
+ /* @__PURE__ */ jsx(
656
+ TextField,
657
+ {
658
+ fullWidth: true,
659
+ size: "small",
660
+ type: "number",
661
+ value: formData.retryIntervalMinutes,
662
+ onChange: (e) => handleChange("retryIntervalMinutes", parseInt(e.target.value) || 5),
663
+ slotProps: { htmlInput: { min: 1 } },
664
+ sx: inputSx
665
+ }
666
+ )
667
+ ] }),
668
+ /* @__PURE__ */ jsxs(Box, { children: [
669
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Agent Type" }),
670
+ /* @__PURE__ */ jsx(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsx(
671
+ Select,
672
+ {
673
+ value: formData.agentType,
674
+ onChange: (e) => handleChange("agentType", e.target.value),
675
+ children: AGENT_TYPES.map((t) => /* @__PURE__ */ jsx(MenuItem, { value: t, children: t }, t))
676
+ }
677
+ ) })
678
+ ] })
679
+ ] })
680
+ ] });
681
+ }
682
+ function ScheduleTab({ formData, setFormData }) {
683
+ const handleChange = (field, value) => setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [field]: value }));
684
+ const toggleDay = (day) => setFormData((prev) => __spreadProps(__spreadValues({}, prev), {
685
+ daysOfWeek: prev.daysOfWeek.includes(day) ? prev.daysOfWeek.filter((d) => d !== day) : [...prev.daysOfWeek, day].sort()
686
+ }));
687
+ return /* @__PURE__ */ jsxs(Box, { sx: { p: 2.5 }, children: [
688
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Operating Schedule" }),
689
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "grid", gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr", lg: "1fr 1fr 1fr" }, gap: 2, mb: 2 }, children: [
690
+ /* @__PURE__ */ jsxs(Box, { children: [
691
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
692
+ "Start Time ",
693
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
694
+ ] }),
695
+ /* @__PURE__ */ jsx(
696
+ TextField,
697
+ {
698
+ fullWidth: true,
699
+ size: "small",
700
+ type: "time",
701
+ value: formData.startTime,
702
+ onChange: (e) => handleChange("startTime", e.target.value),
703
+ sx: inputSx
704
+ }
705
+ )
706
+ ] }),
707
+ /* @__PURE__ */ jsxs(Box, { children: [
708
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
709
+ "End Time ",
710
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
711
+ ] }),
712
+ /* @__PURE__ */ jsx(
713
+ TextField,
714
+ {
715
+ fullWidth: true,
716
+ size: "small",
717
+ type: "time",
718
+ value: formData.endTime,
719
+ onChange: (e) => handleChange("endTime", e.target.value),
720
+ sx: inputSx
721
+ }
722
+ )
723
+ ] })
724
+ ] }),
725
+ /* @__PURE__ */ jsxs(Box, { sx: { mb: 2 }, children: [
726
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Timezone" }),
727
+ /* @__PURE__ */ jsx(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsx(Select, { value: formData.timezone, onChange: (e) => handleChange("timezone", e.target.value), children: [
728
+ "Etc/UTC",
729
+ "US/Eastern",
730
+ "US/Central",
731
+ "US/Mountain",
732
+ "US/Pacific",
733
+ "Europe/London",
734
+ "Europe/Berlin",
735
+ "Asia/Kolkata",
736
+ "Asia/Tokyo",
737
+ "Australia/Sydney"
738
+ ].map((tz) => /* @__PURE__ */ jsx(MenuItem, { value: tz, children: tz }, tz)) }) })
739
+ ] }),
740
+ /* @__PURE__ */ jsxs(Box, { children: [
741
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Days of Week" }),
742
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", gap: 1, flexWrap: "wrap", mt: 0.5 }, children: DAYS_OF_WEEK.map((day) => /* @__PURE__ */ jsx(
743
+ Chip,
744
+ {
745
+ label: day.label,
746
+ onClick: () => toggleDay(day.value),
747
+ variant: formData.daysOfWeek.includes(day.value) ? "filled" : "outlined",
748
+ size: "small",
749
+ sx: daychipSx(formData.daysOfWeek.includes(day.value))
750
+ },
751
+ day.value
752
+ )) })
753
+ ] })
754
+ ] });
755
+ }
756
+ function QueueLinkingTab({
757
+ formData,
758
+ setFormData,
759
+ editingCampaign,
760
+ parentQueueNameMap,
761
+ onQueuesRefreshed
762
+ }) {
763
+ const { showToast } = useToast();
764
+ const { fetchQueues, createQueue } = useQueues();
765
+ const queueLinks = formData.queueLinks || [];
766
+ const isEditMode = !!editingCampaign;
767
+ const campaignQueues = (editingCampaign == null ? void 0 : editingCampaign.campaignQueues) || [];
768
+ const [allQueues, setAllQueues] = useState2([]);
769
+ const [queueNames, setQueueNames] = useState2({});
770
+ const [selectedQueueIds, setSelectedQueueIds] = useState2([]);
771
+ const [createOpen, setCreateOpen] = useState2(false);
772
+ const [newQueue, setNewQueue] = useState2({ name: "", description: "" });
773
+ const [creatingQueue, setCreatingQueue] = useState2(false);
774
+ const loadQueues = useCallback2(async () => {
775
+ const list = await fetchQueues();
776
+ setAllQueues(list);
777
+ const map = {};
778
+ list.forEach((q) => {
779
+ map[q.id] = q.name;
780
+ });
781
+ setQueueNames(map);
782
+ onQueuesRefreshed == null ? void 0 : onQueuesRefreshed(list);
783
+ }, [fetchQueues, onQueuesRefreshed]);
784
+ useEffect(() => {
785
+ loadQueues();
786
+ }, [loadQueues]);
787
+ const handleCreateQueue = async () => {
788
+ var _a, _b;
789
+ if (!newQueue.name.trim()) {
790
+ showToast("Queue name is required", "warning");
791
+ return;
792
+ }
793
+ setCreatingQueue(true);
794
+ try {
795
+ await createQueue(newQueue);
796
+ showToast("Queue created successfully", "success");
797
+ setCreateOpen(false);
798
+ setNewQueue({ name: "", description: "" });
799
+ loadQueues();
800
+ } catch (err) {
801
+ showToast(((_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 create queue", "error");
802
+ } finally {
803
+ setCreatingQueue(false);
804
+ }
805
+ };
806
+ const linkedIds = new Set(
807
+ isEditMode ? campaignQueues.map((q) => q.queueId) : queueLinks.map((q) => q.queueId)
808
+ );
809
+ const availableQueues = allQueues.filter((q) => !linkedIds.has(q.id));
810
+ const handleAddQueues = () => {
811
+ if (selectedQueueIds.length === 0) return;
812
+ const newLinks = selectedQueueIds.map((qId) => ({
813
+ queueId: qId,
814
+ priorityOverride: 5,
815
+ minWaitBeforeCallback: 0
816
+ }));
817
+ setFormData((prev) => __spreadProps(__spreadValues({}, prev), { queueLinks: [...prev.queueLinks || [], ...newLinks] }));
818
+ showToast(`${selectedQueueIds.length} queue(s) added`, "success");
819
+ setSelectedQueueIds([]);
820
+ };
821
+ const handleRemoveQueue = (queueId) => {
822
+ setFormData((prev) => __spreadProps(__spreadValues({}, prev), {
823
+ queueLinks: (prev.queueLinks || []).filter((q) => q.queueId !== queueId)
824
+ }));
825
+ showToast("Queue removed", "success");
826
+ };
827
+ const handleCellUpdate = (queueId, field, value) => {
828
+ const numVal = parseInt(value) || 0;
829
+ setFormData((prev) => __spreadProps(__spreadValues({}, prev), {
830
+ queueLinks: (prev.queueLinks || []).map(
831
+ (q) => q.queueId === queueId ? __spreadProps(__spreadValues({}, q), { [field]: numVal }) : q
832
+ )
833
+ }));
834
+ };
835
+ return /* @__PURE__ */ jsxs(Box, { sx: { p: 2.5 }, children: [
836
+ createOpen && /* @__PURE__ */ jsx(
837
+ Box,
838
+ {
839
+ sx: {
840
+ position: "fixed",
841
+ inset: 0,
842
+ zIndex: 1600,
843
+ backgroundColor: "rgba(0,0,0,0.45)",
844
+ display: "flex",
845
+ alignItems: "center",
846
+ justifyContent: "center"
847
+ },
848
+ onClick: (e) => {
849
+ if (e.target === e.currentTarget && !creatingQueue) setCreateOpen(false);
850
+ },
851
+ children: /* @__PURE__ */ jsxs(Paper, { elevation: 6, sx: { width: { xs: "90vw", sm: 420 }, borderRadius: "16px", overflow: "hidden", boxShadow: "0 8px 32px rgba(26,95,108,0.18)" }, children: [
852
+ /* @__PURE__ */ jsxs(Box, { sx: __spreadProps(__spreadValues({}, dialogHeaderSx), { backgroundColor: "#1A5F6C", color: "#fff" }), children: [
853
+ /* @__PURE__ */ jsx(Typography, { fontWeight: 700, fontSize: "1rem", fontFamily: "poppins, Arial, sans-serif", children: "Create New Queue" }),
854
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: () => !creatingQueue && setCreateOpen(false), sx: { color: "#fff" }, children: "\u2715" })
855
+ ] }),
856
+ /* @__PURE__ */ jsxs(Box, { sx: { p: 2.5, display: "flex", flexDirection: "column", gap: 1.5 }, children: [
857
+ /* @__PURE__ */ jsxs(Box, { children: [
858
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
859
+ "Queue Name ",
860
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
861
+ ] }),
862
+ /* @__PURE__ */ jsx(
863
+ TextField,
864
+ {
865
+ fullWidth: true,
866
+ size: "small",
867
+ value: newQueue.name,
868
+ onChange: (e) => setNewQueue(__spreadProps(__spreadValues({}, newQueue), { name: e.target.value })),
869
+ sx: inputSx
870
+ }
871
+ )
872
+ ] }),
873
+ /* @__PURE__ */ jsxs(Box, { children: [
874
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Description" }),
875
+ /* @__PURE__ */ jsx(
876
+ TextField,
877
+ {
878
+ fullWidth: true,
879
+ size: "small",
880
+ multiline: true,
881
+ rows: 3,
882
+ value: newQueue.description,
883
+ onChange: (e) => setNewQueue(__spreadProps(__spreadValues({}, newQueue), { description: e.target.value })),
884
+ sx: inputSx
885
+ }
886
+ )
887
+ ] })
888
+ ] }),
889
+ /* @__PURE__ */ jsxs(Box, { sx: dialogFooterSx, children: [
890
+ /* @__PURE__ */ jsx(SDKButton, { variant: "cancel", onClick: () => setCreateOpen(false), disabled: creatingQueue, children: "Cancel" }),
891
+ /* @__PURE__ */ jsx(
892
+ SDKButton,
893
+ {
894
+ onClick: handleCreateQueue,
895
+ disabled: creatingQueue,
896
+ startIcon: creatingQueue ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, color: "inherit" }) : void 0,
897
+ children: "Create"
898
+ }
899
+ )
900
+ ] })
901
+ ] })
902
+ }
903
+ ),
904
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", mb: 2 }, children: [
905
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Linked Queues" }),
906
+ /* @__PURE__ */ jsx(SDKButton, { startIcon: /* @__PURE__ */ jsx(AddIcon, {}), onClick: () => setCreateOpen(true), children: "Create New Queue" })
907
+ ] }),
908
+ /* @__PURE__ */ jsxs(Box, { sx: {
909
+ display: "flex",
910
+ alignItems: { xs: "stretch", sm: "center" },
911
+ flexDirection: { xs: "column", sm: "row" },
912
+ gap: 1.5,
913
+ mb: 2
914
+ }, children: [
915
+ /* @__PURE__ */ jsx(FormControl, { size: "small", sx: { flex: 2 }, children: /* @__PURE__ */ jsx(
916
+ Select,
917
+ {
918
+ multiple: true,
919
+ value: selectedQueueIds,
920
+ onChange: (e) => setSelectedQueueIds(e.target.value),
921
+ displayEmpty: true,
922
+ renderValue: (selected) => selected.length === 0 ? /* @__PURE__ */ jsx(Typography, { sx: { color: "#999", fontSize: "0.85rem" }, children: "Select queues to link" }) : /* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexWrap: "wrap", gap: 0.5 }, children: selected.map((id) => /* @__PURE__ */ jsx(
923
+ Chip,
924
+ {
925
+ size: "small",
926
+ label: queueNames[id] || parentQueueNameMap[id] || `Queue #${id}`,
927
+ sx: { height: 22, fontSize: "0.75rem", fontWeight: 600, backgroundColor: "#e0f2f1", color: "#00695c" }
928
+ },
929
+ id
930
+ )) }),
931
+ sx: {
932
+ borderRadius: "8px",
933
+ fontSize: "0.85rem",
934
+ "& .MuiSelect-select": { display: "flex", flexWrap: "wrap", gap: 0.5, py: 0.75 }
935
+ },
936
+ MenuProps: {
937
+ PaperProps: { sx: { maxHeight: 250, borderRadius: "8px", mt: 0.5, boxShadow: "0 4px 20px rgba(0,0,0,0.12)" } }
938
+ },
939
+ children: availableQueues.length === 0 ? /* @__PURE__ */ jsx(MenuItem, { value: "", disabled: true, children: "No available queues" }) : availableQueues.map((q) => /* @__PURE__ */ jsxs(MenuItem, { value: q.id, sx: { py: 0.75, px: 1.5, fontSize: "0.85rem" }, children: [
940
+ /* @__PURE__ */ jsx(
941
+ Checkbox,
942
+ {
943
+ size: "small",
944
+ checked: selectedQueueIds.includes(q.id),
945
+ sx: { p: 0.5, mr: 1, color: "#1A5F6C", "&.Mui-checked": { color: "#1A5F6C" } }
946
+ }
947
+ ),
948
+ q.name,
949
+ " (ID: ",
950
+ q.id,
951
+ ")"
952
+ ] }, q.id))
953
+ }
954
+ ) }),
955
+ /* @__PURE__ */ jsx(SDKButton, { onClick: handleAddQueues, disabled: selectedQueueIds.length === 0, sx: { whiteSpace: "nowrap" }, children: "Add To List" })
956
+ ] }),
957
+ queueLinks.length === 0 ? /* @__PURE__ */ jsx(Paper, { variant: "outlined", sx: { p: 3, textAlign: "center", borderRadius: 2, borderStyle: "dashed" }, children: /* @__PURE__ */ jsx(Typography, { sx: { color: "#999", fontSize: "0.9rem" }, children: "No queues linked yet. Select queues above to add." }) }) : /* @__PURE__ */ jsx(TableContainer, { component: Paper, variant: "outlined", sx: { borderRadius: 2, overflow: "visible" }, children: /* @__PURE__ */ jsxs(Table, { size: "small", children: [
958
+ /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { sx: { backgroundColor: "#f1f1f1" }, children: [
959
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Queue Name" }),
960
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Priority Override" }),
961
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Min Wait Before Callback" }),
962
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, headCellSx), { textAlign: "right" }), children: "Action" })
963
+ ] }) }),
964
+ /* @__PURE__ */ jsx(TableBody, { children: queueLinks.map((q) => {
965
+ var _a;
966
+ return /* @__PURE__ */ jsxs(TableRow, { sx: tableRowSx, children: [
967
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: queueNames[q.queueId] || parentQueueNameMap[q.queueId] || `Queue #${q.queueId}` }),
968
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: /* @__PURE__ */ jsx(FormControl, { size: "small", sx: { width: 120 }, children: /* @__PURE__ */ jsx(
969
+ Select,
970
+ {
971
+ value: (_a = q.priorityOverride) != null ? _a : 5,
972
+ onChange: (e) => handleCellUpdate(q.queueId, "priorityOverride", String(e.target.value)),
973
+ children: LEAD_PRIORITY_OPTIONS.map((opt) => /* @__PURE__ */ jsx(MenuItem, { value: opt.value, children: opt.label }, opt.label))
974
+ }
975
+ ) }) }),
976
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: /* @__PURE__ */ jsx(
977
+ TextField,
978
+ {
979
+ size: "small",
980
+ type: "number",
981
+ value: q.minWaitBeforeCallback,
982
+ onChange: (e) => handleCellUpdate(q.queueId, "minWaitBeforeCallback", e.target.value),
983
+ slotProps: {
984
+ htmlInput: { min: 0, style: { fontSize: "0.85rem", padding: "4px 8px" } },
985
+ input: {
986
+ endAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx(Typography, { sx: { fontSize: "0.75rem", color: "#666" }, children: "s" }) })
987
+ }
988
+ },
989
+ sx: { width: 100, "& .MuiOutlinedInput-root": { borderRadius: "4px" } }
990
+ }
991
+ ) }),
992
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { textAlign: "right" }), children: /* @__PURE__ */ jsx(SDKButton, { variant: "danger", size: "small", onClick: () => handleRemoveQueue(q.queueId), children: "Remove" }) })
993
+ ] }, q.queueId);
994
+ }) })
995
+ ] }) })
996
+ ] });
997
+ }
998
+ function LeadsTabInDialog({
999
+ editingCampaign,
1000
+ onLeadsChange
1001
+ }) {
1002
+ var _a;
1003
+ const { showToast } = useToast();
1004
+ const { leads, fetchLeads, createLead, uploadLeadsExcel, downloadLeadTemplate } = useLeads();
1005
+ const [adding, setAdding] = useState2(false);
1006
+ const [leadForm, setLeadForm] = useState2({ phoneNumber: "", callerName: "", priority: 5 });
1007
+ const [search, setSearch] = useState2("");
1008
+ const [uploadFile, setUploadFile] = useState2(null);
1009
+ const [uploading, setUploading] = useState2(false);
1010
+ const uploadRef = useRef(null);
1011
+ useEffect(() => {
1012
+ if (editingCampaign) fetchLeads(editingCampaign.id, { skip: 0, limit: 100 });
1013
+ }, [editingCampaign, fetchLeads]);
1014
+ if (!editingCampaign) {
1015
+ return /* @__PURE__ */ jsx(Box, { sx: { p: 4, textAlign: "center" }, children: /* @__PURE__ */ jsx(Typography, { sx: { color: "#999", fontSize: "0.9rem", fontFamily: "poppins, Arial, sans-serif" }, children: "Save the campaign first, then you can add leads." }) });
1016
+ }
1017
+ const handleAddLead = async () => {
1018
+ var _a2, _b, _c;
1019
+ const err = validatePhone(leadForm.phoneNumber);
1020
+ if (err) {
1021
+ showToast(err, "warning");
1022
+ return;
1023
+ }
1024
+ setAdding(true);
1025
+ try {
1026
+ await createLead(editingCampaign.id, __spreadProps(__spreadValues({}, leadForm), { priority: (_a2 = leadForm.priority) != null ? _a2 : 5 }));
1027
+ showToast("Lead added successfully", "success");
1028
+ setLeadForm({ phoneNumber: "", callerName: "", priority: 5 });
1029
+ fetchLeads(editingCampaign.id, { skip: 0, limit: 100 });
1030
+ onLeadsChange == null ? void 0 : onLeadsChange();
1031
+ } catch (err2) {
1032
+ showToast(((_c = (_b = err2 == null ? void 0 : err2.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message) || (err2 == null ? void 0 : err2.message) || "Failed to add lead", "error");
1033
+ } finally {
1034
+ setAdding(false);
1035
+ }
1036
+ };
1037
+ const handleUpload = async () => {
1038
+ var _a2, _b;
1039
+ if (!uploadFile) return;
1040
+ setUploading(true);
1041
+ try {
1042
+ await uploadLeadsExcel(editingCampaign.id, uploadFile);
1043
+ showToast("Leads uploaded successfully", "success");
1044
+ setUploadFile(null);
1045
+ if (uploadRef.current) uploadRef.current.value = "";
1046
+ fetchLeads(editingCampaign.id, { skip: 0, limit: 100 });
1047
+ onLeadsChange == null ? void 0 : onLeadsChange();
1048
+ } catch (err) {
1049
+ showToast(((_b = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b.message) || (err == null ? void 0 : err.message) || "Failed to upload leads", "error");
1050
+ } finally {
1051
+ setUploading(false);
1052
+ }
1053
+ };
1054
+ const handleDownload = async () => {
1055
+ var _a2, _b;
1056
+ try {
1057
+ await downloadLeadTemplate(editingCampaign.id);
1058
+ } catch (err) {
1059
+ showToast(((_b = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b.message) || (err == null ? void 0 : err.message) || "Download failed", "error");
1060
+ }
1061
+ };
1062
+ const filtered = leads.filter(
1063
+ (l) => {
1064
+ var _a2, _b;
1065
+ return !search || ((_a2 = l.callerName) == null ? void 0 : _a2.toLowerCase().includes(search.toLowerCase())) || ((_b = l.phoneNumber) == null ? void 0 : _b.includes(search));
1066
+ }
1067
+ );
1068
+ return /* @__PURE__ */ jsxs(Box, { sx: { p: 2.5 }, children: [
1069
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Add Lead Manually" }),
1070
+ /* @__PURE__ */ jsxs(Paper, { variant: "outlined", sx: { p: 2, mb: 2.5, borderRadius: 2 }, children: [
1071
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "grid", gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr", lg: "1fr 1fr 1fr" }, gap: 2, mb: 2 }, children: [
1072
+ /* @__PURE__ */ jsxs(Box, { children: [
1073
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
1074
+ "Phone Number ",
1075
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
1076
+ ] }),
1077
+ /* @__PURE__ */ jsx(
1078
+ TextField,
1079
+ {
1080
+ fullWidth: true,
1081
+ size: "small",
1082
+ placeholder: "+1234567890",
1083
+ value: leadForm.phoneNumber,
1084
+ onChange: (e) => setLeadForm((p) => __spreadProps(__spreadValues({}, p), { phoneNumber: e.target.value.replace(/[^0-9+\-() ]/g, "") })),
1085
+ error: !!leadForm.phoneNumber && !!validatePhone(leadForm.phoneNumber),
1086
+ helperText: leadForm.phoneNumber ? validatePhone(leadForm.phoneNumber) || "" : "",
1087
+ sx: inputSx
1088
+ }
1089
+ )
1090
+ ] }),
1091
+ /* @__PURE__ */ jsxs(Box, { children: [
1092
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Caller Name" }),
1093
+ /* @__PURE__ */ jsx(
1094
+ TextField,
1095
+ {
1096
+ fullWidth: true,
1097
+ size: "small",
1098
+ value: leadForm.callerName || "",
1099
+ onChange: (e) => setLeadForm((p) => __spreadProps(__spreadValues({}, p), { callerName: e.target.value })),
1100
+ sx: inputSx
1101
+ }
1102
+ )
1103
+ ] }),
1104
+ /* @__PURE__ */ jsxs(Box, { children: [
1105
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Source" }),
1106
+ /* @__PURE__ */ jsx(
1107
+ TextField,
1108
+ {
1109
+ fullWidth: true,
1110
+ size: "small",
1111
+ value: leadForm.source || "",
1112
+ onChange: (e) => setLeadForm((p) => __spreadProps(__spreadValues({}, p), { source: e.target.value })),
1113
+ sx: inputSx
1114
+ }
1115
+ )
1116
+ ] }),
1117
+ /* @__PURE__ */ jsxs(Box, { children: [
1118
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Priority" }),
1119
+ /* @__PURE__ */ jsx(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsx(
1120
+ Select,
1121
+ {
1122
+ value: (_a = leadForm.priority) != null ? _a : 5,
1123
+ onChange: (e) => setLeadForm((p) => __spreadProps(__spreadValues({}, p), { priority: Number(e.target.value) })),
1124
+ children: LEAD_PRIORITY_OPTIONS.map((opt) => /* @__PURE__ */ jsx(MenuItem, { value: opt.value, children: opt.label }, opt.label))
1125
+ }
1126
+ ) })
1127
+ ] }),
1128
+ /* @__PURE__ */ jsxs(Box, { sx: { gridColumn: "1 / -1" }, children: [
1129
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Notes" }),
1130
+ /* @__PURE__ */ jsx(
1131
+ TextField,
1132
+ {
1133
+ fullWidth: true,
1134
+ size: "small",
1135
+ multiline: true,
1136
+ minRows: 2,
1137
+ maxRows: 8,
1138
+ value: leadForm.notes || "",
1139
+ onChange: (e) => setLeadForm((p) => __spreadProps(__spreadValues({}, p), { notes: e.target.value })),
1140
+ sx: inputSx
1141
+ }
1142
+ )
1143
+ ] })
1144
+ ] }),
1145
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ jsx(
1146
+ SDKButton,
1147
+ {
1148
+ onClick: handleAddLead,
1149
+ disabled: adding,
1150
+ startIcon: adding ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, color: "inherit" }) : void 0,
1151
+ children: "Add Lead"
1152
+ }
1153
+ ) })
1154
+ ] }),
1155
+ /* @__PURE__ */ jsx(Typography, { sx: sectionTitleSx, children: "Upload Leads from File" }),
1156
+ /* @__PURE__ */ jsxs(Paper, { variant: "outlined", sx: { p: 2, mb: 2.5, borderRadius: 2 }, children: [
1157
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1.5, flexWrap: "wrap" }, children: [
1158
+ /* @__PURE__ */ jsx(SDKButton, { variant: "outlined", startIcon: /* @__PURE__ */ jsx(UploadFileIcon, {}), onClick: () => {
1159
+ var _a2;
1160
+ return (_a2 = uploadRef.current) == null ? void 0 : _a2.click();
1161
+ }, children: "Choose File" }),
1162
+ /* @__PURE__ */ jsx(
1163
+ "input",
1164
+ {
1165
+ ref: uploadRef,
1166
+ type: "file",
1167
+ accept: ".csv,.xlsx,.xls",
1168
+ hidden: true,
1169
+ onChange: (e) => {
1170
+ var _a2;
1171
+ const f = (_a2 = e.target.files) == null ? void 0 : _a2[0];
1172
+ if (!f) return;
1173
+ if (![".csv", ".xlsx", ".xls"].some((ext) => f.name.toLowerCase().endsWith(ext))) {
1174
+ showToast("Please select a CSV or Excel file", "warning");
1175
+ return;
1176
+ }
1177
+ setUploadFile(f);
1178
+ }
1179
+ }
1180
+ ),
1181
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: "0.82rem", color: "#666", flex: 1, fontFamily: "poppins, Arial, sans-serif" }, children: uploadFile ? uploadFile.name : "No file chosen" }),
1182
+ uploadFile && /* @__PURE__ */ jsx(
1183
+ SDKButton,
1184
+ {
1185
+ variant: "cancel",
1186
+ size: "small",
1187
+ onClick: () => {
1188
+ setUploadFile(null);
1189
+ if (uploadRef.current) uploadRef.current.value = "";
1190
+ },
1191
+ children: "Clear"
1192
+ }
1193
+ ),
1194
+ /* @__PURE__ */ jsx(SDKButton, { variant: "outlined", startIcon: /* @__PURE__ */ jsx(DownloadIcon, {}), onClick: handleDownload, children: "Sample Template" })
1195
+ ] }),
1196
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", justifyContent: "flex-end", mt: 1.5 }, children: /* @__PURE__ */ jsx(
1197
+ SDKButton,
1198
+ {
1199
+ onClick: handleUpload,
1200
+ disabled: uploading || !uploadFile,
1201
+ startIcon: uploading ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, color: "inherit" }) : void 0,
1202
+ children: "Upload"
1203
+ }
1204
+ ) })
1205
+ ] }),
1206
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", mb: 1.5 }, children: [
1207
+ /* @__PURE__ */ jsxs(Typography, { sx: sectionTitleSx, children: [
1208
+ "Leads (",
1209
+ leads.length,
1210
+ ")"
1211
+ ] }),
1212
+ /* @__PURE__ */ jsx(
1213
+ OutlinedInput,
1214
+ {
1215
+ size: "small",
1216
+ value: search,
1217
+ onChange: (e) => setSearch(e.target.value),
1218
+ placeholder: "Search...",
1219
+ sx: { width: 200, fontSize: "0.85rem", height: 34, borderRadius: "20px" },
1220
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(SearchIcon, { sx: { fontSize: 16, color: "#aaa" } }) })
1221
+ }
1222
+ )
1223
+ ] }),
1224
+ filtered.length === 0 ? /* @__PURE__ */ jsx(Paper, { variant: "outlined", sx: { p: 3, textAlign: "center", borderRadius: 2, borderStyle: "dashed" }, children: /* @__PURE__ */ jsx(Typography, { sx: { color: "#999", fontSize: "0.9rem" }, children: leads.length === 0 ? "No leads yet." : "No leads match your search." }) }) : /* @__PURE__ */ jsx(TableContainer, { component: Paper, variant: "outlined", sx: { borderRadius: 2, overflow: "visible" }, children: /* @__PURE__ */ jsxs(Table, { size: "small", children: [
1225
+ /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { sx: { backgroundColor: "#f1f1f1" }, children: [
1226
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Phone Number" }),
1227
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Status" }),
1228
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Source" }),
1229
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Attempts" }),
1230
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Last Outcome" }),
1231
+ /* @__PURE__ */ jsx(TableCell, { sx: headCellSx, children: "Notes" })
1232
+ ] }) }),
1233
+ /* @__PURE__ */ jsx(TableBody, { children: filtered.map((lead) => {
1234
+ var _a2;
1235
+ return /* @__PURE__ */ jsxs(TableRow, { sx: tableRowSx, children: [
1236
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: lead.phoneNumber }),
1237
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: /* @__PURE__ */ jsx(Chip, { label: lead.status || "pending", size: "small", sx: leadStatusChipSx(lead.status) }) }),
1238
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: lead.source || "" }),
1239
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: (_a2 = lead.attemptCount) != null ? _a2 : 0 }),
1240
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: lead.lastOutcome || "" }),
1241
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { maxWidth: 200, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }), children: lead.notes ? /* @__PURE__ */ jsx(Tooltip, { title: lead.notes, arrow: true, placement: "top", children: /* @__PURE__ */ jsx("span", { children: lead.notes }) }) : "" })
1242
+ ] }, lead.id);
1243
+ }) })
1244
+ ] }) })
1245
+ ] });
1246
+ }
1247
+ var CampaignDialog = memo(function CampaignDialog2({
1248
+ open,
1249
+ editingCampaign,
1250
+ formData,
1251
+ setFormData,
1252
+ saving,
1253
+ onSave,
1254
+ onClose,
1255
+ parentQueueNameMap,
1256
+ onQueuesRefreshed,
1257
+ onLeadsChange
1258
+ }) {
1259
+ const { showToast } = useToast();
1260
+ const [tab, setTab] = useState2(0);
1261
+ useEffect(() => {
1262
+ if (open) setTab(0);
1263
+ }, [open]);
1264
+ if (!open) return null;
1265
+ const TAB_LABELS = ["Basic Info", "Dialing Configuration", "Schedule & Operating Hours", "Queue Linking", "Leads"];
1266
+ const lastSaveTab = 3;
1267
+ const leadsTabDisabled = !editingCampaign;
1268
+ const validateTab = (t) => {
1269
+ if (t === 0) {
1270
+ if (!formData.name.trim()) {
1271
+ showToast("Please fill Campaign Name", "warning");
1272
+ return false;
1273
+ }
1274
+ if (!formData.campaignType) {
1275
+ showToast("Please fill Campaign Type", "warning");
1276
+ return false;
1277
+ }
1278
+ if (!formData.dialingMode) {
1279
+ showToast("Please fill Dialing Mode", "warning");
1280
+ return false;
1281
+ }
1282
+ }
1283
+ if (t === 1) {
1284
+ if (!formData.maxConcurrentCalls) {
1285
+ showToast("Please fill Max Concurrent Calls", "warning");
1286
+ return false;
1287
+ }
1288
+ if (!formData.maxAttempts) {
1289
+ showToast("Please fill Max Attempts", "warning");
1290
+ return false;
1291
+ }
1292
+ }
1293
+ if (t === 2) {
1294
+ if (!formData.startTime) {
1295
+ showToast("Please fill Start Time", "warning");
1296
+ return false;
1297
+ }
1298
+ if (!formData.endTime) {
1299
+ showToast("Please fill End Time", "warning");
1300
+ return false;
1301
+ }
1302
+ }
1303
+ return true;
1304
+ };
1305
+ const handleTabChange = (newTab) => {
1306
+ if (newTab === 4 && leadsTabDisabled) return;
1307
+ if (newTab > tab && !validateTab(tab)) return;
1308
+ setTab(newTab);
1309
+ };
1310
+ return /* @__PURE__ */ jsx(
1311
+ Box,
1312
+ {
1313
+ sx: {
1314
+ position: "fixed",
1315
+ inset: 0,
1316
+ zIndex: 1300,
1317
+ backgroundColor: "rgba(0,0,0,0.45)",
1318
+ display: "flex",
1319
+ alignItems: "center",
1320
+ justifyContent: "center"
1321
+ },
1322
+ onClick: (e) => {
1323
+ if (e.target === e.currentTarget) onClose();
1324
+ },
1325
+ children: /* @__PURE__ */ jsxs(
1326
+ Paper,
1327
+ {
1328
+ elevation: 6,
1329
+ sx: {
1330
+ width: { xs: "95vw", sm: 720, md: 880 },
1331
+ maxHeight: "92vh",
1332
+ display: "flex",
1333
+ flexDirection: "column",
1334
+ borderRadius: "16px",
1335
+ overflow: "hidden",
1336
+ boxShadow: "0 8px 32px rgba(26,95,108,0.18)"
1337
+ },
1338
+ children: [
1339
+ /* @__PURE__ */ jsxs(Box, { sx: __spreadProps(__spreadValues({}, dialogHeaderSx), {
1340
+ backgroundColor: "#1A5F6C",
1341
+ color: "#fff",
1342
+ "& .MuiIconButton-root": { color: "#fff" }
1343
+ }), children: [
1344
+ /* @__PURE__ */ jsx(Typography, { fontWeight: 700, fontSize: "1rem", fontFamily: "poppins, Arial, sans-serif", children: editingCampaign ? "Edit Campaign" : "Create Campaign" }),
1345
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onClose, sx: { color: "#fff" }, children: "\u2715" })
1346
+ ] }),
1347
+ /* @__PURE__ */ jsx(
1348
+ Tabs,
1349
+ {
1350
+ value: tab,
1351
+ onChange: (_, v) => handleTabChange(v),
1352
+ variant: "scrollable",
1353
+ scrollButtons: "auto",
1354
+ sx: {
1355
+ borderBottom: "1px solid #eee",
1356
+ minHeight: 44,
1357
+ "& .MuiTab-root": {
1358
+ fontSize: "0.85rem",
1359
+ minHeight: 44,
1360
+ textTransform: "none",
1361
+ fontWeight: 600,
1362
+ fontFamily: "poppins, Arial, sans-serif"
1363
+ },
1364
+ "& .Mui-selected": { color: "#1A5F6C" }
1365
+ },
1366
+ TabIndicatorProps: { style: { height: 3, backgroundColor: "#1A5F6C", borderRadius: "3px 3px 0 0" } },
1367
+ children: TAB_LABELS.map((label, i) => /* @__PURE__ */ jsx(Tab, { label, value: i, disabled: i === 4 && leadsTabDisabled }, label))
1368
+ }
1369
+ ),
1370
+ /* @__PURE__ */ jsxs(Box, { sx: { flex: 1, overflowY: "auto", minHeight: 380 }, children: [
1371
+ tab === 0 && /* @__PURE__ */ jsx(BasicInfoTab, { formData, setFormData, isEditMode: !!editingCampaign }),
1372
+ tab === 1 && /* @__PURE__ */ jsx(DialingConfigTab, { formData, setFormData }),
1373
+ tab === 2 && /* @__PURE__ */ jsx(ScheduleTab, { formData, setFormData }),
1374
+ tab === 3 && /* @__PURE__ */ jsx(
1375
+ QueueLinkingTab,
1376
+ {
1377
+ formData,
1378
+ setFormData,
1379
+ editingCampaign,
1380
+ parentQueueNameMap,
1381
+ onQueuesRefreshed
1382
+ }
1383
+ ),
1384
+ tab === 4 && /* @__PURE__ */ jsx(
1385
+ LeadsTabInDialog,
1386
+ {
1387
+ editingCampaign,
1388
+ onLeadsChange
1389
+ }
1390
+ )
1391
+ ] }),
1392
+ /* @__PURE__ */ jsxs(Box, { sx: dialogFooterSx, children: [
1393
+ /* @__PURE__ */ jsx(SDKButton, { variant: "cancel", onClick: onClose, children: "Cancel" }),
1394
+ tab > 0 && /* @__PURE__ */ jsx(SDKButton, { variant: "outlined", onClick: () => setTab((t) => t - 1), children: "Back" }),
1395
+ tab < lastSaveTab && /* @__PURE__ */ jsx(SDKButton, { onClick: () => handleTabChange(tab + 1), children: "Next" }),
1396
+ tab === lastSaveTab && /* @__PURE__ */ jsx(
1397
+ SDKPermissionGuard,
1398
+ {
1399
+ permissions: [
1400
+ editingCampaign ? SDK_PERMISSIONS.CAMPAIGNS_UPDATE : SDK_PERMISSIONS.CAMPAIGNS_CREATE,
1401
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
1402
+ ],
1403
+ showFallback: false,
1404
+ children: /* @__PURE__ */ jsx(
1405
+ SDKButton,
1406
+ {
1407
+ onClick: onSave,
1408
+ disabled: saving,
1409
+ startIcon: saving ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, color: "inherit" }) : void 0,
1410
+ children: editingCampaign ? "Update" : "Create"
1411
+ }
1412
+ )
1413
+ }
1414
+ )
1415
+ ] })
1416
+ ]
1417
+ }
1418
+ )
1419
+ }
1420
+ );
1421
+ });
1422
+ var AddLeadDialog = memo(function AddLeadDialog2({
1423
+ open,
1424
+ data,
1425
+ onChange,
1426
+ saving,
1427
+ onSave,
1428
+ onClose
1429
+ }) {
1430
+ var _a;
1431
+ if (!open) return null;
1432
+ const phoneError = data.phoneNumber ? validatePhone(data.phoneNumber) : null;
1433
+ return /* @__PURE__ */ jsx(
1434
+ Box,
1435
+ {
1436
+ sx: {
1437
+ position: "fixed",
1438
+ inset: 0,
1439
+ zIndex: 1400,
1440
+ backgroundColor: "rgba(0,0,0,0.45)",
1441
+ display: "flex",
1442
+ alignItems: "center",
1443
+ justifyContent: "center"
1444
+ },
1445
+ onClick: (e) => {
1446
+ if (e.target === e.currentTarget) onClose();
1447
+ },
1448
+ children: /* @__PURE__ */ jsxs(Paper, { elevation: 6, sx: { width: { xs: "95vw", sm: 560, lg: 720 }, borderRadius: "16px", overflow: "hidden", boxShadow: "0 8px 32px rgba(26,95,108,0.18)" }, children: [
1449
+ /* @__PURE__ */ jsxs(Box, { sx: __spreadProps(__spreadValues({}, dialogHeaderSx), { backgroundColor: "#1A5F6C", color: "#fff" }), children: [
1450
+ /* @__PURE__ */ jsx(Typography, { fontWeight: 700, fontSize: "1rem", fontFamily: "poppins, Arial, sans-serif", children: "Add Lead" }),
1451
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onClose, sx: { color: "#fff" }, children: "\u2715" })
1452
+ ] }),
1453
+ /* @__PURE__ */ jsx(Box, { sx: { p: 2.5 }, children: /* @__PURE__ */ jsxs(Box, { sx: { display: "grid", gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr", lg: "1fr 1fr 1fr" }, gap: 2 }, children: [
1454
+ /* @__PURE__ */ jsxs(Box, { children: [
1455
+ /* @__PURE__ */ jsxs(Typography, { sx: labelSx, children: [
1456
+ "Phone Number ",
1457
+ /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: "*" })
1458
+ ] }),
1459
+ /* @__PURE__ */ jsx(
1460
+ TextField,
1461
+ {
1462
+ fullWidth: true,
1463
+ size: "small",
1464
+ placeholder: "+1234567890",
1465
+ value: data.phoneNumber,
1466
+ onChange: (e) => onChange(__spreadProps(__spreadValues({}, data), { phoneNumber: e.target.value.replace(/[^0-9+\-() ]/g, "") })),
1467
+ error: !!phoneError,
1468
+ helperText: phoneError || "",
1469
+ sx: inputSx
1470
+ }
1471
+ )
1472
+ ] }),
1473
+ /* @__PURE__ */ jsxs(Box, { children: [
1474
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Caller Name" }),
1475
+ /* @__PURE__ */ jsx(
1476
+ TextField,
1477
+ {
1478
+ fullWidth: true,
1479
+ size: "small",
1480
+ value: data.callerName || "",
1481
+ onChange: (e) => onChange(__spreadProps(__spreadValues({}, data), { callerName: e.target.value })),
1482
+ sx: inputSx
1483
+ }
1484
+ )
1485
+ ] }),
1486
+ /* @__PURE__ */ jsxs(Box, { children: [
1487
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Source" }),
1488
+ /* @__PURE__ */ jsx(
1489
+ TextField,
1490
+ {
1491
+ fullWidth: true,
1492
+ size: "small",
1493
+ value: data.source || "",
1494
+ onChange: (e) => onChange(__spreadProps(__spreadValues({}, data), { source: e.target.value })),
1495
+ sx: inputSx
1496
+ }
1497
+ )
1498
+ ] }),
1499
+ /* @__PURE__ */ jsxs(Box, { children: [
1500
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Priority" }),
1501
+ /* @__PURE__ */ jsx(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsx(
1502
+ Select,
1503
+ {
1504
+ value: (_a = data.priority) != null ? _a : 5,
1505
+ onChange: (e) => onChange(__spreadProps(__spreadValues({}, data), { priority: Number(e.target.value) })),
1506
+ children: LEAD_PRIORITY_OPTIONS.map((o) => /* @__PURE__ */ jsx(MenuItem, { value: o.value, children: o.label }, o.label))
1507
+ }
1508
+ ) })
1509
+ ] }),
1510
+ /* @__PURE__ */ jsxs(Box, { sx: { gridColumn: "1 / -1" }, children: [
1511
+ /* @__PURE__ */ jsx(Typography, { sx: labelSx, children: "Notes" }),
1512
+ /* @__PURE__ */ jsx(
1513
+ TextField,
1514
+ {
1515
+ fullWidth: true,
1516
+ size: "small",
1517
+ multiline: true,
1518
+ minRows: 2,
1519
+ maxRows: 8,
1520
+ value: data.notes || "",
1521
+ onChange: (e) => onChange(__spreadProps(__spreadValues({}, data), { notes: e.target.value })),
1522
+ sx: inputSx
1523
+ }
1524
+ )
1525
+ ] })
1526
+ ] }) }),
1527
+ /* @__PURE__ */ jsxs(Box, { sx: dialogFooterSx, children: [
1528
+ /* @__PURE__ */ jsx(SDKButton, { variant: "cancel", onClick: onClose, children: "Cancel" }),
1529
+ /* @__PURE__ */ jsx(
1530
+ SDKButton,
1531
+ {
1532
+ onClick: onSave,
1533
+ disabled: saving,
1534
+ startIcon: saving ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, color: "inherit" }) : void 0,
1535
+ children: "Add Lead"
1536
+ }
1537
+ )
1538
+ ] })
1539
+ ] })
1540
+ }
1541
+ );
1542
+ });
1543
+ function ConfirmDialog({
1544
+ open,
1545
+ title,
1546
+ message,
1547
+ loading,
1548
+ onConfirm,
1549
+ onClose
1550
+ }) {
1551
+ if (!open) return null;
1552
+ return /* @__PURE__ */ jsx(
1553
+ Box,
1554
+ {
1555
+ sx: { position: "fixed", inset: 0, zIndex: 1500, backgroundColor: "rgba(0,0,0,0.45)", display: "flex", alignItems: "center", justifyContent: "center" },
1556
+ onClick: (e) => {
1557
+ if (e.target === e.currentTarget) onClose();
1558
+ },
1559
+ children: /* @__PURE__ */ jsxs(Paper, { elevation: 6, sx: { width: { xs: "90vw", sm: 400 }, borderRadius: "16px", overflow: "hidden", boxShadow: "0 8px 32px rgba(0,0,0,0.18)" }, children: [
1560
+ /* @__PURE__ */ jsxs(Box, { sx: __spreadProps(__spreadValues({}, dialogHeaderSx), { borderBottom: "none", pb: 0 }), children: [
1561
+ /* @__PURE__ */ jsx(Typography, { fontWeight: 700, fontSize: "1rem", fontFamily: "poppins, Arial, sans-serif", children: title }),
1562
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onClose, children: "\u2715" })
1563
+ ] }),
1564
+ /* @__PURE__ */ jsx(Box, { sx: { px: 2.5, py: 1.5 }, children: /* @__PURE__ */ jsx(Typography, { fontSize: "0.85rem", color: "#555", fontFamily: "poppins, Arial, sans-serif", children: message }) }),
1565
+ /* @__PURE__ */ jsxs(Box, { sx: dialogFooterSx, children: [
1566
+ /* @__PURE__ */ jsx(SDKButton, { variant: "cancel", onClick: onClose, children: "Cancel" }),
1567
+ /* @__PURE__ */ jsx(
1568
+ SDKButton,
1569
+ {
1570
+ variant: "danger",
1571
+ onClick: onConfirm,
1572
+ disabled: loading,
1573
+ startIcon: loading ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, color: "inherit" }) : void 0,
1574
+ children: "Confirm"
1575
+ }
1576
+ )
1577
+ ] })
1578
+ ] })
1579
+ }
1580
+ );
1581
+ }
1582
+ function ImportLeadsDialog({
1583
+ open,
1584
+ file,
1585
+ onFileChange,
1586
+ uploading,
1587
+ onUpload,
1588
+ onDownloadTemplate,
1589
+ onClose
1590
+ }) {
1591
+ const fileRef = useRef(null);
1592
+ if (!open) return null;
1593
+ return /* @__PURE__ */ jsx(
1594
+ Box,
1595
+ {
1596
+ sx: { position: "fixed", inset: 0, zIndex: 1400, backgroundColor: "rgba(0,0,0,0.45)", display: "flex", alignItems: "center", justifyContent: "center" },
1597
+ onClick: (e) => {
1598
+ if (e.target === e.currentTarget) onClose();
1599
+ },
1600
+ children: /* @__PURE__ */ jsxs(Paper, { elevation: 6, sx: { width: { xs: "90vw", sm: 460 }, borderRadius: "16px", overflow: "hidden", boxShadow: "0 8px 32px rgba(26,95,108,0.18)" }, children: [
1601
+ /* @__PURE__ */ jsxs(Box, { sx: __spreadProps(__spreadValues({}, dialogHeaderSx), { backgroundColor: "#1A5F6C", color: "#fff" }), children: [
1602
+ /* @__PURE__ */ jsx(Typography, { fontWeight: 700, fontSize: "1rem", fontFamily: "poppins, Arial, sans-serif", children: "Import Leads" }),
1603
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onClose, sx: { color: "#fff" }, children: "\u2715" })
1604
+ ] }),
1605
+ /* @__PURE__ */ jsxs(Box, { sx: { p: 2.5 }, children: [
1606
+ /* @__PURE__ */ jsx(Typography, { fontSize: "0.82rem", color: "#555", fontFamily: "poppins, Arial, sans-serif", mb: 2, children: "Upload a CSV or Excel file. Use the template for the correct format." }),
1607
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1.5, flexWrap: "wrap", mb: 1.5 }, children: [
1608
+ /* @__PURE__ */ jsx(
1609
+ SDKButton,
1610
+ {
1611
+ variant: "outlined",
1612
+ startIcon: /* @__PURE__ */ jsx(UploadFileIcon, {}),
1613
+ onClick: () => {
1614
+ var _a;
1615
+ return (_a = fileRef.current) == null ? void 0 : _a.click();
1616
+ },
1617
+ children: "Choose File"
1618
+ }
1619
+ ),
1620
+ /* @__PURE__ */ jsx(
1621
+ "input",
1622
+ {
1623
+ ref: fileRef,
1624
+ type: "file",
1625
+ accept: ".csv,.xlsx,.xls",
1626
+ hidden: true,
1627
+ onChange: (e) => {
1628
+ var _a;
1629
+ const f = (_a = e.target.files) == null ? void 0 : _a[0];
1630
+ if (!f) return;
1631
+ if ([".csv", ".xlsx", ".xls"].some((ext) => f.name.toLowerCase().endsWith(ext))) onFileChange(f);
1632
+ }
1633
+ }
1634
+ ),
1635
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: "0.82rem", color: "#666", flex: 1, fontFamily: "poppins, Arial, sans-serif" }, children: file ? file.name : "No file chosen" }),
1636
+ file && /* @__PURE__ */ jsx(
1637
+ SDKButton,
1638
+ {
1639
+ variant: "cancel",
1640
+ size: "small",
1641
+ onClick: () => {
1642
+ onFileChange(null);
1643
+ if (fileRef.current) fileRef.current.value = "";
1644
+ },
1645
+ children: "Clear"
1646
+ }
1647
+ )
1648
+ ] }),
1649
+ /* @__PURE__ */ jsx(SDKButton, { variant: "outlined", startIcon: /* @__PURE__ */ jsx(DownloadIcon, {}), onClick: onDownloadTemplate, children: "Download Template" })
1650
+ ] }),
1651
+ /* @__PURE__ */ jsxs(Box, { sx: dialogFooterSx, children: [
1652
+ /* @__PURE__ */ jsx(SDKButton, { variant: "cancel", onClick: onClose, children: "Cancel" }),
1653
+ /* @__PURE__ */ jsx(
1654
+ SDKButton,
1655
+ {
1656
+ onClick: onUpload,
1657
+ disabled: uploading || !file,
1658
+ startIcon: uploading ? /* @__PURE__ */ jsx(CircularProgress, { size: 14, color: "inherit" }) : void 0,
1659
+ children: "Upload"
1660
+ }
1661
+ )
1662
+ ] })
1663
+ ] })
1664
+ }
1665
+ );
1666
+ }
1667
+ var CampaignsContent = memo(function CampaignsContent2() {
1668
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1669
+ const theme = useTheme();
1670
+ const { showToast } = useToast();
1671
+ const { hasPermission } = useSDKPermissions();
1672
+ const callerData = useGetCallerData();
1673
+ const isAgentIdle = callerData.status === "IDLE";
1674
+ const hasOutboundPermission = hasPermission(SDK_PERMISSIONS.CALL_OUTBOUND);
1675
+ const {
1676
+ campaigns,
1677
+ loading,
1678
+ fetchCampaigns,
1679
+ getCampaignById,
1680
+ createCampaign,
1681
+ updateCampaign,
1682
+ activateCampaign,
1683
+ pauseCampaign,
1684
+ archiveCampaign
1685
+ } = useCampaigns();
1686
+ const {
1687
+ leads,
1688
+ leadTotal,
1689
+ leadsMeta,
1690
+ loading: leadsLoading,
1691
+ fetchLeads,
1692
+ createLead,
1693
+ deleteLead,
1694
+ dialPreview,
1695
+ uploadLeadsExcel,
1696
+ downloadLeadTemplate,
1697
+ exportLeads
1698
+ } = useLeads();
1699
+ const { fetchQueues } = useQueues();
1700
+ const [queueNameMap, setQueueNameMap] = useState2({});
1701
+ useEffect(() => {
1702
+ fetchQueues().then((qs) => {
1703
+ const map = {};
1704
+ qs.forEach((q) => {
1705
+ map[q.id] = q.name;
1706
+ });
1707
+ setQueueNameMap(map);
1708
+ }).catch(() => {
1709
+ });
1710
+ }, [fetchQueues]);
1711
+ const handleQueuesRefreshed = useCallback2((qs) => {
1712
+ const map = {};
1713
+ qs.forEach((q) => {
1714
+ map[q.id] = q.name;
1715
+ });
1716
+ setQueueNameMap(map);
1717
+ }, []);
1718
+ const [selectedId, setSelectedId] = useState2(null);
1719
+ const [showArchived, setShowArchived] = useState2(false);
1720
+ const [campaignListCollapsed, setCampaignListCollapsed] = useState2(false);
1721
+ const [dialogOpen, setDialogOpen] = useState2(false);
1722
+ const [editingCampaign, setEditingCampaign] = useState2(null);
1723
+ const [formData, setFormData] = useState2(defaultFormData);
1724
+ const [saving, setSaving] = useState2(false);
1725
+ const [archiveOpen, setArchiveOpen] = useState2(false);
1726
+ const [archiveTarget, setArchiveTarget] = useState2(null);
1727
+ const [archiving, setArchiving] = useState2(false);
1728
+ const [leadPage, setLeadPage] = useState2(0);
1729
+ const [leadRowsPerPage, setLeadRowsPerPage] = useState2(10);
1730
+ const [leadSearch, setLeadSearch] = useState2("");
1731
+ const [debouncedSearch, setDebouncedSearch] = useState2("");
1732
+ const [leadStatusFilter, setLeadStatusFilter] = useState2("All states");
1733
+ const debounceRef = useRef(null);
1734
+ const [addLeadOpen, setAddLeadOpen] = useState2(false);
1735
+ const [addLeadData, setAddLeadData] = useState2({ phoneNumber: "", callerName: "", priority: 5 });
1736
+ const [addLeadSaving, setAddLeadSaving] = useState2(false);
1737
+ const [importOpen, setImportOpen] = useState2(false);
1738
+ const [importFile, setImportFile] = useState2(null);
1739
+ const [importing, setImporting] = useState2(false);
1740
+ const [deleteLeadOpen, setDeleteLeadOpen] = useState2(false);
1741
+ const [deleteLeadTarget, setDeleteLeadTarget] = useState2(null);
1742
+ const [deletingLead, setDeletingLead] = useState2(false);
1743
+ const [dialLoading, setDialLoading] = useState2(null);
1744
+ const selected = (_a = campaigns.find((c) => c.id === selectedId)) != null ? _a : null;
1745
+ const visibleCampaigns = campaigns.filter(
1746
+ (c) => {
1747
+ var _a2;
1748
+ return showArchived ? true : ((_a2 = c.status) == null ? void 0 : _a2.toLowerCase()) !== "archived";
1749
+ }
1750
+ );
1751
+ useEffect(() => {
1752
+ fetchCampaigns();
1753
+ }, [fetchCampaigns]);
1754
+ useEffect(() => {
1755
+ debounceRef.current = setTimeout(() => setDebouncedSearch(leadSearch.trim()), 400);
1756
+ return () => {
1757
+ if (debounceRef.current) clearTimeout(debounceRef.current);
1758
+ };
1759
+ }, [leadSearch]);
1760
+ useEffect(() => {
1761
+ if (!selectedId) return;
1762
+ setLeadPage(0);
1763
+ fetchLeads(selectedId, {
1764
+ skip: 0,
1765
+ limit: leadRowsPerPage,
1766
+ status: leadStatusFilter !== "All states" ? leadStatusFilter : void 0,
1767
+ phone_number: debouncedSearch || void 0
1768
+ });
1769
+ }, [selectedId, leadRowsPerPage, leadStatusFilter, debouncedSearch, fetchLeads]);
1770
+ const refetchLeads = useCallback2((page = leadPage) => {
1771
+ if (!selectedId) return;
1772
+ fetchLeads(selectedId, {
1773
+ skip: page * leadRowsPerPage,
1774
+ limit: leadRowsPerPage,
1775
+ status: leadStatusFilter !== "All states" ? leadStatusFilter : void 0,
1776
+ phone_number: debouncedSearch || void 0
1777
+ });
1778
+ }, [selectedId, leadPage, leadRowsPerPage, leadStatusFilter, debouncedSearch, fetchLeads]);
1779
+ const handleOpenCreate = () => {
1780
+ setEditingCampaign(null);
1781
+ setFormData(defaultFormData);
1782
+ setDialogOpen(true);
1783
+ };
1784
+ const handleOpenEdit = async (c) => {
1785
+ setEditingCampaign(c);
1786
+ setFormData(campaignToFormData(c));
1787
+ setDialogOpen(true);
1788
+ try {
1789
+ const fresh = await getCampaignById(c.id);
1790
+ setEditingCampaign(fresh);
1791
+ setFormData(campaignToFormData(fresh));
1792
+ } catch (e) {
1793
+ }
1794
+ };
1795
+ const handleSave = async () => {
1796
+ var _a2, _b2, _c2, _d2, _e2;
1797
+ if (!formData.name.trim()) {
1798
+ showToast("Campaign name is required", "warning");
1799
+ return;
1800
+ }
1801
+ setSaving(true);
1802
+ const startTime = ((_a2 = formData.startTime) == null ? void 0 : _a2.length) === 5 ? `${formData.startTime}:00` : formData.startTime;
1803
+ const endTime = ((_b2 = formData.endTime) == null ? void 0 : _b2.length) === 5 ? `${formData.endTime}:00` : formData.endTime;
1804
+ try {
1805
+ if (editingCampaign) {
1806
+ await updateCampaign(editingCampaign.id, __spreadProps(__spreadValues({}, formData), { startTime, endTime }));
1807
+ showToast("Campaign updated", "success");
1808
+ } else {
1809
+ const payload = __spreadProps(__spreadValues({}, formData), { startTime, endTime });
1810
+ if (!payload.scheduledStart) delete payload.scheduledStart;
1811
+ if (!payload.scheduledEnd) delete payload.scheduledEnd;
1812
+ if (!payload.callerId) delete payload.callerId;
1813
+ if (!payload.answerTimeoutSeconds) delete payload.answerTimeoutSeconds;
1814
+ if (payload.aiBotId == null) delete payload.aiBotId;
1815
+ if (!((_c2 = payload.queueLinks) == null ? void 0 : _c2.length)) delete payload.queueLinks;
1816
+ if (payload.settings && !Object.keys(payload.settings).length) delete payload.settings;
1817
+ const created = await createCampaign(payload);
1818
+ showToast("Campaign created", "success");
1819
+ setSelectedId(created.id);
1820
+ }
1821
+ setDialogOpen(false);
1822
+ fetchCampaigns();
1823
+ } catch (err) {
1824
+ showToast(((_e2 = (_d2 = err == null ? void 0 : err.response) == null ? void 0 : _d2.data) == null ? void 0 : _e2.message) || (err == null ? void 0 : err.message) || "Failed to save campaign", "error");
1825
+ } finally {
1826
+ setSaving(false);
1827
+ }
1828
+ };
1829
+ const handleStart = async (c) => {
1830
+ var _a2, _b2;
1831
+ try {
1832
+ await activateCampaign(c.id);
1833
+ showToast("Campaign started", "success");
1834
+ fetchCampaigns();
1835
+ } catch (err) {
1836
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Failed to start", "error");
1837
+ }
1838
+ };
1839
+ const handlePause = async (c) => {
1840
+ var _a2, _b2;
1841
+ try {
1842
+ await pauseCampaign(c.id);
1843
+ showToast("Campaign paused", "success");
1844
+ fetchCampaigns();
1845
+ } catch (err) {
1846
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Failed to pause", "error");
1847
+ }
1848
+ };
1849
+ const confirmArchive = async () => {
1850
+ var _a2, _b2;
1851
+ if (!archiveTarget) return;
1852
+ setArchiving(true);
1853
+ try {
1854
+ await archiveCampaign(archiveTarget.id);
1855
+ showToast("Campaign archived", "success");
1856
+ setArchiveOpen(false);
1857
+ setArchiveTarget(null);
1858
+ fetchCampaigns();
1859
+ } catch (err) {
1860
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Failed to archive", "error");
1861
+ } finally {
1862
+ setArchiving(false);
1863
+ }
1864
+ };
1865
+ const handleAddLead = async () => {
1866
+ var _a2, _b2;
1867
+ if (!selectedId) return;
1868
+ const err = validatePhone(addLeadData.phoneNumber);
1869
+ if (err) {
1870
+ showToast(err, "warning");
1871
+ return;
1872
+ }
1873
+ setAddLeadSaving(true);
1874
+ try {
1875
+ await createLead(selectedId, addLeadData);
1876
+ showToast("Lead added", "success");
1877
+ setAddLeadOpen(false);
1878
+ setAddLeadData({ phoneNumber: "", callerName: "", priority: 5 });
1879
+ refetchLeads(0);
1880
+ setLeadPage(0);
1881
+ } catch (err2) {
1882
+ showToast(((_b2 = (_a2 = err2 == null ? void 0 : err2.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err2 == null ? void 0 : err2.message) || "Failed to add lead", "error");
1883
+ } finally {
1884
+ setAddLeadSaving(false);
1885
+ }
1886
+ };
1887
+ const handleImport = async () => {
1888
+ var _a2, _b2;
1889
+ if (!selectedId || !importFile) return;
1890
+ setImporting(true);
1891
+ try {
1892
+ const result = await uploadLeadsExcel(selectedId, importFile);
1893
+ showToast((result == null ? void 0 : result.message) || "Leads uploaded", "success");
1894
+ setImportFile(null);
1895
+ setImportOpen(false);
1896
+ refetchLeads(0);
1897
+ setLeadPage(0);
1898
+ } catch (err) {
1899
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Upload failed", "error");
1900
+ } finally {
1901
+ setImporting(false);
1902
+ }
1903
+ };
1904
+ const handleExport = async () => {
1905
+ var _a2, _b2;
1906
+ if (!selectedId) return;
1907
+ try {
1908
+ await exportLeads(selectedId);
1909
+ showToast("Leads exported", "success");
1910
+ } catch (err) {
1911
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Export failed", "error");
1912
+ }
1913
+ };
1914
+ const handleDownloadTemplate = async () => {
1915
+ var _a2, _b2;
1916
+ if (!selectedId) return;
1917
+ try {
1918
+ await downloadLeadTemplate(selectedId);
1919
+ } catch (err) {
1920
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Download failed", "error");
1921
+ }
1922
+ };
1923
+ const handleDialPreview = async (leadId) => {
1924
+ var _a2, _b2;
1925
+ if (!selectedId) return;
1926
+ setDialLoading(leadId);
1927
+ try {
1928
+ const res = await dialPreview(selectedId, leadId);
1929
+ showToast((res == null ? void 0 : res.message) || "Preview dial initiated", "success");
1930
+ } catch (err) {
1931
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Dial failed", "error");
1932
+ } finally {
1933
+ setDialLoading(null);
1934
+ }
1935
+ };
1936
+ const confirmDeleteLead = async () => {
1937
+ var _a2, _b2;
1938
+ if (!selectedId || !deleteLeadTarget) return;
1939
+ setDeletingLead(true);
1940
+ try {
1941
+ await deleteLead(selectedId, deleteLeadTarget.id);
1942
+ showToast("Lead deleted", "success");
1943
+ setDeleteLeadOpen(false);
1944
+ setDeleteLeadTarget(null);
1945
+ refetchLeads(leadPage);
1946
+ } catch (err) {
1947
+ showToast(((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.message) || (err == null ? void 0 : err.message) || "Delete failed", "error");
1948
+ } finally {
1949
+ setDeletingLead(false);
1950
+ }
1951
+ };
1952
+ const sc = selected;
1953
+ const scActive = ((_b = sc == null ? void 0 : sc.status) == null ? void 0 : _b.toLowerCase()) === "active";
1954
+ const scDraft = ((_c = sc == null ? void 0 : sc.status) == null ? void 0 : _c.toLowerCase()) === "draft";
1955
+ const scPaused = ((_d = sc == null ? void 0 : sc.status) == null ? void 0 : _d.toLowerCase()) === "paused";
1956
+ const scArchived = ((_e = sc == null ? void 0 : sc.status) == null ? void 0 : _e.toLowerCase()) === "archived";
1957
+ return /* @__PURE__ */ jsxs(Box, { sx: { fontFamily: "poppins, Arial, sans-serif" }, children: [
1958
+ /* @__PURE__ */ jsx(
1959
+ SDKPageHeader,
1960
+ {
1961
+ title: "Call Scheduling",
1962
+ actions: /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1963
+ /* @__PURE__ */ jsx(
1964
+ SDKButton,
1965
+ {
1966
+ startIcon: /* @__PURE__ */ jsx(RefreshIcon, {}),
1967
+ onClick: () => {
1968
+ fetchCampaigns();
1969
+ if (selectedId) refetchLeads();
1970
+ },
1971
+ children: "Refresh"
1972
+ }
1973
+ ),
1974
+ /* @__PURE__ */ jsx(
1975
+ SDKPermissionGuard,
1976
+ {
1977
+ permissions: [
1978
+ SDK_PERMISSIONS.CAMPAIGNS_CREATE,
1979
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
1980
+ ],
1981
+ showFallback: false,
1982
+ children: /* @__PURE__ */ jsx(SDKButton, { startIcon: /* @__PURE__ */ jsx(AddIcon, {}), onClick: handleOpenCreate, children: "New Campaign" })
1983
+ }
1984
+ )
1985
+ ] })
1986
+ }
1987
+ ),
1988
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: { xs: "column", md: "row" }, gap: 1.5, p: 1.5 }, children: [
1989
+ /* @__PURE__ */ jsx(
1990
+ Paper,
1991
+ {
1992
+ elevation: 0,
1993
+ sx: {
1994
+ width: campaignListCollapsed ? { xs: "100%", md: 48 } : { xs: "100%", md: 280, lg: 320 },
1995
+ minWidth: campaignListCollapsed ? { xs: "auto", md: 48 } : { xs: "auto", md: 240 },
1996
+ flexShrink: 0,
1997
+ borderRadius: "16px",
1998
+ display: "flex",
1999
+ flexDirection: "column",
2000
+ maxHeight: { xs: campaignListCollapsed ? "auto" : 260, md: "calc(100vh - 160px)" },
2001
+ overflow: "hidden",
2002
+ border: "1px solid #e0e0e0",
2003
+ boxShadow: "0 1px 3px rgba(0,0,0,0.08)",
2004
+ transition: "width 0.2s ease, min-width 0.2s ease"
2005
+ },
2006
+ children: campaignListCollapsed ? /* @__PURE__ */ jsxs(Box, { sx: {
2007
+ display: "flex",
2008
+ flexDirection: { xs: "row", md: "column" },
2009
+ alignItems: "center",
2010
+ gap: 0.75,
2011
+ p: 0.75,
2012
+ height: "100%",
2013
+ overflowY: { xs: "visible", md: "auto" },
2014
+ overflowX: { xs: "auto", md: "visible" }
2015
+ }, children: [
2016
+ /* @__PURE__ */ jsx(Tooltip, { title: "Expand campaigns", arrow: true, placement: "right", children: /* @__PURE__ */ jsx(
2017
+ IconButton,
2018
+ {
2019
+ size: "small",
2020
+ onClick: () => setCampaignListCollapsed(false),
2021
+ sx: {
2022
+ color: "#1A5F6C",
2023
+ backgroundColor: "#f0f7f8",
2024
+ flexShrink: 0,
2025
+ "&:hover": { backgroundColor: "#e0eff1" }
2026
+ },
2027
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, { fontSize: "small" })
2028
+ }
2029
+ ) }),
2030
+ visibleCampaigns.map((c, idx) => {
2031
+ var _a2;
2032
+ const isSel = c.id === selectedId;
2033
+ const status = (c.status || "draft").toLowerCase();
2034
+ const statusColor = (_a2 = STATUS_COLORS[status]) != null ? _a2 : "#9e9e9e";
2035
+ return /* @__PURE__ */ jsx(
2036
+ Tooltip,
2037
+ {
2038
+ arrow: true,
2039
+ placement: "right",
2040
+ title: `${c.name} \u2022 ${c.status || "draft"}`,
2041
+ children: /* @__PURE__ */ jsx(
2042
+ Box,
2043
+ {
2044
+ onClick: () => setSelectedId(c.id),
2045
+ sx: {
2046
+ width: 32,
2047
+ height: 32,
2048
+ borderRadius: "8px",
2049
+ display: "flex",
2050
+ alignItems: "center",
2051
+ justifyContent: "center",
2052
+ cursor: "pointer",
2053
+ flexShrink: 0,
2054
+ backgroundColor: isSel ? "#fff" : "#fafafa",
2055
+ color: "#333",
2056
+ fontFamily: "poppins, Arial, sans-serif",
2057
+ fontWeight: 700,
2058
+ fontSize: "0.8rem",
2059
+ borderLeft: `3px solid ${statusColor}`,
2060
+ boxShadow: isSel ? `-3px 0 8px ${statusColor}66` : `-2px 0 4px ${statusColor}33`,
2061
+ transition: "box-shadow 0.15s ease",
2062
+ "&:hover": {
2063
+ boxShadow: `-3px 0 8px ${statusColor}80`
2064
+ }
2065
+ },
2066
+ children: idx + 1
2067
+ }
2068
+ )
2069
+ },
2070
+ c.id
2071
+ );
2072
+ })
2073
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2074
+ /* @__PURE__ */ jsxs(Box, { sx: {
2075
+ display: "flex",
2076
+ alignItems: "center",
2077
+ justifyContent: "space-between",
2078
+ px: 2,
2079
+ py: 1.25,
2080
+ borderBottom: "1px solid #eee",
2081
+ backgroundColor: "#fafafa",
2082
+ gap: 1
2083
+ }, children: [
2084
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.5, minWidth: 0 }, children: [
2085
+ /* @__PURE__ */ jsx(Tooltip, { title: "Minimize", arrow: true, children: /* @__PURE__ */ jsx(
2086
+ IconButton,
2087
+ {
2088
+ size: "small",
2089
+ onClick: () => setCampaignListCollapsed(true),
2090
+ sx: { p: 0.5, color: "#666" },
2091
+ children: /* @__PURE__ */ jsx(ChevronLeftIcon, { fontSize: "small" })
2092
+ }
2093
+ ) }),
2094
+ /* @__PURE__ */ jsx(Typography, { sx: { fontWeight: 700, fontSize: "0.95rem", color: "#333", fontFamily: "poppins, Arial, sans-serif" }, children: "Campaigns" })
2095
+ ] }),
2096
+ /* @__PURE__ */ jsx(
2097
+ FormControlLabel,
2098
+ {
2099
+ control: /* @__PURE__ */ jsx(
2100
+ Checkbox,
2101
+ {
2102
+ size: "small",
2103
+ checked: showArchived,
2104
+ onChange: (e) => setShowArchived(e.target.checked),
2105
+ sx: { p: 0.5 }
2106
+ }
2107
+ ),
2108
+ label: /* @__PURE__ */ jsx(Typography, { sx: { fontSize: "0.78rem", color: "#666" }, children: "Show archived" }),
2109
+ sx: { mr: 0 }
2110
+ }
2111
+ )
2112
+ ] }),
2113
+ /* @__PURE__ */ jsx(Box, { sx: { flex: 1, overflow: "auto", p: 1 }, children: loading ? /* @__PURE__ */ jsx(Box, { sx: { display: "flex", justifyContent: "center", py: 4 }, children: /* @__PURE__ */ jsx(CircularProgress, { size: 24, sx: { color: "#1A5F6C" } }) }) : visibleCampaigns.length === 0 ? /* @__PURE__ */ jsx(Typography, { sx: { textAlign: "center", py: 3, color: "#999", fontSize: "0.85rem" }, children: "No campaigns" }) : visibleCampaigns.map((c) => {
2114
+ var _a2, _b2;
2115
+ const isSel = c.id === selectedId;
2116
+ const wStr = `${((_a2 = c.startTime) == null ? void 0 : _a2.slice(0, 5)) || "09:00"}\u2013${((_b2 = c.endTime) == null ? void 0 : _b2.slice(0, 5)) || "17:00"}`;
2117
+ return /* @__PURE__ */ jsxs(
2118
+ Paper,
2119
+ {
2120
+ elevation: 0,
2121
+ onClick: () => setSelectedId(c.id),
2122
+ sx: isSel ? campaignCardSelectedSx : __spreadProps(__spreadValues({}, campaignCardBaseSx), {
2123
+ "&:hover": { borderColor: "#1A5F6C", backgroundColor: "#f5fafb", boxShadow: "0 2px 6px rgba(26,95,108,0.1)" }
2124
+ }),
2125
+ children: [
2126
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 0.5 }, children: [
2127
+ /* @__PURE__ */ jsx(Typography, { sx: { fontWeight: 600, fontSize: "0.88rem", color: "#1a1a1a", fontFamily: "poppins, Arial, sans-serif" }, children: c.name }),
2128
+ /* @__PURE__ */ jsx(Chip, { label: c.status || "draft", size: "small", sx: statusChipSx(c.status) })
2129
+ ] }),
2130
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: "0.73rem", color: "#999", fontFamily: "poppins, Arial, sans-serif" }, children: [
2131
+ c.dialingMode,
2132
+ " \xB7 TZ: ",
2133
+ c.timezone || "Etc/UTC",
2134
+ " \xB7 ",
2135
+ wStr
2136
+ ] })
2137
+ ]
2138
+ },
2139
+ c.id
2140
+ );
2141
+ }) })
2142
+ ] })
2143
+ }
2144
+ ),
2145
+ /* @__PURE__ */ jsx(Box, { sx: { flex: 1, display: "flex", flexDirection: "column", gap: 1.5, minWidth: 0, overflow: "hidden" }, children: !sc ? /* @__PURE__ */ jsx(
2146
+ Paper,
2147
+ {
2148
+ elevation: 0,
2149
+ sx: {
2150
+ borderRadius: "16px",
2151
+ display: "flex",
2152
+ alignItems: "center",
2153
+ justifyContent: "center",
2154
+ minHeight: 200,
2155
+ border: "2px dashed #d0d0d0",
2156
+ backgroundColor: "#fafafa"
2157
+ },
2158
+ children: /* @__PURE__ */ jsxs(Box, { sx: { textAlign: "center" }, children: [
2159
+ /* @__PURE__ */ jsx(SettingsIcon, { sx: { fontSize: 40, color: "#ccc", mb: 1 } }),
2160
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: "0.95rem", color: "#999", fontFamily: "poppins, Arial, sans-serif" }, children: "Select a campaign to view details" })
2161
+ ] })
2162
+ }
2163
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
2164
+ /* @__PURE__ */ jsxs(
2165
+ Paper,
2166
+ {
2167
+ elevation: 0,
2168
+ sx: {
2169
+ borderRadius: "16px",
2170
+ p: { xs: 1.5, sm: 2.5 },
2171
+ border: "1px solid #e0e0e0",
2172
+ boxShadow: "0 1px 3px rgba(0,0,0,0.08)"
2173
+ },
2174
+ children: [
2175
+ /* @__PURE__ */ jsxs(Box, { sx: {
2176
+ display: "flex",
2177
+ alignItems: { xs: "flex-start", sm: "center" },
2178
+ justifyContent: "space-between",
2179
+ flexWrap: "wrap",
2180
+ gap: 1,
2181
+ mb: 2
2182
+ }, children: [
2183
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, children: [
2184
+ /* @__PURE__ */ jsx(Typography, { sx: { fontWeight: 700, fontSize: { xs: "1rem", sm: "1.2rem" }, color: "#1a1a1a", fontFamily: "poppins, Arial, sans-serif" }, children: sc.name }),
2185
+ /* @__PURE__ */ jsx(Chip, { label: sc.status || "draft", size: "small", sx: statusChipSx(sc.status) })
2186
+ ] }),
2187
+ !scArchived && /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", gap: 1, flexWrap: "wrap" }, children: [
2188
+ /* @__PURE__ */ jsx(
2189
+ SDKPermissionGuard,
2190
+ {
2191
+ permissions: [
2192
+ SDK_PERMISSIONS.CAMPAIGNS_UPDATE,
2193
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2194
+ ],
2195
+ showFallback: false,
2196
+ children: /* @__PURE__ */ jsx(
2197
+ SDKButton,
2198
+ {
2199
+ variant: "outlined",
2200
+ startIcon: /* @__PURE__ */ jsx(EditIcon, {}),
2201
+ onClick: () => handleOpenEdit(sc),
2202
+ children: "Edit"
2203
+ }
2204
+ )
2205
+ }
2206
+ ),
2207
+ (scDraft || scPaused) && /* @__PURE__ */ jsx(
2208
+ SDKPermissionGuard,
2209
+ {
2210
+ permissions: [
2211
+ SDK_PERMISSIONS.CAMPAIGNS_CONTROL,
2212
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2213
+ ],
2214
+ showFallback: false,
2215
+ children: /* @__PURE__ */ jsx(
2216
+ SDKButton,
2217
+ {
2218
+ startIcon: /* @__PURE__ */ jsx(PlayArrowIcon, {}),
2219
+ onClick: () => handleStart(sc),
2220
+ sx: { backgroundColor: "#4caf50", "&:hover": { backgroundColor: "#388e3c" } },
2221
+ children: "Start"
2222
+ }
2223
+ )
2224
+ }
2225
+ ),
2226
+ scActive && /* @__PURE__ */ jsx(
2227
+ SDKPermissionGuard,
2228
+ {
2229
+ permissions: [
2230
+ SDK_PERMISSIONS.CAMPAIGNS_CONTROL,
2231
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2232
+ ],
2233
+ showFallback: false,
2234
+ children: /* @__PURE__ */ jsx(
2235
+ SDKButton,
2236
+ {
2237
+ startIcon: /* @__PURE__ */ jsx(PauseIcon, {}),
2238
+ onClick: () => handlePause(sc),
2239
+ sx: { backgroundColor: "#ff9800", boxShadow: "0 2px 8px rgba(255,152,0,0.25)", "&:hover": { backgroundColor: "#f57c00" } },
2240
+ children: "Pause"
2241
+ }
2242
+ )
2243
+ }
2244
+ ),
2245
+ /* @__PURE__ */ jsx(
2246
+ SDKPermissionGuard,
2247
+ {
2248
+ permissions: [
2249
+ SDK_PERMISSIONS.CAMPAIGNS_DELETE,
2250
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2251
+ ],
2252
+ showFallback: false,
2253
+ children: /* @__PURE__ */ jsx(
2254
+ SDKButton,
2255
+ {
2256
+ variant: "danger",
2257
+ startIcon: /* @__PURE__ */ jsx(ArchiveIcon, {}),
2258
+ onClick: () => {
2259
+ setArchiveTarget(sc);
2260
+ setArchiveOpen(true);
2261
+ },
2262
+ children: "Archive"
2263
+ }
2264
+ )
2265
+ }
2266
+ )
2267
+ ] })
2268
+ ] }),
2269
+ sc.description && /* @__PURE__ */ jsx(Typography, { sx: { fontSize: "0.85rem", color: "#666", mb: 1.5, fontFamily: "poppins, Arial, sans-serif", lineHeight: 1.5 }, children: sc.description }),
2270
+ /* @__PURE__ */ jsx(
2271
+ Box,
2272
+ {
2273
+ sx: {
2274
+ overflowX: "auto",
2275
+ pb: 0.5,
2276
+ "&::-webkit-scrollbar": { height: 6 },
2277
+ "&::-webkit-scrollbar-track": { backgroundColor: "#f0f0f0", borderRadius: 3 },
2278
+ "&::-webkit-scrollbar-thumb": {
2279
+ backgroundColor: "#c0c0c0",
2280
+ borderRadius: 3,
2281
+ "&:hover": { backgroundColor: "#a0a0a0" }
2282
+ }
2283
+ },
2284
+ children: /* @__PURE__ */ jsx(
2285
+ Box,
2286
+ {
2287
+ sx: {
2288
+ display: "flex",
2289
+ flexWrap: "nowrap",
2290
+ gap: 1.5
2291
+ },
2292
+ children: [
2293
+ {
2294
+ accent: "#1565c0",
2295
+ fields: [
2296
+ { label: "Type", value: sc.campaignType || "N/A" },
2297
+ { label: "Mode", value: sc.dialingMode || "N/A" }
2298
+ ]
2299
+ },
2300
+ {
2301
+ accent: "#2e7d32",
2302
+ fields: [
2303
+ { label: "Agent", value: sc.agentType || "HUMAN" },
2304
+ { label: "Dialer", value: (leadsMeta == null ? void 0 : leadsMeta.isDialerEnabled) ? "Enabled" : "Disabled" }
2305
+ ]
2306
+ },
2307
+ {
2308
+ accent: "#c62828",
2309
+ fields: [
2310
+ { label: "Priority", value: leadPriorityChipSx(sc.priority).label },
2311
+ { label: "Max Concurrent", value: String((_f = sc.maxConcurrentCalls) != null ? _f : 1) }
2312
+ ]
2313
+ },
2314
+ {
2315
+ accent: "#283593",
2316
+ fields: [
2317
+ { label: "Retry", value: `${(_g = sc.retryIntervalMinutes) != null ? _g : 15}min / ${(_h = sc.maxAttempts) != null ? _h : 3} attempts` },
2318
+ { label: "Leads", value: `${(_i = sc.totalLeads) != null ? _i : 0} total / ${(_j = sc.completedLeads) != null ? _j : 0} completed / ${(_k = sc.successfulCalls) != null ? _k : 0} success` }
2319
+ ]
2320
+ }
2321
+ ].map((card, idx) => /* @__PURE__ */ jsx(
2322
+ Box,
2323
+ {
2324
+ sx: {
2325
+ display: "flex",
2326
+ flexDirection: "column",
2327
+ gap: 0.5,
2328
+ px: 1.5,
2329
+ py: 1,
2330
+ borderRadius: "10px",
2331
+ backgroundColor: "#fafafa",
2332
+ borderLeft: `3px solid ${card.accent}`,
2333
+ flex: "0 0 auto",
2334
+ minWidth: 180
2335
+ },
2336
+ children: card.fields.map((field) => /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.75 }, children: [
2337
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontFamily: "poppins, Arial, sans-serif", fontSize: "0.72rem", fontWeight: 600, color: "#888", whiteSpace: "nowrap", flexShrink: 0 }, children: [
2338
+ field.label,
2339
+ ":"
2340
+ ] }),
2341
+ /* @__PURE__ */ jsx(Typography, { sx: { fontFamily: "poppins, Arial, sans-serif", fontSize: "0.75rem", fontWeight: 700, color: "#333", whiteSpace: "nowrap" }, children: field.value })
2342
+ ] }, field.label))
2343
+ },
2344
+ idx
2345
+ ))
2346
+ }
2347
+ )
2348
+ }
2349
+ )
2350
+ ]
2351
+ }
2352
+ ),
2353
+ /* @__PURE__ */ jsxs(
2354
+ Paper,
2355
+ {
2356
+ elevation: 0,
2357
+ sx: {
2358
+ borderRadius: "16px",
2359
+ overflow: "hidden",
2360
+ border: "1px solid #e0e0e0",
2361
+ boxShadow: "0 1px 3px rgba(0,0,0,0.08)"
2362
+ },
2363
+ children: [
2364
+ /* @__PURE__ */ jsxs(Box, { sx: {
2365
+ display: "flex",
2366
+ alignItems: { xs: "flex-start", sm: "center" },
2367
+ justifyContent: "space-between",
2368
+ flexDirection: { xs: "column", sm: "row" },
2369
+ gap: 1,
2370
+ px: { xs: 1.5, sm: 2 },
2371
+ py: 1.5,
2372
+ borderBottom: "1px solid #eee",
2373
+ backgroundColor: "#fafafa"
2374
+ }, children: [
2375
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, children: [
2376
+ /* @__PURE__ */ jsx(Typography, { sx: { fontWeight: 700, fontSize: "1rem", color: "#1a1a1a", fontFamily: "poppins, Arial, sans-serif" }, children: "Leads" }),
2377
+ /* @__PURE__ */ jsx(
2378
+ SDKPermissionGuard,
2379
+ {
2380
+ permissions: [
2381
+ SDK_PERMISSIONS.CAMPAIGNS_UPDATE,
2382
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2383
+ ],
2384
+ showFallback: false,
2385
+ children: /* @__PURE__ */ jsx(SDKButton, { variant: "outlined", onClick: () => setImportOpen(true), disabled: scArchived, startIcon: /* @__PURE__ */ jsx(UploadFileIcon, { sx: { fontSize: 15 } }), size: "small", children: "Import Leads" })
2386
+ }
2387
+ ),
2388
+ /* @__PURE__ */ jsx(
2389
+ SDKPermissionGuard,
2390
+ {
2391
+ permissions: [
2392
+ SDK_PERMISSIONS.CAMPAIGNS_READ,
2393
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2394
+ ],
2395
+ showFallback: false,
2396
+ children: /* @__PURE__ */ jsx(SDKButton, { variant: "primary", onClick: handleExport, disabled: leadsLoading || leadTotal === 0, startIcon: /* @__PURE__ */ jsx(DownloadIcon, { sx: { fontSize: 15 } }), size: "small", children: "Export Excel" })
2397
+ }
2398
+ ),
2399
+ /* @__PURE__ */ jsx(
2400
+ SDKPermissionGuard,
2401
+ {
2402
+ permissions: [
2403
+ SDK_PERMISSIONS.CAMPAIGNS_UPDATE,
2404
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2405
+ ],
2406
+ showFallback: false,
2407
+ children: /* @__PURE__ */ jsx(SDKButton, { variant: "primary", onClick: () => setAddLeadOpen(true), disabled: scArchived, startIcon: /* @__PURE__ */ jsx(AddIcon, { sx: { fontSize: 15 } }), size: "small", children: "Add Lead" })
2408
+ }
2409
+ )
2410
+ ] }),
2411
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1, width: { xs: "100%", sm: "auto" } }, children: [
2412
+ /* @__PURE__ */ jsx(
2413
+ OutlinedInput,
2414
+ {
2415
+ size: "small",
2416
+ value: leadSearch,
2417
+ onChange: (e) => {
2418
+ setLeadSearch(e.target.value);
2419
+ setLeadPage(0);
2420
+ },
2421
+ placeholder: "Search number...",
2422
+ sx: { width: { xs: "100%", sm: 200 }, fontSize: "0.85rem", height: 34, borderRadius: "20px" },
2423
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(SearchIcon, { sx: { fontSize: 16, color: "#aaa" } }) })
2424
+ }
2425
+ ),
2426
+ /* @__PURE__ */ jsx(FormControl, { size: "small", sx: { minWidth: 130 }, children: /* @__PURE__ */ jsx(
2427
+ Select,
2428
+ {
2429
+ value: leadStatusFilter,
2430
+ onChange: (e) => {
2431
+ setLeadStatusFilter(e.target.value);
2432
+ setLeadPage(0);
2433
+ },
2434
+ sx: { height: 34, borderRadius: "30px", fontSize: "0.85rem" },
2435
+ children: LEAD_STATUSES.map((s) => /* @__PURE__ */ jsx(MenuItem, { value: s, children: s }, s))
2436
+ }
2437
+ ) })
2438
+ ] })
2439
+ ] }),
2440
+ /* @__PURE__ */ jsx(Box, { sx: {
2441
+ overflowX: "auto",
2442
+ overflowY: "visible",
2443
+ WebkitOverflowScrolling: "touch",
2444
+ "&::-webkit-scrollbar": { height: 4 },
2445
+ "&::-webkit-scrollbar-thumb": { backgroundColor: "#ccc", borderRadius: 2 }
2446
+ }, children: /* @__PURE__ */ jsxs(Table, { size: "small", sx: { minWidth: 980 }, children: [
2447
+ /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsx(TableRow, { sx: { backgroundColor: "#f1f1f1" }, children: [
2448
+ "Number",
2449
+ "Status",
2450
+ "Priority",
2451
+ "Source",
2452
+ "Call ID",
2453
+ "Queue Name",
2454
+ "Attempts",
2455
+ "Created At",
2456
+ "Last Attempt",
2457
+ "Next Attempt",
2458
+ "Last Outcome",
2459
+ "Completed At",
2460
+ "Notes",
2461
+ "Actions"
2462
+ ].map((col) => /* @__PURE__ */ jsx(TableCell, { sx: __spreadValues(__spreadValues({}, headCellSx), col === "Actions" ? { textAlign: "center" } : {}), children: col }, col)) }) }),
2463
+ /* @__PURE__ */ jsx(TableBody, { children: leadsLoading ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 14, align: "center", sx: { py: 4 }, children: /* @__PURE__ */ jsx(CircularProgress, { size: 24, sx: { color: "#1A5F6C" } }) }) }) : leads.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
2464
+ TableCell,
2465
+ {
2466
+ colSpan: 14,
2467
+ align: "center",
2468
+ sx: { py: 4, color: "#999", fontFamily: "poppins, Arial, sans-serif" },
2469
+ children: 'No leads found. Add leads using "Add Lead" or "Import Leads".'
2470
+ }
2471
+ ) }) : leads.map((lead) => {
2472
+ var _a2;
2473
+ const nonDeletable = ["IN_PROGRESS", "COMPLETED", "FAILED", "DO_NOT_CALL"];
2474
+ const leadStatus = (lead.status || "").toUpperCase();
2475
+ const deleteDisabled = nonDeletable.includes(leadStatus);
2476
+ const isDialerEnabled = !!(leadsMeta == null ? void 0 : leadsMeta.isDialerEnabled);
2477
+ const isCompleted = leadStatus === "COMPLETED";
2478
+ const isInProgress = leadStatus === "IN_PROGRESS";
2479
+ const isDialable = isDialerEnabled && hasOutboundPermission && isAgentIdle && !isCompleted && !isInProgress && dialLoading !== lead.id;
2480
+ const dialTooltip = !isDialerEnabled ? "Dialer is not enabled" : !hasOutboundPermission ? "No outbound call permission" : isCompleted ? "Lead is completed" : isInProgress ? "Lead is in progress" : !isAgentIdle ? "Agent is not idle" : dialLoading === lead.id ? "Dialing\u2026" : `Call ${lead.phoneNumber}`;
2481
+ const { chip: prioChip, label: prioLabel } = leadPriorityChipSx(lead.priority);
2482
+ return /* @__PURE__ */ jsxs(TableRow, { sx: tableRowSx, children: [
2483
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: lead.phoneNumber }),
2484
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: /* @__PURE__ */ jsx(Chip, { label: lead.status || "pending", size: "small", sx: leadStatusChipSx(lead.status) }) }),
2485
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: /* @__PURE__ */ jsx(Chip, { label: prioLabel, size: "small", sx: prioChip }) }),
2486
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: lead.source || "" }),
2487
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { maxWidth: 140, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }), children: /* @__PURE__ */ jsx(Tooltip, { title: lead.originalCallId || "", children: /* @__PURE__ */ jsx("span", { children: lead.originalCallId || "" }) }) }),
2488
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: lead.originalQueueId ? queueNameMap[lead.originalQueueId] || `Queue #${lead.originalQueueId}` : "" }),
2489
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: (_a2 = lead.attemptCount) != null ? _a2 : 0 }),
2490
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { whiteSpace: "nowrap" }), children: lead.createdAt ? new Date(lead.createdAt).toLocaleString() : "" }),
2491
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { whiteSpace: "nowrap" }), children: lead.lastAttemptAt ? new Date(lead.lastAttemptAt).toLocaleString() : "" }),
2492
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { whiteSpace: "nowrap" }), children: lead.nextAttemptAt ? new Date(lead.nextAttemptAt).toLocaleString() : "" }),
2493
+ /* @__PURE__ */ jsx(TableCell, { sx: bodyCellSx, children: lead.lastOutcome || "" }),
2494
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { whiteSpace: "nowrap" }), children: lead.completedAt ? new Date(lead.completedAt).toLocaleString() : "" }),
2495
+ /* @__PURE__ */ jsx(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { maxWidth: 150, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }), children: lead.notes ? /* @__PURE__ */ jsx(Tooltip, { title: lead.notes, arrow: true, placement: "top", children: /* @__PURE__ */ jsx("span", { children: lead.notes }) }) : "" }),
2496
+ /* @__PURE__ */ jsxs(TableCell, { sx: __spreadProps(__spreadValues({}, bodyCellSx), { textAlign: "center", whiteSpace: "nowrap" }), children: [
2497
+ /* @__PURE__ */ jsx(Tooltip, { title: dialTooltip, children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
2498
+ IconButton,
2499
+ {
2500
+ size: "small",
2501
+ onClick: () => handleDialPreview(lead.id),
2502
+ disabled: !isDialable,
2503
+ sx: {
2504
+ color: isDialable ? "#2e7d32" : "#bdbdbd",
2505
+ backgroundColor: isDialable ? "#e8f5e9" : "transparent",
2506
+ borderRadius: "50%",
2507
+ transition: "all 0.2s ease-in-out",
2508
+ "&:hover": {
2509
+ backgroundColor: isDialable ? "#43a047" : "transparent",
2510
+ color: isDialable ? "#fff" : "#bdbdbd",
2511
+ transform: isDialable ? "scale(1.2)" : "none",
2512
+ boxShadow: isDialable ? "0 0 8px rgba(67,160,71,0.5)" : "none"
2513
+ }
2514
+ },
2515
+ children: dialLoading === lead.id ? /* @__PURE__ */ jsx(CircularProgress, { size: 16 }) : /* @__PURE__ */ jsx(PhoneIcon, { sx: { fontSize: 18 } })
2516
+ }
2517
+ ) }) }),
2518
+ /* @__PURE__ */ jsx(
2519
+ SDKPermissionGuard,
2520
+ {
2521
+ permissions: [
2522
+ SDK_PERMISSIONS.CAMPAIGNS_DELETE,
2523
+ SDK_PERMISSIONS.CAMPAIGNS_MANAGE
2524
+ ],
2525
+ showFallback: false,
2526
+ children: /* @__PURE__ */ jsx(Tooltip, { title: deleteDisabled ? `Cannot delete \u2014 status is ${leadStatus.toLowerCase().replace("_", " ")}` : `Delete lead ${lead.phoneNumber}`, children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
2527
+ IconButton,
2528
+ {
2529
+ size: "small",
2530
+ onClick: () => {
2531
+ setDeleteLeadTarget(lead);
2532
+ setDeleteLeadOpen(true);
2533
+ },
2534
+ disabled: deleteDisabled,
2535
+ sx: {
2536
+ ml: 0.5,
2537
+ color: deleteDisabled ? "#bdbdbd" : "#c62828",
2538
+ backgroundColor: deleteDisabled ? "transparent" : "#ffebee",
2539
+ borderRadius: "50%",
2540
+ transition: "all 0.2s ease-in-out",
2541
+ "&:hover": {
2542
+ backgroundColor: deleteDisabled ? "transparent" : "#d32f2f",
2543
+ color: deleteDisabled ? "#bdbdbd" : "#fff",
2544
+ transform: deleteDisabled ? "none" : "scale(1.2)",
2545
+ boxShadow: deleteDisabled ? "none" : "0 0 8px rgba(211,47,47,0.5)"
2546
+ }
2547
+ },
2548
+ children: /* @__PURE__ */ jsx(DeleteIcon, { sx: { fontSize: 18 } })
2549
+ }
2550
+ ) }) })
2551
+ }
2552
+ )
2553
+ ] })
2554
+ ] }, lead.id);
2555
+ }) })
2556
+ ] }) }),
2557
+ leads.length > 0 && /* @__PURE__ */ jsx(
2558
+ TablePagination,
2559
+ {
2560
+ component: "div",
2561
+ count: leadTotal,
2562
+ page: leadPage,
2563
+ rowsPerPage: leadRowsPerPage,
2564
+ onPageChange: (_, p) => {
2565
+ setLeadPage(p);
2566
+ refetchLeads(p);
2567
+ },
2568
+ onRowsPerPageChange: (e) => {
2569
+ setLeadRowsPerPage(parseInt(e.target.value, 10));
2570
+ setLeadPage(0);
2571
+ },
2572
+ rowsPerPageOptions: [5, 10, 25, 50],
2573
+ sx: {
2574
+ fontSize: "0.82rem",
2575
+ "& .MuiTablePagination-toolbar": { minHeight: 40, px: 1 },
2576
+ "& .MuiTablePagination-selectLabel, & .MuiTablePagination-displayedRows": { fontSize: "0.82rem" }
2577
+ }
2578
+ }
2579
+ )
2580
+ ]
2581
+ }
2582
+ )
2583
+ ] }) })
2584
+ ] }),
2585
+ /* @__PURE__ */ jsx(
2586
+ CampaignDialog,
2587
+ {
2588
+ open: dialogOpen,
2589
+ editingCampaign,
2590
+ formData,
2591
+ setFormData,
2592
+ saving,
2593
+ onSave: handleSave,
2594
+ onClose: () => setDialogOpen(false),
2595
+ parentQueueNameMap: queueNameMap,
2596
+ onQueuesRefreshed: handleQueuesRefreshed,
2597
+ onLeadsChange: () => {
2598
+ fetchCampaigns();
2599
+ if (selectedId) refetchLeads();
2600
+ }
2601
+ }
2602
+ ),
2603
+ /* @__PURE__ */ jsx(
2604
+ AddLeadDialog,
2605
+ {
2606
+ open: addLeadOpen,
2607
+ data: addLeadData,
2608
+ onChange: setAddLeadData,
2609
+ saving: addLeadSaving,
2610
+ onSave: handleAddLead,
2611
+ onClose: () => setAddLeadOpen(false)
2612
+ }
2613
+ ),
2614
+ /* @__PURE__ */ jsx(
2615
+ ImportLeadsDialog,
2616
+ {
2617
+ open: importOpen,
2618
+ file: importFile,
2619
+ onFileChange: setImportFile,
2620
+ uploading: importing,
2621
+ onUpload: handleImport,
2622
+ onDownloadTemplate: handleDownloadTemplate,
2623
+ onClose: () => {
2624
+ setImportOpen(false);
2625
+ setImportFile(null);
2626
+ }
2627
+ }
2628
+ ),
2629
+ /* @__PURE__ */ jsx(
2630
+ ConfirmDialog,
2631
+ {
2632
+ open: archiveOpen,
2633
+ title: "Archive Campaign",
2634
+ message: `Archive "${archiveTarget == null ? void 0 : archiveTarget.name}"? It will no longer run.`,
2635
+ loading: archiving,
2636
+ onConfirm: confirmArchive,
2637
+ onClose: () => {
2638
+ setArchiveOpen(false);
2639
+ setArchiveTarget(null);
2640
+ }
2641
+ }
2642
+ ),
2643
+ /* @__PURE__ */ jsx(
2644
+ ConfirmDialog,
2645
+ {
2646
+ open: deleteLeadOpen,
2647
+ title: "Delete Lead",
2648
+ message: `Delete lead ${deleteLeadTarget == null ? void 0 : deleteLeadTarget.phoneNumber}? This cannot be undone.`,
2649
+ loading: deletingLead,
2650
+ onConfirm: confirmDeleteLead,
2651
+ onClose: () => {
2652
+ setDeleteLeadOpen(false);
2653
+ setDeleteLeadTarget(null);
2654
+ }
2655
+ }
2656
+ )
2657
+ ] });
2658
+ });
2659
+ var Campaigns = () => /* @__PURE__ */ jsx(SDKProvider, { children: /* @__PURE__ */ jsx(CampaignsContent, {}) });
2660
+ var campaigns_default = Campaigns;
2661
+ export {
2662
+ campaigns_default as default
2663
+ };
2664
+ //# sourceMappingURL=campaigns-FR7EIRXI.mjs.map