@consilioweb/payload-support 0.6.0 → 0.6.1

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 (84) hide show
  1. package/dist/{styles/theme.css → components/TicketConversation.css} +13 -326
  2. package/dist/components/TicketConversation.js +3004 -0
  3. package/dist/index.cjs +11 -11
  4. package/dist/index.js +11 -11
  5. package/dist/views.cjs +6184 -0
  6. package/dist/{views/TicketingSettingsView/TicketingSettings.module.scss → views.css} +66 -138
  7. package/dist/views.d.cts +30 -0
  8. package/dist/views.d.ts +30 -0
  9. package/dist/views.js +6165 -0
  10. package/package.json +14 -7
  11. package/src/plugin.ts +11 -11
  12. package/src/views.ts +17 -0
  13. package/dist/components/TicketConversation/components/AISummaryPanel.js +0 -76
  14. package/dist/components/TicketConversation/components/ActionPanels.js +0 -118
  15. package/dist/components/TicketConversation/components/ActivityLog.js +0 -23
  16. package/dist/components/TicketConversation/components/ClientBar.js +0 -42
  17. package/dist/components/TicketConversation/components/ClientHistory.js +0 -137
  18. package/dist/components/TicketConversation/components/CodeBlock.js +0 -152
  19. package/dist/components/TicketConversation/components/CodeBlockInserter.js +0 -155
  20. package/dist/components/TicketConversation/components/QuickActions.js +0 -65
  21. package/dist/components/TicketConversation/components/TicketHeader.js +0 -92
  22. package/dist/components/TicketConversation/components/TimeTrackingPanel.js +0 -133
  23. package/dist/components/TicketConversation/config.js +0 -41
  24. package/dist/components/TicketConversation/constants.js +0 -96
  25. package/dist/components/TicketConversation/context.js +0 -11
  26. package/dist/components/TicketConversation/hooks/useAI.js +0 -176
  27. package/dist/components/TicketConversation/hooks/useMessageActions.js +0 -135
  28. package/dist/components/TicketConversation/hooks/useReply.js +0 -187
  29. package/dist/components/TicketConversation/hooks/useTicketActions.js +0 -230
  30. package/dist/components/TicketConversation/hooks/useTimeTracking.js +0 -122
  31. package/dist/components/TicketConversation/hooks/useTranslation.js +0 -70
  32. package/dist/components/TicketConversation/index.js +0 -1123
  33. package/dist/components/TicketConversation/locales/en.json +0 -878
  34. package/dist/components/TicketConversation/locales/fr.json +0 -878
  35. package/dist/components/TicketConversation/types.js +0 -2
  36. package/dist/components/TicketConversation/utils.js +0 -25
  37. package/dist/styles/BillingView.module.scss +0 -311
  38. package/dist/styles/ChatView.module.scss +0 -438
  39. package/dist/styles/CommandPalette.module.scss +0 -160
  40. package/dist/styles/CrmView.module.scss +0 -554
  41. package/dist/styles/EmailTracking.module.scss +0 -238
  42. package/dist/styles/ImportConversation.module.scss +0 -267
  43. package/dist/styles/Layout.module.scss +0 -55
  44. package/dist/styles/Logs.module.scss +0 -164
  45. package/dist/styles/NewTicket.module.scss +0 -143
  46. package/dist/styles/PendingEmails.module.scss +0 -629
  47. package/dist/styles/SupportDashboard.module.scss +0 -649
  48. package/dist/styles/TicketDetail.module.scss +0 -1050
  49. package/dist/styles/TicketInbox.module.scss +0 -296
  50. package/dist/styles/TicketingSettings.module.scss +0 -358
  51. package/dist/styles/TimeDashboard.module.scss +0 -287
  52. package/dist/styles/_tokens.scss +0 -78
  53. package/dist/views/BillingView/client.js +0 -204
  54. package/dist/views/BillingView/index.js +0 -29
  55. package/dist/views/ChatView/client.js +0 -252
  56. package/dist/views/ChatView/index.js +0 -29
  57. package/dist/views/CrmView/client.js +0 -232
  58. package/dist/views/CrmView/index.js +0 -29
  59. package/dist/views/EmailTrackingView/client.js +0 -154
  60. package/dist/views/EmailTrackingView/index.js +0 -29
  61. package/dist/views/ImportConversationView/client.js +0 -204
  62. package/dist/views/ImportConversationView/index.js +0 -29
  63. package/dist/views/LogsView/client.js +0 -148
  64. package/dist/views/LogsView/index.js +0 -27
  65. package/dist/views/NewTicketView/client.js +0 -224
  66. package/dist/views/NewTicketView/index.js +0 -27
  67. package/dist/views/PendingEmailsView/client.js +0 -172
  68. package/dist/views/PendingEmailsView/index.js +0 -29
  69. package/dist/views/SupportDashboardView/client.js +0 -296
  70. package/dist/views/SupportDashboardView/index.js +0 -29
  71. package/dist/views/TicketDetailView/client.js +0 -844
  72. package/dist/views/TicketDetailView/index.js +0 -29
  73. package/dist/views/TicketInboxView/client.js +0 -294
  74. package/dist/views/TicketInboxView/index.js +0 -27
  75. package/dist/views/TicketingSettingsView/client.js +0 -728
  76. package/dist/views/TicketingSettingsView/index.js +0 -29
  77. package/dist/views/TimeDashboardView/client.js +0 -164
  78. package/dist/views/TimeDashboardView/index.js +0 -29
  79. package/dist/views/shared/AdminViewHeader.js +0 -67
  80. package/dist/views/shared/ErrorBoundary.js +0 -50
  81. package/dist/views/shared/Skeleton.js +0 -72
  82. package/dist/views/shared/adminTokens.js +0 -32
  83. package/dist/views/shared/config.js +0 -41
  84. package/dist/views/shared/index.js +0 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@consilioweb/payload-support",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Payload CMS plugin — professional support & ticketing system with AI, SLA, time tracking, live chat, and more",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -27,13 +27,20 @@
27
27
  "default": "./dist/client.cjs"
28
28
  }
29
29
  },
30
- "./views/*": {
31
- "types": "./dist/views/*/index.d.ts",
32
- "default": "./dist/views/*/index.js"
30
+ "./views": {
31
+ "import": {
32
+ "types": "./dist/views.d.ts",
33
+ "default": "./dist/views.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/views.d.cts",
37
+ "default": "./dist/views.cjs"
38
+ }
33
39
  },
34
- "./components/*": {
35
- "types": "./dist/components/*/index.d.ts",
36
- "default": "./dist/components/*/index.js"
40
+ "./components/TicketConversation": {
41
+ "import": {
42
+ "default": "./dist/components/TicketConversation.js"
43
+ }
37
44
  }
38
45
  },
39
46
  "files": [
package/src/plugin.ts CHANGED
@@ -106,26 +106,26 @@ export function supportPlugin(config?: SupportPluginConfig): Plugin {
106
106
  (incomingConfig.admin?.components?.views as Record<string, AdminViewConfig>) || {}
107
107
 
108
108
  const supportViews: Record<string, AdminViewConfig> = {
109
- 'support-inbox': viewConfig(`${viewsBase}/TicketInboxView`, `${bp}/inbox`),
110
- 'support-dashboard': viewConfig(`${viewsBase}/SupportDashboardView`, `${bp}/dashboard`),
111
- 'support-ticket': viewConfig(`${viewsBase}/TicketDetailView`, `${bp}/ticket`),
112
- 'support-new-ticket': viewConfig(`${viewsBase}/NewTicketView`, `${bp}/new-ticket`),
113
- 'support-settings': viewConfig(`${viewsBase}/TicketingSettingsView`, `${bp}/settings`),
114
- 'support-logs': viewConfig(`${viewsBase}/LogsView`, `${bp}/logs`),
115
- 'support-crm': viewConfig(`${viewsBase}/CrmView`, `${bp}/crm`),
109
+ 'support-inbox': viewConfig(`${viewsBase}#TicketInboxView`, `${bp}/inbox`),
110
+ 'support-dashboard': viewConfig(`${viewsBase}#SupportDashboardView`, `${bp}/dashboard`),
111
+ 'support-ticket': viewConfig(`${viewsBase}#TicketDetailView`, `${bp}/ticket`),
112
+ 'support-new-ticket': viewConfig(`${viewsBase}#NewTicketView`, `${bp}/new-ticket`),
113
+ 'support-settings': viewConfig(`${viewsBase}#TicketingSettingsView`, `${bp}/settings`),
114
+ 'support-logs': viewConfig(`${viewsBase}#LogsView`, `${bp}/logs`),
115
+ 'support-crm': viewConfig(`${viewsBase}#CrmView`, `${bp}/crm`),
116
116
  }
117
117
 
118
118
  if (features.chat) {
119
- supportViews['support-chat'] = viewConfig(`${viewsBase}/ChatView`, `${bp}/chat`)
119
+ supportViews['support-chat'] = viewConfig(`${viewsBase}#ChatView`, `${bp}/chat`)
120
120
  }
121
121
  if (features.pendingEmails) {
122
- supportViews['support-emails'] = viewConfig(`${viewsBase}/PendingEmailsView`, `${bp}/emails`)
122
+ supportViews['support-emails'] = viewConfig(`${viewsBase}#PendingEmailsView`, `${bp}/emails`)
123
123
  }
124
124
  if (features.emailTracking) {
125
- supportViews['support-tracking'] = viewConfig(`${viewsBase}/EmailTrackingView`, `${bp}/tracking`)
125
+ supportViews['support-tracking'] = viewConfig(`${viewsBase}#EmailTrackingView`, `${bp}/tracking`)
126
126
  }
127
127
  if (features.timeTracking) {
128
- supportViews['support-time'] = viewConfig(`${viewsBase}/TimeDashboardView`, `${bp}/time`)
128
+ supportViews['support-time'] = viewConfig(`${viewsBase}#TimeDashboardView`, `${bp}/time`)
129
129
  }
130
130
 
131
131
  // ─── Endpoints ───────────────────────────────────────
package/src/views.ts ADDED
@@ -0,0 +1,17 @@
1
+ // Admin views barrel — server components exported for Payload importMap
2
+ // Pattern copied from @consilioweb/payload-admin-theme which works reliably
3
+ // with Next.js transpilePackages.
4
+
5
+ export { default as TicketInboxView } from './views/TicketInboxView/index'
6
+ export { default as TicketDetailView } from './views/TicketDetailView/index'
7
+ export { default as SupportDashboardView } from './views/SupportDashboardView/index'
8
+ export { default as NewTicketView } from './views/NewTicketView/index'
9
+ export { default as TicketingSettingsView } from './views/TicketingSettingsView/index'
10
+ export { default as LogsView } from './views/LogsView/index'
11
+ export { default as ChatView } from './views/ChatView/index'
12
+ export { default as CrmView } from './views/CrmView/index'
13
+ export { default as PendingEmailsView } from './views/PendingEmailsView/index'
14
+ export { default as EmailTrackingView } from './views/EmailTrackingView/index'
15
+ export { default as BillingView } from './views/BillingView/index'
16
+ export { default as TimeDashboardView } from './views/TimeDashboardView/index'
17
+ export { default as ImportConversationView } from './views/ImportConversationView/index'
@@ -1,76 +0,0 @@
1
- "use client";
2
- import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { s } from '../constants';
4
-
5
- function AISummaryPanel({
6
- showAiSummary,
7
- setShowAiSummary,
8
- aiSummary,
9
- aiGenerating,
10
- aiSaving,
11
- aiSaved,
12
- handleAiGenerate,
13
- handleAiSave
14
- }) {
15
- return /* @__PURE__ */ jsxs("div", { style: { marginBottom: "14px" }, children: [
16
- /* @__PURE__ */ jsx(
17
- "button",
18
- {
19
- onClick: () => {
20
- setShowAiSummary(!showAiSummary);
21
- if (!showAiSummary && !aiSummary) handleAiGenerate();
22
- },
23
- style: {
24
- ...s.ghostBtn("#7c3aed", false),
25
- fontSize: "12px",
26
- display: "inline-flex",
27
- alignItems: "center",
28
- gap: "6px"
29
- },
30
- children: showAiSummary ? "Masquer la synth\xE8se IA" : "Synth\xE8se IA"
31
- }
32
- ),
33
- showAiSummary && /* @__PURE__ */ jsxs("div", { style: {
34
- marginTop: "10px",
35
- padding: "14px 18px",
36
- borderRadius: "8px",
37
- backgroundColor: "#faf5ff",
38
- border: "1px solid #e9d5ff"
39
- }, children: [
40
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "10px" }, children: [
41
- /* @__PURE__ */ jsx("h4", { style: { fontSize: "13px", fontWeight: 600, color: "#7c3aed", margin: 0 }, children: "Synth\xE8se IA" }),
42
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px" }, children: [
43
- /* @__PURE__ */ jsx(
44
- "button",
45
- {
46
- onClick: handleAiGenerate,
47
- disabled: aiGenerating,
48
- style: { ...s.outlineBtn("#7c3aed", aiGenerating), fontSize: "11px", padding: "4px 10px" },
49
- children: aiGenerating ? "G\xE9n\xE9ration..." : "R\xE9g\xE9n\xE9rer"
50
- }
51
- ),
52
- aiSummary && !aiGenerating && /* @__PURE__ */ jsx(
53
- "button",
54
- {
55
- onClick: handleAiSave,
56
- disabled: aiSaving || aiSaved,
57
- style: { ...s.btn(aiSaved ? "#16a34a" : "#2563eb", aiSaving), fontSize: "11px", padding: "4px 10px" },
58
- children: aiSaved ? "Sauvegard\xE9" : aiSaving ? "Sauvegarde..." : "Sauvegarder (note interne)"
59
- }
60
- )
61
- ] })
62
- ] }),
63
- aiGenerating ? /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: "10px", color: "#7c3aed", fontSize: "13px" }, children: "Analyse de la conversation en cours..." }) : aiSummary ? /* @__PURE__ */ jsx(
64
- "div",
65
- {
66
- style: { fontSize: "13px", lineHeight: "1.7", color: "#1e1b4b", whiteSpace: "pre-wrap" },
67
- dangerouslySetInnerHTML: {
68
- __html: aiSummary.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>").replace(/\n/g, "<br/>")
69
- }
70
- }
71
- ) : /* @__PURE__ */ jsx("p", { style: { color: "#999", fontStyle: "italic", fontSize: "13px", margin: 0 }, children: `Cliquez sur "R\xE9g\xE9n\xE9rer" pour lancer l'analyse` })
72
- ] })
73
- ] });
74
- }
75
-
76
- export { AISummaryPanel };
@@ -1,118 +0,0 @@
1
- "use client";
2
- import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { useRef } from 'react';
4
- import { s } from '../constants';
5
-
6
- function MergePanel({
7
- mergeTarget,
8
- setMergeTarget,
9
- mergeTargetInfo,
10
- setMergeTargetInfo,
11
- mergeError,
12
- setMergeError,
13
- merging,
14
- handleMergeLookup,
15
- handleMerge
16
- }) {
17
- return /* @__PURE__ */ jsxs("div", { style: { padding: "14px 18px", borderRadius: "8px", backgroundColor: "#fdf2f8", border: "1px solid #fbcfe8", marginBottom: "14px" }, children: [
18
- /* @__PURE__ */ jsx("h4", { style: { fontSize: "13px", fontWeight: 600, marginBottom: "10px", color: "#831843" }, children: "Fusionner ce ticket dans un autre" }),
19
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", alignItems: "center", marginBottom: "8px" }, children: [
20
- /* @__PURE__ */ jsx(
21
- "input",
22
- {
23
- type: "text",
24
- value: mergeTarget,
25
- onChange: (e) => {
26
- setMergeTarget(e.target.value);
27
- setMergeTargetInfo(null);
28
- setMergeError("");
29
- },
30
- placeholder: "TK-0001",
31
- style: { ...s.input, width: "130px" }
32
- }
33
- ),
34
- /* @__PURE__ */ jsx("button", { onClick: handleMergeLookup, style: { ...s.outlineBtn("#ec4899"), fontSize: "12px", padding: "6px 14px" }, children: "Rechercher" }),
35
- mergeError && /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "#be185d", fontWeight: 600 }, children: mergeError })
36
- ] }),
37
- mergeTargetInfo && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
38
- /* @__PURE__ */ jsxs("span", { style: { fontSize: "13px", fontWeight: 600 }, children: [
39
- mergeTargetInfo.ticketNumber,
40
- " \u2014 ",
41
- mergeTargetInfo.subject
42
- ] }),
43
- /* @__PURE__ */ jsx("button", { onClick: handleMerge, disabled: merging, style: { ...s.btn("#ec4899", merging), color: "#fff", fontSize: "12px", padding: "6px 14px" }, children: merging ? "Fusion..." : "Confirmer la fusion" })
44
- ] })
45
- ] });
46
- }
47
- function ExtMessagePanel({
48
- extMsgBody,
49
- setExtMsgBody,
50
- extMsgAuthor,
51
- setExtMsgAuthor,
52
- extMsgDate,
53
- setExtMsgDate,
54
- extMsgFiles,
55
- setExtMsgFiles,
56
- sendingExtMsg,
57
- handleSendExtMsg,
58
- handleExtFileChange
59
- }) {
60
- const extFileInputRef = useRef(null);
61
- return /* @__PURE__ */ jsxs("div", { style: { padding: "14px 18px", borderRadius: "8px", backgroundColor: "#eef2ff", border: "1px solid #c7d2fe", marginBottom: "14px" }, children: [
62
- /* @__PURE__ */ jsx("h4", { style: { fontSize: "13px", fontWeight: 600, marginBottom: "10px", color: "#312e81" }, children: "Ajouter un message re\xE7u (email, SMS, WhatsApp...)" }),
63
- /* @__PURE__ */ jsx(
64
- "textarea",
65
- {
66
- value: extMsgBody,
67
- onChange: (e) => setExtMsgBody(e.target.value),
68
- placeholder: "Coller le contenu du message re\xE7u...",
69
- rows: 3,
70
- style: { ...s.input, width: "100%", resize: "vertical", marginBottom: "10px" }
71
- }
72
- ),
73
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", alignItems: "center", flexWrap: "wrap", marginBottom: "10px" }, children: [
74
- /* @__PURE__ */ jsxs("select", { value: extMsgAuthor, onChange: (e) => setExtMsgAuthor(e.target.value), style: { ...s.input, fontSize: "12px" }, children: [
75
- /* @__PURE__ */ jsx("option", { value: "client", children: "Envoy\xE9 par le client" }),
76
- /* @__PURE__ */ jsx("option", { value: "admin", children: "Envoy\xE9 par le support" })
77
- ] }),
78
- /* @__PURE__ */ jsx(
79
- "input",
80
- {
81
- type: "datetime-local",
82
- value: extMsgDate,
83
- onChange: (e) => setExtMsgDate(e.target.value),
84
- style: { ...s.input, fontSize: "12px" }
85
- }
86
- ),
87
- /* @__PURE__ */ jsx("input", { ref: extFileInputRef, type: "file", multiple: true, onChange: handleExtFileChange, style: { display: "none" }, accept: "image/*,.pdf,.doc,.docx,.txt,.zip" }),
88
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => extFileInputRef.current?.click(), style: { ...s.ghostBtn("#6b7280"), fontSize: "12px", padding: "6px 12px" }, children: "+ PJ" })
89
- ] }),
90
- extMsgFiles.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginBottom: "10px", display: "flex", gap: "6px", flexWrap: "wrap" }, children: extMsgFiles.map((file, i) => /* @__PURE__ */ jsxs("span", { style: { ...s.badge("#f1f5f9", "#374151"), display: "inline-flex", alignItems: "center", gap: "4px" }, children: [
91
- file.name,
92
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setExtMsgFiles((prev) => prev.filter((_, idx) => idx !== i)), style: { border: "none", background: "none", color: "#ef4444", fontWeight: 700, cursor: "pointer", fontSize: "14px", lineHeight: 1 }, children: "\xD7" })
93
- ] }, i)) }),
94
- /* @__PURE__ */ jsx("button", { onClick: handleSendExtMsg, disabled: sendingExtMsg || !extMsgBody.trim(), style: s.btn("#818cf8", sendingExtMsg || !extMsgBody.trim()), children: sendingExtMsg ? "Ajout..." : "Ajouter (sans notification)" })
95
- ] });
96
- }
97
- function SnoozePanel({ snoozeSaving, handleSnooze }) {
98
- return /* @__PURE__ */ jsxs("div", { style: { padding: "14px 18px", borderRadius: "8px", backgroundColor: "#faf5ff", border: "1px solid #e9d5ff", marginBottom: "14px" }, children: [
99
- /* @__PURE__ */ jsx("h4", { style: { fontSize: "13px", fontWeight: 600, marginBottom: "10px", color: "#5b21b6" }, children: "Snooze \u2014 masquer temporairement" }),
100
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap", alignItems: "center" }, children: [
101
- /* @__PURE__ */ jsx("button", { onClick: () => handleSnooze(1), disabled: snoozeSaving, style: { ...s.outlineBtn("#8b5cf6", snoozeSaving), fontSize: "12px" }, children: "1 jour" }),
102
- /* @__PURE__ */ jsx("button", { onClick: () => handleSnooze(3), disabled: snoozeSaving, style: { ...s.outlineBtn("#8b5cf6", snoozeSaving), fontSize: "12px" }, children: "3 jours" }),
103
- /* @__PURE__ */ jsx("button", { onClick: () => handleSnooze(7), disabled: snoozeSaving, style: { ...s.outlineBtn("#8b5cf6", snoozeSaving), fontSize: "12px" }, children: "1 semaine" }),
104
- /* @__PURE__ */ jsx(
105
- "input",
106
- {
107
- type: "datetime-local",
108
- onChange: (e) => {
109
- if (e.target.value) handleSnooze(null, e.target.value);
110
- },
111
- style: { ...s.input, fontSize: "12px" }
112
- }
113
- )
114
- ] })
115
- ] });
116
- }
117
-
118
- export { ExtMessagePanel, MergePanel, SnoozePanel };
@@ -1,23 +0,0 @@
1
- "use client";
2
- import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { useState } from 'react';
4
- import { s, C } from '../constants';
5
-
6
- function ActivityLog({ activityLog }) {
7
- const [showActivity, setShowActivity] = useState(false);
8
- return /* @__PURE__ */ jsxs("div", { style: s.section, children: [
9
- /* @__PURE__ */ jsxs("h4", { style: { ...s.sectionTitle, cursor: "pointer" }, onClick: () => setShowActivity(!showActivity), children: [
10
- "Historique ",
11
- /* @__PURE__ */ jsx("span", { style: s.badge("#f1f5f9", "#475569"), children: activityLog.length }),
12
- /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: C.textMuted, transition: "transform 0.2s", display: "inline-block", transform: showActivity ? "rotate(90deg)" : "none" }, children: "\u25B6" })
13
- ] }),
14
- showActivity && (activityLog.length === 0 ? /* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: C.textMuted, fontStyle: "italic" }, children: "Aucune activit\xE9 enregistr\xE9e." }) : /* @__PURE__ */ jsx("div", { style: { fontSize: "12px", display: "flex", flexDirection: "column", gap: "2px", borderLeft: "2px solid #bfdbfe", paddingLeft: "14px", marginLeft: "4px" }, children: activityLog.map((entry) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px", alignItems: "center", padding: "5px 0", borderBottom: "1px solid #f8fafc" }, children: [
15
- /* @__PURE__ */ jsx("span", { style: { color: C.textMuted, fontSize: "11px", whiteSpace: "nowrap", fontWeight: 500 }, children: new Date(entry.createdAt).toLocaleString("fr-FR", { day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }) }),
16
- /* @__PURE__ */ jsx("span", { style: s.badge(entry.actorType === "admin" ? "#eff6ff" : "#dcfce7", entry.actorType === "admin" ? "#1e40af" : "#166534"), children: entry.actorType || "system" }),
17
- /* @__PURE__ */ jsx("span", { style: { color: "#374151", fontWeight: 500 }, children: (entry.detail || entry.action).replace(/\[object Object\]/g, "(utilisateur)") }),
18
- /* @__PURE__ */ jsx("span", { style: { color: C.textMuted, fontSize: "11px" }, children: entry.actorEmail })
19
- ] }, entry.id)) }))
20
- ] });
21
- }
22
-
23
- export { ActivityLog };
@@ -1,42 +0,0 @@
1
- "use client";
2
- import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { C, s } from '../constants';
4
-
5
- function ClientBar({ client }) {
6
- return /* @__PURE__ */ jsxs("div", { style: {
7
- display: "flex",
8
- alignItems: "center",
9
- gap: "12px",
10
- padding: "10px 16px",
11
- borderRadius: "8px",
12
- backgroundColor: "var(--theme-elevation-100)",
13
- marginBottom: "16px",
14
- flexWrap: "wrap"
15
- }, children: [
16
- /* @__PURE__ */ jsx("span", { style: { fontSize: "16px" }, children: "\u{1F464}" }),
17
- /* @__PURE__ */ jsx("span", { style: { fontWeight: 700, fontSize: "13px", color: C.textPrimary }, children: client.company }),
18
- /* @__PURE__ */ jsxs("span", { style: { color: C.textSecondary, fontSize: "13px" }, children: [
19
- client.firstName,
20
- " ",
21
- client.lastName
22
- ] }),
23
- /* @__PURE__ */ jsx("span", { style: { color: C.textMuted, fontSize: "12px" }, children: "|" }),
24
- /* @__PURE__ */ jsx("a", { href: `mailto:${client.email}`, style: { color: "#2563eb", fontSize: "12px", fontWeight: 600, textDecoration: "none" }, children: client.email }),
25
- client.phone && /* @__PURE__ */ jsx("span", { style: { color: C.textSecondary, fontSize: "12px" }, children: client.phone }),
26
- /* @__PURE__ */ jsxs("span", { style: { marginLeft: "auto", display: "inline-flex", gap: "8px", alignItems: "center" }, children: [
27
- /* @__PURE__ */ jsx("a", { href: `/admin/collections/support-clients/${client.id}`, style: { ...s.ghostBtn("#475569"), fontSize: "11px", padding: "4px 10px", textDecoration: "none" }, children: "Fiche client" }),
28
- /* @__PURE__ */ jsx(
29
- "button",
30
- {
31
- type: "button",
32
- onClick: () => window.open(`/api/admin/impersonate?clientId=${client.id}`, "_blank"),
33
- style: { ...s.ghostBtn("#7c3aed"), fontSize: "11px", padding: "4px 10px" },
34
- title: "Se connecter au portail support en tant que ce client",
35
- children: "Voir en tant que client"
36
- }
37
- )
38
- ] })
39
- ] });
40
- }
41
-
42
- export { ClientBar };
@@ -1,137 +0,0 @@
1
- "use client";
2
- import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { useState } from 'react';
4
- import { s, C, statusLabels, projectStatusLabels } from '../constants';
5
-
6
- function ClientHistory({
7
- client: _client,
8
- clientTickets,
9
- clientProjects,
10
- clientNotes,
11
- onNotesChange,
12
- onNotesSave,
13
- savingNotes,
14
- notesSaved
15
- }) {
16
- const [showClientHistory, setShowClientHistory] = useState(false);
17
- return /* @__PURE__ */ jsxs("div", { style: s.section, children: [
18
- /* @__PURE__ */ jsxs(
19
- "button",
20
- {
21
- type: "button",
22
- onClick: () => setShowClientHistory(!showClientHistory),
23
- style: {
24
- background: "none",
25
- border: `1px dashed ${C.border}`,
26
- borderRadius: "6px",
27
- padding: "8px 14px",
28
- cursor: "pointer",
29
- color: C.textSecondary,
30
- fontSize: "13px",
31
- fontWeight: 600,
32
- width: "100%",
33
- textAlign: "left",
34
- display: "flex",
35
- alignItems: "center",
36
- justifyContent: "space-between"
37
- },
38
- children: [
39
- /* @__PURE__ */ jsxs("span", { children: [
40
- "Historique client (",
41
- clientTickets.length,
42
- " ticket",
43
- clientTickets.length !== 1 ? "s" : "",
44
- ", ",
45
- clientProjects.length,
46
- " projet",
47
- clientProjects.length !== 1 ? "s" : "",
48
- ")"
49
- ] }),
50
- /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", transition: "transform 0.2s", display: "inline-block", transform: showClientHistory ? "rotate(90deg)" : "none" }, children: "\u25B6" })
51
- ]
52
- }
53
- ),
54
- showClientHistory && /* @__PURE__ */ jsxs("div", { style: { marginTop: "10px", padding: "14px 18px", borderRadius: "8px", backgroundColor: C.white, border: `1px solid ${C.border}` }, children: [
55
- /* @__PURE__ */ jsx("h5", { style: { fontSize: "12px", fontWeight: 600, color: C.textSecondary, marginBottom: "8px" }, children: "Derniers tickets" }),
56
- clientTickets.length === 0 ? /* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: C.textMuted, fontStyle: "italic", marginBottom: "14px" }, children: "Aucun autre ticket" }) : /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "4px", marginBottom: "14px" }, children: clientTickets.map((t) => {
57
- const st = statusLabels[t.status] || statusLabels.open;
58
- return /* @__PURE__ */ jsxs(
59
- "a",
60
- {
61
- href: `/admin/support/ticket?id=${t.id}`,
62
- style: {
63
- display: "flex",
64
- alignItems: "center",
65
- gap: "8px",
66
- padding: "6px 10px",
67
- borderRadius: "6px",
68
- border: `1px solid ${C.border}`,
69
- textDecoration: "none",
70
- fontSize: "12px",
71
- color: "#374151",
72
- backgroundColor: "#fafafa"
73
- },
74
- children: [
75
- /* @__PURE__ */ jsx("span", { style: { fontFamily: "'SF Mono', 'Fira Code', 'JetBrains Mono', 'Cascadia Code', monospace", fontWeight: 600, color: C.textMuted, fontSize: "11px", whiteSpace: "nowrap" }, children: t.ticketNumber }),
76
- /* @__PURE__ */ jsx("span", { style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontWeight: 600 }, children: t.subject }),
77
- /* @__PURE__ */ jsx("span", { style: s.badge(st.bg, st.color), children: st.label }),
78
- /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", color: C.textMuted, whiteSpace: "nowrap" }, children: new Date(t.createdAt).toLocaleDateString("fr-FR", { day: "numeric", month: "short" }) })
79
- ]
80
- },
81
- t.id
82
- );
83
- }) }),
84
- /* @__PURE__ */ jsx("h5", { style: { fontSize: "12px", fontWeight: 600, color: C.textSecondary, marginBottom: "8px" }, children: "Projets" }),
85
- clientProjects.length === 0 ? /* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: C.textMuted, fontStyle: "italic", marginBottom: "14px" }, children: "Aucun projet" }) : /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap", marginBottom: "14px" }, children: clientProjects.map((p) => {
86
- const ps = projectStatusLabels[p.status] || projectStatusLabels.active;
87
- return /* @__PURE__ */ jsxs(
88
- "a",
89
- {
90
- href: `/admin/collections/projects/${p.id}`,
91
- style: {
92
- display: "inline-flex",
93
- alignItems: "center",
94
- gap: "6px",
95
- padding: "5px 10px",
96
- borderRadius: "6px",
97
- border: `1px solid ${C.border}`,
98
- textDecoration: "none",
99
- fontSize: "12px",
100
- fontWeight: 600,
101
- color: "#374151",
102
- backgroundColor: "#fafafa"
103
- },
104
- children: [
105
- p.name,
106
- /* @__PURE__ */ jsx("span", { style: s.badge(ps.bg, ps.color), children: ps.label })
107
- ]
108
- },
109
- p.id
110
- );
111
- }) }),
112
- /* @__PURE__ */ jsx("h5", { style: { fontSize: "12px", fontWeight: 600, color: C.textSecondary, marginBottom: "8px" }, children: "Notes internes" }),
113
- /* @__PURE__ */ jsx(
114
- "textarea",
115
- {
116
- value: clientNotes,
117
- onChange: (e) => onNotesChange(e.target.value),
118
- rows: 3,
119
- style: { ...s.input, width: "100%", resize: "vertical", fontSize: "12px", marginBottom: "8px" },
120
- placeholder: "Notes sur ce client..."
121
- }
122
- ),
123
- /* @__PURE__ */ jsx(
124
- "button",
125
- {
126
- type: "button",
127
- onClick: onNotesSave,
128
- disabled: savingNotes,
129
- style: { ...s.btn(notesSaved ? "#16a34a" : C.blue, savingNotes), fontSize: "11px", padding: "5px 12px" },
130
- children: notesSaved ? "Sauvegarde OK" : savingNotes ? "Sauvegarde..." : "Sauvegarder les notes"
131
- }
132
- )
133
- ] })
134
- ] });
135
- }
136
-
137
- export { ClientHistory };
@@ -1,152 +0,0 @@
1
- "use client";
2
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
- import { useState } from 'react';
4
-
5
- const LANG_CONFIG = {
6
- javascript: { label: "JavaScript", accent: "#f7df1e" },
7
- js: { label: "JavaScript", accent: "#f7df1e" },
8
- typescript: { label: "TypeScript", accent: "#3178c6" },
9
- ts: { label: "TypeScript", accent: "#3178c6" },
10
- tsx: { label: "TSX", accent: "#3178c6" },
11
- jsx: { label: "JSX", accent: "#f7df1e" },
12
- php: { label: "PHP", accent: "#777bb4" },
13
- python: { label: "Python", accent: "#3776ab" },
14
- py: { label: "Python", accent: "#3776ab" },
15
- html: { label: "HTML", accent: "#e34f26" },
16
- css: { label: "CSS", accent: "#1572b6" },
17
- scss: { label: "SCSS", accent: "#cc6699" },
18
- json: { label: "JSON", accent: "#292929" },
19
- sql: { label: "SQL", accent: "#e48e00" },
20
- bash: { label: "Bash", accent: "#4eaa25" },
21
- sh: { label: "Shell", accent: "#4eaa25" },
22
- yaml: { label: "YAML", accent: "#cb171e" },
23
- yml: { label: "YAML", accent: "#cb171e" },
24
- xml: { label: "XML", accent: "#f16529" },
25
- markdown: { label: "Markdown", accent: "#083fa1" },
26
- md: { label: "Markdown", accent: "#083fa1" },
27
- diff: { label: "Diff", accent: "#41b883" },
28
- go: { label: "Go", accent: "#00add8" },
29
- rust: { label: "Rust", accent: "#dea584" },
30
- java: { label: "Java", accent: "#ed8b00" },
31
- c: { label: "C", accent: "#555555" },
32
- cpp: { label: "C++", accent: "#00599c" },
33
- ruby: { label: "Ruby", accent: "#cc342d" },
34
- swift: { label: "Swift", accent: "#f05138" },
35
- nginx: { label: "Nginx", accent: "#009639" },
36
- docker: { label: "Docker", accent: "#2496ed" },
37
- dockerfile: { label: "Dockerfile", accent: "#2496ed" },
38
- env: { label: ".env", accent: "#ecd53f" }
39
- };
40
- const DEFAULT_CONFIG = { label: "Code", accent: "#6b7280" };
41
- function SingleCodeBlock({ lang, code }) {
42
- const [copied, setCopied] = useState(false);
43
- const config = LANG_CONFIG[lang.toLowerCase()] || (lang ? { label: lang.toUpperCase(), accent: "#6b7280" } : DEFAULT_CONFIG);
44
- const handleCopy = () => {
45
- navigator.clipboard.writeText(code);
46
- setCopied(true);
47
- setTimeout(() => setCopied(false), 1500);
48
- };
49
- const lines = code.split("\n");
50
- return /* @__PURE__ */ jsxs("div", { style: {
51
- marginTop: 8,
52
- marginBottom: 8,
53
- borderRadius: 8,
54
- overflow: "hidden",
55
- border: "1px solid #334155",
56
- backgroundColor: "#0f172a",
57
- fontSize: 13
58
- }, children: [
59
- /* @__PURE__ */ jsxs("div", { style: {
60
- display: "flex",
61
- alignItems: "center",
62
- justifyContent: "space-between",
63
- padding: "6px 12px",
64
- backgroundColor: "#1e293b",
65
- borderBottom: "1px solid #334155"
66
- }, children: [
67
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
68
- /* @__PURE__ */ jsx("span", { style: {
69
- display: "inline-block",
70
- width: 8,
71
- height: 8,
72
- borderRadius: "50%",
73
- backgroundColor: config.accent,
74
- flexShrink: 0
75
- } }),
76
- /* @__PURE__ */ jsx("span", { style: {
77
- fontSize: 11,
78
- fontWeight: 700,
79
- color: "#e2e8f0",
80
- letterSpacing: "0.02em"
81
- }, children: config.label })
82
- ] }),
83
- /* @__PURE__ */ jsx(
84
- "button",
85
- {
86
- onClick: handleCopy,
87
- style: {
88
- background: "none",
89
- border: "1px solid #475569",
90
- borderRadius: 4,
91
- padding: "2px 10px",
92
- fontSize: 11,
93
- color: copied ? "#4ade80" : "#94a3b8",
94
- cursor: "pointer",
95
- fontWeight: 600,
96
- transition: "color 150ms"
97
- },
98
- children: copied ? "Copi\xE9 !" : "Copier"
99
- }
100
- )
101
- ] }),
102
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", overflowX: "auto" }, children: [
103
- /* @__PURE__ */ jsx("div", { style: {
104
- padding: "12px 0",
105
- borderRight: "1px solid #334155",
106
- userSelect: "none",
107
- flexShrink: 0
108
- }, children: lines.map((_, i) => /* @__PURE__ */ jsx("div", { style: {
109
- padding: "0 12px",
110
- fontSize: 12,
111
- lineHeight: "20px",
112
- color: "#475569",
113
- textAlign: "right",
114
- fontFamily: '"SF Mono", "Fira Code", "JetBrains Mono", monospace'
115
- }, children: i + 1 }, i)) }),
116
- /* @__PURE__ */ jsx("pre", { style: {
117
- margin: 0,
118
- padding: 12,
119
- overflow: "auto",
120
- flex: 1
121
- }, children: /* @__PURE__ */ jsx("code", { style: {
122
- fontSize: 12,
123
- lineHeight: "20px",
124
- fontFamily: '"SF Mono", "Fira Code", "JetBrains Mono", monospace',
125
- color: "#e2e8f0",
126
- whiteSpace: "pre"
127
- }, children: code }) })
128
- ] })
129
- ] });
130
- }
131
- function CodeBlockRenderer({ text }) {
132
- const parts = text.split(/(```[\s\S]*?```)/g);
133
- const hasCodeBlock = parts.some((p) => p.startsWith("```"));
134
- if (!hasCodeBlock) return null;
135
- return /* @__PURE__ */ jsx(Fragment, { children: parts.map((part, i) => {
136
- if (part.startsWith("```")) {
137
- const match = part.match(/^```(\w*)\n?([\s\S]*?)```$/);
138
- if (match) {
139
- const lang = match[1] || "";
140
- const code = match[2].replace(/\n$/, "");
141
- return /* @__PURE__ */ jsx(SingleCodeBlock, { lang, code }, i);
142
- }
143
- }
144
- return null;
145
- }) });
146
- }
147
- function CodeBlockRendererHtml({ html }) {
148
- const stripped = html.replace(/<[^>]+>/g, "");
149
- return /* @__PURE__ */ jsx(CodeBlockRenderer, { text: stripped });
150
- }
151
-
152
- export { CodeBlockRenderer, CodeBlockRendererHtml };