@consilioweb/payload-support 0.8.2 → 0.9.5
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/dist/components/RichTextEditor/index.cjs +233 -0
- package/dist/components/RichTextEditor/index.js +232 -0
- package/dist/components/TicketConversation/components/CodeBlock.cjs +24 -7
- package/dist/components/TicketConversation/components/CodeBlock.js +23 -9
- package/dist/index.cjs +19 -1
- package/dist/index.js +19 -1
- package/dist/views/BillingView/client.cjs +260 -103
- package/dist/views/BillingView/client.js +259 -103
- package/dist/views/ChatView/client.cjs +184 -137
- package/dist/views/ChatView/client.js +180 -137
- package/dist/views/CrmView/client.cjs +270 -122
- package/dist/views/CrmView/client.js +266 -122
- package/dist/views/EmailTrackingView/client.cjs +80 -69
- package/dist/views/EmailTrackingView/client.js +80 -70
- package/dist/views/ImportConversationView/client.cjs +127 -94
- package/dist/views/ImportConversationView/client.js +123 -94
- package/dist/views/LogsView/client.cjs +56 -58
- package/dist/views/LogsView/client.js +52 -58
- package/dist/views/NewTicketView/client.cjs +39 -55
- package/dist/views/NewTicketView/client.js +38 -55
- package/dist/views/PendingEmailsView/client.cjs +399 -102
- package/dist/views/PendingEmailsView/client.js +396 -103
- package/dist/views/SupportDashboardView/client.cjs +276 -137
- package/dist/views/SupportDashboardView/client.js +275 -137
- package/dist/views/TicketDetailView/client.cjs +487 -204
- package/dist/views/TicketDetailView/client.js +486 -204
- package/dist/views/TicketInboxView/client.cjs +62 -65
- package/dist/views/TicketInboxView/client.js +62 -66
- package/dist/views/TicketingSettingsView/client.cjs +10 -8
- package/dist/views/TicketingSettingsView/client.js +10 -8
- package/dist/views/TimeDashboardView/client.cjs +70 -59
- package/dist/views/TimeDashboardView/client.js +69 -59
- package/package.json +7 -3
- package/src/components/RichTextEditor/index.tsx +261 -0
- package/src/components/TicketConversation/components/CodeBlock.tsx +53 -14
- package/src/plugin.ts +2 -0
- package/src/utils/emailTemplate.ts +37 -0
- package/src/views/BillingView/client.tsx +362 -69
- package/src/views/ChatView/client.tsx +225 -140
- package/src/views/CrmView/client.tsx +447 -189
- package/src/views/EmailTrackingView/client.tsx +111 -71
- package/src/views/ImportConversationView/client.tsx +255 -70
- package/src/views/LogsView/client.tsx +85 -50
- package/src/views/NewTicketView/client.tsx +37 -53
- package/src/views/PendingEmailsView/client.tsx +512 -92
- package/src/views/SupportDashboardView/client.tsx +294 -134
- package/src/views/TicketDetailView/client.tsx +486 -213
- package/src/views/TicketInboxView/client.tsx +52 -61
- package/src/views/TicketingSettingsView/client.tsx +10 -9
- package/src/views/TimeDashboardView/client.tsx +184 -69
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var useTranslation = require('../../components/TicketConversation/hooks/useTranslation');
|
|
6
|
+
var styles = require('../../styles/ImportConversation.module.scss');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
6
11
|
|
|
7
12
|
function ImportConversationClient() {
|
|
8
13
|
const { t } = useTranslation.useTranslation();
|
|
@@ -29,33 +34,43 @@ function ImportConversationClient() {
|
|
|
29
34
|
setPreview(null);
|
|
30
35
|
const reader = new FileReader();
|
|
31
36
|
reader.onload = (e) => {
|
|
32
|
-
|
|
37
|
+
const content = e.target?.result;
|
|
38
|
+
setMarkdown(content);
|
|
33
39
|
};
|
|
34
40
|
reader.readAsText(file);
|
|
35
41
|
}, []);
|
|
36
|
-
const onDrop = react.useCallback(
|
|
37
|
-
e
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
const onDrop = react.useCallback(
|
|
43
|
+
(e) => {
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
setIsDragOver(false);
|
|
46
|
+
const file = e.dataTransfer.files[0];
|
|
47
|
+
if (file) handleFile(file);
|
|
48
|
+
},
|
|
49
|
+
[handleFile]
|
|
50
|
+
);
|
|
51
|
+
const onFileChange = react.useCallback(
|
|
52
|
+
(e) => {
|
|
53
|
+
const file = e.target.files?.[0];
|
|
54
|
+
if (file) handleFile(file);
|
|
55
|
+
},
|
|
56
|
+
[handleFile]
|
|
57
|
+
);
|
|
46
58
|
const doPreview = react.useCallback(async () => {
|
|
47
59
|
if (!markdown) return;
|
|
48
60
|
setLoading(true);
|
|
49
61
|
setError("");
|
|
50
62
|
setPreview(null);
|
|
51
63
|
try {
|
|
52
|
-
const res = await fetch("/api/support/import-conversation", {
|
|
64
|
+
const res = await fetch("/api/support/import-conversation", {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers: { "Content-Type": "application/json" },
|
|
67
|
+
body: JSON.stringify({ markdown, previewOnly: true })
|
|
68
|
+
});
|
|
53
69
|
const data = await res.json();
|
|
54
70
|
if (!res.ok) {
|
|
55
|
-
setError(data.error || "Erreur");
|
|
71
|
+
setError(data.error || "Erreur lors de l'analyse");
|
|
56
72
|
return;
|
|
57
73
|
}
|
|
58
|
-
;
|
|
59
74
|
setPreview(data);
|
|
60
75
|
} catch {
|
|
61
76
|
setError("Erreur reseau");
|
|
@@ -68,13 +83,16 @@ function ImportConversationClient() {
|
|
|
68
83
|
setLoading(true);
|
|
69
84
|
setError("");
|
|
70
85
|
try {
|
|
71
|
-
const res = await fetch("/api/support/import-conversation", {
|
|
86
|
+
const res = await fetch("/api/support/import-conversation", {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "Content-Type": "application/json" },
|
|
89
|
+
body: JSON.stringify({ markdown })
|
|
90
|
+
});
|
|
72
91
|
const data = await res.json();
|
|
73
92
|
if (!res.ok) {
|
|
74
|
-
setError(data.error || "Erreur");
|
|
93
|
+
setError(data.error || "Erreur lors de l'import");
|
|
75
94
|
return;
|
|
76
95
|
}
|
|
77
|
-
;
|
|
78
96
|
setResult(data);
|
|
79
97
|
setPreview(null);
|
|
80
98
|
} catch {
|
|
@@ -91,112 +109,127 @@ function ImportConversationClient() {
|
|
|
91
109
|
setError("");
|
|
92
110
|
if (fileRef.current) fileRef.current.value = "";
|
|
93
111
|
}, []);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
btn: { padding: "8px 16px", borderRadius: 8, border: "1px solid var(--theme-elevation-200)", fontSize: 13, cursor: "pointer", background: "var(--theme-elevation-0)", color: "var(--theme-text)", fontWeight: 600 },
|
|
100
|
-
btnPrimary: { padding: "8px 16px", borderRadius: 8, border: "none", fontSize: 13, cursor: "pointer", background: "#2563eb", color: "#fff", fontWeight: 600 },
|
|
101
|
-
btnGreen: { padding: "8px 16px", borderRadius: 8, border: "none", fontSize: 13, cursor: "pointer", background: "#16a34a", color: "#fff", fontWeight: 600 },
|
|
102
|
-
btnAmber: { padding: "8px 16px", borderRadius: 8, border: "none", fontSize: 13, cursor: "pointer", background: "#d97706", color: "#fff", fontWeight: 600 },
|
|
103
|
-
section: { padding: 16, borderRadius: 10, border: "1px solid var(--theme-elevation-150)", marginBottom: 12 },
|
|
104
|
-
infoRow: { display: "flex", justifyContent: "space-between", padding: "4px 0", fontSize: 13 },
|
|
105
|
-
infoLabel: { color: "var(--theme-elevation-500)" },
|
|
106
|
-
infoValue: { fontWeight: 600, color: "var(--theme-text)" },
|
|
107
|
-
msgAdmin: { padding: "8px 12px", borderRadius: 8, background: "#dbeafe", marginBottom: 6 },
|
|
108
|
-
msgClient: { padding: "8px 12px", borderRadius: 8, background: "var(--theme-elevation-50)", marginBottom: 6 },
|
|
109
|
-
resultSuccess: { padding: 20, borderRadius: 10, border: "2px solid #22c55e", background: "#f0fdf4" },
|
|
110
|
-
resultError: { padding: 16, borderRadius: 10, border: "1px solid #fecaca", background: "#fef2f2", color: "#dc2626", marginBottom: 12 }
|
|
111
|
-
};
|
|
112
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.page, children: [
|
|
113
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 20 }, children: [
|
|
114
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: 22, fontWeight: 700, margin: 0 }, children: t("import.title") }),
|
|
115
|
-
result && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: reset, style: S.btnPrimary, children: t("import.newImport") })
|
|
116
|
-
] }),
|
|
117
|
-
!result && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: isDragOver ? S.dropzoneDragOver : markdown ? S.dropzoneHasFile : S.dropzone, onDragOver: (e) => {
|
|
118
|
-
e.preventDefault();
|
|
119
|
-
setIsDragOver(true);
|
|
120
|
-
}, onDragLeave: () => setIsDragOver(false), onDrop, onClick: () => fileRef.current?.click(), children: [
|
|
121
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 24, marginBottom: 8 }, children: "\u2191" }),
|
|
122
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 14, color: "var(--theme-text)" }, children: markdown ? t("import.dropzoneLoaded") : t("import.dropzoneText") }),
|
|
123
|
-
!markdown && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 12, color: "var(--theme-elevation-400)", marginTop: 8 }, children: t("import.acceptedFormats") }),
|
|
124
|
-
fileName && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 12, fontWeight: 600, marginTop: 8 }, children: fileName }),
|
|
125
|
-
/* @__PURE__ */ jsxRuntime.jsx("input", { ref: fileRef, type: "file", accept: ".md,.txt", onChange: onFileChange, style: { display: "none" } })
|
|
112
|
+
const dropzoneClass = isDragOver ? styles__default.default.dropzoneDragOver : markdown ? styles__default.default.dropzoneHasFile : styles__default.default.dropzone;
|
|
113
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.page, children: [
|
|
114
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.header, children: [
|
|
115
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: styles__default.default.title, children: t("import.title") }) }),
|
|
116
|
+
result && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: reset, className: styles__default.default.btnPrimary, children: t("import.newImport") })
|
|
126
117
|
] }),
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
118
|
+
!result && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
className: dropzoneClass,
|
|
122
|
+
onDragOver: (e) => {
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
setIsDragOver(true);
|
|
125
|
+
},
|
|
126
|
+
onDragLeave: () => setIsDragOver(false),
|
|
127
|
+
onDrop,
|
|
128
|
+
onClick: () => fileRef.current?.click(),
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.dropzoneIcon, children: "\u2191" }),
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: styles__default.default.dropzoneText, children: markdown ? t("import.dropzoneLoaded") : t("import.dropzoneText") }),
|
|
132
|
+
!markdown && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 12, color: "var(--theme-elevation-400)", marginTop: 8 }, children: t("import.acceptedFormats") }),
|
|
133
|
+
fileName && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles__default.default.fileName, children: fileName }),
|
|
134
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
135
|
+
"input",
|
|
136
|
+
{
|
|
137
|
+
ref: fileRef,
|
|
138
|
+
type: "file",
|
|
139
|
+
accept: ".md,.txt",
|
|
140
|
+
onChange: onFileChange,
|
|
141
|
+
style: { display: "none" }
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
),
|
|
147
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.resultError, children: [
|
|
148
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.resultTitleError, children: "\u26A0 Erreur" }),
|
|
149
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: styles__default.default.errorText, children: error })
|
|
130
150
|
] }),
|
|
131
|
-
markdown && !preview && !result && /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
151
|
+
markdown && !preview && !result && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.btnRow, children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: doPreview, disabled: loading, className: styles__default.default.btnAmber, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.btnContent, children: [
|
|
152
|
+
"\u{1F441} ",
|
|
153
|
+
loading ? t("import.analyzing") : t("import.preview")
|
|
154
|
+
] }) }) }),
|
|
132
155
|
preview && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
133
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
134
|
-
/* @__PURE__ */ jsxRuntime.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: S.infoValue, children: preview.client.name })
|
|
156
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.section, children: [
|
|
157
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.sectionTitle, children: [
|
|
158
|
+
"\u{1F464} ",
|
|
159
|
+
t("import.client")
|
|
138
160
|
] }),
|
|
139
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
140
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
141
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
161
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
162
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.name") }),
|
|
163
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: preview.client.name })
|
|
142
164
|
] }),
|
|
143
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
144
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
145
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
166
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.email") }),
|
|
167
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: preview.client.email })
|
|
146
168
|
] }),
|
|
147
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
148
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
149
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.company") }),
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: preview.client.company })
|
|
172
|
+
] }),
|
|
173
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.parsing") }),
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badgeInfo, children: preview.parseMethod === "structured" ? t("import.parsingRegex") : t("import.parsingAi") }) })
|
|
150
176
|
] })
|
|
151
177
|
] }),
|
|
152
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
153
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
154
|
-
|
|
155
|
-
|
|
178
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.section, children: [
|
|
179
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.sectionTitle, children: [
|
|
180
|
+
"\u{1F4AC} ",
|
|
181
|
+
preview.subject,
|
|
182
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.sectionTitleRight, children: [
|
|
156
183
|
preview.messageCount,
|
|
157
184
|
" ",
|
|
158
185
|
t("import.messages")
|
|
159
186
|
] })
|
|
160
187
|
] }),
|
|
161
|
-
preview.messages.map((msg, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
162
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
163
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", {
|
|
188
|
+
preview.messages.map((msg, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: msg.from === "admin" ? styles__default.default.msgAdmin : styles__default.default.msgClient, children: [
|
|
189
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.msgHeader, children: [
|
|
190
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.msgAuthor, children: [
|
|
164
191
|
msg.from === "admin" ? ">> " : "<< ",
|
|
165
192
|
msg.name
|
|
166
193
|
] }),
|
|
167
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
194
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.msgDate, children: msg.date })
|
|
168
195
|
] }),
|
|
169
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
196
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.msgPreview, children: msg.preview })
|
|
170
197
|
] }, i))
|
|
171
198
|
] }),
|
|
172
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
173
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setPreview(null),
|
|
174
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: doImport, disabled: loading,
|
|
199
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.btnRow, children: [
|
|
200
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setPreview(null), className: styles__default.default.btnMuted, children: t("common.cancel") }),
|
|
201
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: doImport, disabled: loading, className: styles__default.default.btnGreen, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.btnContent, children: [
|
|
202
|
+
"\u279C ",
|
|
203
|
+
loading ? t("import.importing") : t("import.importButton", { count: String(preview.messageCount) })
|
|
204
|
+
] }) })
|
|
175
205
|
] })
|
|
176
206
|
] }),
|
|
177
|
-
result && /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
178
|
-
/* @__PURE__ */ jsxRuntime.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
207
|
+
result && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.resultSuccess, children: [
|
|
208
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.resultTitleSuccess, children: [
|
|
209
|
+
"\u2713 ",
|
|
210
|
+
t("import.resultTitle")
|
|
211
|
+
] }),
|
|
212
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
213
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultTicket") }),
|
|
214
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: `/admin/support/ticket?id=${result.ticketId}`, className: styles__default.default.link, children: result.ticketNumber }) })
|
|
182
215
|
] }),
|
|
183
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
184
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
185
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", {
|
|
216
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
217
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultClient") }),
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.infoValue, children: [
|
|
186
219
|
result.clientName,
|
|
187
220
|
" (",
|
|
188
221
|
result.clientEmail,
|
|
189
222
|
")",
|
|
190
|
-
result.isNewClient && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: 8
|
|
223
|
+
result.isNewClient && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badgeNew, style: { marginLeft: 8 }, children: t("import.resultNew") })
|
|
191
224
|
] })
|
|
192
225
|
] }),
|
|
193
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
194
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
195
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
226
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
227
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultCompany") }),
|
|
228
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: result.clientCompany })
|
|
196
229
|
] }),
|
|
197
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
198
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
199
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
230
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.infoRow, children: [
|
|
231
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoLabel, children: t("import.resultMessages") }),
|
|
232
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.infoValue, children: t("import.resultImported", { count: String(result.messagesImported) }) })
|
|
200
233
|
] })
|
|
201
234
|
] })
|
|
202
235
|
] });
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { useState, useRef, useCallback } from 'react';
|
|
4
4
|
import { useTranslation } from '../../components/TicketConversation/hooks/useTranslation.js';
|
|
5
|
+
import styles from '../../styles/ImportConversation.module.scss';
|
|
5
6
|
|
|
6
7
|
function ImportConversationClient() {
|
|
7
8
|
const { t } = useTranslation();
|
|
@@ -28,33 +29,43 @@ function ImportConversationClient() {
|
|
|
28
29
|
setPreview(null);
|
|
29
30
|
const reader = new FileReader();
|
|
30
31
|
reader.onload = (e) => {
|
|
31
|
-
|
|
32
|
+
const content = e.target?.result;
|
|
33
|
+
setMarkdown(content);
|
|
32
34
|
};
|
|
33
35
|
reader.readAsText(file);
|
|
34
36
|
}, []);
|
|
35
|
-
const onDrop = useCallback(
|
|
36
|
-
e
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
const onDrop = useCallback(
|
|
38
|
+
(e) => {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
setIsDragOver(false);
|
|
41
|
+
const file = e.dataTransfer.files[0];
|
|
42
|
+
if (file) handleFile(file);
|
|
43
|
+
},
|
|
44
|
+
[handleFile]
|
|
45
|
+
);
|
|
46
|
+
const onFileChange = useCallback(
|
|
47
|
+
(e) => {
|
|
48
|
+
const file = e.target.files?.[0];
|
|
49
|
+
if (file) handleFile(file);
|
|
50
|
+
},
|
|
51
|
+
[handleFile]
|
|
52
|
+
);
|
|
45
53
|
const doPreview = useCallback(async () => {
|
|
46
54
|
if (!markdown) return;
|
|
47
55
|
setLoading(true);
|
|
48
56
|
setError("");
|
|
49
57
|
setPreview(null);
|
|
50
58
|
try {
|
|
51
|
-
const res = await fetch("/api/support/import-conversation", {
|
|
59
|
+
const res = await fetch("/api/support/import-conversation", {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: { "Content-Type": "application/json" },
|
|
62
|
+
body: JSON.stringify({ markdown, previewOnly: true })
|
|
63
|
+
});
|
|
52
64
|
const data = await res.json();
|
|
53
65
|
if (!res.ok) {
|
|
54
|
-
setError(data.error || "Erreur");
|
|
66
|
+
setError(data.error || "Erreur lors de l'analyse");
|
|
55
67
|
return;
|
|
56
68
|
}
|
|
57
|
-
;
|
|
58
69
|
setPreview(data);
|
|
59
70
|
} catch {
|
|
60
71
|
setError("Erreur reseau");
|
|
@@ -67,13 +78,16 @@ function ImportConversationClient() {
|
|
|
67
78
|
setLoading(true);
|
|
68
79
|
setError("");
|
|
69
80
|
try {
|
|
70
|
-
const res = await fetch("/api/support/import-conversation", {
|
|
81
|
+
const res = await fetch("/api/support/import-conversation", {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: { "Content-Type": "application/json" },
|
|
84
|
+
body: JSON.stringify({ markdown })
|
|
85
|
+
});
|
|
71
86
|
const data = await res.json();
|
|
72
87
|
if (!res.ok) {
|
|
73
|
-
setError(data.error || "Erreur");
|
|
88
|
+
setError(data.error || "Erreur lors de l'import");
|
|
74
89
|
return;
|
|
75
90
|
}
|
|
76
|
-
;
|
|
77
91
|
setResult(data);
|
|
78
92
|
setPreview(null);
|
|
79
93
|
} catch {
|
|
@@ -90,112 +104,127 @@ function ImportConversationClient() {
|
|
|
90
104
|
setError("");
|
|
91
105
|
if (fileRef.current) fileRef.current.value = "";
|
|
92
106
|
}, []);
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
btn: { padding: "8px 16px", borderRadius: 8, border: "1px solid var(--theme-elevation-200)", fontSize: 13, cursor: "pointer", background: "var(--theme-elevation-0)", color: "var(--theme-text)", fontWeight: 600 },
|
|
99
|
-
btnPrimary: { padding: "8px 16px", borderRadius: 8, border: "none", fontSize: 13, cursor: "pointer", background: "#2563eb", color: "#fff", fontWeight: 600 },
|
|
100
|
-
btnGreen: { padding: "8px 16px", borderRadius: 8, border: "none", fontSize: 13, cursor: "pointer", background: "#16a34a", color: "#fff", fontWeight: 600 },
|
|
101
|
-
btnAmber: { padding: "8px 16px", borderRadius: 8, border: "none", fontSize: 13, cursor: "pointer", background: "#d97706", color: "#fff", fontWeight: 600 },
|
|
102
|
-
section: { padding: 16, borderRadius: 10, border: "1px solid var(--theme-elevation-150)", marginBottom: 12 },
|
|
103
|
-
infoRow: { display: "flex", justifyContent: "space-between", padding: "4px 0", fontSize: 13 },
|
|
104
|
-
infoLabel: { color: "var(--theme-elevation-500)" },
|
|
105
|
-
infoValue: { fontWeight: 600, color: "var(--theme-text)" },
|
|
106
|
-
msgAdmin: { padding: "8px 12px", borderRadius: 8, background: "#dbeafe", marginBottom: 6 },
|
|
107
|
-
msgClient: { padding: "8px 12px", borderRadius: 8, background: "var(--theme-elevation-50)", marginBottom: 6 },
|
|
108
|
-
resultSuccess: { padding: 20, borderRadius: 10, border: "2px solid #22c55e", background: "#f0fdf4" },
|
|
109
|
-
resultError: { padding: 16, borderRadius: 10, border: "1px solid #fecaca", background: "#fef2f2", color: "#dc2626", marginBottom: 12 }
|
|
110
|
-
};
|
|
111
|
-
return /* @__PURE__ */ jsxs("div", { style: S.page, children: [
|
|
112
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 20 }, children: [
|
|
113
|
-
/* @__PURE__ */ jsx("h1", { style: { fontSize: 22, fontWeight: 700, margin: 0 }, children: t("import.title") }),
|
|
114
|
-
result && /* @__PURE__ */ jsx("button", { onClick: reset, style: S.btnPrimary, children: t("import.newImport") })
|
|
115
|
-
] }),
|
|
116
|
-
!result && /* @__PURE__ */ jsxs("div", { style: isDragOver ? S.dropzoneDragOver : markdown ? S.dropzoneHasFile : S.dropzone, onDragOver: (e) => {
|
|
117
|
-
e.preventDefault();
|
|
118
|
-
setIsDragOver(true);
|
|
119
|
-
}, onDragLeave: () => setIsDragOver(false), onDrop, onClick: () => fileRef.current?.click(), children: [
|
|
120
|
-
/* @__PURE__ */ jsx("div", { style: { fontSize: 24, marginBottom: 8 }, children: "\u2191" }),
|
|
121
|
-
/* @__PURE__ */ jsx("p", { style: { fontSize: 14, color: "var(--theme-text)" }, children: markdown ? t("import.dropzoneLoaded") : t("import.dropzoneText") }),
|
|
122
|
-
!markdown && /* @__PURE__ */ jsx("p", { style: { fontSize: 12, color: "var(--theme-elevation-400)", marginTop: 8 }, children: t("import.acceptedFormats") }),
|
|
123
|
-
fileName && /* @__PURE__ */ jsx("p", { style: { fontSize: 12, fontWeight: 600, marginTop: 8 }, children: fileName }),
|
|
124
|
-
/* @__PURE__ */ jsx("input", { ref: fileRef, type: "file", accept: ".md,.txt", onChange: onFileChange, style: { display: "none" } })
|
|
107
|
+
const dropzoneClass = isDragOver ? styles.dropzoneDragOver : markdown ? styles.dropzoneHasFile : styles.dropzone;
|
|
108
|
+
return /* @__PURE__ */ jsxs("div", { className: styles.page, children: [
|
|
109
|
+
/* @__PURE__ */ jsxs("div", { className: styles.header, children: [
|
|
110
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("h1", { className: styles.title, children: t("import.title") }) }),
|
|
111
|
+
result && /* @__PURE__ */ jsx("button", { onClick: reset, className: styles.btnPrimary, children: t("import.newImport") })
|
|
125
112
|
] }),
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
113
|
+
!result && /* @__PURE__ */ jsxs(
|
|
114
|
+
"div",
|
|
115
|
+
{
|
|
116
|
+
className: dropzoneClass,
|
|
117
|
+
onDragOver: (e) => {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
setIsDragOver(true);
|
|
120
|
+
},
|
|
121
|
+
onDragLeave: () => setIsDragOver(false),
|
|
122
|
+
onDrop,
|
|
123
|
+
onClick: () => fileRef.current?.click(),
|
|
124
|
+
children: [
|
|
125
|
+
/* @__PURE__ */ jsx("div", { className: styles.dropzoneIcon, children: "\u2191" }),
|
|
126
|
+
/* @__PURE__ */ jsx("p", { className: styles.dropzoneText, children: markdown ? t("import.dropzoneLoaded") : t("import.dropzoneText") }),
|
|
127
|
+
!markdown && /* @__PURE__ */ jsx("p", { style: { fontSize: 12, color: "var(--theme-elevation-400)", marginTop: 8 }, children: t("import.acceptedFormats") }),
|
|
128
|
+
fileName && /* @__PURE__ */ jsx("p", { className: styles.fileName, children: fileName }),
|
|
129
|
+
/* @__PURE__ */ jsx(
|
|
130
|
+
"input",
|
|
131
|
+
{
|
|
132
|
+
ref: fileRef,
|
|
133
|
+
type: "file",
|
|
134
|
+
accept: ".md,.txt",
|
|
135
|
+
onChange: onFileChange,
|
|
136
|
+
style: { display: "none" }
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
error && /* @__PURE__ */ jsxs("div", { className: styles.resultError, children: [
|
|
143
|
+
/* @__PURE__ */ jsx("div", { className: styles.resultTitleError, children: "\u26A0 Erreur" }),
|
|
144
|
+
/* @__PURE__ */ jsx("p", { className: styles.errorText, children: error })
|
|
129
145
|
] }),
|
|
130
|
-
markdown && !preview && !result && /* @__PURE__ */ jsx("div", {
|
|
146
|
+
markdown && !preview && !result && /* @__PURE__ */ jsx("div", { className: styles.btnRow, children: /* @__PURE__ */ jsx("button", { onClick: doPreview, disabled: loading, className: styles.btnAmber, children: /* @__PURE__ */ jsxs("span", { className: styles.btnContent, children: [
|
|
147
|
+
"\u{1F441} ",
|
|
148
|
+
loading ? t("import.analyzing") : t("import.preview")
|
|
149
|
+
] }) }) }),
|
|
131
150
|
preview && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
132
|
-
/* @__PURE__ */ jsxs("div", {
|
|
133
|
-
/* @__PURE__ */
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
151
|
+
/* @__PURE__ */ jsxs("div", { className: styles.section, children: [
|
|
152
|
+
/* @__PURE__ */ jsxs("div", { className: styles.sectionTitle, children: [
|
|
153
|
+
"\u{1F464} ",
|
|
154
|
+
t("import.client")
|
|
155
|
+
] }),
|
|
156
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
157
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.name") }),
|
|
158
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoValue, children: preview.client.name })
|
|
137
159
|
] }),
|
|
138
|
-
/* @__PURE__ */ jsxs("div", {
|
|
139
|
-
/* @__PURE__ */ jsx("span", {
|
|
140
|
-
/* @__PURE__ */ jsx("span", {
|
|
160
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
161
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.email") }),
|
|
162
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoValue, children: preview.client.email })
|
|
141
163
|
] }),
|
|
142
|
-
/* @__PURE__ */ jsxs("div", {
|
|
143
|
-
/* @__PURE__ */ jsx("span", {
|
|
144
|
-
/* @__PURE__ */ jsx("span", {
|
|
164
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
165
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.company") }),
|
|
166
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoValue, children: preview.client.company })
|
|
145
167
|
] }),
|
|
146
|
-
/* @__PURE__ */ jsxs("div", {
|
|
147
|
-
/* @__PURE__ */ jsx("span", {
|
|
148
|
-
/* @__PURE__ */ jsx("span", {
|
|
168
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
169
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.parsing") }),
|
|
170
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoValue, children: /* @__PURE__ */ jsx("span", { className: styles.badgeInfo, children: preview.parseMethod === "structured" ? t("import.parsingRegex") : t("import.parsingAi") }) })
|
|
149
171
|
] })
|
|
150
172
|
] }),
|
|
151
|
-
/* @__PURE__ */ jsxs("div", {
|
|
152
|
-
/* @__PURE__ */ jsxs("div", {
|
|
153
|
-
|
|
154
|
-
|
|
173
|
+
/* @__PURE__ */ jsxs("div", { className: styles.section, children: [
|
|
174
|
+
/* @__PURE__ */ jsxs("div", { className: styles.sectionTitle, children: [
|
|
175
|
+
"\u{1F4AC} ",
|
|
176
|
+
preview.subject,
|
|
177
|
+
/* @__PURE__ */ jsxs("span", { className: styles.sectionTitleRight, children: [
|
|
155
178
|
preview.messageCount,
|
|
156
179
|
" ",
|
|
157
180
|
t("import.messages")
|
|
158
181
|
] })
|
|
159
182
|
] }),
|
|
160
|
-
preview.messages.map((msg, i) => /* @__PURE__ */ jsxs("div", {
|
|
161
|
-
/* @__PURE__ */ jsxs("div", {
|
|
162
|
-
/* @__PURE__ */ jsxs("span", {
|
|
183
|
+
preview.messages.map((msg, i) => /* @__PURE__ */ jsxs("div", { className: msg.from === "admin" ? styles.msgAdmin : styles.msgClient, children: [
|
|
184
|
+
/* @__PURE__ */ jsxs("div", { className: styles.msgHeader, children: [
|
|
185
|
+
/* @__PURE__ */ jsxs("span", { className: styles.msgAuthor, children: [
|
|
163
186
|
msg.from === "admin" ? ">> " : "<< ",
|
|
164
187
|
msg.name
|
|
165
188
|
] }),
|
|
166
|
-
/* @__PURE__ */ jsx("span", {
|
|
189
|
+
/* @__PURE__ */ jsx("span", { className: styles.msgDate, children: msg.date })
|
|
167
190
|
] }),
|
|
168
|
-
/* @__PURE__ */ jsx("div", {
|
|
191
|
+
/* @__PURE__ */ jsx("div", { className: styles.msgPreview, children: msg.preview })
|
|
169
192
|
] }, i))
|
|
170
193
|
] }),
|
|
171
|
-
/* @__PURE__ */ jsxs("div", {
|
|
172
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setPreview(null),
|
|
173
|
-
/* @__PURE__ */ jsx("button", { onClick: doImport, disabled: loading,
|
|
194
|
+
/* @__PURE__ */ jsxs("div", { className: styles.btnRow, children: [
|
|
195
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setPreview(null), className: styles.btnMuted, children: t("common.cancel") }),
|
|
196
|
+
/* @__PURE__ */ jsx("button", { onClick: doImport, disabled: loading, className: styles.btnGreen, children: /* @__PURE__ */ jsxs("span", { className: styles.btnContent, children: [
|
|
197
|
+
"\u279C ",
|
|
198
|
+
loading ? t("import.importing") : t("import.importButton", { count: String(preview.messageCount) })
|
|
199
|
+
] }) })
|
|
174
200
|
] })
|
|
175
201
|
] }),
|
|
176
|
-
result && /* @__PURE__ */ jsxs("div", {
|
|
177
|
-
/* @__PURE__ */
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
202
|
+
result && /* @__PURE__ */ jsxs("div", { className: styles.resultSuccess, children: [
|
|
203
|
+
/* @__PURE__ */ jsxs("div", { className: styles.resultTitleSuccess, children: [
|
|
204
|
+
"\u2713 ",
|
|
205
|
+
t("import.resultTitle")
|
|
206
|
+
] }),
|
|
207
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
208
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.resultTicket") }),
|
|
209
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoValue, children: /* @__PURE__ */ jsx("a", { href: `/admin/support/ticket?id=${result.ticketId}`, className: styles.link, children: result.ticketNumber }) })
|
|
181
210
|
] }),
|
|
182
|
-
/* @__PURE__ */ jsxs("div", {
|
|
183
|
-
/* @__PURE__ */ jsx("span", {
|
|
184
|
-
/* @__PURE__ */ jsxs("span", {
|
|
211
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
212
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.resultClient") }),
|
|
213
|
+
/* @__PURE__ */ jsxs("span", { className: styles.infoValue, children: [
|
|
185
214
|
result.clientName,
|
|
186
215
|
" (",
|
|
187
216
|
result.clientEmail,
|
|
188
217
|
")",
|
|
189
|
-
result.isNewClient && /* @__PURE__ */ jsx("span", { style: { marginLeft: 8
|
|
218
|
+
result.isNewClient && /* @__PURE__ */ jsx("span", { className: styles.badgeNew, style: { marginLeft: 8 }, children: t("import.resultNew") })
|
|
190
219
|
] })
|
|
191
220
|
] }),
|
|
192
|
-
/* @__PURE__ */ jsxs("div", {
|
|
193
|
-
/* @__PURE__ */ jsx("span", {
|
|
194
|
-
/* @__PURE__ */ jsx("span", {
|
|
221
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
222
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.resultCompany") }),
|
|
223
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoValue, children: result.clientCompany })
|
|
195
224
|
] }),
|
|
196
|
-
/* @__PURE__ */ jsxs("div", {
|
|
197
|
-
/* @__PURE__ */ jsx("span", {
|
|
198
|
-
/* @__PURE__ */ jsx("span", {
|
|
225
|
+
/* @__PURE__ */ jsxs("div", { className: styles.infoRow, children: [
|
|
226
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoLabel, children: t("import.resultMessages") }),
|
|
227
|
+
/* @__PURE__ */ jsx("span", { className: styles.infoValue, children: t("import.resultImported", { count: String(result.messagesImported) }) })
|
|
199
228
|
] })
|
|
200
229
|
] })
|
|
201
230
|
] });
|