@consilioweb/payload-support 0.9.6 → 0.9.7

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.
@@ -138,6 +138,7 @@ const TicketDetailClient = () => {
138
138
  const [replyHtml, setReplyHtml] = React.useState("");
139
139
  const [isInternal, setIsInternal] = React.useState(false);
140
140
  const [notifyClient, setNotifyClient] = React.useState(true);
141
+ const [sendAsClient, setSendAsClient] = React.useState(false);
141
142
  const [sending, setSending] = React.useState(false);
142
143
  const [showMenu, setShowMenu] = React.useState(false);
143
144
  const [clientTyping, setClientTyping] = React.useState(false);
@@ -419,12 +420,21 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
419
420
  method: "POST",
420
421
  headers: { "Content-Type": "application/json" },
421
422
  credentials: "include",
422
- body: JSON.stringify({ ticket: Number(ticketId), body: finalBody, ...finalHtml ? { bodyHtml: finalHtml } : {}, authorType: "admin", isInternal, skipNotification: isInternal || !notifyClient })
423
+ body: JSON.stringify({
424
+ ticket: Number(ticketId),
425
+ body: finalBody,
426
+ ...finalHtml ? { bodyHtml: finalHtml } : {},
427
+ authorType: sendAsClient ? "client" : "admin",
428
+ ...sendAsClient && client ? { authorClient: client.id } : {},
429
+ isInternal: sendAsClient ? false : isInternal,
430
+ skipNotification: sendAsClient || isInternal || !notifyClient
431
+ })
423
432
  });
424
433
  if (res.ok) {
425
434
  setReplyBody("");
426
435
  setReplyHtml("");
427
436
  setIsInternal(false);
437
+ setSendAsClient(false);
428
438
  setPendingFiles([]);
429
439
  editorRef.current?.clear();
430
440
  fetchAll();
@@ -789,18 +799,39 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
789
799
  ] }, i)) }),
790
800
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.composerFooter, children: [
791
801
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s__default.default.composerOptions, children: [
792
- /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
793
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: isInternal, onChange: (e) => setIsInternal(e.target.checked) }),
794
- " ",
795
- t("detail.internalNote")
796
- ] }),
797
- /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
798
- /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: notifyClient, onChange: (e) => setNotifyClient(e.target.checked), disabled: isInternal }),
799
- " ",
800
- t("detail.notify")
802
+ /* @__PURE__ */ jsxRuntime.jsxs(
803
+ "select",
804
+ {
805
+ value: sendAsClient ? "client" : "admin",
806
+ onChange: (e) => {
807
+ const asClient = e.target.value === "client";
808
+ setSendAsClient(asClient);
809
+ if (asClient) {
810
+ setIsInternal(false);
811
+ setNotifyClient(false);
812
+ }
813
+ },
814
+ style: { fontSize: "12px", padding: "4px 8px", fontWeight: 600, borderRadius: 6, border: "1px solid var(--theme-elevation-200)", background: "var(--theme-elevation-0)", color: "var(--theme-text)" },
815
+ children: [
816
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "En tant que : Support" }),
817
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "client", children: "En tant que : Client" })
818
+ ]
819
+ }
820
+ ),
821
+ !sendAsClient && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
822
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
823
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: isInternal, onChange: (e) => setIsInternal(e.target.checked) }),
824
+ " ",
825
+ t("detail.internalNote")
826
+ ] }),
827
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
828
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: notifyClient, onChange: (e) => setNotifyClient(e.target.checked), disabled: isInternal }),
829
+ " ",
830
+ t("detail.notify")
831
+ ] })
801
832
  ] })
802
833
  ] }),
803
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.sendBtn} ${isInternal ? s__default.default.sendBtnInternal : ""}`, onClick: handleSend, disabled: sending || !replyBody.trim(), "data-action": "send-reply", children: sending ? t("detail.sending") : isInternal ? t("detail.sendNote") : t("detail.sendReply") })
834
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: `${s__default.default.sendBtn} ${isInternal ? s__default.default.sendBtnInternal : ""}`, onClick: handleSend, disabled: sending || !replyBody.trim(), "data-action": "send-reply", children: sending ? t("detail.sending") : sendAsClient ? "Ajouter message client" : isInternal ? t("detail.sendNote") : t("detail.sendReply") })
804
835
  ] })
805
836
  ]
806
837
  }
@@ -131,6 +131,7 @@ const TicketDetailClient = () => {
131
131
  const [replyHtml, setReplyHtml] = useState("");
132
132
  const [isInternal, setIsInternal] = useState(false);
133
133
  const [notifyClient, setNotifyClient] = useState(true);
134
+ const [sendAsClient, setSendAsClient] = useState(false);
134
135
  const [sending, setSending] = useState(false);
135
136
  const [showMenu, setShowMenu] = useState(false);
136
137
  const [clientTyping, setClientTyping] = useState(false);
@@ -412,12 +413,21 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
412
413
  method: "POST",
413
414
  headers: { "Content-Type": "application/json" },
414
415
  credentials: "include",
415
- body: JSON.stringify({ ticket: Number(ticketId), body: finalBody, ...finalHtml ? { bodyHtml: finalHtml } : {}, authorType: "admin", isInternal, skipNotification: isInternal || !notifyClient })
416
+ body: JSON.stringify({
417
+ ticket: Number(ticketId),
418
+ body: finalBody,
419
+ ...finalHtml ? { bodyHtml: finalHtml } : {},
420
+ authorType: sendAsClient ? "client" : "admin",
421
+ ...sendAsClient && client ? { authorClient: client.id } : {},
422
+ isInternal: sendAsClient ? false : isInternal,
423
+ skipNotification: sendAsClient || isInternal || !notifyClient
424
+ })
416
425
  });
417
426
  if (res.ok) {
418
427
  setReplyBody("");
419
428
  setReplyHtml("");
420
429
  setIsInternal(false);
430
+ setSendAsClient(false);
421
431
  setPendingFiles([]);
422
432
  editorRef.current?.clear();
423
433
  fetchAll();
@@ -782,18 +792,39 @@ ${uploadedLinks.join("\n")}` : replyBody.trim() || "[Contenu enrichi]";
782
792
  ] }, i)) }),
783
793
  /* @__PURE__ */ jsxs("div", { className: s.composerFooter, children: [
784
794
  /* @__PURE__ */ jsxs("div", { className: s.composerOptions, children: [
785
- /* @__PURE__ */ jsxs("label", { children: [
786
- /* @__PURE__ */ jsx("input", { type: "checkbox", checked: isInternal, onChange: (e) => setIsInternal(e.target.checked) }),
787
- " ",
788
- t("detail.internalNote")
789
- ] }),
790
- /* @__PURE__ */ jsxs("label", { children: [
791
- /* @__PURE__ */ jsx("input", { type: "checkbox", checked: notifyClient, onChange: (e) => setNotifyClient(e.target.checked), disabled: isInternal }),
792
- " ",
793
- t("detail.notify")
795
+ /* @__PURE__ */ jsxs(
796
+ "select",
797
+ {
798
+ value: sendAsClient ? "client" : "admin",
799
+ onChange: (e) => {
800
+ const asClient = e.target.value === "client";
801
+ setSendAsClient(asClient);
802
+ if (asClient) {
803
+ setIsInternal(false);
804
+ setNotifyClient(false);
805
+ }
806
+ },
807
+ style: { fontSize: "12px", padding: "4px 8px", fontWeight: 600, borderRadius: 6, border: "1px solid var(--theme-elevation-200)", background: "var(--theme-elevation-0)", color: "var(--theme-text)" },
808
+ children: [
809
+ /* @__PURE__ */ jsx("option", { value: "admin", children: "En tant que : Support" }),
810
+ /* @__PURE__ */ jsx("option", { value: "client", children: "En tant que : Client" })
811
+ ]
812
+ }
813
+ ),
814
+ !sendAsClient && /* @__PURE__ */ jsxs(Fragment, { children: [
815
+ /* @__PURE__ */ jsxs("label", { children: [
816
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: isInternal, onChange: (e) => setIsInternal(e.target.checked) }),
817
+ " ",
818
+ t("detail.internalNote")
819
+ ] }),
820
+ /* @__PURE__ */ jsxs("label", { children: [
821
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: notifyClient, onChange: (e) => setNotifyClient(e.target.checked), disabled: isInternal }),
822
+ " ",
823
+ t("detail.notify")
824
+ ] })
794
825
  ] })
795
826
  ] }),
796
- /* @__PURE__ */ jsx("button", { className: `${s.sendBtn} ${isInternal ? s.sendBtnInternal : ""}`, onClick: handleSend, disabled: sending || !replyBody.trim(), "data-action": "send-reply", children: sending ? t("detail.sending") : isInternal ? t("detail.sendNote") : t("detail.sendReply") })
827
+ /* @__PURE__ */ jsx("button", { className: `${s.sendBtn} ${isInternal ? s.sendBtnInternal : ""}`, onClick: handleSend, disabled: sending || !replyBody.trim(), "data-action": "send-reply", children: sending ? t("detail.sending") : sendAsClient ? "Ajouter message client" : isInternal ? t("detail.sendNote") : t("detail.sendReply") })
797
828
  ] })
798
829
  ]
799
830
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@consilioweb/payload-support",
3
- "version": "0.9.6",
3
+ "version": "0.9.7",
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",
@@ -132,6 +132,7 @@ export const TicketDetailClient: React.FC = () => {
132
132
  const [replyHtml, setReplyHtml] = useState('')
133
133
  const [isInternal, setIsInternal] = useState(false)
134
134
  const [notifyClient, setNotifyClient] = useState(true)
135
+ const [sendAsClient, setSendAsClient] = useState(false)
135
136
  const [sending, setSending] = useState(false)
136
137
 
137
138
  const [showMenu, setShowMenu] = useState(false)
@@ -396,8 +397,16 @@ const [clientTyping, setClientTyping] = useState(false)
396
397
  const finalHtml = uploadedLinks.length > 0 ? `${replyHtml || replyBody.trim()}<br/><br/>${uploadedLinks.map((l) => l.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>')).join('<br/>')}` : (replyHtml || undefined)
397
398
 
398
399
  const res = await fetch('/api/ticket-messages', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include',
399
- body: JSON.stringify({ ticket: Number(ticketId), body: finalBody, ...(finalHtml ? { bodyHtml: finalHtml } : {}), authorType: 'admin', isInternal, skipNotification: isInternal || !notifyClient }) })
400
- if (res.ok) { setReplyBody(''); setReplyHtml(''); setIsInternal(false); setPendingFiles([]); editorRef.current?.clear(); fetchAll() }
400
+ body: JSON.stringify({
401
+ ticket: Number(ticketId),
402
+ body: finalBody,
403
+ ...(finalHtml ? { bodyHtml: finalHtml } : {}),
404
+ authorType: sendAsClient ? 'client' : 'admin',
405
+ ...(sendAsClient && client ? { authorClient: client.id } : {}),
406
+ isInternal: sendAsClient ? false : isInternal,
407
+ skipNotification: sendAsClient || isInternal || !notifyClient,
408
+ }) })
409
+ if (res.ok) { setReplyBody(''); setReplyHtml(''); setIsInternal(false); setSendAsClient(false); setPendingFiles([]); editorRef.current?.clear(); fetchAll() }
401
410
  } catch {} finally { setSending(false) }
402
411
  }
403
412
 
@@ -718,13 +727,27 @@ const [clientTyping, setClientTyping] = useState(false)
718
727
  )}
719
728
  <div className={s.composerFooter}>
720
729
  <div className={s.composerOptions}>
721
- {/* #9 — "Internal" -> "Note interne", "Notify" -> "Notifier" */}
722
- <label><input type="checkbox" checked={isInternal} onChange={(e) => setIsInternal(e.target.checked)} /> {t('detail.internalNote')}</label>
723
- <label><input type="checkbox" checked={notifyClient} onChange={(e) => setNotifyClient(e.target.checked)} disabled={isInternal} /> {t('detail.notify')}</label>
730
+ <select
731
+ value={sendAsClient ? 'client' : 'admin'}
732
+ onChange={(e) => {
733
+ const asClient = e.target.value === 'client'
734
+ setSendAsClient(asClient)
735
+ if (asClient) { setIsInternal(false); setNotifyClient(false) }
736
+ }}
737
+ style={{ fontSize: '12px', padding: '4px 8px', fontWeight: 600, borderRadius: 6, border: '1px solid var(--theme-elevation-200)', background: 'var(--theme-elevation-0)', color: 'var(--theme-text)' }}
738
+ >
739
+ <option value="admin">En tant que : Support</option>
740
+ <option value="client">En tant que : Client</option>
741
+ </select>
742
+ {!sendAsClient && (
743
+ <>
744
+ <label><input type="checkbox" checked={isInternal} onChange={(e) => setIsInternal(e.target.checked)} /> {t('detail.internalNote')}</label>
745
+ <label><input type="checkbox" checked={notifyClient} onChange={(e) => setNotifyClient(e.target.checked)} disabled={isInternal} /> {t('detail.notify')}</label>
746
+ </>
747
+ )}
724
748
  </div>
725
- {/* #9 — "Send ->" -> "Envoyer ->" */}
726
749
  <button className={`${s.sendBtn} ${isInternal ? s.sendBtnInternal : ''}`} onClick={handleSend} disabled={sending || !replyBody.trim()} data-action="send-reply">
727
- {sending ? t('detail.sending') : isInternal ? t('detail.sendNote') : t('detail.sendReply')}
750
+ {sending ? t('detail.sending') : sendAsClient ? 'Ajouter message client' : isInternal ? t('detail.sendNote') : t('detail.sendReply')}
728
751
  </button>
729
752
  </div>
730
753
  </div>