@consilioweb/payload-support 5.0.0 → 6.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 (116) hide show
  1. package/README.md +249 -22
  2. package/dist/components/RichTextEditor/index.js +1 -1
  3. package/dist/components/TicketConversation/RewriteDropdown.js +1 -1
  4. package/dist/components/TicketConversation/components/AISummaryPanel.js +3 -0
  5. package/dist/components/TicketConversation/components/ActionPanels.js +13 -8
  6. package/dist/components/TicketConversation/components/ClientHistory.js +1 -0
  7. package/dist/components/TicketConversation/components/CodeBlock.js +1 -0
  8. package/dist/components/TicketConversation/components/CodeBlockInserter.js +1 -1
  9. package/dist/components/TicketConversation/components/QuickActions.js +10 -8
  10. package/dist/components/TicketConversation/components/TicketHeader.js +2 -0
  11. package/dist/components/TicketConversation/components/TimeTrackingPanel.js +15 -9
  12. package/dist/components/TicketConversation/index.d.ts +10 -0
  13. package/dist/components/TicketConversation/index.js +25 -7
  14. package/dist/index.cjs +306 -60
  15. package/dist/index.d.cts +107 -38
  16. package/dist/index.d.ts +107 -38
  17. package/dist/index.js +300 -59
  18. package/dist/styles/BillingView.module.scss +11 -11
  19. package/dist/styles/ChatView.module.scss +7 -7
  20. package/dist/styles/CommandPalette.module.scss +1 -1
  21. package/dist/styles/CrmView.module.scss +9 -9
  22. package/dist/styles/EmailTracking.module.scss +6 -6
  23. package/dist/styles/ImportConversation.module.scss +5 -5
  24. package/dist/styles/Logs.module.scss +5 -5
  25. package/dist/styles/NewTicket.module.scss +2 -2
  26. package/dist/styles/PendingEmails.module.scss +13 -13
  27. package/dist/styles/SupportDashboard.module.scss +24 -8
  28. package/dist/styles/TicketDetail.module.scss +20 -20
  29. package/dist/styles/TicketInbox.module.scss +6 -6
  30. package/dist/styles/TicketingSettings.module.scss +10 -10
  31. package/dist/styles/TimeDashboard.module.scss +6 -6
  32. package/dist/styles/_tokens.scss +3 -1
  33. package/dist/views/BillingView/client.js +15 -8
  34. package/dist/views/ChatView/client.js +2 -0
  35. package/dist/views/CrmView/client.js +2 -0
  36. package/dist/views/EmailTrackingView/client.js +23 -11
  37. package/dist/views/ImportConversationView/client.js +1 -0
  38. package/dist/views/LogsView/client.js +1 -1
  39. package/dist/views/NewTicketView/client.js +20 -13
  40. package/dist/views/PendingEmailsView/client.js +9 -3
  41. package/dist/views/SupportDashboardView/client.js +17 -19
  42. package/dist/views/TicketDetailView/client.js +23 -11
  43. package/dist/views/TicketInboxView/client.js +52 -26
  44. package/dist/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
  45. package/dist/views/TicketingSettingsView/client.js +44 -26
  46. package/dist/views/TimeDashboardView/client.js +10 -7
  47. package/dist/views/shared/ErrorBoundary.d.ts +36 -1
  48. package/dist/views/shared/ErrorBoundary.js +59 -28
  49. package/dist/views/shared/adminTokens.d.ts +15 -5
  50. package/dist/views/shared/adminTokens.js +23 -7
  51. package/dist/views/shared/icons.d.ts +49 -0
  52. package/dist/views/shared/icons.js +92 -0
  53. package/dist/views/shared/locales/en.json +15 -1
  54. package/dist/views/shared/locales/fr.json +15 -1
  55. package/package.json +6 -2
  56. package/scripts/uninstall-data.mjs +178 -0
  57. package/scripts/uninstall.mjs +184 -0
  58. package/src/collections/Tickets.ts +7 -0
  59. package/src/collections/TimeEntries.ts +11 -3
  60. package/src/components/RichTextEditor/index.tsx +1 -1
  61. package/src/components/TicketConversation/RewriteDropdown.tsx +1 -1
  62. package/src/components/TicketConversation/components/AISummaryPanel.tsx +3 -0
  63. package/src/components/TicketConversation/components/ActionPanels.tsx +13 -8
  64. package/src/components/TicketConversation/components/ClientHistory.tsx +1 -0
  65. package/src/components/TicketConversation/components/CodeBlock.tsx +1 -0
  66. package/src/components/TicketConversation/components/CodeBlockInserter.tsx +1 -1
  67. package/src/components/TicketConversation/components/QuickActions.tsx +10 -8
  68. package/src/components/TicketConversation/components/TicketHeader.tsx +2 -0
  69. package/src/components/TicketConversation/components/TimeTrackingPanel.tsx +17 -9
  70. package/src/components/TicketConversation/index.tsx +41 -7
  71. package/src/endpoints/delete-account.ts +191 -47
  72. package/src/endpoints/export-data.ts +104 -4
  73. package/src/endpoints/purge-logs.ts +6 -15
  74. package/src/index.ts +2 -0
  75. package/src/plugin.ts +51 -1
  76. package/src/portal/LiveChat.tsx +1 -1
  77. package/src/portal/auth/profile/page.tsx +3 -2
  78. package/src/portal/icons.tsx +91 -0
  79. package/src/styles/BillingView.module.scss +11 -11
  80. package/src/styles/ChatView.module.scss +7 -7
  81. package/src/styles/CommandPalette.module.scss +1 -1
  82. package/src/styles/CrmView.module.scss +9 -9
  83. package/src/styles/EmailTracking.module.scss +6 -6
  84. package/src/styles/ImportConversation.module.scss +5 -5
  85. package/src/styles/Logs.module.scss +5 -5
  86. package/src/styles/NewTicket.module.scss +2 -2
  87. package/src/styles/PendingEmails.module.scss +13 -13
  88. package/src/styles/SupportDashboard.module.scss +24 -8
  89. package/src/styles/TicketDetail.module.scss +20 -20
  90. package/src/styles/TicketInbox.module.scss +6 -6
  91. package/src/styles/TicketingSettings.module.scss +10 -10
  92. package/src/styles/TimeDashboard.module.scss +6 -6
  93. package/src/styles/_tokens.scss +3 -1
  94. package/src/types.ts +20 -0
  95. package/src/utils/retention.ts +111 -0
  96. package/src/utils/slugs.ts +15 -0
  97. package/src/views/BillingView/client.tsx +17 -8
  98. package/src/views/ChatView/client.tsx +2 -0
  99. package/src/views/CrmView/client.tsx +2 -0
  100. package/src/views/EmailTrackingView/client.tsx +18 -7
  101. package/src/views/ImportConversationView/client.tsx +1 -0
  102. package/src/views/LogsView/client.tsx +1 -1
  103. package/src/views/NewTicketView/client.tsx +22 -13
  104. package/src/views/PendingEmailsView/client.tsx +9 -3
  105. package/src/views/SupportDashboardView/client.tsx +11 -5
  106. package/src/views/TicketDetailView/client.tsx +25 -11
  107. package/src/views/TicketInboxView/client.tsx +47 -7
  108. package/src/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
  109. package/src/views/TicketingSettingsView/client.tsx +201 -144
  110. package/src/views/TimeDashboardView/client.tsx +10 -7
  111. package/src/views/shared/ErrorBoundary.tsx +95 -31
  112. package/src/views/shared/adminTokens.ts +28 -11
  113. package/src/views/shared/icons.tsx +146 -0
  114. package/src/views/shared/locales/en.json +15 -1
  115. package/src/views/shared/locales/fr.json +15 -1
  116. package/src/types/lucide-react.d.ts +0 -42
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
+ import React from 'react';
3
4
  import { s, C } from '../constants.js';
4
5
 
5
6
  function TimeTrackingPanel({
@@ -22,6 +23,8 @@ function TimeTrackingPanel({
22
23
  addingTime,
23
24
  timeSuccess
24
25
  }) {
26
+ const minutesId = React.useId();
27
+ const workDescriptionId = React.useId();
25
28
  const totalH = Math.floor(totalMinutes / 60);
26
29
  const totalM = totalMinutes % 60;
27
30
  return /* @__PURE__ */ jsxs("div", { style: s.section, children: [
@@ -61,6 +64,7 @@ function TimeTrackingPanel({
61
64
  !timerRunning && timerSeconds > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [-5, -1, 1, 5, 15, 30].map((m) => /* @__PURE__ */ jsx(
62
65
  "button",
63
66
  {
67
+ type: "button",
64
68
  onClick: () => setTimerSeconds((p) => Math.max(0, p + m * 60)),
65
69
  style: { width: Math.abs(m) >= 15 ? "32px" : "28px", height: "28px", borderRadius: "6px", border: "1px solid #e2e8f0", background: "white", cursor: "pointer", fontSize: Math.abs(m) >= 15 ? "12px" : "14px", fontWeight: 700, color: "#64748b" },
66
70
  title: `${m > 0 ? "+" : ""}${m} min`,
@@ -68,14 +72,15 @@ function TimeTrackingPanel({
68
72
  },
69
73
  m
70
74
  )) }),
71
- !timerRunning && timerSeconds === 0 && /* @__PURE__ */ jsx("button", { onClick: () => handleTimerStart(true), style: { ...s.btn("#dc2626", false), fontSize: "12px", padding: "6px 16px", display: "flex", alignItems: "center", gap: "6px" }, children: "\u25B6 D\xE9marrer" }),
72
- timerRunning && /* @__PURE__ */ jsx("button", { onClick: handleTimerStop, style: { ...s.btn("#374151", false), fontSize: "12px", padding: "6px 16px", display: "flex", alignItems: "center", gap: "6px" }, children: "\u23F8 Pause" }),
75
+ !timerRunning && timerSeconds === 0 && /* @__PURE__ */ jsx("button", { type: "button", onClick: () => handleTimerStart(true), style: { ...s.btn("#dc2626", false), fontSize: "12px", padding: "6px 16px", display: "flex", alignItems: "center", gap: "6px" }, children: "\u25B6 D\xE9marrer" }),
76
+ timerRunning && /* @__PURE__ */ jsx("button", { type: "button", onClick: handleTimerStop, style: { ...s.btn("#374151", false), fontSize: "12px", padding: "6px 16px", display: "flex", alignItems: "center", gap: "6px" }, children: "\u23F8 Pause" }),
73
77
  !timerRunning && timerSeconds > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
74
- /* @__PURE__ */ jsx("button", { onClick: () => handleTimerStart(false), style: { ...s.btn("#dc2626", false), fontSize: "12px", padding: "6px 14px" }, children: "\u25B6 Reprendre" }),
78
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => handleTimerStart(false), style: { ...s.btn("#dc2626", false), fontSize: "12px", padding: "6px 14px" }, children: "\u25B6 Reprendre" }),
75
79
  /* @__PURE__ */ jsx(
76
80
  "input",
77
81
  {
78
82
  type: "text",
83
+ "aria-label": "Description du temps en cours",
79
84
  value: timerDescription,
80
85
  onChange: (e) => setTimerDescription(e.target.value),
81
86
  placeholder: "Description...",
@@ -85,6 +90,7 @@ function TimeTrackingPanel({
85
90
  /* @__PURE__ */ jsxs(
86
91
  "button",
87
92
  {
93
+ type: "button",
88
94
  onClick: handleTimerSave,
89
95
  disabled: addingTime || timerSeconds < 60,
90
96
  style: { ...s.btn("#16a34a", addingTime || timerSeconds < 60), fontSize: "12px", padding: "6px 14px" },
@@ -96,20 +102,20 @@ function TimeTrackingPanel({
96
102
  ]
97
103
  }
98
104
  ),
99
- /* @__PURE__ */ jsx("button", { onClick: handleTimerDiscard, style: { background: "none", border: "none", cursor: "pointer", fontSize: "14px", color: "#94a3b8", padding: "4px" }, title: "Annuler", children: "\u2715" })
105
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: handleTimerDiscard, style: { background: "none", border: "none", cursor: "pointer", fontSize: "14px", color: "#94a3b8", padding: "4px" }, title: "Annuler", children: "\u2715" })
100
106
  ] }),
101
107
  timerRunning && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "#dc2626", fontWeight: 600 }, children: "\u25CF Enregistrement en cours \u2014 session maintenue active" })
102
108
  ] }),
103
109
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end", flexWrap: "wrap", marginBottom: "14px" }, children: [
104
110
  /* @__PURE__ */ jsxs("div", { children: [
105
- /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "11px", color: C.textSecondary, marginBottom: "3px", fontWeight: 600 }, children: "Min" }),
106
- /* @__PURE__ */ jsx("input", { type: "number", min: "1", value: duration, onChange: (e) => setDuration(e.target.value), placeholder: "30", style: { ...s.input, width: "80px" } })
111
+ /* @__PURE__ */ jsx("label", { htmlFor: minutesId, style: { display: "block", fontSize: "11px", color: C.textSecondary, marginBottom: "3px", fontWeight: 600 }, children: "Min" }),
112
+ /* @__PURE__ */ jsx("input", { id: minutesId, type: "number", min: "1", value: duration, onChange: (e) => setDuration(e.target.value), placeholder: "30", style: { ...s.input, width: "80px" } })
107
113
  ] }),
108
114
  /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
109
- /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "11px", color: C.textSecondary, marginBottom: "3px", fontWeight: 600 }, children: "Description" }),
110
- /* @__PURE__ */ jsx("input", { type: "text", value: timeDescription, onChange: (e) => setTimeDescription(e.target.value), placeholder: "Travail effectu\xE9...", style: { ...s.input, width: "100%" } })
115
+ /* @__PURE__ */ jsx("label", { htmlFor: workDescriptionId, style: { display: "block", fontSize: "11px", color: C.textSecondary, marginBottom: "3px", fontWeight: 600 }, children: "Description" }),
116
+ /* @__PURE__ */ jsx("input", { id: workDescriptionId, type: "text", value: timeDescription, onChange: (e) => setTimeDescription(e.target.value), placeholder: "Travail effectu\xE9...", style: { ...s.input, width: "100%" } })
111
117
  ] }),
112
- /* @__PURE__ */ jsx("button", { onClick: handleAddTime, disabled: addingTime || !duration, style: s.btn(C.amber, addingTime || !duration), children: addingTime ? "..." : "+ Temps" }),
118
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: handleAddTime, disabled: addingTime || !duration, style: s.btn(C.amber, addingTime || !duration), children: addingTime ? "..." : "+ Temps" }),
113
119
  timeSuccess && /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "#16a34a", fontWeight: 600 }, children: timeSuccess })
114
120
  ] }),
115
121
  timeEntries.length > 0 && /* @__PURE__ */ jsx("div", { style: { fontSize: "12px" }, children: /* @__PURE__ */ jsxs("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
@@ -1,4 +1,14 @@
1
1
  import React from 'react';
2
2
  import '../../styles/theme.css';
3
+ /**
4
+ * Payload mounts this component straight from the import map as the `ui` field
5
+ * of the Tickets edit view, so the plugin never gets to render an ancestor for
6
+ * it: the boundary has to live inside the module itself. Without it a single
7
+ * render error in any of the twelve sub-components blanks the whole ticket
8
+ * screen.
9
+ *
10
+ * The document id is used as a reset key so that navigating from a ticket that
11
+ * broke to another one clears the error on its own.
12
+ */
3
13
  declare const TicketConversation: React.FC;
4
14
  export default TicketConversation;
@@ -22,9 +22,10 @@ import { useDocumentIdFromUrl } from './hooks/useDocumentIdFromUrl.js';
22
22
  import { useFeatures } from './hooks/useFeatures.js';
23
23
  import { SkeletonText } from './SkeletonText.js';
24
24
  import { RewriteDropdown } from './RewriteDropdown.js';
25
+ import { AdminErrorBoundary } from '../../views/shared/ErrorBoundary.js';
25
26
  import '../../styles/theme.css';
26
27
 
27
- const TicketConversation = () => {
28
+ const TicketConversationInner = () => {
28
29
  const { id } = useDocumentIdFromUrl();
29
30
  const { features } = useFeatures();
30
31
  const [messages, setMessages] = useState([]);
@@ -368,6 +369,7 @@ const TicketConversation = () => {
368
369
  "input",
369
370
  {
370
371
  type: "text",
372
+ "aria-label": "Rechercher dans la conversation",
371
373
  value: searchQuery,
372
374
  onChange: (e) => setSearchQuery(e.target.value),
373
375
  placeholder: "Rechercher...",
@@ -386,6 +388,7 @@ const TicketConversation = () => {
386
388
  showCollapse && hiddenCount > 0 && /* @__PURE__ */ jsxs(
387
389
  "button",
388
390
  {
391
+ type: "button",
389
392
  onClick: () => setMessagesCollapsed(false),
390
393
  style: {
391
394
  background: "none",
@@ -411,6 +414,7 @@ const TicketConversation = () => {
411
414
  !messagesCollapsed && filtered.length > 1 && !isSearching && /* @__PURE__ */ jsx(
412
415
  "button",
413
416
  {
417
+ type: "button",
414
418
  onClick: () => setMessagesCollapsed(true),
415
419
  style: {
416
420
  background: "none",
@@ -468,6 +472,7 @@ const TicketConversation = () => {
468
472
  msg.authorType === "email" ? /* @__PURE__ */ jsx("span", { style: s.badge(C.emailBg, C.orange), children: "Email" }) : /* @__PURE__ */ jsxs(
469
473
  "select",
470
474
  {
475
+ "aria-label": "Auteur du message",
471
476
  value: msg.authorType,
472
477
  onChange: (e) => handleToggleAuthor(msg.id, e.target.value === "admin" ? "client" : "admin"),
473
478
  disabled: togglingAuthor === msg.id,
@@ -515,6 +520,7 @@ const TicketConversation = () => {
515
520
  !msg.isInternal && !msg.deletedAt && /* @__PURE__ */ jsxs(
516
521
  "button",
517
522
  {
523
+ type: "button",
518
524
  onClick: () => handleSplitMessage(msg.id, ticketSubject),
519
525
  style: { background: "none", border: "none", cursor: "pointer", fontSize: "10px", color: "#6b7280", padding: 0 },
520
526
  title: "Extraire en nouveau ticket",
@@ -554,6 +560,7 @@ const TicketConversation = () => {
554
560
  /* @__PURE__ */ jsx(
555
561
  "textarea",
556
562
  {
563
+ "aria-label": "Editer le message",
557
564
  value: editBody,
558
565
  onChange: (e) => {
559
566
  setEditBody(e.target.value);
@@ -564,8 +571,8 @@ const TicketConversation = () => {
564
571
  }
565
572
  ),
566
573
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", marginTop: "8px" }, children: [
567
- /* @__PURE__ */ jsx("button", { onClick: () => handleEditSave(msg.id), disabled: savingEdit || !editBody.trim() && !editHtml, style: { ...s.btn(C.blue, savingEdit), fontSize: "11px", padding: "5px 12px" }, children: savingEdit ? "..." : "Enregistrer" }),
568
- /* @__PURE__ */ jsx("button", { onClick: handleEditCancel, style: { ...s.ghostBtn("#6b7280"), fontSize: "11px", padding: "5px 12px" }, children: "Annuler" })
574
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => handleEditSave(msg.id), disabled: savingEdit || !editBody.trim() && !editHtml, style: { ...s.btn(C.blue, savingEdit), fontSize: "11px", padding: "5px 12px" }, children: savingEdit ? "..." : "Enregistrer" }),
575
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: handleEditCancel, style: { ...s.ghostBtn("#6b7280"), fontSize: "11px", padding: "5px 12px" }, children: "Annuler" })
569
576
  ] })
570
577
  ] }) : msg.deletedAt ? /* @__PURE__ */ jsx("div", { style: { fontSize: "13px", color: "#94a3b8", fontStyle: "italic" }, children: "Ce message a \xE9t\xE9 supprim\xE9." }) : msg.bodyHtml ? /* @__PURE__ */ jsxs(Fragment, { children: [
571
578
  /* @__PURE__ */ jsx(
@@ -753,6 +760,7 @@ const TicketConversation = () => {
753
760
  features.ai && /* @__PURE__ */ jsx(
754
761
  "button",
755
762
  {
763
+ type: "button",
756
764
  onClick: handleAiSuggestReply,
757
765
  disabled: aiReplying || messages.length === 0,
758
766
  style: { ...s.outlineBtn("#17807c", aiReplying || messages.length === 0), fontSize: "11px", padding: "3px 10px", borderRadius: "14px" },
@@ -780,7 +788,7 @@ const TicketConversation = () => {
780
788
  }
781
789
  ),
782
790
  features.canned && cannedResponses.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
783
- /* @__PURE__ */ jsxs("select", { onChange: handleCannedSelect, style: { ...s.input, fontSize: "11px", padding: "3px 8px", fontWeight: 600 }, children: [
791
+ /* @__PURE__ */ jsxs("select", { "aria-label": "Reponse rapide", onChange: handleCannedSelect, style: { ...s.input, fontSize: "11px", padding: "3px 8px", fontWeight: 600 }, children: [
784
792
  /* @__PURE__ */ jsx("option", { value: "", children: "R\xE9ponse rapide..." }),
785
793
  cannedResponses.map((cr) => /* @__PURE__ */ jsx("option", { value: String(cr.id), children: cr.title }, cr.id))
786
794
  ] }),
@@ -797,6 +805,7 @@ const TicketConversation = () => {
797
805
  /* @__PURE__ */ jsx("div", { style: { border: `1px solid ${C.border}`, borderRadius: "8px", overflow: "hidden" }, children: /* @__PURE__ */ jsx(
798
806
  "textarea",
799
807
  {
808
+ "aria-label": "Reponse au client",
800
809
  value: replyBody,
801
810
  onChange: (e) => {
802
811
  const text = e.target.value;
@@ -810,7 +819,6 @@ const TicketConversation = () => {
810
819
  minHeight: "120px",
811
820
  padding: "12px",
812
821
  border: "none",
813
- outline: "none",
814
822
  fontSize: "14px",
815
823
  lineHeight: 1.5,
816
824
  resize: "vertical",
@@ -828,6 +836,7 @@ const TicketConversation = () => {
828
836
  ref: fileInputRef,
829
837
  type: "file",
830
838
  multiple: true,
839
+ "aria-label": "Joindre des fichiers",
831
840
  onChange: handleReplyFileChange,
832
841
  style: { display: "none" },
833
842
  accept: "image/*,.pdf,.doc,.docx,.txt,.zip"
@@ -850,6 +859,7 @@ const TicketConversation = () => {
850
859
  "button",
851
860
  {
852
861
  type: "button",
862
+ "aria-label": `Retirer la piece jointe ${file.name}`,
853
863
  onClick: () => setReplyFiles((prev) => prev.filter((_, idx) => idx !== i)),
854
864
  style: { border: "none", background: "none", color: "#ef4444", fontWeight: 700, cursor: "pointer", fontSize: "14px", lineHeight: 1 },
855
865
  children: "\xD7"
@@ -861,6 +871,7 @@ const TicketConversation = () => {
861
871
  /* @__PURE__ */ jsxs(
862
872
  "select",
863
873
  {
874
+ "aria-label": "Envoyer en tant que",
864
875
  value: sendAsClient ? "client" : "admin",
865
876
  onChange: (e) => setSendAsClient(e.target.value === "client"),
866
877
  style: { ...s.input, fontSize: "12px", padding: "6px 8px", fontWeight: 600 },
@@ -881,10 +892,11 @@ const TicketConversation = () => {
881
892
  /* @__PURE__ */ jsx("input", { type: "checkbox", checked: notifyClient, onChange: (e) => setNotifyClient(e.target.checked), style: { width: "14px", height: "14px", accentColor: "#16a34a" } }),
882
893
  "Envoyer au client"
883
894
  ] }),
884
- /* @__PURE__ */ jsx("button", { "data-action": "send-reply", onClick: handleSendReply, disabled: sending || !replyBody.trim() && !replyHtml, style: { ...s.btn(isInternal ? C.amber : notifyClient ? "#16a34a" : C.blue, sending || !replyBody.trim() && !replyHtml), fontSize: "13px", padding: "8px 20px", marginLeft: "auto" }, children: sending ? "Envoi..." : isInternal ? "Ajouter note" : notifyClient ? "Envoyer + Notifier" : "Sauvegarder" }),
895
+ /* @__PURE__ */ jsx("button", { type: "button", "data-action": "send-reply", onClick: handleSendReply, disabled: sending || !replyBody.trim() && !replyHtml, style: { ...s.btn(isInternal ? C.amber : notifyClient ? "#16a34a" : C.blue, sending || !replyBody.trim() && !replyHtml), fontSize: "13px", padding: "8px 20px", marginLeft: "auto" }, children: sending ? "Envoi..." : isInternal ? "Ajouter note" : notifyClient ? "Envoyer + Notifier" : "Sauvegarder" }),
885
896
  !isInternal && /* @__PURE__ */ jsx(
886
897
  "button",
887
898
  {
899
+ type: "button",
888
900
  onClick: () => setShowSchedule(!showSchedule),
889
901
  disabled: !replyBody.trim() && !replyHtml,
890
902
  style: { ...s.outlineBtn("#17807c", !replyBody.trim() && !replyHtml), fontSize: "12px", padding: "8px 12px" },
@@ -899,6 +911,7 @@ const TicketConversation = () => {
899
911
  "input",
900
912
  {
901
913
  type: "datetime-local",
914
+ "aria-label": "Date et heure d'envoi programme",
902
915
  value: scheduleDate,
903
916
  onChange: (e) => setScheduleDate(e.target.value),
904
917
  min: (/* @__PURE__ */ new Date()).toISOString().slice(0, 16),
@@ -908,13 +921,14 @@ const TicketConversation = () => {
908
921
  /* @__PURE__ */ jsx(
909
922
  "button",
910
923
  {
924
+ type: "button",
911
925
  onClick: handleScheduleReply,
912
926
  disabled: sending || !scheduleDate || !replyBody.trim() && !replyHtml,
913
927
  style: { ...s.btn("#17807c", sending || !scheduleDate || !replyBody.trim() && !replyHtml), fontSize: "12px", padding: "6px 14px" },
914
928
  children: sending ? "..." : "\u23F0 Programmer"
915
929
  }
916
930
  ),
917
- /* @__PURE__ */ jsx("button", { onClick: () => setShowSchedule(false), style: { background: "none", border: "none", cursor: "pointer", color: "#94a3b8", fontSize: "14px" }, children: "\u2715" })
931
+ /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Annuler la programmation", onClick: () => setShowSchedule(false), style: { background: "none", border: "none", cursor: "pointer", color: "#94a3b8", fontSize: "14px" }, children: "\u2715" })
918
932
  ] }),
919
933
  /* @__PURE__ */ jsxs("div", { style: { fontSize: "11px", color: C.textMuted, marginTop: "4px", textAlign: "right" }, children: [
920
934
  "\u2318",
@@ -1104,6 +1118,10 @@ const TicketConversation = () => {
1104
1118
  ] })
1105
1119
  ] });
1106
1120
  };
1121
+ const TicketConversation = () => {
1122
+ const { id } = useDocumentIdFromUrl();
1123
+ return /* @__PURE__ */ jsx(AdminErrorBoundary, { viewName: "TicketConversation", resetKeys: [id], children: /* @__PURE__ */ jsx(TicketConversationInner, {}) });
1124
+ };
1107
1125
  var TicketConversation_default = TicketConversation;
1108
1126
 
1109
1127
  export { TicketConversation_default as default };