@consilioweb/payload-support 0.16.0 → 1.1.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.
- package/README.md +357 -435
- package/dist/components/TicketConversation/RewriteDropdown.cjs +98 -0
- package/dist/components/TicketConversation/RewriteDropdown.js +93 -0
- package/dist/components/TicketConversation/SkeletonText.cjs +21 -0
- package/dist/components/TicketConversation/SkeletonText.js +20 -0
- package/dist/components/TicketConversation/constants.cjs +27 -0
- package/dist/components/TicketConversation/constants.js +26 -1
- package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.cjs +20 -0
- package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.js +19 -0
- package/dist/components/TicketConversation/index.cjs +10 -147
- package/dist/components/TicketConversation/index.js +4 -141
- package/dist/index.cjs +1763 -677
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1760 -677
- package/dist/views/BillingView/client.cjs +40 -54
- package/dist/views/BillingView/client.js +40 -54
- package/dist/views/ChatView/client.cjs +4 -3
- package/dist/views/ChatView/client.js +4 -3
- package/dist/views/CrmView/client.cjs +7 -7
- package/dist/views/CrmView/client.js +7 -7
- package/dist/views/EmailTrackingView/client.cjs +6 -5
- package/dist/views/EmailTrackingView/client.js +6 -5
- package/dist/views/ImportConversationView/client.cjs +4 -4
- package/dist/views/ImportConversationView/client.js +4 -4
- package/dist/views/LogsView/client.cjs +3 -2
- package/dist/views/LogsView/client.js +3 -2
- package/dist/views/NewTicketView/client.cjs +1 -1
- package/dist/views/NewTicketView/client.js +1 -1
- package/dist/views/PendingEmailsView/client.cjs +7 -6
- package/dist/views/PendingEmailsView/client.js +7 -6
- package/dist/views/SupportDashboardView/client.cjs +19 -22
- package/dist/views/SupportDashboardView/client.js +19 -22
- package/dist/views/TicketDetailView/NextActionItem.cjs +40 -0
- package/dist/views/TicketDetailView/NextActionItem.js +34 -0
- package/dist/views/TicketDetailView/RewriteDropdown.cjs +80 -0
- package/dist/views/TicketDetailView/RewriteDropdown.js +78 -0
- package/dist/views/TicketDetailView/client.cjs +59 -190
- package/dist/views/TicketDetailView/client.js +52 -183
- package/dist/views/TicketDetailView/constants.cjs +20 -0
- package/dist/views/TicketDetailView/constants.js +16 -0
- package/dist/views/TicketDetailView/helpers.cjs +23 -0
- package/dist/views/TicketDetailView/helpers.js +20 -0
- package/dist/views/TicketDetailView/types.cjs +2 -0
- package/dist/views/TicketDetailView/types.js +1 -0
- package/dist/views/TicketInboxView/client.cjs +14 -10
- package/dist/views/TicketInboxView/client.js +14 -10
- package/dist/views/TicketingSettingsView/client.cjs +101 -96
- package/dist/views/TicketingSettingsView/client.js +92 -88
- package/dist/views/TimeDashboardView/client.cjs +2 -2
- package/dist/views/TimeDashboardView/client.js +2 -2
- package/dist/views/shared/StatusPill.cjs +23 -12
- package/dist/views/shared/StatusPill.js +23 -12
- package/dist/views/shared/dateLocale.cjs +5 -0
- package/dist/views/shared/dateLocale.js +3 -0
- package/package.json +28 -15
- package/src/__tests__/generateTrackingToken.test.ts +53 -0
- package/src/__tests__/integration/ai-agent.test.ts +46 -0
- package/src/__tests__/integration/auth.test.ts +43 -0
- package/src/__tests__/integration/automation-rules.test.ts +68 -0
- package/src/__tests__/integration/buildTestPayload.ts +52 -0
- package/src/__tests__/integration/channels.test.ts +52 -0
- package/src/__tests__/integration/core-behaviors.test.ts +58 -0
- package/src/__tests__/integration/dashboard-volume.test.ts +31 -0
- package/src/__tests__/integration/digest.test.ts +48 -0
- package/src/__tests__/integration/invoice-pdf.test.ts +30 -0
- package/src/__tests__/integration/isolation.test.ts +81 -0
- package/src/__tests__/integration/mentions-invoice.test.ts +50 -0
- package/src/__tests__/integration/nps.test.ts +37 -0
- package/src/__tests__/integration/per-team-sla.test.ts +44 -0
- package/src/__tests__/integration/push.test.ts +75 -0
- package/src/__tests__/integration/sanitization.test.ts +35 -0
- package/src/__tests__/integration/sla-pause.test.ts +39 -0
- package/src/__tests__/integration/smoke.test.ts +26 -0
- package/src/__tests__/integration/snooze.test.ts +68 -0
- package/src/__tests__/integration/teams.test.ts +38 -0
- package/src/__tests__/rateLimiter.test.ts +89 -0
- package/src/__tests__/sanitizeHtml.test.ts +165 -0
- package/src/__tests__/sla.test.ts +258 -0
- package/src/collections/AutomationRules.ts +66 -0
- package/src/collections/NotificationQueue.ts +30 -0
- package/src/collections/PushSubscription.ts +28 -0
- package/src/collections/SatisfactionSurveys.ts +11 -2
- package/src/collections/SlaPolicies.ts +10 -0
- package/src/collections/SupportClients.ts +58 -1
- package/src/collections/SupportTeam.ts +27 -0
- package/src/collections/TicketActivityLog.ts +9 -4
- package/src/collections/TicketMessages.ts +140 -31
- package/src/collections/Tickets.ts +31 -73
- package/src/collections/index.ts +4 -0
- package/src/components/TicketConversation/RewriteDropdown.tsx +86 -0
- package/src/components/TicketConversation/SkeletonText.tsx +23 -0
- package/src/components/TicketConversation/constants.ts +29 -0
- package/src/components/TicketConversation/hooks/useDocumentIdFromUrl.ts +21 -0
- package/src/components/TicketConversation/index.tsx +4 -152
- package/src/endpoints/admin-chat-stream.ts +3 -4
- package/src/endpoints/admin-chat.ts +11 -20
- package/src/endpoints/admin-stats.ts +77 -35
- package/src/endpoints/ai-agent.ts +36 -0
- package/src/endpoints/apply-macro.ts +8 -14
- package/src/endpoints/auth-2fa.ts +12 -12
- package/src/endpoints/auto-close.ts +6 -10
- package/src/endpoints/billing.ts +17 -4
- package/src/endpoints/bulk-action.ts +7 -12
- package/src/endpoints/channels.ts +89 -0
- package/src/endpoints/chat-stream.ts +3 -4
- package/src/endpoints/chat.ts +7 -12
- package/src/endpoints/chatbot.ts +2 -2
- package/src/endpoints/client-intelligence.ts +4 -4
- package/src/endpoints/delete-account.ts +9 -16
- package/src/endpoints/email-stats.ts +2 -2
- package/src/endpoints/escalate.ts +2 -2
- package/src/endpoints/export-csv.ts +2 -2
- package/src/endpoints/export-data.ts +5 -8
- package/src/endpoints/import-conversation.ts +6 -10
- package/src/endpoints/index.ts +22 -1
- package/src/endpoints/invite-collaborator.ts +30 -15
- package/src/endpoints/invoice.ts +127 -0
- package/src/endpoints/kb-search.ts +2 -2
- package/src/endpoints/login.ts +12 -4
- package/src/endpoints/merge-clients.ts +14 -19
- package/src/endpoints/merge-tickets.ts +11 -18
- package/src/endpoints/oauth-google.ts +86 -39
- package/src/endpoints/pending-emails-process.ts +15 -25
- package/src/endpoints/process-digests.ts +93 -0
- package/src/endpoints/process-scheduled.ts +6 -10
- package/src/endpoints/process-snooze.ts +78 -0
- package/src/endpoints/purge-logs.ts +2 -2
- package/src/endpoints/push.ts +49 -0
- package/src/endpoints/resend-notification.ts +3 -4
- package/src/endpoints/round-robin-config.ts +3 -4
- package/src/endpoints/satisfaction.ts +21 -14
- package/src/endpoints/search.ts +5 -8
- package/src/endpoints/seed-kb.ts +3 -4
- package/src/endpoints/send-reminder.ts +6 -9
- package/src/endpoints/settings.ts +5 -2
- package/src/endpoints/signature.ts +3 -4
- package/src/endpoints/sla-check.ts +2 -2
- package/src/endpoints/split-ticket.ts +7 -12
- package/src/endpoints/statuses.ts +2 -2
- package/src/endpoints/ticket-feedback.ts +4 -6
- package/src/endpoints/ticket-synthesis.ts +2 -2
- package/src/endpoints/track-open.ts +16 -28
- package/src/endpoints/transfer-ticket.ts +21 -9
- package/src/endpoints/user-prefs.ts +3 -4
- package/src/hooks/automationRules.ts +84 -0
- package/src/hooks/checkSLA.ts +63 -17
- package/src/plugin.ts +8 -0
- package/src/portal/LiveChat.tsx +2 -63
- package/src/portal/auth/tickets/detail/CloseTicketButton.tsx +10 -0
- package/src/portal/auth/tickets/detail/MarkSolutionButton.tsx +14 -2
- package/src/portal/auth/tickets/detail/MessageActions.tsx +37 -18
- package/src/portal/auth/tickets/detail/ReopenTicketButton.tsx +10 -0
- package/src/portal/auth/tickets/detail/TransferAndInviteActions.tsx +3 -2
- package/src/portal/auth/tickets/detail/page.tsx +2 -2
- package/src/portal/helpers.ts +46 -0
- package/src/portal/login/page.tsx +3 -8
- package/src/portal/types.ts +15 -0
- package/src/types/lucide-react.d.ts +34 -0
- package/src/types/payload-config.d.ts +10 -0
- package/src/utils/adminNotification.ts +2 -2
- package/src/utils/aiAgent.ts +147 -0
- package/src/utils/auth.ts +5 -4
- package/src/utils/channels.ts +36 -0
- package/src/utils/db.ts +73 -0
- package/src/utils/emailTemplate.ts +8 -1
- package/src/utils/fireWebhooks.ts +4 -6
- package/src/utils/generateTicketSynthesis.ts +7 -12
- package/src/utils/invoicePdf.ts +88 -0
- package/src/utils/notificationQueue.ts +36 -0
- package/src/utils/push.ts +63 -0
- package/src/utils/readSettings.ts +22 -6
- package/src/utils/sanitizeHtml.ts +57 -0
- package/src/utils/slugs.ts +8 -0
- package/src/utils/teamAccess.ts +27 -0
- package/src/utils/ticketAccess.ts +53 -0
- package/src/utils/webhookDispatcher.ts +4 -6
- package/src/views/BillingView/client.tsx +49 -37
- package/src/views/ChatView/client.tsx +4 -3
- package/src/views/CrmView/client.tsx +7 -7
- package/src/views/EmailTrackingView/client.tsx +7 -6
- package/src/views/ImportConversationView/client.tsx +4 -4
- package/src/views/LogsView/client.tsx +3 -2
- package/src/views/NewTicketView/client.tsx +1 -1
- package/src/views/PendingEmailsView/client.tsx +7 -6
- package/src/views/SupportDashboardView/client.tsx +21 -21
- package/src/views/TicketDetailView/NextActionItem.tsx +30 -0
- package/src/views/TicketDetailView/RewriteDropdown.tsx +63 -0
- package/src/views/TicketDetailView/client.tsx +54 -179
- package/src/views/TicketDetailView/constants.ts +23 -0
- package/src/views/TicketDetailView/helpers.ts +17 -0
- package/src/views/TicketDetailView/types.ts +10 -0
- package/src/views/TicketInboxView/client.tsx +16 -10
- package/src/views/TicketingSettingsView/client.tsx +90 -87
- package/src/views/TimeDashboardView/client.tsx +2 -2
- package/src/views/shared/StatusPill.tsx +24 -12
- package/src/views/shared/dateLocale.ts +5 -0
- package/src/views/shared/locales/en.json +708 -0
- package/src/views/shared/locales/fr.json +708 -0
|
@@ -10,7 +10,12 @@ var CodeBlockInserter = require('../../components/TicketConversation/components/
|
|
|
10
10
|
var config = require('../shared/config');
|
|
11
11
|
var sla = require('../shared/sla');
|
|
12
12
|
var useTranslation = require('../../components/TicketConversation/hooks/useTranslation');
|
|
13
|
+
var dateLocale = require('../shared/dateLocale');
|
|
13
14
|
var s = require('../../styles/TicketDetail.module.scss');
|
|
15
|
+
var constants = require('./constants');
|
|
16
|
+
var helpers = require('./helpers');
|
|
17
|
+
var RewriteDropdown = require('./RewriteDropdown');
|
|
18
|
+
var NextActionItem = require('./NextActionItem');
|
|
14
19
|
|
|
15
20
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
21
|
|
|
@@ -18,139 +23,6 @@ var React__default = /*#__PURE__*/_interopDefault(React);
|
|
|
18
23
|
var Link__default = /*#__PURE__*/_interopDefault(Link);
|
|
19
24
|
var s__default = /*#__PURE__*/_interopDefault(s);
|
|
20
25
|
|
|
21
|
-
const ALIASES = [
|
|
22
|
-
{ value: "Support Consilioweb", label: "En tant que : Support Consilioweb" },
|
|
23
|
-
{ value: "contact@consilioweb.fr", label: "En tant que : contact@consilioweb.fr" }
|
|
24
|
-
];
|
|
25
|
-
const STATUS_STYLE = {
|
|
26
|
-
open: { bg: "#dbeafe", color: "#1e40af" },
|
|
27
|
-
waiting_client: { bg: "#fef3c7", color: "#92400e" },
|
|
28
|
-
resolved: { bg: "#dcfce7", color: "#166534" }
|
|
29
|
-
};
|
|
30
|
-
function timeAgo(d) {
|
|
31
|
-
const date = new Date(d), now = /* @__PURE__ */ new Date();
|
|
32
|
-
if (date.toDateString() === now.toDateString()) return date.toLocaleTimeString("fr-FR", { hour: "2-digit", minute: "2-digit" });
|
|
33
|
-
const y = new Date(now);
|
|
34
|
-
y.setDate(y.getDate() - 1);
|
|
35
|
-
if (date.toDateString() === y.toDateString()) return `Hier, ${date.toLocaleTimeString("fr-FR", { hour: "2-digit", minute: "2-digit" })}`;
|
|
36
|
-
return date.toLocaleDateString("fr-FR", { day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" });
|
|
37
|
-
}
|
|
38
|
-
function dateLabel(d) {
|
|
39
|
-
const date = new Date(d), now = /* @__PURE__ */ new Date();
|
|
40
|
-
if (date.toDateString() === now.toDateString()) return "Aujourd'hui";
|
|
41
|
-
const y = new Date(now);
|
|
42
|
-
y.setDate(y.getDate() - 1);
|
|
43
|
-
if (date.toDateString() === y.toDateString()) return "Hier";
|
|
44
|
-
return date.toLocaleDateString("fr-FR", { day: "numeric", month: "long" });
|
|
45
|
-
}
|
|
46
|
-
const REWRITE_STYLES = [
|
|
47
|
-
{ id: "auto", label: "\u270F\uFE0F Auto", desc: "Garde le ton actuel" },
|
|
48
|
-
{ id: "tutoyer", label: "\u{1F44B} Tutoyer", desc: "Passe en tu" },
|
|
49
|
-
{ id: "vouvoyer", label: "\u{1F3A9} Vouvoyer", desc: "Passe en vous" },
|
|
50
|
-
{ id: "formel", label: "\u{1F4BC} Formel", desc: "Ton professionnel" },
|
|
51
|
-
{ id: "amical", label: "\u{1F60A} Amical", desc: "Ton chaleureux" },
|
|
52
|
-
{ id: "court", label: "\u26A1 Court", desc: "Version concise" }
|
|
53
|
-
];
|
|
54
|
-
const RewriteDropdown = ({ disabled, loading, onSelect, toolbarBtnClass }) => {
|
|
55
|
-
const [open, setOpen] = React.useState(false);
|
|
56
|
-
const ref = React.useRef(null);
|
|
57
|
-
React.useEffect(() => {
|
|
58
|
-
if (!open) return;
|
|
59
|
-
const close = (e) => {
|
|
60
|
-
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
61
|
-
};
|
|
62
|
-
document.addEventListener("mousedown", close);
|
|
63
|
-
return () => document.removeEventListener("mousedown", close);
|
|
64
|
-
}, [open]);
|
|
65
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, style: { position: "relative", display: "inline-block" }, children: [
|
|
66
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
67
|
-
"button",
|
|
68
|
-
{
|
|
69
|
-
type: "button",
|
|
70
|
-
className: toolbarBtnClass,
|
|
71
|
-
onClick: () => setOpen(!open),
|
|
72
|
-
disabled,
|
|
73
|
-
style: { fontSize: 11, fontWeight: 700, padding: "4px 10px", width: "auto", display: "flex", alignItems: "center", gap: 4 },
|
|
74
|
-
children: [
|
|
75
|
-
loading ? "..." : "\u270F\uFE0F Reformuler",
|
|
76
|
-
!loading && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 9, opacity: 0.6 }, children: "\u25BC" })
|
|
77
|
-
]
|
|
78
|
-
}
|
|
79
|
-
),
|
|
80
|
-
open && !disabled && !loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
81
|
-
position: "absolute",
|
|
82
|
-
bottom: "100%",
|
|
83
|
-
left: 0,
|
|
84
|
-
marginBottom: 4,
|
|
85
|
-
background: "#fff",
|
|
86
|
-
border: "1px solid #e5e7eb",
|
|
87
|
-
borderRadius: 8,
|
|
88
|
-
boxShadow: "0 4px 16px rgba(0,0,0,0.12)",
|
|
89
|
-
zIndex: 100,
|
|
90
|
-
minWidth: 180,
|
|
91
|
-
overflow: "hidden"
|
|
92
|
-
}, children: REWRITE_STYLES.map((style) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
93
|
-
"button",
|
|
94
|
-
{
|
|
95
|
-
type: "button",
|
|
96
|
-
onClick: () => {
|
|
97
|
-
setOpen(false);
|
|
98
|
-
onSelect(style.id);
|
|
99
|
-
},
|
|
100
|
-
style: {
|
|
101
|
-
display: "flex",
|
|
102
|
-
flexDirection: "column",
|
|
103
|
-
width: "100%",
|
|
104
|
-
padding: "8px 12px",
|
|
105
|
-
border: "none",
|
|
106
|
-
background: "transparent",
|
|
107
|
-
cursor: "pointer",
|
|
108
|
-
textAlign: "left",
|
|
109
|
-
borderBottom: "1px solid #f3f4f6"
|
|
110
|
-
},
|
|
111
|
-
onMouseEnter: (e) => {
|
|
112
|
-
e.currentTarget.style.background = "#f9fafb";
|
|
113
|
-
},
|
|
114
|
-
onMouseLeave: (e) => {
|
|
115
|
-
e.currentTarget.style.background = "transparent";
|
|
116
|
-
},
|
|
117
|
-
children: [
|
|
118
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, fontWeight: 600 }, children: style.label }),
|
|
119
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10, color: "#9ca3af" }, children: style.desc })
|
|
120
|
-
]
|
|
121
|
-
},
|
|
122
|
-
style.id
|
|
123
|
-
)) })
|
|
124
|
-
] });
|
|
125
|
-
};
|
|
126
|
-
function NextActionItem({ action, index, onToggle }) {
|
|
127
|
-
const [pending, setPending] = React.useState(false);
|
|
128
|
-
const labelMap = { now: "Maintenant", today: "Aujourd'hui", "this-week": "Cette semaine" };
|
|
129
|
-
const done = !!action.done;
|
|
130
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: s__default.default.aiCardNextAction, children: [
|
|
131
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
132
|
-
"button",
|
|
133
|
-
{
|
|
134
|
-
type: "button",
|
|
135
|
-
className: `${s__default.default.aiCardNextCheck} ${done ? s__default.default.aiCardNextCheckDone : ""}`,
|
|
136
|
-
onClick: async () => {
|
|
137
|
-
setPending(true);
|
|
138
|
-
try {
|
|
139
|
-
await onToggle(!done);
|
|
140
|
-
} finally {
|
|
141
|
-
setPending(false);
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
"aria-pressed": done,
|
|
145
|
-
"aria-label": done ? "Marquer non fait" : "Marquer fait",
|
|
146
|
-
disabled: pending,
|
|
147
|
-
children: done && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\u2713" })
|
|
148
|
-
}
|
|
149
|
-
),
|
|
150
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `${s__default.default.aiCardNextLabel} ${done ? s__default.default.aiCardNextLabelDone : ""}`, children: action.label }),
|
|
151
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.aiCardNextWhen, children: labelMap[action.priority] || action.priority })
|
|
152
|
-
] });
|
|
153
|
-
}
|
|
154
26
|
const TicketDetailClient = () => {
|
|
155
27
|
const { t } = useTranslation.useTranslation();
|
|
156
28
|
const searchParams = navigation.useSearchParams();
|
|
@@ -705,12 +577,12 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
705
577
|
if (!ticketId) return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 60, textAlign: "center", color: "#94a3b8", fontSize: 14 }, children: t("detail.selectTicket") });
|
|
706
578
|
if (loading) return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 60, textAlign: "center", color: "#94a3b8", fontSize: 14 }, children: t("common.loading") });
|
|
707
579
|
if (!ticket) return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 60, textAlign: "center", color: "#94a3b8", fontSize: 14 }, children: t("detail.notFound") });
|
|
708
|
-
const st = STATUS_STYLE[ticket.status || "open"] || STATUS_STYLE.open;
|
|
580
|
+
const st = constants.STATUS_STYLE[ticket.status || "open"] || constants.STATUS_STYLE.open;
|
|
709
581
|
const totalMin = timeEntries.reduce((a, e) => a + (e.duration || 0), 0);
|
|
710
582
|
const initials = client ? `${(client.firstName?.[0] || "").toUpperCase()}${(client.lastName?.[0] || "").toUpperCase()}` : "?";
|
|
711
583
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.page, children: [
|
|
712
584
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.topBar, children: [
|
|
713
|
-
/* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/admin/support/inbox", className: s__default.default.backLink, "aria-label": "
|
|
585
|
+
/* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/admin/support/inbox", className: s__default.default.backLink, "aria-label": t("detail.backToInbox"), children: "\u2190" }),
|
|
714
586
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.ticketMeta, children: [
|
|
715
587
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: s__default.default.ticketNumber, children: [
|
|
716
588
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: ticket.ticketNumber }),
|
|
@@ -763,7 +635,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
763
635
|
});
|
|
764
636
|
if (slaInfo.state !== "breach") return null;
|
|
765
637
|
const duration = sla.formatSlaRemaining(slaInfo.remainingMs).replace(/^−/, "");
|
|
766
|
-
const target = slaInfo.due ? new Date(slaInfo.due).toLocaleString(
|
|
638
|
+
const target = slaInfo.due ? new Date(slaInfo.due).toLocaleString(dateLocale.DATE_LOCALE, { day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" }) : "";
|
|
767
639
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.slaBanner, role: "alert", children: [
|
|
768
640
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.slaBannerIcon, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
769
641
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 9v4M12 17h.01" }),
|
|
@@ -818,7 +690,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
818
690
|
const isAdmin = msg.authorType === "admin";
|
|
819
691
|
const isPendingDelete = undoToast?.msgId === msg.id;
|
|
820
692
|
return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
821
|
-
showDate && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.dateSeparator, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.dateSeparatorText, children: dateLabel(msg.createdAt) }) }),
|
|
693
|
+
showDate && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.dateSeparator, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.dateSeparatorText, children: helpers.dateLabel(msg.createdAt) }) }),
|
|
822
694
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${s__default.default.message} ${isAdmin ? s__default.default.messageAdmin : s__default.default.messageClient} ${msg.isInternal ? s__default.default.messageInternal : ""}`, style: isPendingDelete ? { opacity: 0.3, pointerEvents: "none" } : void 0, children: [
|
|
823
695
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
824
696
|
"div",
|
|
@@ -833,20 +705,20 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
833
705
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.messageContent, children: [
|
|
834
706
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.messageHeader, children: [
|
|
835
707
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.messageAuthor, children: msg.fromAlias || (isAdmin ? "Support" : msg.authorType === "email" ? "Email" : client?.firstName || "Client") }),
|
|
836
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.messageTime, children: timeAgo(msg.createdAt) }),
|
|
837
|
-
msg.isInternal && /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.badge, style: { background: "#fef3c7", color: "#92400e" }, children: "
|
|
838
|
-
msg.isSolution && /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.badge, style: { background: "#dcfce7", color: "#166534" }, children: "
|
|
708
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.messageTime, children: helpers.timeAgo(msg.createdAt) }),
|
|
709
|
+
msg.isInternal && /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.badge, style: { background: "#fef3c7", color: "#92400e" }, children: t("detail.badgeInternal") }),
|
|
710
|
+
msg.isSolution && /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.badge, style: { background: "#dcfce7", color: "#166534" }, children: t("detail.badgeSolution") }),
|
|
839
711
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.messageMeta, children: isAdmin && !msg.isInternal && (() => {
|
|
840
712
|
const ext = msg;
|
|
841
713
|
if (ext.emailOpenedAt) {
|
|
842
|
-
const d = new Date(ext.emailOpenedAt).toLocaleString(
|
|
714
|
+
const d = new Date(ext.emailOpenedAt).toLocaleString(dateLocale.DATE_LOCALE, { day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" });
|
|
843
715
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "#16a34a", cursor: "help" }, title: `Ouvert le ${d}`, children: [
|
|
844
716
|
"\u2713\u2713 Lu ",
|
|
845
717
|
d
|
|
846
718
|
] });
|
|
847
719
|
}
|
|
848
720
|
if (ext.emailSentAt) {
|
|
849
|
-
const d = new Date(ext.emailSentAt).toLocaleString(
|
|
721
|
+
const d = new Date(ext.emailSentAt).toLocaleString(dateLocale.DATE_LOCALE, { day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" });
|
|
850
722
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "#2563eb", cursor: "help" }, title: `Envoy\xE9 le ${d}`, children: [
|
|
851
723
|
"\u2713 Envoy\xE9 ",
|
|
852
724
|
d
|
|
@@ -865,7 +737,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
865
737
|
setEditingHtml(html);
|
|
866
738
|
setEditingBody(text);
|
|
867
739
|
},
|
|
868
|
-
placeholder: "
|
|
740
|
+
placeholder: t("detail.editPlaceholder"),
|
|
869
741
|
minHeight: 120,
|
|
870
742
|
onFileUpload: async (file) => {
|
|
871
743
|
try {
|
|
@@ -883,8 +755,8 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
883
755
|
}
|
|
884
756
|
),
|
|
885
757
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 6, justifyContent: "flex-end" }, children: [
|
|
886
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: cancelEditMessage, disabled: editSaving, style: { padding: "5px 12px", fontSize: 12, borderRadius: 5, border: "1px solid var(--theme-elevation-200)", background: "var(--theme-elevation-0)", color: "var(--theme-text)", cursor: "pointer" }, children: "
|
|
887
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: saveEditMessage, disabled: editSaving || !editingBody.trim(), style: { padding: "5px 12px", fontSize: 12, fontWeight: 600, borderRadius: 5, border: "none", background: "#2563eb", color: "#fff", cursor: editSaving ? "wait" : "pointer", opacity: editSaving ? 0.6 : 1 }, children: editSaving ? "
|
|
758
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: cancelEditMessage, disabled: editSaving, style: { padding: "5px 12px", fontSize: 12, borderRadius: 5, border: "1px solid var(--theme-elevation-200)", background: "var(--theme-elevation-0)", color: "var(--theme-text)", cursor: "pointer" }, children: t("common.cancel") }),
|
|
759
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: saveEditMessage, disabled: editSaving || !editingBody.trim(), style: { padding: "5px 12px", fontSize: 12, fontWeight: 600, borderRadius: 5, border: "none", background: "#2563eb", color: "#fff", cursor: editSaving ? "wait" : "pointer", opacity: editSaving ? 0.6 : 1 }, children: editSaving ? t("detail.editSaving") : t("detail.editSave") })
|
|
888
760
|
] })
|
|
889
761
|
] }) : msg.deletedAt ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.messageBody, style: { color: "#94a3b8", fontStyle: "italic" }, children: t("detail.messageDeleted") }) : msg.bodyHtml && CodeBlock.hasCodeBlocks(msg.bodyHtml.replace(/<[^>]+>/g, "")) ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock.CodeBlockRendererHtml, { html: msg.bodyHtml }) : msg.bodyHtml ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${s__default.default.messageBody} ${s__default.default.rteDisplay}`, dangerouslySetInnerHTML: { __html: msg.bodyHtml } }) : CodeBlock.hasCodeBlocks(msg.body) ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock.MessageWithCodeBlocks, { text: msg.body, style: { fontSize: "13px", lineHeight: 1.5 } }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.messageBody, children: msg.body }),
|
|
890
762
|
Array.isArray(msg.attachments) && msg.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.attachments, children: msg.attachments.map((att, i) => {
|
|
@@ -897,7 +769,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
897
769
|
}) })
|
|
898
770
|
] }),
|
|
899
771
|
editingMsgId !== msg.id && !msg.deletedAt && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.messageActions, children: [
|
|
900
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.actionIcon, title: "
|
|
772
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.actionIcon, title: t("detail.editMessage"), "aria-label": t("detail.editMessageLabel"), onClick: () => startEditMessage(msg), style: { fontSize: 11, width: "auto", padding: "4px 8px" }, children: t("detail.editMessage") }),
|
|
901
773
|
/* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.actionIcon} ${s__default.default.danger}`, title: t("actions.deleteMessage"), "aria-label": t("actions.deleteMessage"), onClick: () => handleDeleteMessage(msg.id), style: { fontSize: 11, width: "auto", padding: "4px 8px" }, children: t("actions.deleteMessage") }),
|
|
902
774
|
features.splitTicket && !msg.isInternal && /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.actionIcon, title: t("actions.extractMessage"), "aria-label": t("actions.extractToNewTicket"), onClick: () => {
|
|
903
775
|
setSplitModal({ messageId: msg.id, preview: msg.body.slice(0, 200) });
|
|
@@ -963,7 +835,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
963
835
|
children: aiReplying ? `\u23F3 ${t("composer.aiSuggestion.loading")}` : `\u2728 ${t("detail.iaSuggestion")}`
|
|
964
836
|
}
|
|
965
837
|
),
|
|
966
|
-
/* @__PURE__ */ jsxRuntime.jsx(RewriteDropdown, { disabled: aiRewriting || !replyBody.trim(), loading: aiRewriting, onSelect: (style) => handleAiRewrite(style), toolbarBtnClass: s__default.default.toolbarBtn })
|
|
838
|
+
/* @__PURE__ */ jsxRuntime.jsx(RewriteDropdown.RewriteDropdown, { disabled: aiRewriting || !replyBody.trim(), loading: aiRewriting, onSelect: (style) => handleAiRewrite(style), toolbarBtnClass: s__default.default.toolbarBtn })
|
|
967
839
|
] }),
|
|
968
840
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
969
841
|
CodeBlockInserter.CodeBlockInserter,
|
|
@@ -993,7 +865,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
993
865
|
},
|
|
994
866
|
disabled: applyingMacro,
|
|
995
867
|
style: { marginLeft: 0 },
|
|
996
|
-
"aria-label": "
|
|
868
|
+
"aria-label": t("detail.macros"),
|
|
997
869
|
children: [
|
|
998
870
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: applyingMacro ? t("detail.applyingMacro") : t("detail.macros") }),
|
|
999
871
|
macros.map((m) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: m.id, children: m.name }, m.id))
|
|
@@ -1001,7 +873,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1001
873
|
}
|
|
1002
874
|
),
|
|
1003
875
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.toolbarDivider }),
|
|
1004
|
-
features.canned && cannedResponses.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("select", { className: s__default.default.cannedSelect, "aria-label": "
|
|
876
|
+
features.canned && cannedResponses.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("select", { className: s__default.default.cannedSelect, "aria-label": t("detail.cannedResponses"), onChange: (e) => {
|
|
1005
877
|
const cr = cannedResponses.find((c) => String(c.id) === e.target.value);
|
|
1006
878
|
if (cr) {
|
|
1007
879
|
let b = cr.body;
|
|
@@ -1046,11 +918,8 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1046
918
|
}
|
|
1047
919
|
),
|
|
1048
920
|
pendingFiles.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.uploadPreview, children: pendingFiles.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.uploadPreviewItem, children: [
|
|
1049
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1050
|
-
|
|
1051
|
-
f.name
|
|
1052
|
-
] }),
|
|
1053
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.uploadRemoveBtn, "aria-label": `Retirer ${f.name}`, onClick: () => setPendingFiles((prev) => prev.filter((_, j) => j !== i)), children: "\xD7" })
|
|
921
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("detail.uploadItem", { name: f.name }) }),
|
|
922
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.uploadRemoveBtn, "aria-label": t("detail.removeUpload", { name: f.name }), onClick: () => setPendingFiles((prev) => prev.filter((_, j) => j !== i)), children: "\xD7" })
|
|
1054
923
|
] }, i)) })
|
|
1055
924
|
] }),
|
|
1056
925
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.composerFooter, children: [
|
|
@@ -1069,8 +938,8 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1069
938
|
},
|
|
1070
939
|
style: { fontSize: "12px", padding: "4px 8px", fontWeight: 600, borderRadius: 6, border: "1px solid var(--theme-elevation-200)", background: "var(--theme-elevation-0)", color: "var(--theme-text)" },
|
|
1071
940
|
children: [
|
|
1072
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "
|
|
1073
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "client", children: "
|
|
941
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: t("detail.sendAsSupport") }),
|
|
942
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "client", children: t("detail.sendAsClient") })
|
|
1074
943
|
]
|
|
1075
944
|
}
|
|
1076
945
|
),
|
|
@@ -1084,7 +953,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1084
953
|
title: t("composer.aliases.tooltip"),
|
|
1085
954
|
children: [
|
|
1086
955
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: t("composer.aliases.self") }),
|
|
1087
|
-
ALIASES.map((a) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: a.value, children: a.label }, a.value))
|
|
956
|
+
constants.ALIASES.map((a) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: a.value, children: a.label }, a.value))
|
|
1088
957
|
]
|
|
1089
958
|
}
|
|
1090
959
|
),
|
|
@@ -1105,7 +974,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1105
974
|
/* @__PURE__ */ jsxRuntime.jsx("kbd", { children: "\u2318" }),
|
|
1106
975
|
/* @__PURE__ */ jsxRuntime.jsx("kbd", { children: "\u21B5" })
|
|
1107
976
|
] }),
|
|
1108
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.sendBtn} ${isInternal ? s__default.default.sendBtnInternal : ""}`, onClick: handleSend, disabled: sending || !replyBody.trim(), "data-action": "send-reply", children: sending ? t("detail.sending") : sendAsClient ? "
|
|
977
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.sendBtn} ${isInternal ? s__default.default.sendBtnInternal : ""}`, onClick: handleSend, disabled: sending || !replyBody.trim(), "data-action": "send-reply", children: sending ? t("detail.sending") : sendAsClient ? t("detail.addClientMessage") : isInternal ? t("detail.sendNote") : t("detail.sendReply") })
|
|
1109
978
|
] })
|
|
1110
979
|
]
|
|
1111
980
|
}
|
|
@@ -1178,7 +1047,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1178
1047
|
clientSummary && clientSummary.summary && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${s__default.default.sideSection} ${s__default.default.aiCard}`, children: [
|
|
1179
1048
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.aiCardTitle, children: [
|
|
1180
1049
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.aiCardIcon, "aria-hidden": true, children: "\u2728" }),
|
|
1181
|
-
"
|
|
1050
|
+
t("detail.aiCard.title")
|
|
1182
1051
|
] }),
|
|
1183
1052
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: s__default.default.aiCardLead, children: clientSummary.summary }),
|
|
1184
1053
|
clientSummary.recurringTopics && clientSummary.recurringTopics.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.aiCardChips, children: clientSummary.recurringTopics.slice(0, 5).map((tp, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.aiChip, children: tp.topic }, `tp-${i}`)) }),
|
|
@@ -1189,7 +1058,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1189
1058
|
clientSummary?.nextActions && clientSummary.nextActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1190
1059
|
/* @__PURE__ */ jsxRuntime.jsx("h5", { className: s__default.default.aiCardNextTitle, children: t("detail.aiCard.nextActions.title") }),
|
|
1191
1060
|
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: s__default.default.aiCardNextActions, children: clientSummary.nextActions.map((action, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1192
|
-
NextActionItem,
|
|
1061
|
+
NextActionItem.NextActionItem,
|
|
1193
1062
|
{
|
|
1194
1063
|
action,
|
|
1195
1064
|
index: i,
|
|
@@ -1257,12 +1126,12 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1257
1126
|
":",
|
|
1258
1127
|
String(timerSeconds % 60).padStart(2, "0")
|
|
1259
1128
|
] }),
|
|
1260
|
-
!timerRunning ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.timerBtn, onClick: () => setTimerRunning(true), "aria-label": "
|
|
1129
|
+
!timerRunning ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.timerBtn, onClick: () => setTimerRunning(true), "aria-label": t("detail.timerStart"), children: timerSeconds > 0 ? "\u25B6" : "\u25B6 Go" }) : /* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.timerBtn} ${s__default.default.timerBtnRunning}`, onClick: () => setTimerRunning(false), "aria-label": t("detail.timerPause"), children: "\u23F8 Pause" }),
|
|
1261
1130
|
timerSeconds >= 60 && !timerRunning && /* @__PURE__ */ jsxRuntime.jsxs("button", { className: `${s__default.default.timerBtn} ${s__default.default.timerBtnGhost}`, onClick: () => {
|
|
1262
1131
|
handleTimerSave();
|
|
1263
1132
|
localStorage.removeItem(`timer-sec-${ticketId}`);
|
|
1264
1133
|
localStorage.removeItem(`timer-run-${ticketId}`);
|
|
1265
|
-
}, "aria-label": "
|
|
1134
|
+
}, "aria-label": t("detail.timerSave"), children: [
|
|
1266
1135
|
"\u{1F4BE} ",
|
|
1267
1136
|
Math.round(timerSeconds / 60),
|
|
1268
1137
|
"m"
|
|
@@ -1281,11 +1150,11 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1281
1150
|
fetchAll();
|
|
1282
1151
|
} catch {
|
|
1283
1152
|
}
|
|
1284
|
-
}, style: { fontSize: 11 }, children: "
|
|
1153
|
+
}, style: { fontSize: 11 }, children: t("detail.addTime") })
|
|
1285
1154
|
] }),
|
|
1286
1155
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8, fontSize: 11, color: "var(--theme-elevation-500)" }, children: [
|
|
1287
1156
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "2px 0", alignItems: "center" }, children: [
|
|
1288
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "
|
|
1157
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("detail.billing.billable") }),
|
|
1289
1158
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1290
1159
|
"button",
|
|
1291
1160
|
{
|
|
@@ -1298,12 +1167,12 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1298
1167
|
}
|
|
1299
1168
|
},
|
|
1300
1169
|
style: { fontWeight: 600, color: ticket.billable !== false ? "#16a34a" : "#dc2626", background: "none", border: "none", cursor: "pointer", fontSize: 11, textDecoration: "underline" },
|
|
1301
|
-
children: ticket.billable !== false ? "
|
|
1170
|
+
children: ticket.billable !== false ? t("detail.billing.yes") : t("detail.billing.no")
|
|
1302
1171
|
}
|
|
1303
1172
|
)
|
|
1304
1173
|
] }),
|
|
1305
1174
|
totalMin > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "2px 0" }, children: [
|
|
1306
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "
|
|
1175
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("detail.billing.estimatedAmount") }),
|
|
1307
1176
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 700, color: "var(--theme-text)" }, children: [
|
|
1308
1177
|
(totalMin / 60 * 60).toFixed(0),
|
|
1309
1178
|
"\u20AC"
|
|
@@ -1311,7 +1180,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1311
1180
|
] })
|
|
1312
1181
|
] }),
|
|
1313
1182
|
timeEntries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 8, fontSize: 11 }, children: timeEntries.slice(0, 6).map((e) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "3px 0", color: "var(--theme-elevation-500)" }, children: [
|
|
1314
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: new Date(e.date).toLocaleDateString(
|
|
1183
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: new Date(e.date).toLocaleDateString(dateLocale.DATE_LOCALE, { day: "numeric", month: "short" }) }),
|
|
1315
1184
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { title: e.description, style: { fontWeight: 600, cursor: e.description ? "help" : "default" }, children: [
|
|
1316
1185
|
e.duration,
|
|
1317
1186
|
"min"
|
|
@@ -1323,7 +1192,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1323
1192
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.tagsWrap, children: [
|
|
1324
1193
|
tags.map((tag) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: s__default.default.tagChip, children: [
|
|
1325
1194
|
tag,
|
|
1326
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.tagRemove, "aria-label":
|
|
1195
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.tagRemove, "aria-label": t("detail.removeTag", { tag }), onClick: () => handleRemoveTag(tag), children: "\xD7" })
|
|
1327
1196
|
] }, tag)),
|
|
1328
1197
|
addingTag ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1329
1198
|
"input",
|
|
@@ -1339,17 +1208,17 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1339
1208
|
}
|
|
1340
1209
|
},
|
|
1341
1210
|
onBlur: handleAddTag,
|
|
1342
|
-
placeholder: "
|
|
1211
|
+
placeholder: t("detail.tagPlaceholder"),
|
|
1343
1212
|
autoFocus: true
|
|
1344
1213
|
}
|
|
1345
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.tagAddBtn, onClick: () => setAddingTag(true), "aria-label": "
|
|
1214
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.tagAddBtn, onClick: () => setAddingTag(true), "aria-label": t("detail.addTag"), children: t("detail.addTagBtn") })
|
|
1346
1215
|
] })
|
|
1347
1216
|
] }),
|
|
1348
1217
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.sideSection, children: [
|
|
1349
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.sideSectionTitle, children: "
|
|
1218
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.sideSectionTitle, children: t("detail.billing.title") }),
|
|
1350
1219
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
1351
1220
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1352
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: "
|
|
1221
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: t("detail.billing.type") }),
|
|
1353
1222
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1354
1223
|
"select",
|
|
1355
1224
|
{
|
|
@@ -1368,14 +1237,14 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1368
1237
|
},
|
|
1369
1238
|
style: { fontSize: 12, padding: "4px 8px", borderRadius: 6, border: "1px solid #e5e7eb", background: "#fff" },
|
|
1370
1239
|
children: [
|
|
1371
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "hourly", children: "
|
|
1372
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "flat", children: "
|
|
1240
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "hourly", children: t("detail.billing.hourly") }),
|
|
1241
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "flat", children: t("detail.billing.flat") })
|
|
1373
1242
|
]
|
|
1374
1243
|
}
|
|
1375
1244
|
)
|
|
1376
1245
|
] }),
|
|
1377
1246
|
ticket?.billingType === "flat" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1378
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: "
|
|
1247
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: t("detail.billing.flatAmount") }),
|
|
1379
1248
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
1380
1249
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1381
1250
|
"input",
|
|
@@ -1403,7 +1272,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1403
1272
|
] })
|
|
1404
1273
|
] }),
|
|
1405
1274
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1406
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: "
|
|
1275
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: t("detail.billing.billedAmount") }),
|
|
1407
1276
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
1408
1277
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1409
1278
|
"input",
|
|
@@ -1431,7 +1300,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1431
1300
|
] })
|
|
1432
1301
|
] }),
|
|
1433
1302
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
1434
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: "
|
|
1303
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: t("detail.billing.payment") }),
|
|
1435
1304
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1436
1305
|
"select",
|
|
1437
1306
|
{
|
|
@@ -1450,16 +1319,16 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1450
1319
|
},
|
|
1451
1320
|
style: { fontSize: 12, padding: "4px 8px", borderRadius: 6, border: "1px solid #e5e7eb", background: "#fff" },
|
|
1452
1321
|
children: [
|
|
1453
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "unpaid", children: "
|
|
1454
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "partial", children: "
|
|
1455
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "paid", children: "
|
|
1322
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "unpaid", children: t("detail.billing.unpaid") }),
|
|
1323
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "partial", children: t("detail.billing.partial") }),
|
|
1324
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "paid", children: t("detail.billing.paid") })
|
|
1456
1325
|
]
|
|
1457
1326
|
}
|
|
1458
1327
|
)
|
|
1459
1328
|
] })
|
|
1460
1329
|
] })
|
|
1461
1330
|
] }),
|
|
1462
|
-
summaryLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.sideSection, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "var(--theme-elevation-400)", textAlign: "center", padding: 8 }, children: "
|
|
1331
|
+
summaryLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.sideSection, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "var(--theme-elevation-400)", textAlign: "center", padding: 8 }, children: t("detail.loadingSummary") }) })
|
|
1463
1332
|
] }),
|
|
1464
1333
|
sidebarTab === "client" && /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "tabpanel", id: "sidebar-panel-client", "aria-labelledby": "sidebar-tab-client", children: [
|
|
1465
1334
|
client && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.sideSection, children: [
|
|
@@ -1487,7 +1356,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1487
1356
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.previousTicketsSubject, children: pt.subject || `#${pt.id}` }),
|
|
1488
1357
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: s__default.default.previousTicketsMeta, children: [
|
|
1489
1358
|
pt.status ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.previousTicketsStatus, children: pt.status }) : null,
|
|
1490
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.previousTicketsDate, children: new Date(pt.createdAt).toLocaleDateString(
|
|
1359
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s__default.default.previousTicketsDate, children: new Date(pt.createdAt).toLocaleDateString(dateLocale.DATE_LOCALE, { day: "numeric", month: "short", year: "numeric" }) })
|
|
1491
1360
|
] })
|
|
1492
1361
|
] }) }, pt.id)) })
|
|
1493
1362
|
] })
|
|
@@ -1498,23 +1367,23 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1498
1367
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.activityDot, style: { backgroundColor: a.actorType === "admin" ? "#2563eb" : a.actorType === "system" ? "#6b7280" : "#16a34a" } }),
|
|
1499
1368
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.activityContent, children: [
|
|
1500
1369
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.activityText, children: (a.detail || a.action).slice(0, 120) }),
|
|
1501
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.activityTime, children: timeAgo(a.createdAt) })
|
|
1370
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.activityTime, children: helpers.timeAgo(a.createdAt) })
|
|
1502
1371
|
] })
|
|
1503
1372
|
] }, a.id))
|
|
1504
1373
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.sideSection, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.previousTicketsEmpty, children: "\u2014" }) }) })
|
|
1505
1374
|
] })
|
|
1506
1375
|
] }),
|
|
1507
1376
|
undoToast && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.undoToast, role: "alert", children: [
|
|
1508
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "
|
|
1509
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.undoBtn, onClick: handleUndoDelete, children: "
|
|
1377
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("detail.messageDeletedToast") }),
|
|
1378
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.undoBtn, onClick: handleUndoDelete, children: t("common.cancel") })
|
|
1510
1379
|
] }),
|
|
1511
1380
|
splitModal && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.splitOverlay, onClick: (e) => {
|
|
1512
1381
|
if (e.target === e.currentTarget) {
|
|
1513
1382
|
setSplitModal(null);
|
|
1514
1383
|
setSplitSubject("");
|
|
1515
1384
|
}
|
|
1516
|
-
}, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.splitModal, role: "dialog", "aria-label": "
|
|
1517
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: s__default.default.splitTitle, children: "
|
|
1385
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.splitModal, role: "dialog", "aria-label": t("actions.extractToNewTicket"), children: [
|
|
1386
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: s__default.default.splitTitle, children: t("actions.extractToNewTicket") }),
|
|
1518
1387
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s__default.default.splitPreview, children: splitModal.preview }),
|
|
1519
1388
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1520
1389
|
"input",
|
|
@@ -1525,7 +1394,7 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1525
1394
|
onKeyDown: (e) => {
|
|
1526
1395
|
if (e.key === "Enter") handleSplitConfirm();
|
|
1527
1396
|
},
|
|
1528
|
-
placeholder: "
|
|
1397
|
+
placeholder: t("detail.split.subjectPlaceholder"),
|
|
1529
1398
|
autoFocus: true
|
|
1530
1399
|
}
|
|
1531
1400
|
),
|
|
@@ -1533,8 +1402,8 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
|
|
|
1533
1402
|
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.splitCancelBtn, onClick: () => {
|
|
1534
1403
|
setSplitModal(null);
|
|
1535
1404
|
setSplitSubject("");
|
|
1536
|
-
}, children: "
|
|
1537
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.splitConfirmBtn, onClick: handleSplitConfirm, disabled: !splitSubject.trim(), children: "
|
|
1405
|
+
}, children: t("common.cancel") }),
|
|
1406
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: s__default.default.splitConfirmBtn, onClick: handleSplitConfirm, disabled: !splitSubject.trim(), children: t("detail.split.createBtn") })
|
|
1538
1407
|
] })
|
|
1539
1408
|
] }) })
|
|
1540
1409
|
] });
|