@consilioweb/payload-support 2.0.1 → 3.0.0

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 (215) hide show
  1. package/README.md +636 -402
  2. package/dist/components/RichTextEditor/index.d.ts +19 -0
  3. package/dist/components/TicketConversation/RewriteDropdown.d.ts +6 -0
  4. package/dist/components/TicketConversation/SkeletonText.d.ts +4 -0
  5. package/dist/components/TicketConversation/components/AISummaryPanel.d.ts +14 -0
  6. package/dist/components/TicketConversation/components/ActionPanels.d.ts +47 -0
  7. package/dist/components/TicketConversation/components/ActivityLog.d.ts +5 -0
  8. package/dist/components/TicketConversation/components/ClientBar.d.ts +5 -0
  9. package/dist/components/TicketConversation/components/ClientHistory.d.ts +24 -0
  10. package/dist/components/TicketConversation/components/CodeBlock.d.ts +26 -0
  11. package/dist/components/TicketConversation/components/CodeBlockInserter.d.ts +12 -0
  12. package/dist/components/TicketConversation/components/QuickActions.d.ts +32 -0
  13. package/dist/components/TicketConversation/components/TicketHeader.d.ts +19 -0
  14. package/dist/components/TicketConversation/components/TimeTrackingPanel.d.ts +24 -0
  15. package/dist/components/TicketConversation/config.d.ts +10 -0
  16. package/dist/components/TicketConversation/config.js +1 -40
  17. package/dist/components/TicketConversation/constants.d.ts +56 -0
  18. package/dist/components/TicketConversation/context.d.ts +53 -0
  19. package/dist/components/TicketConversation/hooks/useAI.d.ts +21 -0
  20. package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.d.ts +3 -0
  21. package/dist/components/TicketConversation/hooks/useFeatures.d.ts +23 -0
  22. package/dist/components/TicketConversation/hooks/useFeatures.js +61 -0
  23. package/dist/components/TicketConversation/hooks/useMessageActions.d.ts +20 -0
  24. package/dist/components/TicketConversation/hooks/useReply.d.ts +27 -0
  25. package/dist/components/TicketConversation/hooks/useTicketActions.d.ts +58 -0
  26. package/dist/components/TicketConversation/hooks/useTimeTracking.d.ts +18 -0
  27. package/dist/components/TicketConversation/hooks/useTranslation.d.ts +33 -0
  28. package/dist/components/TicketConversation/index.d.ts +4 -0
  29. package/dist/components/TicketConversation/index.js +2 -2
  30. package/dist/components/TicketConversation/types.d.ts +56 -0
  31. package/dist/components/TicketConversation/utils.d.ts +2 -0
  32. package/dist/index.cjs +392 -320
  33. package/dist/index.d.cts +100 -3
  34. package/dist/index.d.ts +100 -3
  35. package/dist/index.js +388 -321
  36. package/dist/utils/features.d.ts +123 -0
  37. package/dist/utils/features.js +147 -0
  38. package/dist/views/BillingView/client.d.ts +2 -0
  39. package/dist/views/BillingView/index.d.ts +4 -0
  40. package/dist/views/ChatView/client.d.ts +2 -0
  41. package/dist/views/ChatView/client.js +9 -9
  42. package/dist/views/ChatView/index.d.ts +4 -0
  43. package/dist/views/CrmView/client.d.ts +2 -0
  44. package/dist/views/CrmView/client.js +6 -9
  45. package/dist/views/CrmView/index.d.ts +4 -0
  46. package/dist/views/EmailTrackingView/client.d.ts +2 -0
  47. package/dist/views/EmailTrackingView/index.d.ts +4 -0
  48. package/dist/views/ImportConversationView/client.d.ts +2 -0
  49. package/dist/views/ImportConversationView/index.d.ts +4 -0
  50. package/dist/views/LogsView/client.d.ts +2 -0
  51. package/dist/views/LogsView/index.d.ts +4 -0
  52. package/dist/views/NewTicketView/client.d.ts +2 -0
  53. package/dist/views/NewTicketView/index.d.ts +4 -0
  54. package/dist/views/PendingEmailsView/client.d.ts +2 -0
  55. package/dist/views/PendingEmailsView/index.d.ts +4 -0
  56. package/dist/views/SupportDashboardView/client.d.ts +2 -0
  57. package/dist/views/SupportDashboardView/index.d.ts +4 -0
  58. package/dist/views/TicketDetailView/NextActionItem.d.ts +6 -0
  59. package/dist/views/TicketDetailView/RewriteDropdown.d.ts +7 -0
  60. package/dist/views/TicketDetailView/client.d.ts +2 -0
  61. package/dist/views/TicketDetailView/client.js +2 -2
  62. package/dist/views/TicketDetailView/constants.d.ts +13 -0
  63. package/dist/views/TicketDetailView/helpers.d.ts +2 -0
  64. package/dist/views/TicketDetailView/index.d.ts +4 -0
  65. package/dist/views/TicketDetailView/types.d.ts +40 -0
  66. package/dist/views/TicketInboxView/client.d.ts +2 -0
  67. package/dist/views/TicketInboxView/client.js +5 -5
  68. package/dist/views/TicketInboxView/index.d.ts +4 -0
  69. package/dist/views/TicketingSettingsView/client.d.ts +2 -0
  70. package/dist/views/TicketingSettingsView/client.js +5 -4
  71. package/dist/views/TicketingSettingsView/index.d.ts +4 -0
  72. package/dist/views/TimeDashboardView/client.d.ts +2 -0
  73. package/dist/views/TimeDashboardView/index.d.ts +4 -0
  74. package/dist/views/shared/AdminViewHeader.d.ts +13 -0
  75. package/dist/views/shared/ErrorBoundary.d.ts +17 -0
  76. package/dist/views/shared/Skeleton.d.ts +21 -0
  77. package/dist/views/shared/StatusPill.d.ts +8 -0
  78. package/dist/views/shared/adminTokens.d.ts +19 -0
  79. package/dist/views/shared/config.d.ts +8 -0
  80. package/dist/views/shared/config.js +1 -40
  81. package/dist/views/shared/dateLocale.d.ts +5 -0
  82. package/dist/views/shared/index.d.ts +12 -0
  83. package/dist/views/shared/index.js +2 -1
  84. package/dist/views/shared/sla.d.ts +14 -0
  85. package/dist/views.d.ts +13 -13
  86. package/package.json +16 -31
  87. package/src/collections/SupportClients.ts +29 -0
  88. package/src/collections/TicketCollaborators.ts +6 -1
  89. package/src/collections/TicketMessages.ts +46 -24
  90. package/src/collections/Tickets.ts +117 -79
  91. package/src/collections/TimeEntries.ts +57 -32
  92. package/src/components/TicketConversation/config.ts +16 -80
  93. package/src/components/TicketConversation/hooks/useFeatures.ts +109 -0
  94. package/src/components/TicketConversation/index.tsx +2 -2
  95. package/src/endpoints/ai.ts +2 -1
  96. package/src/endpoints/client-intelligence.ts +2 -1
  97. package/src/endpoints/process-scheduled.ts +13 -8
  98. package/src/endpoints/round-robin-config.ts +30 -20
  99. package/src/endpoints/settings.ts +28 -77
  100. package/src/index.ts +6 -2
  101. package/src/portal/LiveChat.tsx +33 -22
  102. package/src/portal/auth/tickets/detail/TicketPolling.tsx +5 -1
  103. package/src/types/lucide-react.d.ts +10 -2
  104. package/src/utils/aiAgent.ts +2 -1
  105. package/src/utils/aiProvider.ts +21 -0
  106. package/src/utils/features.ts +297 -0
  107. package/src/utils/fireWebhooks.ts +6 -0
  108. package/src/utils/generateTicketSynthesis.ts +2 -1
  109. package/src/utils/index.ts +4 -2
  110. package/src/utils/readSettings.ts +82 -9
  111. package/src/utils/webhookDispatcher.ts +19 -7
  112. package/src/views/ChatView/client.tsx +13 -9
  113. package/src/views/CrmView/client.tsx +10 -11
  114. package/src/views/TicketDetailView/client.tsx +2 -2
  115. package/src/views/TicketInboxView/client.tsx +10 -5
  116. package/src/views/TicketingSettingsView/client.tsx +8 -6
  117. package/src/views/shared/config.ts +14 -80
  118. package/src/views/shared/index.ts +3 -1
  119. package/dist/components/RichTextEditor/index.cjs +0 -279
  120. package/dist/components/TicketConversation/RewriteDropdown.cjs +0 -98
  121. package/dist/components/TicketConversation/SkeletonText.cjs +0 -21
  122. package/dist/components/TicketConversation/components/AISummaryPanel.cjs +0 -85
  123. package/dist/components/TicketConversation/components/ActionPanels.cjs +0 -193
  124. package/dist/components/TicketConversation/components/ActivityLog.cjs +0 -24
  125. package/dist/components/TicketConversation/components/ClientBar.cjs +0 -43
  126. package/dist/components/TicketConversation/components/ClientHistory.cjs +0 -138
  127. package/dist/components/TicketConversation/components/CodeBlock.cjs +0 -171
  128. package/dist/components/TicketConversation/components/CodeBlockInserter.cjs +0 -156
  129. package/dist/components/TicketConversation/components/QuickActions.cjs +0 -87
  130. package/dist/components/TicketConversation/components/TicketHeader.cjs +0 -93
  131. package/dist/components/TicketConversation/components/TimeTrackingPanel.cjs +0 -134
  132. package/dist/components/TicketConversation/config.cjs +0 -44
  133. package/dist/components/TicketConversation/constants.cjs +0 -127
  134. package/dist/components/TicketConversation/context.cjs +0 -13
  135. package/dist/components/TicketConversation/hooks/useAI.cjs +0 -196
  136. package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.cjs +0 -20
  137. package/dist/components/TicketConversation/hooks/useMessageActions.cjs +0 -136
  138. package/dist/components/TicketConversation/hooks/useReply.cjs +0 -188
  139. package/dist/components/TicketConversation/hooks/useTicketActions.cjs +0 -290
  140. package/dist/components/TicketConversation/hooks/useTimeTracking.cjs +0 -123
  141. package/dist/components/TicketConversation/hooks/useTranslation.cjs +0 -101
  142. package/dist/components/TicketConversation/index.cjs +0 -1114
  143. package/dist/components/TicketConversation/types.cjs +0 -2
  144. package/dist/components/TicketConversation/utils.cjs +0 -27
  145. package/dist/views/BillingView/client.cjs +0 -469
  146. package/dist/views/BillingView/index.cjs +0 -34
  147. package/dist/views/ChatView/client.cjs +0 -301
  148. package/dist/views/ChatView/index.cjs +0 -34
  149. package/dist/views/CrmView/client.cjs +0 -458
  150. package/dist/views/CrmView/index.cjs +0 -34
  151. package/dist/views/EmailTrackingView/client.cjs +0 -171
  152. package/dist/views/EmailTrackingView/index.cjs +0 -34
  153. package/dist/views/ImportConversationView/client.cjs +0 -238
  154. package/dist/views/ImportConversationView/index.cjs +0 -34
  155. package/dist/views/LogsView/client.cjs +0 -148
  156. package/dist/views/LogsView/index.cjs +0 -32
  157. package/dist/views/NewTicketView/client.cjs +0 -213
  158. package/dist/views/NewTicketView/index.cjs +0 -32
  159. package/dist/views/PendingEmailsView/client.cjs +0 -471
  160. package/dist/views/PendingEmailsView/index.cjs +0 -34
  161. package/dist/views/SupportDashboardView/client.cjs +0 -437
  162. package/dist/views/SupportDashboardView/index.cjs +0 -34
  163. package/dist/views/TicketDetailView/NextActionItem.cjs +0 -40
  164. package/dist/views/TicketDetailView/RewriteDropdown.cjs +0 -80
  165. package/dist/views/TicketDetailView/client.cjs +0 -1412
  166. package/dist/views/TicketDetailView/constants.cjs +0 -20
  167. package/dist/views/TicketDetailView/helpers.cjs +0 -23
  168. package/dist/views/TicketDetailView/index.cjs +0 -34
  169. package/dist/views/TicketDetailView/types.cjs +0 -2
  170. package/dist/views/TicketInboxView/client.cjs +0 -359
  171. package/dist/views/TicketInboxView/index.cjs +0 -32
  172. package/dist/views/TicketingSettingsView/client.cjs +0 -740
  173. package/dist/views/TicketingSettingsView/index.cjs +0 -34
  174. package/dist/views/TimeDashboardView/client.cjs +0 -180
  175. package/dist/views/TimeDashboardView/index.cjs +0 -34
  176. package/dist/views/shared/AdminViewHeader.cjs +0 -68
  177. package/dist/views/shared/ErrorBoundary.cjs +0 -55
  178. package/dist/views/shared/Skeleton.cjs +0 -77
  179. package/dist/views/shared/StatusPill.cjs +0 -47
  180. package/dist/views/shared/adminTokens.cjs +0 -34
  181. package/dist/views/shared/config.cjs +0 -44
  182. package/dist/views/shared/dateLocale.cjs +0 -5
  183. package/dist/views/shared/index.cjs +0 -72
  184. package/dist/views/shared/sla.cjs +0 -37
  185. package/dist/views.cjs +0 -86
  186. package/dist/views.d.cts +0 -13
  187. package/src/__tests__/aiSummaryRendering.test.ts +0 -21
  188. package/src/__tests__/authResponses.test.ts +0 -69
  189. package/src/__tests__/capabilities.test.ts +0 -71
  190. package/src/__tests__/generateTrackingToken.test.ts +0 -67
  191. package/src/__tests__/integration/ai-agent.test.ts +0 -46
  192. package/src/__tests__/integration/auth.test.ts +0 -43
  193. package/src/__tests__/integration/automation-rules.test.ts +0 -68
  194. package/src/__tests__/integration/buildTestPayload.ts +0 -52
  195. package/src/__tests__/integration/channels.test.ts +0 -52
  196. package/src/__tests__/integration/core-behaviors.test.ts +0 -81
  197. package/src/__tests__/integration/dashboard-volume.test.ts +0 -31
  198. package/src/__tests__/integration/digest.test.ts +0 -48
  199. package/src/__tests__/integration/invoice-pdf.test.ts +0 -30
  200. package/src/__tests__/integration/isolation.test.ts +0 -81
  201. package/src/__tests__/integration/mentions-invoice.test.ts +0 -50
  202. package/src/__tests__/integration/nps.test.ts +0 -37
  203. package/src/__tests__/integration/per-team-sla.test.ts +0 -44
  204. package/src/__tests__/integration/push.test.ts +0 -75
  205. package/src/__tests__/integration/sanitization.test.ts +0 -35
  206. package/src/__tests__/integration/sla-pause.test.ts +0 -39
  207. package/src/__tests__/integration/smoke.test.ts +0 -26
  208. package/src/__tests__/integration/snooze.test.ts +0 -68
  209. package/src/__tests__/integration/teams.test.ts +0 -38
  210. package/src/__tests__/rateLimiter.test.ts +0 -83
  211. package/src/__tests__/sanitizeHtml.test.ts +0 -165
  212. package/src/__tests__/sla.test.ts +0 -258
  213. package/src/__tests__/trackOpenEndpoint.test.ts +0 -54
  214. package/src/__tests__/translations.test.ts +0 -67
  215. package/src/__tests__/webhookSecurity.test.ts +0 -58
@@ -1,171 +0,0 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var React = require('react');
5
- var useTranslation = require('../../components/TicketConversation/hooks/useTranslation');
6
- var dateLocale = require('../shared/dateLocale');
7
- var s = require('../../styles/EmailTracking.module.scss');
8
-
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
-
11
- var React__default = /*#__PURE__*/_interopDefault(React);
12
- var s__default = /*#__PURE__*/_interopDefault(s);
13
-
14
- const STATUS_CFG = {
15
- success: { labelKey: "logs.statusSuccess", bg: "#dcfce7", color: "#16a34a" },
16
- error: { labelKey: "emailTracking.errorLabel", bg: "#fef2f2", color: "#dc2626" },
17
- ignored: { labelKey: "logs.statusIgnored", bg: "#f3f4f6", color: "#6b7280" }
18
- };
19
- function fmtDate(d) {
20
- return new Date(d).toLocaleDateString(dateLocale.DATE_LOCALE, { day: "2-digit", month: "2-digit", year: "2-digit", hour: "2-digit", minute: "2-digit" });
21
- }
22
- const EmailTrackingClient = () => {
23
- const { t } = useTranslation.useTranslation();
24
- const [logs, setLogs] = React.useState([]);
25
- const [stats, setStats] = React.useState(null);
26
- const [loading, setLoading] = React.useState(true);
27
- const [tab, setTab] = React.useState("all");
28
- const [dateRange, setDateRange] = React.useState(7);
29
- const [search, setSearch] = React.useState("");
30
- const [expandedRow, setExpandedRow] = React.useState(null);
31
- const [page, setPage] = React.useState(1);
32
- const [hasMore, setHasMore] = React.useState(false);
33
- const [totalDocs, setTotalDocs] = React.useState(0);
34
- const LIMIT = 30;
35
- const fetchStats = React.useCallback(async () => {
36
- try {
37
- const r = await fetch(`/api/support/email-stats?days=${dateRange}`);
38
- if (r.ok) setStats(await r.json());
39
- } catch {
40
- }
41
- }, [dateRange]);
42
- const fetchLogs = React.useCallback(async () => {
43
- const cutoff = new Date(Date.now() - dateRange * 864e5).toISOString();
44
- const where = [`where[createdAt][greater_than]=${cutoff}`];
45
- if (tab !== "all") where.push(`where[status][equals]=${tab}`);
46
- if (search.trim()) {
47
- where.push(`where[or][0][recipientEmail][contains]=${encodeURIComponent(search)}`, `where[or][1][subject][contains]=${encodeURIComponent(search)}`);
48
- }
49
- try {
50
- const r = await fetch(`/api/email-logs?${where.join("&")}&sort=-createdAt&limit=${LIMIT}&page=${page}&depth=0`);
51
- if (r.ok) {
52
- const d = await r.json();
53
- setLogs(d.docs);
54
- setHasMore(d.hasNextPage);
55
- setTotalDocs(d.totalDocs);
56
- }
57
- } catch {
58
- }
59
- setLoading(false);
60
- }, [dateRange, tab, search, page]);
61
- React.useEffect(() => {
62
- setLoading(true);
63
- setPage(1);
64
- }, [dateRange, tab, search]);
65
- React.useEffect(() => {
66
- fetchStats();
67
- fetchLogs();
68
- }, [fetchStats, fetchLogs]);
69
- const tabsList = [
70
- { key: "all", label: t("emailTracking.tabs.all"), count: stats?.total },
71
- { key: "success", label: t("emailTracking.tabs.success"), count: stats?.success },
72
- { key: "error", label: t("emailTracking.tabs.errors"), count: stats?.errors },
73
- { key: "ignored", label: t("emailTracking.tabs.ignored"), count: stats?.ignored }
74
- ];
75
- if (loading && !stats) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.loading, children: t("common.loading") });
76
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.page, children: [
77
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.header, children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: s__default.default.title, children: t("emailTracking.title") }) }),
78
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.statGrid, children: [
79
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.statCard, children: [
80
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.statLabel, children: t("emailTracking.stats.emailsSent") }),
81
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.statValue, children: stats?.total ?? "\u2014" })
82
- ] }),
83
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.statCard, children: [
84
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.statLabel, children: t("emailTracking.stats.successRate") }),
85
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.statValue, children: [
86
- stats ? `${stats.successRate}` : "\u2014",
87
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.statUnit, children: "%" })
88
- ] })
89
- ] }),
90
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.statCard, children: [
91
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.statLabel, children: t("emailTracking.stats.errors") }),
92
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.statValue, children: stats?.errors ?? "\u2014" })
93
- ] }),
94
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.statCard, children: [
95
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.statLabel, children: t("emailTracking.stats.avgTime") }),
96
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.statValue, children: [
97
- stats ? stats.avgProcessingTime : "\u2014",
98
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.statUnit, children: "ms" })
99
- ] })
100
- ] })
101
- ] }),
102
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.filters, children: [
103
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.tabs, children: tabsList.map((t2) => /* @__PURE__ */ jsxRuntime.jsxs("button", { className: `${s__default.default.tab} ${tab === t2.key ? s__default.default.tabActive : ""}`, onClick: () => setTab(t2.key), children: [
104
- t2.label,
105
- " ",
106
- typeof t2.count === "number" && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { marginLeft: 4, opacity: 0.6 }, children: [
107
- "(",
108
- t2.count,
109
- ")"
110
- ] })
111
- ] }, t2.key)) }),
112
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.dateRangeGroup, children: [7, 30, 90].map((v) => /* @__PURE__ */ jsxRuntime.jsxs("button", { className: `${s__default.default.dateRangeBtn} ${dateRange === v ? s__default.default.dateRangeActive : ""}`, onClick: () => setDateRange(v), children: [
113
- v,
114
- "j"
115
- ] }, v)) }),
116
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "text", className: s__default.default.searchInput, placeholder: t("emailTracking.searchPlaceholder"), value: search, onChange: (e) => setSearch(e.target.value) })
117
- ] }),
118
- logs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.empty, children: t("emailTracking.noLogs") }) : /* @__PURE__ */ jsxRuntime.jsxs("table", { className: s__default.default.table, children: [
119
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
120
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("emailTracking.tableHeaders.date") }),
121
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("emailTracking.tableHeaders.recipient") }),
122
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("emailTracking.tableHeaders.subject") }),
123
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("emailTracking.tableHeaders.ticket") }),
124
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("emailTracking.tableHeaders.status") }),
125
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("emailTracking.tableHeaders.action") }),
126
- /* @__PURE__ */ jsxRuntime.jsx("th", { style: { textAlign: "right" }, children: t("emailTracking.tableHeaders.time") })
127
- ] }) }),
128
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((log) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
129
- /* @__PURE__ */ jsxRuntime.jsxs("tr", { onClick: () => log.status === "error" && log.errorMessage ? setExpandedRow(expandedRow === log.id ? null : log.id) : null, style: { cursor: log.status === "error" && log.errorMessage ? "pointer" : "default" }, children: [
130
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { fontSize: 12, whiteSpace: "nowrap" }, children: fmtDate(log.createdAt) }),
131
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { maxWidth: 200, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: log.recipientEmail, children: log.recipientEmail || "\u2014" }),
132
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { maxWidth: 250, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: log.subject, children: log.subject || "\u2014" }),
133
- /* @__PURE__ */ jsxRuntime.jsx("td", { children: log.ticketNumber ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.ticketLink, children: log.ticketNumber }) : "\u2014" }),
134
- /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.statusBadge, style: { background: STATUS_CFG[log.status]?.bg, color: STATUS_CFG[log.status]?.color }, children: STATUS_CFG[log.status]?.labelKey ? t(STATUS_CFG[log.status].labelKey) : log.status }) }),
135
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { fontSize: 12 }, children: log.action || "\u2014" }),
136
- /* @__PURE__ */ jsxRuntime.jsxs("td", { style: { textAlign: "right" }, children: [
137
- log.processingTimeMs != null ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${s__default.default.processingTime} ${log.processingTimeMs > 2e3 ? s__default.default.timeSlow : log.processingTimeMs > 500 ? s__default.default.timeMedium : s__default.default.timeFast}`, children: [
138
- log.processingTimeMs,
139
- "ms"
140
- ] }) : "\u2014",
141
- log.status === "error" && log.errorMessage && /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.expandBtn, onClick: (e) => {
142
- e.stopPropagation();
143
- setExpandedRow(expandedRow === log.id ? null : log.id);
144
- }, children: expandedRow === log.id ? "\u25B4" : "\u25BE" })
145
- ] })
146
- ] }),
147
- expandedRow === log.id && log.errorMessage && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 7, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.errorDetail, children: [
148
- "Erreur",
149
- log.httpStatus ? ` (HTTP ${log.httpStatus})` : "",
150
- ": ",
151
- log.errorMessage
152
- ] }) }) })
153
- ] }, log.id)) })
154
- ] }),
155
- totalDocs > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.pagination, children: [
156
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.pageBtn, onClick: () => setPage((p) => Math.max(1, p - 1)), disabled: page <= 1, children: t("common.previous") }),
157
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 12, color: "var(--theme-elevation-500)", alignSelf: "center" }, children: [
158
- t("common.page"),
159
- " ",
160
- page,
161
- " \u2014 ",
162
- totalDocs,
163
- " ",
164
- t("common.results")
165
- ] }),
166
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.pageBtn, onClick: () => setPage((p) => p + 1), disabled: !hasMore, children: t("common.next") })
167
- ] })
168
- ] });
169
- };
170
-
171
- exports.EmailTrackingClient = EmailTrackingClient;
@@ -1,34 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var jsxRuntime = require('react/jsx-runtime');
6
- var templates = require('@payloadcms/next/templates');
7
- var navigation = require('next/navigation');
8
- var ErrorBoundary = require('../shared/ErrorBoundary');
9
- var client = require('./client');
10
-
11
- const EmailTrackingView = ({ initPageResult }) => {
12
- const { req, visibleEntities } = initPageResult;
13
- if (!req.user) {
14
- navigation.redirect("/admin/login");
15
- }
16
- return /* @__PURE__ */ jsxRuntime.jsx(
17
- templates.DefaultTemplate,
18
- {
19
- i18n: req.i18n,
20
- locale: initPageResult.locale,
21
- params: {},
22
- payload: req.payload,
23
- permissions: initPageResult.permissions,
24
- searchParams: {},
25
- user: req.user,
26
- visibleEntities,
27
- children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary.AdminErrorBoundary, { viewName: "EmailTrackingView", children: /* @__PURE__ */ jsxRuntime.jsx(client.EmailTrackingClient, {}) })
28
- }
29
- );
30
- };
31
- var EmailTrackingView_default = EmailTrackingView;
32
-
33
- exports.EmailTrackingView = EmailTrackingView;
34
- exports.default = EmailTrackingView_default;
@@ -1,238 +0,0 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var react = require('react');
5
- var useTranslation = require('../../components/TicketConversation/hooks/useTranslation');
6
- var styles = require('../../styles/ImportConversation.module.scss');
7
-
8
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
-
10
- var styles__default = /*#__PURE__*/_interopDefault(styles);
11
-
12
- function ImportConversationClient() {
13
- const { t } = useTranslation.useTranslation();
14
- const [markdown, setMarkdown] = react.useState("");
15
- const [fileName, setFileName] = react.useState("");
16
- const [isDragOver, setIsDragOver] = react.useState(false);
17
- const [preview, setPreview] = react.useState(null);
18
- const [result, setResult] = react.useState(null);
19
- const [error, setError] = react.useState("");
20
- const [loading, setLoading] = react.useState(false);
21
- const fileRef = react.useRef(null);
22
- const handleFile = react.useCallback((file) => {
23
- if (!file.name.endsWith(".md") && !file.name.endsWith(".txt")) {
24
- setError(t("import.formatError"));
25
- return;
26
- }
27
- if (file.size > 512e3) {
28
- setError(t("import.sizeError"));
29
- return;
30
- }
31
- setError("");
32
- setFileName(file.name);
33
- setResult(null);
34
- setPreview(null);
35
- const reader = new FileReader();
36
- reader.onload = (e) => {
37
- const content = e.target?.result;
38
- setMarkdown(content);
39
- };
40
- reader.readAsText(file);
41
- }, []);
42
- const onDrop = react.useCallback(
43
- (e) => {
44
- e.preventDefault();
45
- setIsDragOver(false);
46
- const file = e.dataTransfer.files[0];
47
- if (file) handleFile(file);
48
- },
49
- [handleFile]
50
- );
51
- const onFileChange = react.useCallback(
52
- (e) => {
53
- const file = e.target.files?.[0];
54
- if (file) handleFile(file);
55
- },
56
- [handleFile]
57
- );
58
- const doPreview = react.useCallback(async () => {
59
- if (!markdown) return;
60
- setLoading(true);
61
- setError("");
62
- setPreview(null);
63
- try {
64
- const res = await fetch("/api/support/import-conversation", {
65
- method: "POST",
66
- headers: { "Content-Type": "application/json" },
67
- body: JSON.stringify({ markdown, previewOnly: true })
68
- });
69
- const data = await res.json();
70
- if (!res.ok) {
71
- setError(data.error || t("import.analyzeError"));
72
- return;
73
- }
74
- setPreview(data);
75
- } catch {
76
- setError(t("import.networkError"));
77
- } finally {
78
- setLoading(false);
79
- }
80
- }, [markdown]);
81
- const doImport = react.useCallback(async () => {
82
- if (!markdown) return;
83
- setLoading(true);
84
- setError("");
85
- try {
86
- const res = await fetch("/api/support/import-conversation", {
87
- method: "POST",
88
- headers: { "Content-Type": "application/json" },
89
- body: JSON.stringify({ markdown })
90
- });
91
- const data = await res.json();
92
- if (!res.ok) {
93
- setError(data.error || t("import.importError"));
94
- return;
95
- }
96
- setResult(data);
97
- setPreview(null);
98
- } catch {
99
- setError(t("import.networkError"));
100
- } finally {
101
- setLoading(false);
102
- }
103
- }, [markdown]);
104
- const reset = react.useCallback(() => {
105
- setMarkdown("");
106
- setFileName("");
107
- setPreview(null);
108
- setResult(null);
109
- setError("");
110
- if (fileRef.current) fileRef.current.value = "";
111
- }, []);
112
- const dropzoneClass = isDragOver ? styles__default.default.dropzoneDragOver : markdown ? styles__default.default.dropzoneHasFile : styles__default.default.dropzone;
113
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.page, children: [
114
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.header, children: [
115
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: styles__default.default.title, children: t("import.title") }) }),
116
- result && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: reset, className: styles__default.default.btnPrimary, children: t("import.newImport") })
117
- ] }),
118
- !result && /* @__PURE__ */ jsxRuntime.jsxs(
119
- "div",
120
- {
121
- className: dropzoneClass,
122
- onDragOver: (e) => {
123
- e.preventDefault();
124
- setIsDragOver(true);
125
- },
126
- onDragLeave: () => setIsDragOver(false),
127
- onDrop,
128
- onClick: () => fileRef.current?.click(),
129
- children: [
130
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.dropzoneIcon, children: "\u2191" }),
131
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles__default.default.dropzoneText, children: markdown ? t("import.dropzoneLoaded") : t("import.dropzoneText") }),
132
- !markdown && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 12, color: "var(--theme-elevation-400)", marginTop: 8 }, children: t("import.acceptedFormats") }),
133
- fileName && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles__default.default.fileName, children: fileName }),
134
- /* @__PURE__ */ jsxRuntime.jsx(
135
- "input",
136
- {
137
- ref: fileRef,
138
- type: "file",
139
- accept: ".md,.txt",
140
- onChange: onFileChange,
141
- style: { display: "none" }
142
- }
143
- )
144
- ]
145
- }
146
- ),
147
- error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.resultError, children: [
148
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.resultTitleError, children: "\u26A0 Erreur" }),
149
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles__default.default.errorText, children: error })
150
- ] }),
151
- markdown && !preview && !result && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.btnRow, children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: doPreview, disabled: loading, className: styles__default.default.btnAmber, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.btnContent, children: [
152
- "\u{1F441} ",
153
- loading ? t("import.analyzing") : t("import.preview")
154
- ] }) }) }),
155
- preview && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
156
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.section, children: [
157
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.sectionTitle, children: [
158
- "\u{1F464} ",
159
- t("import.client")
160
- ] }),
161
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
162
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.name") }),
163
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: preview.client.name })
164
- ] }),
165
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
166
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.email") }),
167
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: preview.client.email })
168
- ] }),
169
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
170
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.company") }),
171
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: preview.client.company })
172
- ] }),
173
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
174
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.parsing") }),
175
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badgeInfo, children: preview.parseMethod === "structured" ? t("import.parsingRegex") : t("import.parsingAi") }) })
176
- ] })
177
- ] }),
178
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.section, children: [
179
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.sectionTitle, children: [
180
- "\u{1F4AC} ",
181
- preview.subject,
182
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.sectionTitleRight, children: [
183
- preview.messageCount,
184
- " ",
185
- t("import.messages")
186
- ] })
187
- ] }),
188
- preview.messages.map((msg, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: msg.from === "admin" ? styles__default.default.msgAdmin : styles__default.default.msgClient, children: [
189
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.msgHeader, children: [
190
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.msgAuthor, children: [
191
- msg.from === "admin" ? ">> " : "<< ",
192
- msg.name
193
- ] }),
194
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.msgDate, children: msg.date })
195
- ] }),
196
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.msgPreview, children: msg.preview })
197
- ] }, i))
198
- ] }),
199
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.btnRow, children: [
200
- /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setPreview(null), className: styles__default.default.btnMuted, children: t("common.cancel") }),
201
- /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: doImport, disabled: loading, className: styles__default.default.btnGreen, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.btnContent, children: [
202
- "\u279C ",
203
- loading ? t("import.importing") : t("import.importButton", { count: String(preview.messageCount) })
204
- ] }) })
205
- ] })
206
- ] }),
207
- result && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.resultSuccess, children: [
208
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.resultTitleSuccess, children: [
209
- "\u2713 ",
210
- t("import.resultTitle")
211
- ] }),
212
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
213
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultTicket") }),
214
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: `/admin/support/ticket?id=${result.ticketId}`, className: styles__default.default.link, children: result.ticketNumber }) })
215
- ] }),
216
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
217
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultClient") }),
218
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.infoValue, children: [
219
- result.clientName,
220
- " (",
221
- result.clientEmail,
222
- ")",
223
- result.isNewClient && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badgeNew, style: { marginLeft: 8 }, children: t("import.resultNew") })
224
- ] })
225
- ] }),
226
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
227
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultCompany") }),
228
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: result.clientCompany })
229
- ] }),
230
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
231
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultMessages") }),
232
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: t("import.resultImported", { count: String(result.messagesImported) }) })
233
- ] })
234
- ] })
235
- ] });
236
- }
237
-
238
- exports.ImportConversationClient = ImportConversationClient;
@@ -1,34 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var jsxRuntime = require('react/jsx-runtime');
6
- var templates = require('@payloadcms/next/templates');
7
- var navigation = require('next/navigation');
8
- var ErrorBoundary = require('../shared/ErrorBoundary');
9
- var client = require('./client');
10
-
11
- const ImportConversationView = ({ initPageResult }) => {
12
- const { req, visibleEntities } = initPageResult;
13
- if (!req.user) {
14
- navigation.redirect("/admin/login");
15
- }
16
- return /* @__PURE__ */ jsxRuntime.jsx(
17
- templates.DefaultTemplate,
18
- {
19
- i18n: req.i18n,
20
- locale: initPageResult.locale,
21
- params: {},
22
- payload: req.payload,
23
- permissions: initPageResult.permissions,
24
- searchParams: {},
25
- user: req.user,
26
- visibleEntities,
27
- children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary.AdminErrorBoundary, { viewName: "ImportConversationView", children: /* @__PURE__ */ jsxRuntime.jsx(client.ImportConversationClient, {}) })
28
- }
29
- );
30
- };
31
- var ImportConversationView_default = ImportConversationView;
32
-
33
- exports.ImportConversationView = ImportConversationView;
34
- exports.default = ImportConversationView_default;
@@ -1,148 +0,0 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var react = require('react');
5
- var navigation = require('next/navigation');
6
- var useTranslation = require('../../components/TicketConversation/hooks/useTranslation');
7
- var dateLocale = require('../shared/dateLocale');
8
- var s = require('../../styles/Logs.module.scss');
9
-
10
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
-
12
- var s__default = /*#__PURE__*/_interopDefault(s);
13
-
14
- function fmtDate(d) {
15
- return new Date(d).toLocaleDateString(dateLocale.DATE_LOCALE, { day: "2-digit", month: "2-digit", year: "2-digit", hour: "2-digit", minute: "2-digit" });
16
- }
17
- const LogsClient = () => {
18
- const { t } = useTranslation.useTranslation();
19
- const searchParams = navigation.useSearchParams();
20
- const [logType, setLogType] = react.useState(() => {
21
- const t2 = searchParams.get("type");
22
- return t2 === "auth" ? "auth" : "email";
23
- });
24
- const [logs, setLogs] = react.useState([]);
25
- const [loading, setLoading] = react.useState(true);
26
- const [page, setPage] = react.useState(1);
27
- const [hasMore, setHasMore] = react.useState(false);
28
- const [totalDocs, setTotalDocs] = react.useState(0);
29
- const [purgeResult, setPurgeResult] = react.useState(null);
30
- const collection = logType === "email" ? "email-logs" : "auth-logs";
31
- const fetchLogs = react.useCallback(async () => {
32
- try {
33
- const res = await fetch(`/api/${collection}?sort=-createdAt&limit=30&page=${page}&depth=0`, { credentials: "include" });
34
- if (res.ok) {
35
- const d = await res.json();
36
- setLogs(d.docs || []);
37
- setHasMore(d.hasNextPage);
38
- setTotalDocs(d.totalDocs);
39
- }
40
- } catch {
41
- }
42
- setLoading(false);
43
- }, [collection, page]);
44
- react.useEffect(() => {
45
- setLoading(true);
46
- setPage(1);
47
- }, [logType]);
48
- react.useEffect(() => {
49
- fetchLogs();
50
- }, [fetchLogs]);
51
- const handlePurge = async (days) => {
52
- const label = days === 0 ? t("logs.purgeAllLabel") : t("logs.purgeDaysLabel", { days: String(days) });
53
- if (!window.confirm(t("logs.purgeConfirm", { label, collection }))) return;
54
- try {
55
- const res = await fetch(`/api/support/purge-logs?collection=${collection}&days=${days}`, { method: "DELETE", credentials: "include" });
56
- if (res.ok) {
57
- const d = await res.json();
58
- setPurgeResult(t("logs.purgeResult", { count: String(d.purged) }));
59
- setTimeout(() => setPurgeResult(null), 5e3);
60
- fetchLogs();
61
- }
62
- } catch {
63
- }
64
- };
65
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.page, children: [
66
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.header, children: [
67
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: s__default.default.title, children: logType === "email" ? t("logs.title") : t("logs.titleAuth") }),
68
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.headerActions, children: [
69
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.purgeBtn, onClick: () => handlePurge(7), children: t("logs.purge7") }),
70
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.purgeBtn, onClick: () => handlePurge(30), children: t("logs.purge30") }),
71
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.purgeBtn, onClick: () => handlePurge(90), children: t("logs.purge90") }),
72
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.purgeBtn} ${s__default.default.purgeBtnDanger}`, onClick: () => handlePurge(0), children: t("logs.purgeAll") })
73
- ] })
74
- ] }),
75
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.tabs, children: [
76
- /* @__PURE__ */ jsxRuntime.jsxs("button", { className: `${s__default.default.tab} ${logType === "email" ? s__default.default.tabActive : ""}`, onClick: () => setLogType("email"), children: [
77
- t("logs.tabs.email"),
78
- " (",
79
- logType === "email" ? totalDocs : "...",
80
- ")"
81
- ] }),
82
- /* @__PURE__ */ jsxRuntime.jsxs("button", { className: `${s__default.default.tab} ${logType === "auth" ? s__default.default.tabActive : ""}`, onClick: () => setLogType("auth"), children: [
83
- t("logs.tabs.auth"),
84
- " (",
85
- logType === "auth" ? totalDocs : "...",
86
- ")"
87
- ] })
88
- ] }),
89
- purgeResult && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.purgeResult, children: purgeResult }),
90
- loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.loading, children: t("common.loading") }) : logs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.empty, children: t("logs.noLogs") }) : logType === "email" ? /* @__PURE__ */ jsxRuntime.jsxs("table", { className: s__default.default.table, children: [
91
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
92
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.date") }),
93
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.status") }),
94
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.recipient") }),
95
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.subject") }),
96
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.action") }),
97
- /* @__PURE__ */ jsxRuntime.jsx("th", { style: { textAlign: "right" }, children: t("logs.tableHeaders.time") })
98
- ] }) }),
99
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((log) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
100
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: s__default.default.mono, children: fmtDate(log.createdAt) }),
101
- /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.badge, style: {
102
- background: log.status === "success" ? "#dcfce7" : log.status === "error" ? "#fef2f2" : "#f3f4f6",
103
- color: log.status === "success" ? "#16a34a" : log.status === "error" ? "#dc2626" : "#6b7280"
104
- }, children: log.status === "success" ? t("logs.statusSuccess") : log.status === "error" ? t("logs.statusError") : t("logs.statusIgnored") }) }),
105
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: s__default.default.truncate, title: log.recipientEmail, children: log.recipientEmail || "\u2014" }),
106
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: s__default.default.truncate, title: log.subject, children: log.subject || "\u2014" }),
107
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { fontSize: 12, color: "var(--theme-elevation-500)" }, children: log.action || "\u2014" }),
108
- /* @__PURE__ */ jsxRuntime.jsx("td", { style: { textAlign: "right" }, children: log.processingTimeMs != null ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: s__default.default.mono, style: { color: log.processingTimeMs > 2e3 ? "#dc2626" : log.processingTimeMs > 500 ? "#d97706" : "#16a34a" }, children: [
109
- log.processingTimeMs,
110
- "ms"
111
- ] }) : "\u2014" })
112
- ] }, log.id)) })
113
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("table", { className: s__default.default.table, children: [
114
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
115
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.date") }),
116
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.status") }),
117
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.email") }),
118
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.ip") }),
119
- /* @__PURE__ */ jsxRuntime.jsx("th", { children: t("logs.tableHeaders.userAgent") })
120
- ] }) }),
121
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: logs.map((log) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
122
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: s__default.default.mono, children: fmtDate(log.createdAt) }),
123
- /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.badge, style: {
124
- background: log.success ? "#dcfce7" : "#fef2f2",
125
- color: log.success ? "#16a34a" : "#dc2626"
126
- }, children: log.success ? t("logs.statusSuccess") : t("logs.statusFailed") }) }),
127
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: s__default.default.mono, children: log.email || "\u2014" }),
128
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: s__default.default.mono, children: log.ip || "\u2014" }),
129
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: s__default.default.truncate, style: { fontSize: 11 }, children: log.userAgent || "\u2014" })
130
- ] }, log.id)) })
131
- ] }),
132
- totalDocs > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.pagination, children: [
133
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.pageBtn, onClick: () => setPage((p) => Math.max(1, p - 1)), disabled: page <= 1, children: t("common.previous") }),
134
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: s__default.default.pageInfo, children: [
135
- t("common.page"),
136
- " ",
137
- page,
138
- " \u2014 ",
139
- totalDocs,
140
- " ",
141
- t("common.results")
142
- ] }),
143
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.pageBtn, onClick: () => setPage((p) => p + 1), disabled: !hasMore, children: t("common.next") })
144
- ] })
145
- ] });
146
- };
147
-
148
- exports.LogsClient = LogsClient;