@adatechnology/conversations-ui 0.1.0-rc.4 → 0.1.0-rc.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/chunk-LITPZCWW.js +1465 -0
  2. package/dist/index.d.ts +223 -29
  3. package/dist/index.js +316 -366
  4. package/dist/preview/index.d.ts +92 -3
  5. package/dist/preview/index.js +627 -103
  6. package/dist/types-CeixG2Z9.d.ts +324 -0
  7. package/package.json +2 -2
  8. package/src/Avatar.tsx +13 -2
  9. package/src/ConversationDocumentsPanel.tsx +342 -24
  10. package/src/ConversationListItem.tsx +18 -2
  11. package/src/DocumentsLibrary.tsx +322 -0
  12. package/src/FileIcon.test.ts +83 -0
  13. package/src/FileIcon.tsx +88 -11
  14. package/src/Lightbox.tsx +18 -3
  15. package/src/MediaRenderer.tsx +5 -2
  16. package/src/MessageBubble.tsx +18 -2
  17. package/src/MessageComposer.tsx +20 -3
  18. package/src/WhatsAppMessageEditor.tsx +28 -4
  19. package/src/hooks/useConversationActions.ts +56 -0
  20. package/src/hooks/useConversationDocuments.ts +11 -7
  21. package/src/hooks/useConversationList.ts +15 -9
  22. package/src/hooks/useConversationMessages.ts +2 -2
  23. package/src/index.ts +32 -11
  24. package/src/lib/cn.test.ts +29 -0
  25. package/src/lib/createMediaUrlResolver.ts +33 -0
  26. package/src/lib/paginated.test.ts +33 -0
  27. package/src/lib/paginated.ts +26 -0
  28. package/src/preview/MediaTypesPreview.tsx +87 -0
  29. package/src/preview/createMockConversationsApi.ts +175 -15
  30. package/src/preview/index.ts +6 -1
  31. package/src/preview/mockDocumentsSearch.test.ts +57 -0
  32. package/src/preview/preview.test.ts +5 -3
  33. package/src/preview/previewFileSamples.test.ts +151 -0
  34. package/src/preview/previewFileSamples.ts +74 -0
  35. package/src/preview/previewFixtures.ts +288 -1
  36. package/src/preview/previewMediaSource.test.ts +62 -0
  37. package/src/preview/previewMediaSource.ts +91 -0
  38. package/src/providers/types.ts +127 -9
  39. package/src/settings/WhatsAppCreateTemplateForm.tsx +3 -1
  40. package/src/useWaitingNotifications.ts +74 -29
  41. package/dist/chunk-4R6Y43DQ.js +0 -726
  42. package/dist/types-C0PtaO7S.d.ts +0 -207
package/dist/index.js CHANGED
@@ -4,9 +4,17 @@ import {
4
4
  } from "./chunk-NV2RZ5KT.js";
5
5
  import {
6
6
  AudioPlayer,
7
+ ConversationDocumentsPanel,
7
8
  ConversationLocalesProvider,
8
9
  ConversationWallpaper,
10
+ ConversationsProvider,
11
+ DEFAULT_CONVERSATION_DOCUMENTS_LABELS,
12
+ DEFAULT_DOCUMENTS_LIBRARY_LABELS,
13
+ DEFAULT_LIGHTBOX_LABELS,
14
+ DEFAULT_MESSAGE_COMPOSER_LABELS,
15
+ DOCUMENT_SOURCE_FILTER,
9
16
  DateDivider,
17
+ DocumentsLibrary,
10
18
  EmojiPicker,
11
19
  FileIcon,
12
20
  Lightbox,
@@ -15,10 +23,21 @@ import {
15
23
  MessageComposer,
16
24
  StatusTicks,
17
25
  cn,
26
+ conversationsOf,
27
+ createMediaUrlResolver,
28
+ formatDateTime,
18
29
  formatFileSize,
30
+ formatPhone,
19
31
  formatTimestamp,
20
- useConversationLocales
21
- } from "./chunk-4R6Y43DQ.js";
32
+ isSameDay,
33
+ phoneCountryFlag,
34
+ phoneInitials,
35
+ totalOf,
36
+ useAsyncResource,
37
+ useConversationDocuments,
38
+ useConversationLocales,
39
+ useConversations
40
+ } from "./chunk-LITPZCWW.js";
22
41
  import {
23
42
  htmlToWA,
24
43
  parseWhatsAppFormatting,
@@ -30,6 +49,15 @@ import {
30
49
  import { useRef } from "react";
31
50
  import { Bold, Italic, Strikethrough } from "lucide-react";
32
51
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
52
+ var DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS = {
53
+ bold: "Negrito",
54
+ boldHint: "Negrito (*texto*)",
55
+ italic: "It\xE1lico",
56
+ italicHint: "It\xE1lico (_texto_)",
57
+ strikethrough: "Tachado",
58
+ strikethroughHint: "Tachado (~texto~)",
59
+ insertPlaceholder: (token) => `Inserir ${token}`
60
+ };
33
61
  var INLINE_TOKEN = /(\*[^*\n]+\*|_[^_\n]+_|~[^~\n]+~|`[^`\n]+`|\{[a-zA-Z_]+\})/g;
34
62
  function renderLine(line, lineKey) {
35
63
  const nodes = [];
@@ -65,8 +93,10 @@ function WhatsAppMessageEditor({
65
93
  placeholders = [],
66
94
  rows = 4,
67
95
  previewLabel = "Pr\xE9via (como aparece no WhatsApp)",
68
- emptyPreviewText = "Sua mensagem aparecer\xE1 aqui\u2026"
96
+ emptyPreviewText = "Sua mensagem aparecer\xE1 aqui\u2026",
97
+ labels
69
98
  }) {
99
+ const editorLabels = { ...DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, ...labels };
70
100
  const textareaRef = useRef(null);
71
101
  function wrapSelection(marker) {
72
102
  const textarea = textareaRef.current;
@@ -97,9 +127,9 @@ function WhatsAppMessageEditor({
97
127
  const toolbarButtonClass = "inline-flex items-center justify-center h-8 w-8 rounded-lg border border-gray-200 dark:border-gray-600 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors";
98
128
  return /* @__PURE__ */ jsxs("div", { children: [
99
129
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 mb-2", children: [
100
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("*"), className: toolbarButtonClass, title: "Negrito (*texto*)", "aria-label": "Negrito", children: /* @__PURE__ */ jsx(Bold, { size: 15 }) }),
101
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("_"), className: toolbarButtonClass, title: "It\xE1lico (_texto_)", "aria-label": "It\xE1lico", children: /* @__PURE__ */ jsx(Italic, { size: 15 }) }),
102
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("~"), className: toolbarButtonClass, title: "Tachado (~texto~)", "aria-label": "Tachado", children: /* @__PURE__ */ jsx(Strikethrough, { size: 15 }) }),
130
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("*"), className: toolbarButtonClass, title: editorLabels.boldHint, "aria-label": editorLabels.bold, children: /* @__PURE__ */ jsx(Bold, { size: 15 }) }),
131
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("_"), className: toolbarButtonClass, title: editorLabels.italicHint, "aria-label": editorLabels.italic, children: /* @__PURE__ */ jsx(Italic, { size: 15 }) }),
132
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("~"), className: toolbarButtonClass, title: editorLabels.strikethroughHint, "aria-label": editorLabels.strikethrough, children: /* @__PURE__ */ jsx(Strikethrough, { size: 15 }) }),
103
133
  placeholders.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
104
134
  /* @__PURE__ */ jsx("span", { className: "mx-1 h-5 w-px bg-gray-200 dark:bg-gray-600" }),
105
135
  placeholders.map((token) => /* @__PURE__ */ jsx(
@@ -108,7 +138,7 @@ function WhatsAppMessageEditor({
108
138
  type: "button",
109
139
  onClick: () => insertAtCursor(token),
110
140
  className: "inline-flex items-center h-8 px-2 rounded-lg border border-gray-200 dark:border-gray-600 text-xs text-blue-600 dark:text-blue-300 hover:bg-blue-50 dark:hover:bg-blue-900/40 transition-colors",
111
- title: `Inserir ${token}`,
141
+ title: editorLabels.insertPlaceholder(token),
112
142
  children: token
113
143
  },
114
144
  token
@@ -268,6 +298,9 @@ function SimpleEmojiPicker({ onSelect, label = "Emojis", pickerWidth = "280px",
268
298
 
269
299
  // src/Avatar.tsx
270
300
  import { jsx as jsx3 } from "react/jsx-runtime";
301
+ var DEFAULT_AVATAR_LABELS = {
302
+ unnamedContact: "Contato sem nome"
303
+ };
271
304
  var sizeClasses = {
272
305
  sm: "w-6 h-6 text-xs",
273
306
  md: "w-8 h-8 text-sm",
@@ -293,8 +326,9 @@ function getBgColor(name) {
293
326
  const hash = name.charCodeAt(0) + (name.charCodeAt(name.length - 1) || 0);
294
327
  return bgColors[hash % bgColors.length];
295
328
  }
296
- function Avatar({ name, avatarUrl, size = "md", className = "" }) {
329
+ function Avatar({ name, avatarUrl, size = "md", className = "", labels }) {
297
330
  const sizeClass = sizeClasses[size];
331
+ const unnamedContactLabel = labels?.unnamedContact ?? DEFAULT_AVATAR_LABELS.unnamedContact;
298
332
  if (avatarUrl) {
299
333
  return /* @__PURE__ */ jsx3(
300
334
  "img",
@@ -312,7 +346,7 @@ function Avatar({ name, avatarUrl, size = "md", className = "" }) {
312
346
  {
313
347
  className: `${sizeClass} ${bgColor} rounded-full flex items-center justify-center text-white flex-shrink-0 ${className}`,
314
348
  role: "img",
315
- "aria-label": "Contato sem nome",
349
+ "aria-label": unnamedContactLabel,
316
350
  children: /* @__PURE__ */ jsx3("svg", { viewBox: "0 0 24 24", fill: "currentColor", className: "h-[60%] w-[60%]", "aria-hidden": true, children: /* @__PURE__ */ jsx3("path", { d: "M12 12a5 5 0 1 0 0-10 5 5 0 0 0 0 10Zm0 2c-4.42 0-8 2.24-8 5v1h16v-1c0-2.76-3.58-5-8-5Z" }) })
317
351
  }
318
352
  );
@@ -330,51 +364,6 @@ function Avatar({ name, avatarUrl, size = "md", className = "" }) {
330
364
  // src/ConversationListItem.tsx
331
365
  import { useMemo } from "react";
332
366
 
333
- // src/lib/phone.ts
334
- function formatPhone(number) {
335
- const digits = number.replace(/\D/g, "");
336
- if (digits.length === 13) {
337
- return `+${digits.slice(0, 2)} (${digits.slice(2, 4)}) ${digits.slice(4, 9)}-${digits.slice(9, 13)}`;
338
- }
339
- if (digits.length === 12) {
340
- return `+${digits.slice(0, 2)} (${digits.slice(2, 4)}) ${digits.slice(4, 8)}-${digits.slice(8, 12)}`;
341
- }
342
- if (digits.length === 11) {
343
- return `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7, 11)}`;
344
- }
345
- if (digits.length === 10) {
346
- return `(${digits.slice(0, 2)}) ${digits.slice(2, 6)}-${digits.slice(6, 10)}`;
347
- }
348
- return number;
349
- }
350
- var COUNTRY_FLAG_BY_DIAL_CODE = {
351
- "55": "\u{1F1E7}\u{1F1F7}",
352
- "351": "\u{1F1F5}\u{1F1F9}",
353
- "34": "\u{1F1EA}\u{1F1F8}",
354
- "54": "\u{1F1E6}\u{1F1F7}",
355
- "56": "\u{1F1E8}\u{1F1F1}",
356
- "57": "\u{1F1E8}\u{1F1F4}",
357
- "52": "\u{1F1F2}\u{1F1FD}",
358
- "598": "\u{1F1FA}\u{1F1FE}",
359
- "595": "\u{1F1F5}\u{1F1FE}",
360
- "44": "\u{1F1EC}\u{1F1E7}",
361
- "49": "\u{1F1E9}\u{1F1EA}",
362
- "39": "\u{1F1EE}\u{1F1F9}",
363
- "33": "\u{1F1EB}\u{1F1F7}"
364
- };
365
- function phoneCountryFlag(number) {
366
- const digits = number.replace(/\D/g, "");
367
- for (const length of [3, 2, 1]) {
368
- const flag = COUNTRY_FLAG_BY_DIAL_CODE[digits.slice(0, length)];
369
- if (flag) return flag;
370
- }
371
- return "";
372
- }
373
- function phoneInitials(number) {
374
- const digits = number.replace(/\D/g, "");
375
- return digits.slice(-2);
376
- }
377
-
378
367
  // src/conversationChannel.ts
379
368
  var CONVERSATION_CHANNEL = {
380
369
  WHATSAPP: "whatsapp",
@@ -456,6 +445,10 @@ function contactFlag(params) {
456
445
 
457
446
  // src/ConversationListItem.tsx
458
447
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
448
+ var DEFAULT_CONVERSATION_LIST_ITEM_LABELS = {
449
+ expiredWindow: "Janela expirada",
450
+ warningWindow: "Janela pr\xF3xima do fim"
451
+ };
459
452
  function formatRelativeTime(dateStr) {
460
453
  try {
461
454
  const date = new Date(dateStr);
@@ -516,8 +509,11 @@ var ConversationListItem = ({
516
509
  onClick,
517
510
  onSelect,
518
511
  showDivider = true,
519
- highlightActive = true
512
+ highlightActive = true,
513
+ labels
520
514
  }) => {
515
+ const expiredWindowLabel = labels?.expiredWindow ?? DEFAULT_CONVERSATION_LIST_ITEM_LABELS.expiredWindow;
516
+ const warningWindowLabel = labels?.warningWindow ?? DEFAULT_CONVERSATION_LIST_ITEM_LABELS.warningWindow;
521
517
  const isActive = active || selected;
522
518
  const windowStatus = useMemo(() => getWindowStatus(conversation.lastInboundAt), [conversation.lastInboundAt]);
523
519
  const preview = useMemo(() => lastMessagePreview(conversation), [conversation.lastContent]);
@@ -549,8 +545,8 @@ var ConversationListItem = ({
549
545
  /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1.5 min-w-0", children: [
550
546
  !conversation.clientName && flag ? /* @__PURE__ */ jsx4("span", { "aria-hidden": true, children: flag }) : null,
551
547
  /* @__PURE__ */ jsx4("span", { className: "text-[16px] text-[#111b21] truncate", children: name }),
552
- windowStatus && windowStatus.label === "expired" && /* @__PURE__ */ jsx4("span", { className: "w-2 h-2 rounded-full bg-red-500 flex-shrink-0", title: "Janela expirada" }),
553
- windowStatus && windowStatus.label === "warning" && /* @__PURE__ */ jsx4("span", { className: "w-2 h-2 rounded-full bg-orange-500 flex-shrink-0", title: "Janela pr\xF3xima do fim" })
548
+ windowStatus && windowStatus.label === "expired" && /* @__PURE__ */ jsx4("span", { className: "w-2 h-2 rounded-full bg-red-500 flex-shrink-0", title: expiredWindowLabel }),
549
+ windowStatus && windowStatus.label === "warning" && /* @__PURE__ */ jsx4("span", { className: "w-2 h-2 rounded-full bg-orange-500 flex-shrink-0", title: warningWindowLabel })
554
550
  ] }),
555
551
  timestamp && /* @__PURE__ */ jsx4("span", { className: "text-xs text-[#667781] flex-shrink-0", children: timestamp })
556
552
  ] }),
@@ -1146,116 +1142,6 @@ function isWindowBlocking(window2) {
1146
1142
  return window2 === CONVERSATION_WINDOW.EXPIRED;
1147
1143
  }
1148
1144
 
1149
- // src/ConversationDocumentsPanel.tsx
1150
- import { useState as useState8 } from "react";
1151
-
1152
- // src/providers/ConversationsProvider.tsx
1153
- import { createContext as createContext2, useContext as useContext2 } from "react";
1154
- import { jsx as jsx14 } from "react/jsx-runtime";
1155
- var ConversationsContext = createContext2(null);
1156
- function ConversationsProvider({
1157
- api,
1158
- sse,
1159
- children
1160
- }) {
1161
- return /* @__PURE__ */ jsx14(ConversationsContext.Provider, { value: { api, sse }, children });
1162
- }
1163
- function useConversations() {
1164
- return useContext2(ConversationsContext);
1165
- }
1166
-
1167
- // src/hooks/useAsyncResource.ts
1168
- import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3, useState as useState7 } from "react";
1169
- function useAsyncResource(fetcher, deps) {
1170
- const [data, setData] = useState7(void 0);
1171
- const [loading, setLoading] = useState7(false);
1172
- const [error, setError] = useState7(void 0);
1173
- const requestIdRef = useRef3(0);
1174
- const load = useCallback3(async () => {
1175
- const requestId = ++requestIdRef.current;
1176
- setLoading(true);
1177
- setError(void 0);
1178
- try {
1179
- const result = await fetcher();
1180
- if (requestId === requestIdRef.current) setData(result);
1181
- } catch (err) {
1182
- if (requestId === requestIdRef.current) setError(err instanceof Error ? err : new Error(String(err)));
1183
- } finally {
1184
- if (requestId === requestIdRef.current) setLoading(false);
1185
- }
1186
- }, deps);
1187
- useEffect4(() => {
1188
- load();
1189
- }, [load]);
1190
- return { data, loading, error, refetch: load };
1191
- }
1192
-
1193
- // src/hooks/useConversationDocuments.ts
1194
- function useConversationDocuments(conversationId, params) {
1195
- const context = useConversations();
1196
- if (!context) {
1197
- throw new Error("useConversationDocuments requires an ancestor <ConversationsProvider>");
1198
- }
1199
- const { api } = context;
1200
- const { data, loading, error, refetch } = useAsyncResource(
1201
- () => conversationId ? api.getDocuments(conversationId, params) : Promise.resolve([]),
1202
- [conversationId, params?.search, params?.page]
1203
- );
1204
- return { documents: data ?? [], loading, error, refetch };
1205
- }
1206
-
1207
- // src/ConversationDocumentsPanel.tsx
1208
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1209
- var DEFAULT_CONVERSATION_DOCUMENTS_LABELS = {
1210
- toggle: "\u{1F4CE} Arquivos",
1211
- title: "Arquivos da conversa",
1212
- searchPlaceholder: "Buscar arquivo...",
1213
- empty: "Nenhum arquivo nesta conversa.",
1214
- loading: "Carregando arquivos\u2026",
1215
- failure: "N\xE3o foi poss\xEDvel carregar os arquivos.",
1216
- download: "Baixar"
1217
- };
1218
- function ConversationDocumentsPanel({
1219
- conversationId,
1220
- open,
1221
- labels: labelsOverride,
1222
- className,
1223
- classNames
1224
- }) {
1225
- const labels = { ...DEFAULT_CONVERSATION_DOCUMENTS_LABELS, ...labelsOverride };
1226
- const context = useConversations();
1227
- const [search, setSearch] = useState8("");
1228
- const { documents, loading, error } = useConversationDocuments(open ? conversationId : void 0, { search });
1229
- async function handleDownload(uploadId) {
1230
- const url = await context?.api.getDocumentUrl(uploadId);
1231
- if (url) window.open(url, "_blank", "noopener,noreferrer");
1232
- }
1233
- if (!open) return null;
1234
- return /* @__PURE__ */ jsx15("div", { className: cn("border-b", classNames?.root, className), children: /* @__PURE__ */ jsxs12("section", { className: cn("px-4 py-3", classNames?.body), children: [
1235
- /* @__PURE__ */ jsx15("p", { className: "mb-2 text-sm font-medium", children: labels.title }),
1236
- /* @__PURE__ */ jsx15(
1237
- "input",
1238
- {
1239
- type: "search",
1240
- value: search,
1241
- onChange: (event) => setSearch(event.target.value),
1242
- placeholder: labels.searchPlaceholder,
1243
- className: "mb-2 w-full rounded-md border px-3 py-2 text-sm"
1244
- }
1245
- ),
1246
- loading ? /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-500", children: labels.loading }) : null,
1247
- error ? /* @__PURE__ */ jsx15("p", { className: "text-xs text-red-600 dark:text-red-400", children: labels.failure }) : null,
1248
- !loading && !error && documents.length === 0 ? /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-500", children: labels.empty }) : null,
1249
- /* @__PURE__ */ jsx15("ul", { className: "space-y-1", children: documents.map((document2) => /* @__PURE__ */ jsxs12("li", { className: "flex items-center gap-2 text-xs", children: [
1250
- /* @__PURE__ */ jsx15(FileIcon, { mimeType: document2.mimeType }),
1251
- /* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 truncate", children: document2.filename }),
1252
- /* @__PURE__ */ jsx15("span", { className: "text-gray-500", children: formatFileSize(document2.sizeBytes) }),
1253
- /* @__PURE__ */ jsx15("span", { className: "text-gray-500", children: formatTimestamp(document2.linkedAt) }),
1254
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => void handleDownload(document2.id), className: "cv-header-action", children: labels.download })
1255
- ] }, document2.id)) })
1256
- ] }) });
1257
- }
1258
-
1259
1145
  // src/conversationTranscript.ts
1260
1146
  var SENDER_LABEL = {
1261
1147
  customer: "Cliente",
@@ -1292,53 +1178,67 @@ function downloadTextFile(filename, content) {
1292
1178
  }
1293
1179
 
1294
1180
  // src/useWaitingNotifications.ts
1295
- import { useState as useState9, useEffect as useEffect5, useRef as useRef4, useCallback as useCallback4 } from "react";
1296
- function useWaitingNotifications() {
1297
- const conversationsCtx = useConversations();
1298
- const [conversations, setConversations] = useState9([]);
1299
- const previousUnreadMap = useRef4(/* @__PURE__ */ new Map());
1300
- const notifiedIds = useRef4(/* @__PURE__ */ new Set());
1301
- const pollConversations = useCallback4(async () => {
1302
- if (!conversationsCtx) return;
1181
+ import { useState as useState7, useEffect as useEffect4, useRef as useRef3, useCallback as useCallback3 } from "react";
1182
+ var DEFAULT_POLL_INTERVAL_MS = 1e4;
1183
+ var DEFAULT_LIMIT = 50;
1184
+ var DEFAULT_LABELS = {
1185
+ title: (conversation) => conversation.clientName ?? conversation.whatsappNumber,
1186
+ body: (conversation) => conversation.lastContent ?? "Nova mensagem"
1187
+ };
1188
+ function useWaitingNotifications(params) {
1189
+ const conversationsContext = useConversations();
1190
+ const [conversations, setConversations] = useState7([]);
1191
+ const previousUnreadMap = useRef3(/* @__PURE__ */ new Map());
1192
+ const notifiedIds = useRef3(/* @__PURE__ */ new Set());
1193
+ const isPollingRef = useRef3(false);
1194
+ const isEnabled = params?.enabled ?? true;
1195
+ const intervalMs = params?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
1196
+ const icon = params?.icon;
1197
+ const listParams = params?.params;
1198
+ const labelTitle = params?.labels?.title ?? DEFAULT_LABELS.title;
1199
+ const labelBody = params?.labels?.body ?? DEFAULT_LABELS.body;
1200
+ const refresh = useCallback3(async () => {
1201
+ if (!conversationsContext || isPollingRef.current) return;
1202
+ isPollingRef.current = true;
1303
1203
  try {
1304
- const result = await conversationsCtx.api.fetchConversations({ limit: 50 });
1204
+ const result = conversationsOf(
1205
+ await conversationsContext.api.fetchConversations({ limit: DEFAULT_LIMIT, ...listParams })
1206
+ );
1305
1207
  setConversations(result);
1306
1208
  const currentMap = /* @__PURE__ */ new Map();
1307
- for (const conv of result) {
1308
- currentMap.set(conv.id, conv.unread);
1309
- }
1310
- for (const conv of result) {
1311
- if (conv.unread <= 0) continue;
1312
- const prev = previousUnreadMap.current.get(conv.id) ?? 0;
1313
- if (conv.unread > prev && !notifiedIds.current.has(conv.id)) {
1314
- notifiedIds.current.add(conv.id);
1315
- if (typeof window !== "undefined" && "Notification" in window && Notification.permission === "granted") {
1316
- const title = conv.clientName ?? conv.whatsappNumber;
1317
- const body = conv.lastContent ?? "Nova mensagem";
1318
- new Notification(title, { body, icon: "/favicon.ico" });
1319
- }
1209
+ for (const conversation of result) currentMap.set(conversation.id, conversation.unread);
1210
+ for (const conversation of result) {
1211
+ if (conversation.unread <= 0) continue;
1212
+ const previousUnread = previousUnreadMap.current.get(conversation.id) ?? 0;
1213
+ if (conversation.unread <= previousUnread || notifiedIds.current.has(conversation.id)) continue;
1214
+ notifiedIds.current.add(conversation.id);
1215
+ if (typeof window !== "undefined" && "Notification" in window && Notification.permission === "granted") {
1216
+ new Notification(labelTitle(conversation), { body: labelBody(conversation), ...icon ? { icon } : {} });
1320
1217
  }
1321
1218
  }
1322
1219
  previousUnreadMap.current = currentMap;
1323
1220
  } catch {
1221
+ } finally {
1222
+ isPollingRef.current = false;
1324
1223
  }
1325
- }, [conversationsCtx]);
1326
- useEffect5(() => {
1224
+ }, [conversationsContext, listParams, icon, labelTitle, labelBody]);
1225
+ useEffect4(() => {
1226
+ if (!isEnabled) return;
1327
1227
  if (typeof window !== "undefined" && "Notification" in window && Notification.permission === "default") {
1328
1228
  Notification.requestPermission();
1329
1229
  }
1330
- pollConversations();
1331
- const interval = setInterval(pollConversations, 1e4);
1230
+ void refresh();
1231
+ const interval = setInterval(() => void refresh(), intervalMs);
1332
1232
  return () => clearInterval(interval);
1333
- }, [pollConversations]);
1334
- const unreadCount = conversations.reduce((sum, conv) => sum + conv.unread, 0);
1335
- return { unreadCount, conversations };
1233
+ }, [refresh, isEnabled, intervalMs]);
1234
+ const unreadCount = conversations.reduce((sum, conversation) => sum + conversation.unread, 0);
1235
+ return { unreadCount, conversations, refresh };
1336
1236
  }
1337
1237
 
1338
1238
  // src/settings/WhatsAppTemplateSettingsForm.tsx
1339
1239
  import { Plus, RefreshCw, Save, Trash2 } from "lucide-react";
1340
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1341
- var DEFAULT_LABELS = {
1240
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1241
+ var DEFAULT_LABELS2 = {
1342
1242
  sectionTitle: "WhatsApp",
1343
1243
  sectionDescription: "Template usado para reabrir a janela de 24h com o cliente.",
1344
1244
  templateLabel: "Template aprovado",
@@ -1372,7 +1272,7 @@ function WhatsAppTemplateSettingsForm({
1372
1272
  onSave,
1373
1273
  labels: labelsOverride
1374
1274
  }) {
1375
- const labels = { ...DEFAULT_LABELS, ...labelsOverride };
1275
+ const labels = { ...DEFAULT_LABELS2, ...labelsOverride };
1376
1276
  const selected = templates.find((template) => template.name === selectedTemplateName);
1377
1277
  function handleSelect(name) {
1378
1278
  const template = templates.find((t) => t.name === name);
@@ -1396,16 +1296,16 @@ function WhatsAppTemplateSettingsForm({
1396
1296
  }
1397
1297
  onVariablesChange([...variables, token]);
1398
1298
  }
1399
- return /* @__PURE__ */ jsxs13("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1400
- /* @__PURE__ */ jsxs13("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
1401
- /* @__PURE__ */ jsx16("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }),
1402
- /* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
1299
+ return /* @__PURE__ */ jsxs12("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1300
+ /* @__PURE__ */ jsxs12("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
1301
+ /* @__PURE__ */ jsx14("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }),
1302
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
1403
1303
  ] }),
1404
- /* @__PURE__ */ jsxs13("form", { onSubmit: onSave, className: "p-6 space-y-4", children: [
1405
- /* @__PURE__ */ jsxs13("div", { children: [
1406
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between mb-1.5", children: [
1407
- /* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.templateLabel }),
1408
- /* @__PURE__ */ jsxs13(
1304
+ /* @__PURE__ */ jsxs12("form", { onSubmit: onSave, className: "p-6 space-y-4", children: [
1305
+ /* @__PURE__ */ jsxs12("div", { children: [
1306
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between mb-1.5", children: [
1307
+ /* @__PURE__ */ jsx14("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.templateLabel }),
1308
+ /* @__PURE__ */ jsxs12(
1409
1309
  "button",
1410
1310
  {
1411
1311
  type: "button",
@@ -1413,31 +1313,31 @@ function WhatsAppTemplateSettingsForm({
1413
1313
  disabled: loadingTemplates,
1414
1314
  className: "flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400 hover:underline disabled:opacity-50",
1415
1315
  children: [
1416
- /* @__PURE__ */ jsx16(RefreshCw, { size: 11, className: loadingTemplates ? "animate-spin" : "" }),
1316
+ /* @__PURE__ */ jsx14(RefreshCw, { size: 11, className: loadingTemplates ? "animate-spin" : "" }),
1417
1317
  labels.refreshList
1418
1318
  ]
1419
1319
  }
1420
1320
  )
1421
1321
  ] }),
1422
- templatesError && /* @__PURE__ */ jsxs13("div", { className: "mb-2 rounded-lg bg-amber-50 dark:bg-amber-950/40 border border-amber-200 dark:border-amber-800 px-3 py-2 text-xs text-amber-700 dark:text-amber-400", children: [
1322
+ templatesError && /* @__PURE__ */ jsxs12("div", { className: "mb-2 rounded-lg bg-amber-50 dark:bg-amber-950/40 border border-amber-200 dark:border-amber-800 px-3 py-2 text-xs text-amber-700 dark:text-amber-400", children: [
1423
1323
  labels.errorLoading,
1424
- /* @__PURE__ */ jsx16("br", {}),
1425
- /* @__PURE__ */ jsxs13("span", { className: "text-gray-500 dark:text-gray-400 mt-0.5 block", children: [
1324
+ /* @__PURE__ */ jsx14("br", {}),
1325
+ /* @__PURE__ */ jsxs12("span", { className: "text-gray-500 dark:text-gray-400 mt-0.5 block", children: [
1426
1326
  labels.currentNameSaved,
1427
1327
  " ",
1428
- /* @__PURE__ */ jsx16("strong", { children: selectedTemplateName || "\u2014" })
1328
+ /* @__PURE__ */ jsx14("strong", { children: selectedTemplateName || "\u2014" })
1429
1329
  ] })
1430
1330
  ] }),
1431
- loadingTemplates && /* @__PURE__ */ jsx16("div", { className: "h-10 rounded-xl bg-gray-100 dark:bg-gray-700 animate-pulse" }),
1432
- !loadingTemplates && !templatesError && /* @__PURE__ */ jsxs13(
1331
+ loadingTemplates && /* @__PURE__ */ jsx14("div", { className: "h-10 rounded-xl bg-gray-100 dark:bg-gray-700 animate-pulse" }),
1332
+ !loadingTemplates && !templatesError && /* @__PURE__ */ jsxs12(
1433
1333
  "select",
1434
1334
  {
1435
1335
  value: selectedTemplateName,
1436
1336
  onChange: (e) => handleSelect(e.target.value),
1437
1337
  className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all",
1438
1338
  children: [
1439
- /* @__PURE__ */ jsx16("option", { value: "", children: labels.selectPlaceholder }),
1440
- templates.map((template) => /* @__PURE__ */ jsxs13("option", { value: template.name, disabled: template.status !== "APPROVED", children: [
1339
+ /* @__PURE__ */ jsx14("option", { value: "", children: labels.selectPlaceholder }),
1340
+ templates.map((template) => /* @__PURE__ */ jsxs12("option", { value: template.name, disabled: template.status !== "APPROVED", children: [
1441
1341
  template.displayName,
1442
1342
  " \xB7 ",
1443
1343
  template.shortId,
@@ -1449,27 +1349,27 @@ function WhatsAppTemplateSettingsForm({
1449
1349
  ]
1450
1350
  }
1451
1351
  ),
1452
- selected?.bodyText && /* @__PURE__ */ jsx16("div", { className: "mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 px-3 py-2 text-xs text-gray-600 dark:text-gray-300 whitespace-pre-wrap", children: selected.bodyText })
1352
+ selected?.bodyText && /* @__PURE__ */ jsx14("div", { className: "mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 px-3 py-2 text-xs text-gray-600 dark:text-gray-300 whitespace-pre-wrap", children: selected.bodyText })
1453
1353
  ] }),
1454
- /* @__PURE__ */ jsxs13("div", { children: [
1455
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between mb-1.5", children: [
1456
- /* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.variablesLabel }),
1457
- /* @__PURE__ */ jsxs13(
1354
+ /* @__PURE__ */ jsxs12("div", { children: [
1355
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between mb-1.5", children: [
1356
+ /* @__PURE__ */ jsx14("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.variablesLabel }),
1357
+ /* @__PURE__ */ jsxs12(
1458
1358
  "button",
1459
1359
  {
1460
1360
  type: "button",
1461
1361
  onClick: () => onVariablesChange([...variables, ""]),
1462
1362
  className: "flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400 hover:underline",
1463
1363
  children: [
1464
- /* @__PURE__ */ jsx16(Plus, { size: 12 }),
1364
+ /* @__PURE__ */ jsx14(Plus, { size: 12 }),
1465
1365
  labels.addVariable
1466
1366
  ]
1467
1367
  }
1468
1368
  )
1469
1369
  ] }),
1470
- availableVariables.length > 0 && /* @__PURE__ */ jsxs13("div", { className: "mb-3 rounded-lg border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700/40 p-2.5", children: [
1471
- /* @__PURE__ */ jsx16("p", { className: "text-xs font-medium text-gray-600 dark:text-gray-300 mb-1.5", children: labels.variablesAvailableTitle }),
1472
- /* @__PURE__ */ jsx16("div", { className: "flex flex-wrap gap-1.5", children: availableVariables.map((available) => /* @__PURE__ */ jsxs13(
1370
+ availableVariables.length > 0 && /* @__PURE__ */ jsxs12("div", { className: "mb-3 rounded-lg border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700/40 p-2.5", children: [
1371
+ /* @__PURE__ */ jsx14("p", { className: "text-xs font-medium text-gray-600 dark:text-gray-300 mb-1.5", children: labels.variablesAvailableTitle }),
1372
+ /* @__PURE__ */ jsx14("div", { className: "flex flex-wrap gap-1.5", children: availableVariables.map((available) => /* @__PURE__ */ jsxs12(
1473
1373
  "button",
1474
1374
  {
1475
1375
  type: "button",
@@ -1477,8 +1377,8 @@ function WhatsAppTemplateSettingsForm({
1477
1377
  title: `Inserir ${available.token}`,
1478
1378
  className: "inline-flex items-center gap-1 rounded-md border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 px-2 py-1 text-xs hover:border-blue-400 dark:hover:border-blue-500 transition-colors",
1479
1379
  children: [
1480
- /* @__PURE__ */ jsx16("code", { className: "text-blue-600 dark:text-blue-300", children: available.token }),
1481
- /* @__PURE__ */ jsxs13("span", { className: "text-gray-400 dark:text-gray-500", children: [
1380
+ /* @__PURE__ */ jsx14("code", { className: "text-blue-600 dark:text-blue-300", children: available.token }),
1381
+ /* @__PURE__ */ jsxs12("span", { className: "text-gray-400 dark:text-gray-500", children: [
1482
1382
  "\xB7 ",
1483
1383
  available.label
1484
1384
  ] })
@@ -1486,13 +1386,13 @@ function WhatsAppTemplateSettingsForm({
1486
1386
  },
1487
1387
  available.token
1488
1388
  )) }),
1489
- /* @__PURE__ */ jsx16("p", { className: "mt-1.5 text-[11px] text-gray-400 dark:text-gray-500", children: labels.variablesAvailableHint })
1389
+ /* @__PURE__ */ jsx14("p", { className: "mt-1.5 text-[11px] text-gray-400 dark:text-gray-500", children: labels.variablesAvailableHint })
1490
1390
  ] }),
1491
- /* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-400 dark:text-gray-500 mb-2", children: labels.variablesMappingHint }),
1492
- variables.length === 0 && /* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic", children: labels.noVariables }),
1493
- /* @__PURE__ */ jsx16("div", { className: "space-y-2", children: variables.map((variable, index) => /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
1494
- /* @__PURE__ */ jsx16("span", { className: "text-xs text-gray-400 dark:text-gray-500 w-6 text-right flex-shrink-0", children: `{{${index + 1}}}` }),
1495
- /* @__PURE__ */ jsx16(
1391
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-gray-400 dark:text-gray-500 mb-2", children: labels.variablesMappingHint }),
1392
+ variables.length === 0 && /* @__PURE__ */ jsx14("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic", children: labels.noVariables }),
1393
+ /* @__PURE__ */ jsx14("div", { className: "space-y-2", children: variables.map((variable, index) => /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1394
+ /* @__PURE__ */ jsx14("span", { className: "text-xs text-gray-400 dark:text-gray-500 w-6 text-right flex-shrink-0", children: `{{${index + 1}}}` }),
1395
+ /* @__PURE__ */ jsx14(
1496
1396
  "input",
1497
1397
  {
1498
1398
  type: "text",
@@ -1502,27 +1402,27 @@ function WhatsAppTemplateSettingsForm({
1502
1402
  className: "flex-1 border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all placeholder:text-gray-400 dark:placeholder:text-gray-500"
1503
1403
  }
1504
1404
  ),
1505
- /* @__PURE__ */ jsx16(
1405
+ /* @__PURE__ */ jsx14(
1506
1406
  "button",
1507
1407
  {
1508
1408
  type: "button",
1509
1409
  onClick: () => removeVariable(index),
1510
1410
  className: "text-gray-400 hover:text-red-500 dark:hover:text-red-400 transition-colors flex-shrink-0",
1511
1411
  title: labels.removeVariable,
1512
- children: /* @__PURE__ */ jsx16(Trash2, { size: 14 })
1412
+ children: /* @__PURE__ */ jsx14(Trash2, { size: 14 })
1513
1413
  }
1514
1414
  )
1515
1415
  ] }, index)) })
1516
1416
  ] }),
1517
- saveSuccess && /* @__PURE__ */ jsx16("div", { className: "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 rounded-xl px-4 py-3 text-sm text-green-700 dark:text-green-400", children: labels.saveSuccess }),
1518
- /* @__PURE__ */ jsx16("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs13(
1417
+ saveSuccess && /* @__PURE__ */ jsx14("div", { className: "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 rounded-xl px-4 py-3 text-sm text-green-700 dark:text-green-400", children: labels.saveSuccess }),
1418
+ /* @__PURE__ */ jsx14("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs12(
1519
1419
  "button",
1520
1420
  {
1521
1421
  type: "submit",
1522
1422
  disabled: saving || !selectedTemplateName.trim(),
1523
1423
  className: "flex items-center gap-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-semibold px-5 py-2.5 rounded-xl transition-colors text-sm",
1524
1424
  children: [
1525
- saving ? /* @__PURE__ */ jsx16("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx16(Save, { size: 14 }),
1425
+ saving ? /* @__PURE__ */ jsx14("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx14(Save, { size: 14 }),
1526
1426
  saving ? labels.saving : labels.save
1527
1427
  ]
1528
1428
  }
@@ -1533,12 +1433,13 @@ function WhatsAppTemplateSettingsForm({
1533
1433
 
1534
1434
  // src/settings/WhatsAppCreateTemplateForm.tsx
1535
1435
  import { SendHorizonal } from "lucide-react";
1536
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
1537
- var DEFAULT_LABELS2 = {
1436
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1437
+ var DEFAULT_LABELS3 = {
1538
1438
  sectionTitle: "Criar novo template",
1539
1439
  sectionDescription: "Envia um template para aprova\xE7\xE3o da Meta.",
1540
1440
  nameLabel: "Nome do template",
1541
1441
  nameHint: "Somente letras min\xFAsculas, n\xFAmeros e underscore.",
1442
+ namePlaceholder: "reengajamento_cliente",
1542
1443
  categoryLabel: "Categoria",
1543
1444
  languageLabel: "Idioma",
1544
1445
  headerLabel: "Cabe\xE7alho",
@@ -1584,82 +1485,82 @@ function WhatsAppCreateTemplateForm({
1584
1485
  labels: labelsOverride,
1585
1486
  variableExamples = DEFAULT_VARIABLE_EXAMPLES
1586
1487
  }) {
1587
- const labels = { ...DEFAULT_LABELS2, ...labelsOverride };
1488
+ const labels = { ...DEFAULT_LABELS3, ...labelsOverride };
1588
1489
  const detectedVariables = detectVariables(value.bodyText);
1589
1490
  function set(key, next) {
1590
1491
  onChange({ ...value, [key]: next });
1591
1492
  }
1592
- return /* @__PURE__ */ jsxs14("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1593
- /* @__PURE__ */ jsxs14("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
1594
- /* @__PURE__ */ jsx17("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }),
1595
- /* @__PURE__ */ jsx17("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
1493
+ return /* @__PURE__ */ jsxs13("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1494
+ /* @__PURE__ */ jsxs13("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
1495
+ /* @__PURE__ */ jsx15("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }),
1496
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
1596
1497
  ] }),
1597
- /* @__PURE__ */ jsxs14("form", { onSubmit, className: "p-6 space-y-4", children: [
1598
- /* @__PURE__ */ jsxs14("div", { children: [
1599
- /* @__PURE__ */ jsx17("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.nameLabel }),
1600
- /* @__PURE__ */ jsx17("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.nameHint }),
1601
- /* @__PURE__ */ jsx17(
1498
+ /* @__PURE__ */ jsxs13("form", { onSubmit, className: "p-6 space-y-4", children: [
1499
+ /* @__PURE__ */ jsxs13("div", { children: [
1500
+ /* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.nameLabel }),
1501
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.nameHint }),
1502
+ /* @__PURE__ */ jsx15(
1602
1503
  "input",
1603
1504
  {
1604
1505
  type: "text",
1605
1506
  value: value.name,
1606
1507
  onChange: (e) => set("name", e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, "_")),
1607
- placeholder: "reengajamento_cliente",
1508
+ placeholder: labels.namePlaceholder,
1608
1509
  className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all",
1609
1510
  required: true
1610
1511
  }
1611
1512
  )
1612
1513
  ] }),
1613
- /* @__PURE__ */ jsxs14("div", { className: "grid grid-cols-2 gap-3", children: [
1614
- /* @__PURE__ */ jsxs14("div", { children: [
1615
- /* @__PURE__ */ jsx17("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.categoryLabel }),
1616
- /* @__PURE__ */ jsxs14(
1514
+ /* @__PURE__ */ jsxs13("div", { className: "grid grid-cols-2 gap-3", children: [
1515
+ /* @__PURE__ */ jsxs13("div", { children: [
1516
+ /* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.categoryLabel }),
1517
+ /* @__PURE__ */ jsxs13(
1617
1518
  "select",
1618
1519
  {
1619
1520
  value: value.category,
1620
1521
  onChange: (e) => set("category", e.target.value),
1621
1522
  className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all",
1622
1523
  children: [
1623
- /* @__PURE__ */ jsx17("option", { value: "UTILITY", children: "UTILITY (Transacional)" }),
1624
- /* @__PURE__ */ jsx17("option", { value: "MARKETING", children: "MARKETING (Promocional)" })
1524
+ /* @__PURE__ */ jsx15("option", { value: "UTILITY", children: "UTILITY (Transacional)" }),
1525
+ /* @__PURE__ */ jsx15("option", { value: "MARKETING", children: "MARKETING (Promocional)" })
1625
1526
  ]
1626
1527
  }
1627
1528
  )
1628
1529
  ] }),
1629
- /* @__PURE__ */ jsxs14("div", { children: [
1630
- /* @__PURE__ */ jsx17("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.languageLabel }),
1631
- /* @__PURE__ */ jsxs14(
1530
+ /* @__PURE__ */ jsxs13("div", { children: [
1531
+ /* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.languageLabel }),
1532
+ /* @__PURE__ */ jsxs13(
1632
1533
  "select",
1633
1534
  {
1634
1535
  value: value.language,
1635
1536
  onChange: (e) => set("language", e.target.value),
1636
1537
  className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all",
1637
1538
  children: [
1638
- /* @__PURE__ */ jsx17("option", { value: "pt_BR", children: "Portugu\xEAs (Brasil)" }),
1639
- /* @__PURE__ */ jsx17("option", { value: "en_US", children: "Ingl\xEAs (EUA)" }),
1640
- /* @__PURE__ */ jsx17("option", { value: "es_ES", children: "Espanhol" })
1539
+ /* @__PURE__ */ jsx15("option", { value: "pt_BR", children: "Portugu\xEAs (Brasil)" }),
1540
+ /* @__PURE__ */ jsx15("option", { value: "en_US", children: "Ingl\xEAs (EUA)" }),
1541
+ /* @__PURE__ */ jsx15("option", { value: "es_ES", children: "Espanhol" })
1641
1542
  ]
1642
1543
  }
1643
1544
  )
1644
1545
  ] })
1645
1546
  ] }),
1646
- /* @__PURE__ */ jsxs14("div", { children: [
1647
- /* @__PURE__ */ jsx17("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.headerLabel }),
1648
- /* @__PURE__ */ jsx17("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.headerHint }),
1649
- /* @__PURE__ */ jsxs14("div", { className: "flex gap-2", children: [
1650
- /* @__PURE__ */ jsxs14(
1547
+ /* @__PURE__ */ jsxs13("div", { children: [
1548
+ /* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.headerLabel }),
1549
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.headerHint }),
1550
+ /* @__PURE__ */ jsxs13("div", { className: "flex gap-2", children: [
1551
+ /* @__PURE__ */ jsxs13(
1651
1552
  "select",
1652
1553
  {
1653
1554
  value: value.headerType,
1654
1555
  onChange: (e) => set("headerType", e.target.value),
1655
1556
  className: "border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 transition-all",
1656
1557
  children: [
1657
- /* @__PURE__ */ jsx17("option", { value: "NONE", children: labels.headerNone }),
1658
- /* @__PURE__ */ jsx17("option", { value: "TEXT", children: labels.headerText })
1558
+ /* @__PURE__ */ jsx15("option", { value: "NONE", children: labels.headerNone }),
1559
+ /* @__PURE__ */ jsx15("option", { value: "TEXT", children: labels.headerText })
1659
1560
  ]
1660
1561
  }
1661
1562
  ),
1662
- value.headerType === "TEXT" && /* @__PURE__ */ jsx17(
1563
+ value.headerType === "TEXT" && /* @__PURE__ */ jsx15(
1663
1564
  "input",
1664
1565
  {
1665
1566
  type: "text",
@@ -1672,10 +1573,10 @@ function WhatsAppCreateTemplateForm({
1672
1573
  )
1673
1574
  ] })
1674
1575
  ] }),
1675
- /* @__PURE__ */ jsxs14("div", { children: [
1676
- /* @__PURE__ */ jsx17("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.bodyLabel }),
1677
- /* @__PURE__ */ jsx17("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.bodyHint }),
1678
- /* @__PURE__ */ jsx17(
1576
+ /* @__PURE__ */ jsxs13("div", { children: [
1577
+ /* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.bodyLabel }),
1578
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.bodyHint }),
1579
+ /* @__PURE__ */ jsx15(
1679
1580
  "textarea",
1680
1581
  {
1681
1582
  value: value.bodyText,
@@ -1686,26 +1587,26 @@ function WhatsAppCreateTemplateForm({
1686
1587
  required: true
1687
1588
  }
1688
1589
  ),
1689
- detectedVariables.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 px-3 py-2", children: [
1690
- /* @__PURE__ */ jsx17("p", { className: "font-medium text-gray-500 dark:text-gray-400 mb-1.5 uppercase tracking-wide text-xs", children: labels.detectedVariables }),
1691
- /* @__PURE__ */ jsx17("div", { className: "flex flex-wrap gap-2", children: detectedVariables.map((num) => /* @__PURE__ */ jsxs14("span", { className: "inline-flex items-center gap-1 text-xs", children: [
1692
- /* @__PURE__ */ jsx17("code", { className: "bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300 px-1.5 py-0.5 rounded font-mono", children: `{{${num}}}` }),
1693
- /* @__PURE__ */ jsxs14("span", { className: "text-gray-400 dark:text-gray-500", children: [
1590
+ detectedVariables.length > 0 && /* @__PURE__ */ jsxs13("div", { className: "mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 px-3 py-2", children: [
1591
+ /* @__PURE__ */ jsx15("p", { className: "font-medium text-gray-500 dark:text-gray-400 mb-1.5 uppercase tracking-wide text-xs", children: labels.detectedVariables }),
1592
+ /* @__PURE__ */ jsx15("div", { className: "flex flex-wrap gap-2", children: detectedVariables.map((num) => /* @__PURE__ */ jsxs13("span", { className: "inline-flex items-center gap-1 text-xs", children: [
1593
+ /* @__PURE__ */ jsx15("code", { className: "bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300 px-1.5 py-0.5 rounded font-mono", children: `{{${num}}}` }),
1594
+ /* @__PURE__ */ jsxs13("span", { className: "text-gray-400 dark:text-gray-500", children: [
1694
1595
  "= ",
1695
1596
  variableExamples[Number(num) - 1] ?? labels.variableLabel(Number(num))
1696
1597
  ] })
1697
1598
  ] }, num)) }),
1698
- /* @__PURE__ */ jsxs14("p", { className: "text-gray-400 dark:text-gray-500 mt-1.5 text-xs", children: [
1599
+ /* @__PURE__ */ jsxs13("p", { className: "text-gray-400 dark:text-gray-500 mt-1.5 text-xs", children: [
1699
1600
  labels.configureHintPrefix,
1700
- /* @__PURE__ */ jsx17("strong", { children: labels.configureHintLink }),
1601
+ /* @__PURE__ */ jsx15("strong", { children: labels.configureHintLink }),
1701
1602
  labels.configureHintSuffix
1702
1603
  ] })
1703
1604
  ] })
1704
1605
  ] }),
1705
- /* @__PURE__ */ jsxs14("div", { children: [
1706
- /* @__PURE__ */ jsx17("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.footerLabel }),
1707
- /* @__PURE__ */ jsx17("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.footerHint }),
1708
- /* @__PURE__ */ jsx17(
1606
+ /* @__PURE__ */ jsxs13("div", { children: [
1607
+ /* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.footerLabel }),
1608
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.footerHint }),
1609
+ /* @__PURE__ */ jsx15(
1709
1610
  "input",
1710
1611
  {
1711
1612
  type: "text",
@@ -1717,48 +1618,48 @@ function WhatsAppCreateTemplateForm({
1717
1618
  }
1718
1619
  )
1719
1620
  ] }),
1720
- /* @__PURE__ */ jsxs14("div", { children: [
1721
- /* @__PURE__ */ jsx17("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 block", children: labels.previewLabel }),
1722
- /* @__PURE__ */ jsxs14("div", { className: "rounded-2xl bg-[#e5ddd5] dark:bg-[#1a1a2e] border border-gray-300 dark:border-gray-600 overflow-hidden shadow-inner", children: [
1723
- /* @__PURE__ */ jsxs14("div", { className: "bg-[#075e54] px-4 py-2.5 flex items-center gap-2", children: [
1724
- /* @__PURE__ */ jsx17("div", { className: "w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-xs font-bold", children: previewCompanyName.slice(0, 2).toUpperCase() }),
1725
- /* @__PURE__ */ jsxs14("div", { children: [
1726
- /* @__PURE__ */ jsx17("p", { className: "text-white text-xs font-semibold leading-tight", children: previewCompanyName }),
1727
- /* @__PURE__ */ jsx17("p", { className: "text-white/60 text-xs", children: labels.previewOnline })
1621
+ /* @__PURE__ */ jsxs13("div", { children: [
1622
+ /* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 block", children: labels.previewLabel }),
1623
+ /* @__PURE__ */ jsxs13("div", { className: "rounded-2xl bg-[#e5ddd5] dark:bg-[#1a1a2e] border border-gray-300 dark:border-gray-600 overflow-hidden shadow-inner", children: [
1624
+ /* @__PURE__ */ jsxs13("div", { className: "bg-[#075e54] px-4 py-2.5 flex items-center gap-2", children: [
1625
+ /* @__PURE__ */ jsx15("div", { className: "w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-xs font-bold", children: previewCompanyName.slice(0, 2).toUpperCase() }),
1626
+ /* @__PURE__ */ jsxs13("div", { children: [
1627
+ /* @__PURE__ */ jsx15("p", { className: "text-white text-xs font-semibold leading-tight", children: previewCompanyName }),
1628
+ /* @__PURE__ */ jsx15("p", { className: "text-white/60 text-xs", children: labels.previewOnline })
1728
1629
  ] })
1729
1630
  ] }),
1730
- /* @__PURE__ */ jsxs14("div", { className: "px-3 py-4 space-y-3", style: { minHeight: "120px" }, children: [
1731
- /* @__PURE__ */ jsx17("div", { className: "flex justify-start", style: { maxWidth: "85%" }, children: /* @__PURE__ */ jsxs14("div", { className: "bg-white dark:bg-gray-700 rounded-lg rounded-tl-none px-3 py-2 shadow-sm", children: [
1732
- /* @__PURE__ */ jsx17("p", { className: "text-gray-500 dark:text-gray-400 leading-tight text-sm", children: labels.previewDescription }),
1733
- /* @__PURE__ */ jsx17("p", { className: "text-gray-400 dark:text-gray-500 mt-1 text-right text-[9px]", children: "12:00" })
1631
+ /* @__PURE__ */ jsxs13("div", { className: "px-3 py-4 space-y-3", style: { minHeight: "120px" }, children: [
1632
+ /* @__PURE__ */ jsx15("div", { className: "flex justify-start", style: { maxWidth: "85%" }, children: /* @__PURE__ */ jsxs13("div", { className: "bg-white dark:bg-gray-700 rounded-lg rounded-tl-none px-3 py-2 shadow-sm", children: [
1633
+ /* @__PURE__ */ jsx15("p", { className: "text-gray-500 dark:text-gray-400 leading-tight text-sm", children: labels.previewDescription }),
1634
+ /* @__PURE__ */ jsx15("p", { className: "text-gray-400 dark:text-gray-500 mt-1 text-right text-[9px]", children: "12:00" })
1734
1635
  ] }) }),
1735
- /* @__PURE__ */ jsx17("div", { className: "flex justify-end ml-auto", style: { maxWidth: "85%" }, children: /* @__PURE__ */ jsxs14("div", { className: "bg-[#dcf8c6] dark:bg-[#1b5e20] rounded-lg rounded-tr-none px-3 py-2 shadow-sm", children: [
1736
- value.headerType === "TEXT" && value.headerText && /* @__PURE__ */ jsx17("p", { className: "text-xs font-bold text-gray-700 dark:text-gray-200 mb-1", children: fillPreviewTokens(value.headerText) || labels.previewHeaderFallback }),
1737
- /* @__PURE__ */ jsx17("p", { className: "text-sm text-gray-800 dark:text-gray-100 leading-relaxed", children: value.bodyText ? fillPreviewTokens(value.bodyText) : /* @__PURE__ */ jsx17("span", { className: "text-gray-400 italic", children: labels.previewBodyPlaceholder }) }),
1738
- value.footerText && /* @__PURE__ */ jsx17("p", { className: "text-gray-400 dark:text-gray-400 mt-1 text-xs", children: value.footerText }),
1739
- /* @__PURE__ */ jsx17("p", { className: "text-gray-400 dark:text-gray-400 mt-1 text-right text-[9px]", children: "12:01 \u2713" })
1636
+ /* @__PURE__ */ jsx15("div", { className: "flex justify-end ml-auto", style: { maxWidth: "85%" }, children: /* @__PURE__ */ jsxs13("div", { className: "bg-[#dcf8c6] dark:bg-[#1b5e20] rounded-lg rounded-tr-none px-3 py-2 shadow-sm", children: [
1637
+ value.headerType === "TEXT" && value.headerText && /* @__PURE__ */ jsx15("p", { className: "text-xs font-bold text-gray-700 dark:text-gray-200 mb-1", children: fillPreviewTokens(value.headerText) || labels.previewHeaderFallback }),
1638
+ /* @__PURE__ */ jsx15("p", { className: "text-sm text-gray-800 dark:text-gray-100 leading-relaxed", children: value.bodyText ? fillPreviewTokens(value.bodyText) : /* @__PURE__ */ jsx15("span", { className: "text-gray-400 italic", children: labels.previewBodyPlaceholder }) }),
1639
+ value.footerText && /* @__PURE__ */ jsx15("p", { className: "text-gray-400 dark:text-gray-400 mt-1 text-xs", children: value.footerText }),
1640
+ /* @__PURE__ */ jsx15("p", { className: "text-gray-400 dark:text-gray-400 mt-1 text-right text-[9px]", children: "12:01 \u2713" })
1740
1641
  ] }) })
1741
1642
  ] })
1742
1643
  ] })
1743
1644
  ] }),
1744
- result && /* @__PURE__ */ jsxs14(
1645
+ result && /* @__PURE__ */ jsxs13(
1745
1646
  "div",
1746
1647
  {
1747
1648
  className: `rounded-xl px-4 py-3 text-sm ${result.ok ? "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 text-green-700 dark:text-green-400" : "bg-red-50 dark:bg-red-950/40 border border-red-200 dark:border-red-800 text-red-700 dark:text-red-400"}`,
1748
1649
  children: [
1749
1650
  result.message,
1750
- result.ok && result.status && /* @__PURE__ */ jsx17("p", { className: "text-xs mt-1 opacity-75", children: labels.successStatus(result.status) })
1651
+ result.ok && result.status && /* @__PURE__ */ jsx15("p", { className: "text-xs mt-1 opacity-75", children: labels.successStatus(result.status) })
1751
1652
  ]
1752
1653
  }
1753
1654
  ),
1754
- /* @__PURE__ */ jsx17("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs14(
1655
+ /* @__PURE__ */ jsx15("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs13(
1755
1656
  "button",
1756
1657
  {
1757
1658
  type: "submit",
1758
1659
  disabled: submitting || !value.name || !value.bodyText,
1759
1660
  className: "flex items-center gap-2 bg-emerald-600 hover:bg-emerald-700 disabled:bg-emerald-400 text-white font-semibold px-5 py-2.5 rounded-xl transition-colors text-sm",
1760
1661
  children: [
1761
- submitting ? /* @__PURE__ */ jsx17("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx17(SendHorizonal, { size: 14 }),
1662
+ submitting ? /* @__PURE__ */ jsx15("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx15(SendHorizonal, { size: 14 }),
1762
1663
  submitting ? labels.sending : labels.sendForApproval
1763
1664
  ]
1764
1665
  }
@@ -1769,8 +1670,8 @@ function WhatsAppCreateTemplateForm({
1769
1670
 
1770
1671
  // src/settings/WelcomeFarewellForm.tsx
1771
1672
  import { LogOut, Mail, Save as Save2 } from "lucide-react";
1772
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1773
- var DEFAULT_LABELS3 = {
1673
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1674
+ var DEFAULT_LABELS4 = {
1774
1675
  sectionTitle: "Boas-vindas e encerramento",
1775
1676
  welcomeMessage: "Mensagem de boas-vindas",
1776
1677
  welcomeMessagePlaceholder: "Ol\xE1! Sou o assistente virtual da {empresa}...",
@@ -1796,16 +1697,16 @@ function WelcomeFarewellForm({
1796
1697
  farewellPlaceholders = DEFAULT_FAREWELL_PLACEHOLDERS,
1797
1698
  labels: labelsOverride
1798
1699
  }) {
1799
- const labels = { ...DEFAULT_LABELS3, ...labelsOverride };
1800
- return /* @__PURE__ */ jsxs15("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1801
- /* @__PURE__ */ jsx18("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: /* @__PURE__ */ jsx18("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }) }),
1802
- /* @__PURE__ */ jsxs15("form", { onSubmit: onSave, className: "p-6 space-y-5", children: [
1803
- /* @__PURE__ */ jsxs15("div", { children: [
1804
- /* @__PURE__ */ jsxs15("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5 flex items-center gap-1.5", children: [
1805
- /* @__PURE__ */ jsx18(Mail, { size: 13, className: "text-blue-600 dark:text-blue-400" }),
1700
+ const labels = { ...DEFAULT_LABELS4, ...labelsOverride };
1701
+ return /* @__PURE__ */ jsxs14("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1702
+ /* @__PURE__ */ jsx16("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: /* @__PURE__ */ jsx16("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }) }),
1703
+ /* @__PURE__ */ jsxs14("form", { onSubmit: onSave, className: "p-6 space-y-5", children: [
1704
+ /* @__PURE__ */ jsxs14("div", { children: [
1705
+ /* @__PURE__ */ jsxs14("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5 flex items-center gap-1.5", children: [
1706
+ /* @__PURE__ */ jsx16(Mail, { size: 13, className: "text-blue-600 dark:text-blue-400" }),
1806
1707
  labels.welcomeMessage
1807
1708
  ] }),
1808
- /* @__PURE__ */ jsx18(
1709
+ /* @__PURE__ */ jsx16(
1809
1710
  WhatsAppMessageEditor,
1810
1711
  {
1811
1712
  value: welcomeMessage,
@@ -1814,14 +1715,14 @@ function WelcomeFarewellForm({
1814
1715
  placeholders: welcomePlaceholders
1815
1716
  }
1816
1717
  ),
1817
- /* @__PURE__ */ jsx18("p", { className: "mt-1.5 text-xs text-gray-500 dark:text-gray-400", children: labels.welcomeMessageHint })
1718
+ /* @__PURE__ */ jsx16("p", { className: "mt-1.5 text-xs text-gray-500 dark:text-gray-400", children: labels.welcomeMessageHint })
1818
1719
  ] }),
1819
- /* @__PURE__ */ jsxs15("div", { children: [
1820
- /* @__PURE__ */ jsxs15("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5 flex items-center gap-1.5", children: [
1821
- /* @__PURE__ */ jsx18(LogOut, { size: 13, className: "text-blue-600 dark:text-blue-400" }),
1720
+ /* @__PURE__ */ jsxs14("div", { children: [
1721
+ /* @__PURE__ */ jsxs14("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5 flex items-center gap-1.5", children: [
1722
+ /* @__PURE__ */ jsx16(LogOut, { size: 13, className: "text-blue-600 dark:text-blue-400" }),
1822
1723
  labels.farewellMessage
1823
1724
  ] }),
1824
- /* @__PURE__ */ jsx18(
1725
+ /* @__PURE__ */ jsx16(
1825
1726
  WhatsAppMessageEditor,
1826
1727
  {
1827
1728
  value: farewellMessage,
@@ -1830,17 +1731,17 @@ function WelcomeFarewellForm({
1830
1731
  placeholders: farewellPlaceholders
1831
1732
  }
1832
1733
  ),
1833
- /* @__PURE__ */ jsx18("p", { className: "mt-1.5 text-xs text-gray-500 dark:text-gray-400", children: labels.farewellMessageHint })
1734
+ /* @__PURE__ */ jsx16("p", { className: "mt-1.5 text-xs text-gray-500 dark:text-gray-400", children: labels.farewellMessageHint })
1834
1735
  ] }),
1835
- saveSuccess && /* @__PURE__ */ jsx18("div", { className: "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 rounded-xl px-4 py-3 text-sm text-green-700 dark:text-green-400", children: labels.saveSuccess }),
1836
- /* @__PURE__ */ jsx18("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs15(
1736
+ saveSuccess && /* @__PURE__ */ jsx16("div", { className: "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 rounded-xl px-4 py-3 text-sm text-green-700 dark:text-green-400", children: labels.saveSuccess }),
1737
+ /* @__PURE__ */ jsx16("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs14(
1837
1738
  "button",
1838
1739
  {
1839
1740
  type: "submit",
1840
1741
  disabled: saving,
1841
1742
  className: "flex items-center gap-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-semibold px-5 py-2.5 rounded-xl transition-colors text-sm",
1842
1743
  children: [
1843
- saving ? /* @__PURE__ */ jsx18("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx18(Save2, { size: 14 }),
1744
+ saving ? /* @__PURE__ */ jsx16("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx16(Save2, { size: 14 }),
1844
1745
  saving ? labels.saving : labels.save
1845
1746
  ]
1846
1747
  }
@@ -1850,8 +1751,8 @@ function WelcomeFarewellForm({
1850
1751
  }
1851
1752
 
1852
1753
  // src/settings/WhatsAppTemplatesSettings.tsx
1853
- import { useState as useState10 } from "react";
1854
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1754
+ import { useState as useState8 } from "react";
1755
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1855
1756
  var TEMPLATE_SETTINGS_TAB = {
1856
1757
  SELECT: "select",
1857
1758
  CREATE: "create"
@@ -1866,10 +1767,10 @@ function WhatsAppTemplatesSettings({
1866
1767
  ...settingsProps
1867
1768
  }) {
1868
1769
  const labels = { ...DEFAULT_TEMPLATES_SETTINGS_LABELS, ...labelsOverride };
1869
- const [tab, setTab] = useState10(TEMPLATE_SETTINGS_TAB.SELECT);
1870
- return /* @__PURE__ */ jsxs16("div", { className: "space-y-4", children: [
1871
- /* @__PURE__ */ jsxs16("nav", { className: "flex gap-1 border-b", role: "tablist", children: [
1872
- /* @__PURE__ */ jsx19(
1770
+ const [tab, setTab] = useState8(TEMPLATE_SETTINGS_TAB.SELECT);
1771
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
1772
+ /* @__PURE__ */ jsxs15("nav", { className: "flex gap-1 border-b", role: "tablist", children: [
1773
+ /* @__PURE__ */ jsx17(
1873
1774
  "button",
1874
1775
  {
1875
1776
  type: "button",
@@ -1880,7 +1781,7 @@ function WhatsAppTemplatesSettings({
1880
1781
  children: labels.selectTab
1881
1782
  }
1882
1783
  ),
1883
- create ? /* @__PURE__ */ jsx19(
1784
+ create ? /* @__PURE__ */ jsx17(
1884
1785
  "button",
1885
1786
  {
1886
1787
  type: "button",
@@ -1892,14 +1793,14 @@ function WhatsAppTemplatesSettings({
1892
1793
  }
1893
1794
  ) : null
1894
1795
  ] }),
1895
- tab === TEMPLATE_SETTINGS_TAB.SELECT ? /* @__PURE__ */ jsx19(WhatsAppTemplateSettingsForm, { ...settingsProps }) : create ? /* @__PURE__ */ jsx19(WhatsAppCreateTemplateForm, { ...create }) : null
1796
+ tab === TEMPLATE_SETTINGS_TAB.SELECT ? /* @__PURE__ */ jsx17(WhatsAppTemplateSettingsForm, { ...settingsProps }) : create ? /* @__PURE__ */ jsx17(WhatsAppCreateTemplateForm, { ...create }) : null
1896
1797
  ] });
1897
1798
  }
1898
1799
 
1899
1800
  // src/settings/TopicsForm.tsx
1900
1801
  import { Megaphone, Save as Save3 } from "lucide-react";
1901
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1902
- var DEFAULT_LABELS4 = {
1802
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1803
+ var DEFAULT_LABELS5 = {
1903
1804
  sectionTitle: "T\xF3picos intermedi\xE1rios",
1904
1805
  sectionDescription: "Mensagens autom\xE1ticas para assuntos espec\xEDficos, disparadas quando o cliente demonstra interesse.",
1905
1806
  messagePlaceholder: "Digite a mensagem autom\xE1tica para este t\xF3pico...",
@@ -1915,20 +1816,20 @@ function TopicsForm({
1915
1816
  saveSuccess = false,
1916
1817
  labels: labelsOverride
1917
1818
  }) {
1918
- const labels = { ...DEFAULT_LABELS4, ...labelsOverride };
1919
- return /* @__PURE__ */ jsxs17("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1920
- /* @__PURE__ */ jsxs17("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
1921
- /* @__PURE__ */ jsxs17("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2", children: [
1922
- /* @__PURE__ */ jsx20(Megaphone, { size: 16, className: "text-orange-600 dark:text-orange-400" }),
1819
+ const labels = { ...DEFAULT_LABELS5, ...labelsOverride };
1820
+ return /* @__PURE__ */ jsxs16("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
1821
+ /* @__PURE__ */ jsxs16("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
1822
+ /* @__PURE__ */ jsxs16("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2", children: [
1823
+ /* @__PURE__ */ jsx18(Megaphone, { size: 16, className: "text-orange-600 dark:text-orange-400" }),
1923
1824
  labels.sectionTitle
1924
1825
  ] }),
1925
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
1826
+ /* @__PURE__ */ jsx18("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
1926
1827
  ] }),
1927
- /* @__PURE__ */ jsxs17("form", { onSubmit: onSave, className: "p-6 space-y-6", children: [
1928
- topics.map((topic) => /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
1929
- /* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-4", children: [
1930
- /* @__PURE__ */ jsx20("div", { className: "flex-1", children: /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: topic.label }) }),
1931
- /* @__PURE__ */ jsx20(
1828
+ /* @__PURE__ */ jsxs16("form", { onSubmit: onSave, className: "p-6 space-y-6", children: [
1829
+ topics.map((topic) => /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
1830
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-4", children: [
1831
+ /* @__PURE__ */ jsx18("div", { className: "flex-1", children: /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: topic.label }) }),
1832
+ /* @__PURE__ */ jsx18(
1932
1833
  "button",
1933
1834
  {
1934
1835
  type: "button",
@@ -1936,7 +1837,7 @@ function TopicsForm({
1936
1837
  className: `relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${topic.enabled ? "bg-blue-600 dark:bg-blue-500" : "bg-gray-200 dark:bg-gray-700"}`,
1937
1838
  role: "switch",
1938
1839
  "aria-checked": topic.enabled,
1939
- children: /* @__PURE__ */ jsx20(
1840
+ children: /* @__PURE__ */ jsx18(
1940
1841
  "span",
1941
1842
  {
1942
1843
  className: `pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${topic.enabled ? "translate-x-5" : "translate-x-0"}`
@@ -1945,7 +1846,7 @@ function TopicsForm({
1945
1846
  }
1946
1847
  )
1947
1848
  ] }),
1948
- /* @__PURE__ */ jsx20(
1849
+ /* @__PURE__ */ jsx18(
1949
1850
  "textarea",
1950
1851
  {
1951
1852
  value: topic.message,
@@ -1957,27 +1858,27 @@ function TopicsForm({
1957
1858
  }
1958
1859
  )
1959
1860
  ] }, topic.key)),
1960
- /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-3", children: [
1961
- /* @__PURE__ */ jsxs17(
1861
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-3", children: [
1862
+ /* @__PURE__ */ jsxs16(
1962
1863
  "button",
1963
1864
  {
1964
1865
  type: "submit",
1965
1866
  disabled: saving,
1966
1867
  className: "inline-flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-50",
1967
1868
  children: [
1968
- /* @__PURE__ */ jsx20(Save3, { size: 14 }),
1869
+ /* @__PURE__ */ jsx18(Save3, { size: 14 }),
1969
1870
  labels.saveButton
1970
1871
  ]
1971
1872
  }
1972
1873
  ),
1973
- saveSuccess && /* @__PURE__ */ jsx20("span", { className: "text-sm text-green-600 dark:text-green-400", children: labels.saveSuccess })
1874
+ saveSuccess && /* @__PURE__ */ jsx18("span", { className: "text-sm text-green-600 dark:text-green-400", children: labels.saveSuccess })
1974
1875
  ] })
1975
1876
  ] })
1976
1877
  ] });
1977
1878
  }
1978
1879
 
1979
1880
  // src/hooks/useConversationMessages.ts
1980
- import { useCallback as useCallback5 } from "react";
1881
+ import { useCallback as useCallback4 } from "react";
1981
1882
  function useConversationMessages(conversationId, params) {
1982
1883
  const context = useConversations();
1983
1884
  if (!context) {
@@ -1988,7 +1889,7 @@ function useConversationMessages(conversationId, params) {
1988
1889
  () => api.fetchMessages(conversationId, params),
1989
1890
  [conversationId, params?.limit, params?.before]
1990
1891
  );
1991
- const sendMessage = useCallback5(
1892
+ const sendMessage = useCallback4(
1992
1893
  async (text) => {
1993
1894
  const message = await api.sendMessage(conversationId, text);
1994
1895
  await refetch();
@@ -1996,7 +1897,7 @@ function useConversationMessages(conversationId, params) {
1996
1897
  },
1997
1898
  [api, conversationId, refetch]
1998
1899
  );
1999
- const sendMedia = useCallback5(
1900
+ const sendMedia = useCallback4(
2000
1901
  async (mediaData) => {
2001
1902
  const message = await api.sendMedia(conversationId, mediaData);
2002
1903
  await refetch();
@@ -2004,14 +1905,14 @@ function useConversationMessages(conversationId, params) {
2004
1905
  },
2005
1906
  [api, conversationId, refetch]
2006
1907
  );
2007
- const sendTemplate = useCallback5(
1908
+ const sendTemplate = useCallback4(
2008
1909
  async (templateData) => {
2009
1910
  await api.sendTemplate(conversationId, templateData);
2010
1911
  await refetch();
2011
1912
  },
2012
1913
  [api, conversationId, refetch]
2013
1914
  );
2014
- const markRead = useCallback5(() => api.markRead(conversationId), [api, conversationId]);
1915
+ const markRead = useCallback4(() => api.markRead(conversationId), [api, conversationId]);
2015
1916
  return { messages: data ?? [], loading, error, refetch, sendMessage, sendMedia, sendTemplate, markRead };
2016
1917
  }
2017
1918
 
@@ -2022,11 +1923,15 @@ function useConversationList(params) {
2022
1923
  throw new Error("useConversationList requires an ancestor <ConversationsProvider>");
2023
1924
  }
2024
1925
  const { api } = context;
1926
+ const filtersKey = JSON.stringify(params?.filters ?? {});
2025
1927
  const { data, loading, error, refetch } = useAsyncResource(
2026
1928
  () => api.fetchConversations(params),
2027
- [params?.page, params?.limit, params?.waitingHuman, params?.search]
1929
+ [params?.page, params?.limit, params?.waitingHuman, params?.search, filtersKey]
2028
1930
  );
2029
- return { conversations: data ?? [], loading, error, refetch };
1931
+ if (data === void 0) {
1932
+ return { conversations: [], total: 0, loading, error, refetch };
1933
+ }
1934
+ return { conversations: conversationsOf(data), total: totalOf(data), loading, error, refetch };
2030
1935
  }
2031
1936
 
2032
1937
  // src/hooks/useConversationContext.ts
@@ -2041,12 +1946,12 @@ function useConversationContext(conversationId) {
2041
1946
  }
2042
1947
 
2043
1948
  // src/hooks/useConversationRealtime.ts
2044
- import { useEffect as useEffect6, useRef as useRef5 } from "react";
1949
+ import { useEffect as useEffect5, useRef as useRef4 } from "react";
2045
1950
  function useConversationRealtime(conversationId, onEvent) {
2046
1951
  const context = useConversations();
2047
- const onEventRef = useRef5(onEvent);
1952
+ const onEventRef = useRef4(onEvent);
2048
1953
  onEventRef.current = onEvent;
2049
- useEffect6(() => {
1954
+ useEffect5(() => {
2050
1955
  if (!context || !conversationId) return;
2051
1956
  const source = context.sse.connectConversationStream(conversationId);
2052
1957
  const handler = (event) => onEventRef.current(event);
@@ -2059,9 +1964,9 @@ function useConversationRealtime(conversationId, onEvent) {
2059
1964
  }
2060
1965
  function useGlobalRealtime(onEvent) {
2061
1966
  const context = useConversations();
2062
- const onEventRef = useRef5(onEvent);
1967
+ const onEventRef = useRef4(onEvent);
2063
1968
  onEventRef.current = onEvent;
2064
- useEffect6(() => {
1969
+ useEffect5(() => {
2065
1970
  if (!context) return;
2066
1971
  const source = context.sse.connectGlobalStream();
2067
1972
  const handler = (event) => onEventRef.current(event);
@@ -2072,6 +1977,38 @@ function useGlobalRealtime(onEvent) {
2072
1977
  };
2073
1978
  }, [context]);
2074
1979
  }
1980
+
1981
+ // src/hooks/useConversationActions.ts
1982
+ import { useMemo as useMemo2 } from "react";
1983
+ function useConversationActions(conversationId) {
1984
+ const context = useConversations();
1985
+ if (!context) {
1986
+ throw new Error("useConversationActions requires an ancestor <ConversationsProvider>");
1987
+ }
1988
+ const { api } = context;
1989
+ return useMemo2(
1990
+ () => ({
1991
+ takeover: api.takeover ? () => api.takeover(conversationId) : void 0,
1992
+ release: api.release ? () => api.release(conversationId) : void 0,
1993
+ finalize: api.finalize ? () => api.finalize(conversationId) : void 0
1994
+ }),
1995
+ [api, conversationId]
1996
+ );
1997
+ }
1998
+ function useInboxActions() {
1999
+ const context = useConversations();
2000
+ if (!context) {
2001
+ throw new Error("useInboxActions requires an ancestor <ConversationsProvider>");
2002
+ }
2003
+ const { api } = context;
2004
+ return useMemo2(
2005
+ () => ({
2006
+ markAllRead: api.markAllRead ? () => api.markAllRead() : void 0,
2007
+ listTemplates: api.listTemplates ? () => api.listTemplates() : void 0
2008
+ }),
2009
+ [api]
2010
+ );
2011
+ }
2075
2012
  export {
2076
2013
  AudioPlayer,
2077
2014
  Avatar,
@@ -2089,13 +2026,21 @@ export {
2089
2026
  ConversationRow,
2090
2027
  ConversationWallpaper,
2091
2028
  ConversationsProvider,
2029
+ DEFAULT_AVATAR_LABELS,
2092
2030
  DEFAULT_CONVERSATION_CHANNEL,
2093
2031
  DEFAULT_CONVERSATION_CONTEXT_LABELS,
2094
2032
  DEFAULT_CONVERSATION_DOCUMENTS_LABELS,
2095
2033
  DEFAULT_CONVERSATION_HEADER_LABELS,
2034
+ DEFAULT_CONVERSATION_LIST_ITEM_LABELS,
2035
+ DEFAULT_DOCUMENTS_LIBRARY_LABELS,
2036
+ DEFAULT_LIGHTBOX_LABELS,
2037
+ DEFAULT_MESSAGE_COMPOSER_LABELS,
2096
2038
  DEFAULT_TEMPLATES_SETTINGS_LABELS,
2039
+ DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS,
2097
2040
  DEFAULT_WINDOW_EXPIRED_LABELS,
2041
+ DOCUMENT_SOURCE_FILTER,
2098
2042
  DateDivider,
2043
+ DocumentsLibrary,
2099
2044
  EmojiPicker,
2100
2045
  FileIcon,
2101
2046
  HANDLE_KIND,
@@ -2125,17 +2070,21 @@ export {
2125
2070
  capabilitiesOf,
2126
2071
  channelFiltersFor,
2127
2072
  contactFlag,
2073
+ createMediaUrlResolver,
2128
2074
  downloadTextFile,
2129
2075
  formatContactHandle,
2076
+ formatDateTime,
2130
2077
  formatFileSize,
2131
2078
  formatPhone,
2132
2079
  formatStalledFor,
2133
2080
  formatTimestamp,
2134
2081
  htmlToWA,
2082
+ isSameDay,
2135
2083
  isWindowBlocking,
2136
2084
  parseWhatsAppFormatting,
2137
2085
  phoneInitials,
2138
2086
  toast,
2087
+ useConversationActions,
2139
2088
  useConversationContext,
2140
2089
  useConversationDocuments,
2141
2090
  useConversationList,
@@ -2145,6 +2094,7 @@ export {
2145
2094
  useConversations,
2146
2095
  useDarkMode,
2147
2096
  useGlobalRealtime,
2097
+ useInboxActions,
2148
2098
  useIsDarkTheme,
2149
2099
  useIsNarrow,
2150
2100
  useToast,