@flamingo-stack/openframe-frontend-core 0.0.214 → 0.0.215-snapshot.20260529033323
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/{chunk-KDNGUYZM.cjs → chunk-2G3NXF6J.cjs} +17 -17
- package/dist/{chunk-KDNGUYZM.cjs.map → chunk-2G3NXF6J.cjs.map} +1 -1
- package/dist/{chunk-HWY35EAK.js → chunk-7PCP7YQR.js} +2 -2
- package/dist/{chunk-YZUUFTIK.cjs → chunk-D4MNFY67.cjs} +3 -2
- package/dist/chunk-D4MNFY67.cjs.map +1 -0
- package/dist/{chunk-IZL2KEH6.cjs → chunk-NGFP4RVL.cjs} +24 -24
- package/dist/{chunk-IZL2KEH6.cjs.map → chunk-NGFP4RVL.cjs.map} +1 -1
- package/dist/{chunk-5OWDOFKK.js → chunk-R6MLPU4A.js} +2 -2
- package/dist/{chunk-UKND27XC.js → chunk-WQZP3JIZ.js} +3 -2
- package/dist/{chunk-UKND27XC.js.map → chunk-WQZP3JIZ.js.map} +1 -1
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/index.cjs +49 -49
- package/dist/components/index.js +2 -2
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/tickets/help-center-card.d.ts +5 -1
- package/dist/components/tickets/help-center-card.d.ts.map +1 -1
- package/dist/components/tickets/hooks/use-ticket-actions.d.ts +8 -0
- package/dist/components/tickets/hooks/use-ticket-actions.d.ts.map +1 -1
- package/dist/components/tickets/index.cjs +271 -107
- package/dist/components/tickets/index.cjs.map +1 -1
- package/dist/components/tickets/index.js +201 -37
- package/dist/components/tickets/index.js.map +1 -1
- package/dist/components/tickets/ticket-detail-drawer.d.ts +11 -2
- package/dist/components/tickets/ticket-detail-drawer.d.ts.map +1 -1
- package/dist/components/tickets/types.d.ts +28 -1
- package/dist/components/tickets/types.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/platform/ShellTypeBadge.tsx +2 -2
- package/src/components/tickets/help-center-card.tsx +8 -0
- package/src/components/tickets/help-center-list.tsx +2 -0
- package/src/components/tickets/hooks/use-ticket-actions.ts +188 -12
- package/src/components/tickets/ticket-detail-drawer.tsx +129 -1
- package/src/components/tickets/types.ts +32 -0
- package/dist/chunk-YZUUFTIK.cjs.map +0 -1
- /package/dist/{chunk-HWY35EAK.js.map → chunk-7PCP7YQR.js.map} +0 -0
- /package/dist/{chunk-5OWDOFKK.js.map → chunk-R6MLPU4A.js.map} +0 -0
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var _chunk2G3NXF6Jcjs = require('../../chunk-2G3NXF6J.cjs');
|
|
13
13
|
require('../../chunk-VFKQMAUF.cjs');
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
var
|
|
16
|
+
var _chunkNGFP4RVLcjs = require('../../chunk-NGFP4RVL.cjs');
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
@@ -36,7 +36,8 @@ var _chunkIZL2KEH6cjs = require('../../chunk-IZL2KEH6.cjs');
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
|
|
40
|
+
var _chunkD4MNFY67cjs = require('../../chunk-D4MNFY67.cjs');
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
var _chunkWT5JV2GScjs = require('../../chunk-WT5JV2GS.cjs');
|
|
@@ -99,7 +100,7 @@ function TicketOpenForm({
|
|
|
99
100
|
}) {
|
|
100
101
|
const [subject, setSubject] = _react.useState.call(void 0, "");
|
|
101
102
|
const [content, setContent] = _react.useState.call(void 0, "");
|
|
102
|
-
const { attachments, readyAttachments, hasInflightUploads, addFiles, removeAttachment, clear } =
|
|
103
|
+
const { attachments, readyAttachments, hasInflightUploads, addFiles, removeAttachment, clear } = _chunkD4MNFY67cjs.useChatAttachments.call(void 0, );
|
|
103
104
|
const trimmedSubject = subject.trim();
|
|
104
105
|
const trimmedContent = content.trim();
|
|
105
106
|
const overCap = content.length > TICKET_TEXT_MAX_CHARS;
|
|
@@ -119,7 +120,7 @@ function TicketOpenForm({
|
|
|
119
120
|
clear();
|
|
120
121
|
}
|
|
121
122
|
};
|
|
122
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
123
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.Card, { className: "p-6", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: handleSubmit, className: "flex flex-col md:flex-row gap-6", children: [
|
|
123
124
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0 md:max-w-md", children: [
|
|
124
125
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "text-2xl font-semibold text-ods-text-primary mb-2", children: "Need Support?" }),
|
|
125
126
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary text-sm", children: "Can't find what you're looking for? Submit a support ticket below \u2014 we'll follow up shortly." }),
|
|
@@ -158,7 +159,7 @@ function TicketOpenForm({
|
|
|
158
159
|
}
|
|
159
160
|
),
|
|
160
161
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
161
|
-
|
|
162
|
+
_chunkD4MNFY67cjs.Textarea,
|
|
162
163
|
{
|
|
163
164
|
id: "ticket-content",
|
|
164
165
|
placeholder: "Describe your issue or question in detail...",
|
|
@@ -182,7 +183,7 @@ function TicketOpenForm({
|
|
|
182
183
|
)
|
|
183
184
|
] }),
|
|
184
185
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
185
|
-
|
|
186
|
+
_chunkD4MNFY67cjs.ChatAttachmentChipStrip,
|
|
186
187
|
{
|
|
187
188
|
attachments,
|
|
188
189
|
onRemove: removeAttachment,
|
|
@@ -191,7 +192,7 @@ function TicketOpenForm({
|
|
|
191
192
|
),
|
|
192
193
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-3", children: [
|
|
193
194
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
194
|
-
|
|
195
|
+
_chunkD4MNFY67cjs.ChatAttachmentAddButton,
|
|
195
196
|
{
|
|
196
197
|
attachmentsEnabled: !supportSystemDown,
|
|
197
198
|
attachmentsCount: attachments.length,
|
|
@@ -229,7 +230,7 @@ _chunkUXZ3ZJ3Mcjs.init_button2.call(void 0, );
|
|
|
229
230
|
|
|
230
231
|
var LIST_ENGAGEMENTS_ENDPOINT = "/api/chat/agent/list-engagements";
|
|
231
232
|
function useTicketEngagements(externalTicketId, enabled = true) {
|
|
232
|
-
const identity =
|
|
233
|
+
const identity = _chunkD4MNFY67cjs.useChatIdentity.call(void 0, );
|
|
233
234
|
const identityKey = _nullishCoalesce(_optionalChain([identity, 'access', _ => _.user, 'optionalAccess', _2 => _2.email]), () => ( "anon"));
|
|
234
235
|
const queryEnabled = enabled && identity.authTier !== "anon" && !!_optionalChain([identity, 'access', _3 => _3.user, 'optionalAccess', _4 => _4.email]) && !!externalTicketId && !externalTicketId.startsWith("temp-");
|
|
235
236
|
const query = _reactquery.useQuery.call(void 0, {
|
|
@@ -243,7 +244,7 @@ function useTicketEngagements(externalTicketId, enabled = true) {
|
|
|
243
244
|
refetchOnMount: "always",
|
|
244
245
|
refetchOnWindowFocus: true,
|
|
245
246
|
queryFn: async () => {
|
|
246
|
-
const response = await
|
|
247
|
+
const response = await _chunkD4MNFY67cjs.embedAuthedFetch.call(void 0, LIST_ENGAGEMENTS_ENDPOINT, {
|
|
247
248
|
method: "POST",
|
|
248
249
|
body: JSON.stringify({ ticket_id: externalTicketId })
|
|
249
250
|
});
|
|
@@ -291,7 +292,7 @@ function TicketLinkedDeliveryCard({
|
|
|
291
292
|
{
|
|
292
293
|
className: `rounded-md border border-ods-border bg-ods-bg overflow-hidden ${_nullishCoalesce(className, () => ( ""))}`,
|
|
293
294
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
294
|
-
|
|
295
|
+
_chunk2G3NXF6Jcjs.DeliveryRow,
|
|
295
296
|
{
|
|
296
297
|
item,
|
|
297
298
|
href: clickup.delivery_href,
|
|
@@ -311,40 +312,52 @@ function TicketDetailDrawer({
|
|
|
311
312
|
onSendMessage,
|
|
312
313
|
onClose,
|
|
313
314
|
onReopen,
|
|
314
|
-
onActionCollapsed
|
|
315
|
+
onActionCollapsed,
|
|
316
|
+
replyError,
|
|
317
|
+
onClearReplyError
|
|
315
318
|
}) {
|
|
316
319
|
const isClosed = (_nullishCoalesce(ticket.status, () => ( ""))).toUpperCase() === "CLOSED";
|
|
317
320
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "bg-ods-card border-t border-ods-border px-4 py-4 flex flex-col gap-4", children: [
|
|
321
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, AssignedAgentRow, { assignedOwner: ticket.assignedOwner }),
|
|
318
322
|
ticket.clickup && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketLinkedDeliveryCard, { clickup: ticket.clickup }),
|
|
319
323
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
|
|
320
324
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xs font-medium text-ods-text-secondary mb-2 uppercase tracking-wider", children: "Conversation" }),
|
|
321
325
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketTimelinePanel, { ticket })
|
|
322
326
|
] }),
|
|
323
|
-
/* @__PURE__ */ _jsxruntime.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
327
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "border-t border-ods-border pt-4", children: [
|
|
328
|
+
replyError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
329
|
+
ReplyFailureBanner,
|
|
330
|
+
{
|
|
331
|
+
error: replyError,
|
|
332
|
+
onDismiss: _nullishCoalesce(onClearReplyError, () => ( (() => void 0)))
|
|
333
|
+
}
|
|
334
|
+
),
|
|
335
|
+
isClosed ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
336
|
+
ReopenAction,
|
|
337
|
+
{
|
|
338
|
+
ticketRef: { id: ticket.id, external_id: ticket.external_id },
|
|
339
|
+
busy,
|
|
340
|
+
supportSystemDown,
|
|
341
|
+
onReopen,
|
|
342
|
+
onActionCollapsed
|
|
343
|
+
}
|
|
344
|
+
) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
345
|
+
OpenActions,
|
|
346
|
+
{
|
|
347
|
+
ticket,
|
|
348
|
+
busy,
|
|
349
|
+
supportSystemDown,
|
|
350
|
+
onSendMessage,
|
|
351
|
+
onClose,
|
|
352
|
+
onActionCollapsed
|
|
353
|
+
}
|
|
354
|
+
)
|
|
355
|
+
] })
|
|
343
356
|
] });
|
|
344
357
|
}
|
|
345
358
|
var TURN_SEPARATOR_RE = /[\s]{1,16}---[\s]{1,16}/g;
|
|
346
359
|
function TicketTimelinePanel({ ticket }) {
|
|
347
|
-
const identity =
|
|
360
|
+
const identity = _chunkD4MNFY67cjs.useChatIdentity.call(void 0, );
|
|
348
361
|
const externalId = isOptimistic(ticket) ? null : ticket.external_id;
|
|
349
362
|
const { engagements, isLoading } = useTicketEngagements(externalId, !!externalId);
|
|
350
363
|
const bodyTurns = ticket.body ? ticket.body.split(TURN_SEPARATOR_RE).map((t) => t.trim()).filter(Boolean) : [];
|
|
@@ -356,10 +369,10 @@ function TicketTimelinePanel({ ticket }) {
|
|
|
356
369
|
const customerAvatar = isViewerTheCustomer ? _nullishCoalesce(_optionalChain([identity, 'access', _20 => _20.user, 'optionalAccess', _21 => _21.avatarUrl]), () => ( void 0)) : void 0;
|
|
357
370
|
if (bodyTurns.length === 0 && engagements.length === 0) {
|
|
358
371
|
if (isLoading) {
|
|
359
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
372
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.ConversationCardRowSkeletonList, { rows: 2 });
|
|
360
373
|
}
|
|
361
374
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
362
|
-
|
|
375
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
363
376
|
{
|
|
364
377
|
type: "generic",
|
|
365
378
|
title: "No conversation yet",
|
|
@@ -374,7 +387,7 @@ function TicketTimelinePanel({ ticket }) {
|
|
|
374
387
|
const role = i === 0 ? "Original message" : isResolution ? "Resolution" : `Update ${i}`;
|
|
375
388
|
const text = isResolution ? turn.replace(/^\[Resolution\]\s*/, "") : turn;
|
|
376
389
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
377
|
-
|
|
390
|
+
_chunk2G3NXF6Jcjs.ConversationCardRow,
|
|
378
391
|
{
|
|
379
392
|
author: customerName,
|
|
380
393
|
role,
|
|
@@ -404,7 +417,7 @@ function TicketTimelinePanel({ ticket }) {
|
|
|
404
417
|
avatarSrc = void 0;
|
|
405
418
|
}
|
|
406
419
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
407
|
-
|
|
420
|
+
_chunk2G3NXF6Jcjs.ConversationCardRow,
|
|
408
421
|
{
|
|
409
422
|
author,
|
|
410
423
|
role: "Reply",
|
|
@@ -421,7 +434,7 @@ function TicketTimelinePanel({ ticket }) {
|
|
|
421
434
|
// content rendered — drawer is showing the customer's body
|
|
422
435
|
// turns + cached engagements while a background refetch is
|
|
423
436
|
// in flight. Single row keeps the placeholder modest.
|
|
424
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
437
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.ConversationCardRowSkeletonList, { rows: 1 })
|
|
425
438
|
] });
|
|
426
439
|
}
|
|
427
440
|
function mapEngagementAttachments(files) {
|
|
@@ -474,7 +487,7 @@ function OpenActions({
|
|
|
474
487
|
const [messageText, setMessageText] = _react.useState.call(void 0, "");
|
|
475
488
|
const [resolution, setResolution] = _react.useState.call(void 0, "");
|
|
476
489
|
const [closeDialogOpen, setCloseDialogOpen] = _react.useState.call(void 0, false);
|
|
477
|
-
const attachments =
|
|
490
|
+
const attachments = _chunkD4MNFY67cjs.useChatAttachments.call(void 0, );
|
|
478
491
|
const disabled = busy || supportSystemDown;
|
|
479
492
|
const ticketRef = { id: ticket.id, external_id: ticket.external_id };
|
|
480
493
|
const hasText = messageText.trim().length > 0;
|
|
@@ -497,7 +510,7 @@ function OpenActions({
|
|
|
497
510
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-3", children: [
|
|
498
511
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2", children: [
|
|
499
512
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
500
|
-
|
|
513
|
+
_chunkD4MNFY67cjs.Textarea,
|
|
501
514
|
{
|
|
502
515
|
value: messageText,
|
|
503
516
|
onChange: (e) => setMessageText(e.target.value),
|
|
@@ -508,7 +521,7 @@ function OpenActions({
|
|
|
508
521
|
}
|
|
509
522
|
),
|
|
510
523
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
511
|
-
|
|
524
|
+
_chunkD4MNFY67cjs.ChatAttachmentChipStrip,
|
|
512
525
|
{
|
|
513
526
|
attachments: attachments.attachments,
|
|
514
527
|
onRemove: attachments.removeAttachment,
|
|
@@ -518,7 +531,7 @@ function OpenActions({
|
|
|
518
531
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex justify-between items-center gap-2 flex-wrap", children: [
|
|
519
532
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
|
|
520
533
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
521
|
-
|
|
534
|
+
_chunkD4MNFY67cjs.ChatAttachmentAddButton,
|
|
522
535
|
{
|
|
523
536
|
attachmentsEnabled: !supportSystemDown,
|
|
524
537
|
attachmentsCount: attachments.attachments.length,
|
|
@@ -553,13 +566,13 @@ function OpenActions({
|
|
|
553
566
|
] })
|
|
554
567
|
] })
|
|
555
568
|
] }),
|
|
556
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
557
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
558
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
559
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
569
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.AlertDialog, { open: closeDialogOpen, onOpenChange: setCloseDialogOpen, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkD4MNFY67cjs.AlertDialogContent, { className: "bg-ods-card border-ods-border", children: [
|
|
570
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkD4MNFY67cjs.AlertDialogHeader, { children: [
|
|
571
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.AlertDialogTitle, { className: "text-ods-text-primary font-['DM_Sans'] text-[20px] font-semibold", children: "Close this ticket?" }),
|
|
572
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.AlertDialogDescription, { className: "text-ods-text-secondary font-['DM_Sans'] text-[14px]", children: "Add an optional resolution note below. You can reopen the ticket later if needed." })
|
|
560
573
|
] }),
|
|
561
574
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
562
|
-
|
|
575
|
+
_chunkD4MNFY67cjs.Textarea,
|
|
563
576
|
{
|
|
564
577
|
value: resolution,
|
|
565
578
|
onChange: (e) => setResolution(e.target.value),
|
|
@@ -569,9 +582,9 @@ function OpenActions({
|
|
|
569
582
|
className: "mt-2"
|
|
570
583
|
}
|
|
571
584
|
),
|
|
572
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
585
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkD4MNFY67cjs.AlertDialogFooter, { children: [
|
|
573
586
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
574
|
-
|
|
587
|
+
_chunkD4MNFY67cjs.AlertDialogCancel,
|
|
575
588
|
{
|
|
576
589
|
disabled: busy,
|
|
577
590
|
className: "bg-transparent border-ods-border text-ods-text-primary hover:bg-ods-border",
|
|
@@ -579,7 +592,7 @@ function OpenActions({
|
|
|
579
592
|
}
|
|
580
593
|
),
|
|
581
594
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
582
|
-
|
|
595
|
+
_chunkD4MNFY67cjs.AlertDialogAction,
|
|
583
596
|
{
|
|
584
597
|
onClick: () => void confirmClose(),
|
|
585
598
|
disabled: busy,
|
|
@@ -591,6 +604,56 @@ function OpenActions({
|
|
|
591
604
|
] }) })
|
|
592
605
|
] });
|
|
593
606
|
}
|
|
607
|
+
function ReplyFailureBanner({
|
|
608
|
+
error,
|
|
609
|
+
onDismiss
|
|
610
|
+
}) {
|
|
611
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
612
|
+
"div",
|
|
613
|
+
{
|
|
614
|
+
role: "status",
|
|
615
|
+
"aria-live": "polite",
|
|
616
|
+
className: "mb-3 flex items-start gap-3 rounded-md border border-ods-attention-red-error bg-ods-attention-red-error-secondary px-3 py-2 text-sm text-ods-attention-red-error",
|
|
617
|
+
children: [
|
|
618
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium leading-snug", children: error.message }),
|
|
619
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
620
|
+
_chunkUXZ3ZJ3Mcjs.Button,
|
|
621
|
+
{
|
|
622
|
+
type: "button",
|
|
623
|
+
variant: "transparent",
|
|
624
|
+
onClick: onDismiss,
|
|
625
|
+
"aria-label": "Dismiss reply failure",
|
|
626
|
+
className: "ml-auto px-2 py-0.5 text-xs font-medium uppercase tracking-wider text-ods-attention-red-error hover:bg-ods-attention-red-error/10 border-transparent",
|
|
627
|
+
children: "Dismiss"
|
|
628
|
+
}
|
|
629
|
+
)
|
|
630
|
+
]
|
|
631
|
+
}
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
function AssignedAgentRow({
|
|
635
|
+
assignedOwner
|
|
636
|
+
}) {
|
|
637
|
+
const trimmedName = _optionalChain([assignedOwner, 'optionalAccess', _30 => _30.name, 'optionalAccess', _31 => _31.trim, 'call', _32 => _32()]) || null;
|
|
638
|
+
const emailFallback = _optionalChain([assignedOwner, 'optionalAccess', _33 => _33.email, 'optionalAccess', _34 => _34.trim, 'call', _35 => _35()]) || null;
|
|
639
|
+
const displayLabel = _nullishCoalesce(trimmedName, () => ( (emailFallback ? emailFallback.split("@")[0] : null)));
|
|
640
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 text-xs", children: [
|
|
641
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-text-secondary uppercase tracking-wider font-medium", children: "Assigned to" }),
|
|
642
|
+
displayLabel ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex items-center gap-1.5 text-ods-text-primary font-medium", children: [
|
|
643
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
644
|
+
_chunkD4MNFY67cjs.SquareAvatar,
|
|
645
|
+
{
|
|
646
|
+
size: "sm",
|
|
647
|
+
variant: "round",
|
|
648
|
+
src: _nullishCoalesce(_optionalChain([assignedOwner, 'optionalAccess', _36 => _36.avatarUrl]), () => ( void 0)),
|
|
649
|
+
alt: displayLabel,
|
|
650
|
+
fallback: displayLabel
|
|
651
|
+
}
|
|
652
|
+
),
|
|
653
|
+
displayLabel
|
|
654
|
+
] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-text-secondary italic", children: "Unassigned" })
|
|
655
|
+
] });
|
|
656
|
+
}
|
|
594
657
|
|
|
595
658
|
// src/components/tickets/ticket-row.tsx
|
|
596
659
|
|
|
@@ -609,7 +672,7 @@ function TicketRow({
|
|
|
609
672
|
const rowRef = _react.useRef.call(void 0, null);
|
|
610
673
|
const handleClick = _react.useCallback.call(void 0, () => {
|
|
611
674
|
onToggle(ticket.id);
|
|
612
|
-
|
|
675
|
+
_chunkD4MNFY67cjs.scrollElementIntoView.call(void 0, rowRef.current, {
|
|
613
676
|
adjustTargetY: (raw) => {
|
|
614
677
|
if (!rowRef.current) return raw;
|
|
615
678
|
const expandedDrawer = document.querySelector(
|
|
@@ -635,7 +698,7 @@ function TicketRow({
|
|
|
635
698
|
// so the badge accurately reflects "Closed" with a checkmark.
|
|
636
699
|
statusLabel: _nullishCoalesce(ticket.pipeline_stage_label, () => ( void 0)),
|
|
637
700
|
category: _nullishCoalesce(ticket.customer_company, () => ( void 0)),
|
|
638
|
-
timeAgo: ticket.hubspot_updated_at ?
|
|
701
|
+
timeAgo: ticket.hubspot_updated_at ? _chunkD4MNFY67cjs.formatRelativeTime.call(void 0, ticket.hubspot_updated_at) : void 0,
|
|
639
702
|
// Linked-work chip: surfaced whenever the ticket has a linked
|
|
640
703
|
// ClickUp task. Uses the linked task's own status so the chip text
|
|
641
704
|
// reads "Working" / "Waiting on version release" / etc. — useful
|
|
@@ -650,7 +713,7 @@ function TicketRow({
|
|
|
650
713
|
className: "border-b border-ods-border last:border-b-0",
|
|
651
714
|
children: [
|
|
652
715
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
653
|
-
|
|
716
|
+
_chunkD4MNFY67cjs.ChatTicketItem,
|
|
654
717
|
{
|
|
655
718
|
ticket: tileData,
|
|
656
719
|
onClick: optimistic ? void 0 : handleClick,
|
|
@@ -714,7 +777,7 @@ function useTicketsList(filters) {
|
|
|
714
777
|
pageSize
|
|
715
778
|
};
|
|
716
779
|
if (statusFilter) body.status = statusFilter;
|
|
717
|
-
const response = await
|
|
780
|
+
const response = await _chunkD4MNFY67cjs.embedAuthedFetch.call(void 0, FIND_TICKET_ENDPOINT, {
|
|
718
781
|
method: "POST",
|
|
719
782
|
body: JSON.stringify(body)
|
|
720
783
|
});
|
|
@@ -726,12 +789,12 @@ function useTicketsList(filters) {
|
|
|
726
789
|
}
|
|
727
790
|
});
|
|
728
791
|
const data = query.data;
|
|
729
|
-
const totalCount = _nullishCoalesce(_nullishCoalesce(_optionalChain([data, 'optionalAccess',
|
|
730
|
-
const echoedPage = _nullishCoalesce(_optionalChain([data, 'optionalAccess',
|
|
731
|
-
const echoedPageSize = _nullishCoalesce(_optionalChain([data, 'optionalAccess',
|
|
732
|
-
const totalPages = _nullishCoalesce(_optionalChain([data, 'optionalAccess',
|
|
792
|
+
const totalCount = _nullishCoalesce(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _37 => _37.totalCount]), () => ( _optionalChain([data, 'optionalAccess', _38 => _38.count]))), () => ( (_nullishCoalesce(_optionalChain([data, 'optionalAccess', _39 => _39.tickets, 'optionalAccess', _40 => _40.length]), () => ( 0)))));
|
|
793
|
+
const echoedPage = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _41 => _41.page]), () => ( page));
|
|
794
|
+
const echoedPageSize = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _42 => _42.pageSize]), () => ( pageSize));
|
|
795
|
+
const totalPages = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _43 => _43.totalPages]), () => ( Math.max(1, Math.ceil(totalCount / echoedPageSize))));
|
|
733
796
|
return {
|
|
734
|
-
tickets: _nullishCoalesce(_optionalChain([data, 'optionalAccess',
|
|
797
|
+
tickets: _nullishCoalesce(_optionalChain([data, 'optionalAccess', _44 => _44.tickets]), () => ( [])),
|
|
735
798
|
// Loading-state-truth = `data === undefined`. TanStack v5's
|
|
736
799
|
// `isPending` / `isLoading` flags can be `false` in transient
|
|
737
800
|
// windows where the query is enabled-but-fetch-not-yet-fired
|
|
@@ -753,7 +816,7 @@ function useTicketsList(filters) {
|
|
|
753
816
|
// - Background refetch with existing data: data !== undefined → no load
|
|
754
817
|
// - Filter-change refetch landing on empty results: data?.tickets===[]
|
|
755
818
|
// + isFetching → bridge skeleton (the `||` branch)
|
|
756
|
-
isLoading: enabled && (data === void 0 || query.isFetching && (_nullishCoalesce(_optionalChain([data, 'optionalAccess',
|
|
819
|
+
isLoading: enabled && (data === void 0 || query.isFetching && (_nullishCoalesce(_optionalChain([data, 'optionalAccess', _45 => _45.tickets]), () => ( []))).length === 0),
|
|
757
820
|
isFetching: query.isFetching,
|
|
758
821
|
error: _nullishCoalesce(query.error, () => ( null)),
|
|
759
822
|
refetch: () => {
|
|
@@ -771,6 +834,12 @@ function useTicketsList(filters) {
|
|
|
771
834
|
|
|
772
835
|
|
|
773
836
|
var TICKET_ACTION_ENDPOINT = "/api/chat/agent/ticket-action";
|
|
837
|
+
var REPLY_BANNER_CODES = /* @__PURE__ */ new Set([
|
|
838
|
+
"HUBSPOT_5XX",
|
|
839
|
+
"HUBSPOT_400_VALIDATION",
|
|
840
|
+
"HUBSPOT_404_THREAD",
|
|
841
|
+
"HUBSPOT_REPLY_UNKNOWN"
|
|
842
|
+
]);
|
|
774
843
|
var MIRROR_SYNC_BACKOFF_MS = [3e3, 6e3, 12e3];
|
|
775
844
|
function useTicketActions(options) {
|
|
776
845
|
const queryClient = _reactquery.useQueryClient.call(void 0, );
|
|
@@ -785,6 +854,26 @@ function useTicketActions(options) {
|
|
|
785
854
|
setBusyRows(new Set(busyRowsRef.current));
|
|
786
855
|
}, []);
|
|
787
856
|
const isRowBusy = _react.useCallback.call(void 0, (id) => busyRows.has(id), [busyRows]);
|
|
857
|
+
const [replyErrorByTicket, setReplyErrorByTicket] = _react.useState.call(void 0, () => /* @__PURE__ */ new Map());
|
|
858
|
+
const setReplyError = _react.useCallback.call(void 0,
|
|
859
|
+
(externalId, mapped) => {
|
|
860
|
+
setReplyErrorByTicket((prev) => {
|
|
861
|
+
const next = new Map(prev);
|
|
862
|
+
if (mapped) next.set(externalId, mapped);
|
|
863
|
+
else next.delete(externalId);
|
|
864
|
+
return next;
|
|
865
|
+
});
|
|
866
|
+
},
|
|
867
|
+
[]
|
|
868
|
+
);
|
|
869
|
+
const replyErrorFor = _react.useCallback.call(void 0,
|
|
870
|
+
(externalId) => _nullishCoalesce(replyErrorByTicket.get(externalId), () => ( null)),
|
|
871
|
+
[replyErrorByTicket]
|
|
872
|
+
);
|
|
873
|
+
const clearReplyError = _react.useCallback.call(void 0,
|
|
874
|
+
(externalId) => setReplyError(externalId, null),
|
|
875
|
+
[setReplyError]
|
|
876
|
+
);
|
|
788
877
|
const watcherControllersRef = _react.useRef.call(void 0, /* @__PURE__ */ new Map());
|
|
789
878
|
_react.useEffect.call(void 0, () => {
|
|
790
879
|
return () => {
|
|
@@ -802,7 +891,7 @@ function useTicketActions(options) {
|
|
|
802
891
|
}, []);
|
|
803
892
|
const executeTicketAction = _react.useCallback.call(void 0,
|
|
804
893
|
async (toolName, args) => {
|
|
805
|
-
const res = await
|
|
894
|
+
const res = await _chunkD4MNFY67cjs.embedAuthedFetch.call(void 0, TICKET_ACTION_ENDPOINT, {
|
|
806
895
|
method: "POST",
|
|
807
896
|
body: JSON.stringify({ tool_name: toolName, args })
|
|
808
897
|
});
|
|
@@ -862,9 +951,11 @@ function useTicketActions(options) {
|
|
|
862
951
|
},
|
|
863
952
|
[queryClient, removeOptimistic, toast2]
|
|
864
953
|
);
|
|
954
|
+
const lastUpdateErrorRef = _react.useRef.call(void 0, null);
|
|
865
955
|
const surfaceError = _react.useCallback.call(void 0,
|
|
866
956
|
(err, action) => {
|
|
867
957
|
const mapped = mapTicketActionError(err);
|
|
958
|
+
lastUpdateErrorRef.current = mapped;
|
|
868
959
|
if (mapped.supportSystemDown) onSupportSystemDown();
|
|
869
960
|
toast2({
|
|
870
961
|
title: `Could not ${action}`,
|
|
@@ -899,6 +990,10 @@ function useTicketActions(options) {
|
|
|
899
990
|
// seconds via the mirror refetch. Drawer uses live chat
|
|
900
991
|
// identity for own-replies during this window anyway.
|
|
901
992
|
customer_name: null,
|
|
993
|
+
// No assignee until the real ticket lands. Drawer renders
|
|
994
|
+
// "Unassigned" for this brief window.
|
|
995
|
+
assigned_to: null,
|
|
996
|
+
assignedOwner: null,
|
|
902
997
|
hubspot_updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
903
998
|
_optimistic: true
|
|
904
999
|
};
|
|
@@ -908,7 +1003,7 @@ function useTicketActions(options) {
|
|
|
908
1003
|
const result = await executeTicketAction("create_ticket", {
|
|
909
1004
|
subject: input.subject.trim(),
|
|
910
1005
|
content: input.content.trim(),
|
|
911
|
-
..._optionalChain([input, 'access',
|
|
1006
|
+
..._optionalChain([input, 'access', _46 => _46.attachments, 'optionalAccess', _47 => _47.length]) ? { attachments: input.attachments } : {}
|
|
912
1007
|
});
|
|
913
1008
|
if (result.mirror_synced === false) {
|
|
914
1009
|
toast2(TOAST_COPY.open_mirror_pending);
|
|
@@ -951,10 +1046,23 @@ function useTicketActions(options) {
|
|
|
951
1046
|
ticket_id: ticket.external_id
|
|
952
1047
|
});
|
|
953
1048
|
toast2(successCopy);
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
queryClient.
|
|
957
|
-
|
|
1049
|
+
const statusUpdate = _nullishCoalesce(serverArgs.status, () => ( null));
|
|
1050
|
+
if (statusUpdate) {
|
|
1051
|
+
queryClient.setQueriesData(
|
|
1052
|
+
{ queryKey: ["tickets"] },
|
|
1053
|
+
(prev) => {
|
|
1054
|
+
if (!prev) return prev;
|
|
1055
|
+
let mutated = false;
|
|
1056
|
+
const next = prev.map((t) => {
|
|
1057
|
+
if (t.id !== ticket.id || t.status === statusUpdate) return t;
|
|
1058
|
+
mutated = true;
|
|
1059
|
+
return { ...t, status: statusUpdate };
|
|
1060
|
+
});
|
|
1061
|
+
return mutated ? next : prev;
|
|
1062
|
+
}
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
await queryClient.invalidateQueries({ queryKey: ["ticket-engagements"] });
|
|
958
1066
|
return true;
|
|
959
1067
|
});
|
|
960
1068
|
} catch (err) {
|
|
@@ -974,12 +1082,13 @@ function useTicketActions(options) {
|
|
|
974
1082
|
[setRowBusy, enqueue, executeTicketAction, queryClient, toast2, surfaceError, removeTicketFromCache]
|
|
975
1083
|
);
|
|
976
1084
|
const sendMessage = _react.useCallback.call(void 0,
|
|
977
|
-
(ticket, text, attachments) => {
|
|
1085
|
+
async (ticket, text, attachments) => {
|
|
978
1086
|
const trimmed = text.trim();
|
|
979
1087
|
const hasText = trimmed.length > 0;
|
|
980
1088
|
const hasFiles = attachments.length > 0;
|
|
981
|
-
if (!hasText && !hasFiles) return
|
|
982
|
-
|
|
1089
|
+
if (!hasText && !hasFiles) return false;
|
|
1090
|
+
lastUpdateErrorRef.current = null;
|
|
1091
|
+
const ok = await updateTicket(
|
|
983
1092
|
ticket,
|
|
984
1093
|
{
|
|
985
1094
|
...hasText ? { content_addendum: trimmed } : {},
|
|
@@ -988,15 +1097,25 @@ function useTicketActions(options) {
|
|
|
988
1097
|
TOAST_COPY.comment_success,
|
|
989
1098
|
"send message"
|
|
990
1099
|
);
|
|
1100
|
+
if (ok) {
|
|
1101
|
+
clearReplyError(ticket.external_id);
|
|
1102
|
+
} else {
|
|
1103
|
+
const mapped = lastUpdateErrorRef.current;
|
|
1104
|
+
if (mapped && REPLY_BANNER_CODES.has(mapped.code)) {
|
|
1105
|
+
setReplyError(ticket.external_id, mapped);
|
|
1106
|
+
}
|
|
1107
|
+
lastUpdateErrorRef.current = null;
|
|
1108
|
+
}
|
|
1109
|
+
return ok;
|
|
991
1110
|
},
|
|
992
|
-
[updateTicket]
|
|
1111
|
+
[updateTicket, clearReplyError, setReplyError]
|
|
993
1112
|
);
|
|
994
1113
|
const closeTicket = _react.useCallback.call(void 0,
|
|
995
1114
|
(ticket, resolution) => updateTicket(
|
|
996
1115
|
ticket,
|
|
997
1116
|
{
|
|
998
1117
|
status: "CLOSED",
|
|
999
|
-
..._optionalChain([resolution, 'optionalAccess',
|
|
1118
|
+
..._optionalChain([resolution, 'optionalAccess', _48 => _48.trim, 'call', _49 => _49()]) ? { resolution: resolution.trim() } : {}
|
|
1000
1119
|
},
|
|
1001
1120
|
TOAST_COPY.close_success,
|
|
1002
1121
|
"close ticket"
|
|
@@ -1014,9 +1133,20 @@ function useTicketActions(options) {
|
|
|
1014
1133
|
closeTicket,
|
|
1015
1134
|
reopenTicket,
|
|
1016
1135
|
isSubmittingForm,
|
|
1017
|
-
isRowBusy
|
|
1136
|
+
isRowBusy,
|
|
1137
|
+
replyErrorFor,
|
|
1138
|
+
clearReplyError
|
|
1018
1139
|
}),
|
|
1019
|
-
[
|
|
1140
|
+
[
|
|
1141
|
+
submitTicket,
|
|
1142
|
+
sendMessage,
|
|
1143
|
+
closeTicket,
|
|
1144
|
+
reopenTicket,
|
|
1145
|
+
isSubmittingForm,
|
|
1146
|
+
isRowBusy,
|
|
1147
|
+
replyErrorFor,
|
|
1148
|
+
clearReplyError
|
|
1149
|
+
]
|
|
1020
1150
|
);
|
|
1021
1151
|
}
|
|
1022
1152
|
var TicketActionFailure = class extends Error {
|
|
@@ -1058,7 +1188,7 @@ function mapTicketActionError(err) {
|
|
|
1058
1188
|
removeRowFromCache: false
|
|
1059
1189
|
};
|
|
1060
1190
|
case "RATE_LIMITED": {
|
|
1061
|
-
const retryAfterRaw = _optionalChain([err, 'access',
|
|
1191
|
+
const retryAfterRaw = _optionalChain([err, 'access', _50 => _50.response, 'optionalAccess', _51 => _51.headers, 'access', _52 => _52.get, 'call', _53 => _53("Retry-After")]);
|
|
1062
1192
|
const retryAfterSeconds = retryAfterRaw ? parseInt(retryAfterRaw, 10) : void 0;
|
|
1063
1193
|
return {
|
|
1064
1194
|
code: err.code,
|
|
@@ -1075,6 +1205,34 @@ function mapTicketActionError(err) {
|
|
|
1075
1205
|
supportSystemDown: false,
|
|
1076
1206
|
removeRowFromCache: false
|
|
1077
1207
|
};
|
|
1208
|
+
case "HUBSPOT_5XX":
|
|
1209
|
+
return {
|
|
1210
|
+
code: err.code,
|
|
1211
|
+
message: "We couldn't reach the support system. Your reply wasn't sent \u2014 please retry in a moment.",
|
|
1212
|
+
supportSystemDown: false,
|
|
1213
|
+
removeRowFromCache: false
|
|
1214
|
+
};
|
|
1215
|
+
case "HUBSPOT_400_VALIDATION":
|
|
1216
|
+
return {
|
|
1217
|
+
code: err.code,
|
|
1218
|
+
message: "Your reply was rejected. Please rephrase or remove unsupported content and try again.",
|
|
1219
|
+
supportSystemDown: false,
|
|
1220
|
+
removeRowFromCache: false
|
|
1221
|
+
};
|
|
1222
|
+
case "HUBSPOT_404_THREAD":
|
|
1223
|
+
return {
|
|
1224
|
+
code: err.code,
|
|
1225
|
+
message: "This conversation is no longer accepting replies. Open a new ticket to continue.",
|
|
1226
|
+
supportSystemDown: false,
|
|
1227
|
+
removeRowFromCache: false
|
|
1228
|
+
};
|
|
1229
|
+
case "HUBSPOT_REPLY_UNKNOWN":
|
|
1230
|
+
return {
|
|
1231
|
+
code: err.code,
|
|
1232
|
+
message: "Your reply didn't go through. Please retry.",
|
|
1233
|
+
supportSystemDown: false,
|
|
1234
|
+
removeRowFromCache: false
|
|
1235
|
+
};
|
|
1078
1236
|
default:
|
|
1079
1237
|
return {
|
|
1080
1238
|
code: "UNKNOWN",
|
|
@@ -1116,13 +1274,13 @@ function resolveErrorCode(bodyCode, status) {
|
|
|
1116
1274
|
// src/components/tickets/ticket-center.tsx
|
|
1117
1275
|
|
|
1118
1276
|
function TicketCenter({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
1119
|
-
const identity =
|
|
1277
|
+
const identity = _chunkD4MNFY67cjs.useChatIdentity.call(void 0, );
|
|
1120
1278
|
if (identity.isLoading) {
|
|
1121
1279
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketCenterSkeleton, {});
|
|
1122
1280
|
}
|
|
1123
|
-
if (identity.authTier === "anon" || !_optionalChain([identity, 'access',
|
|
1281
|
+
if (identity.authTier === "anon" || !_optionalChain([identity, 'access', _54 => _54.user, 'optionalAccess', _55 => _55.email])) {
|
|
1124
1282
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1125
|
-
|
|
1283
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1126
1284
|
{
|
|
1127
1285
|
type: "generic",
|
|
1128
1286
|
title: "Sign in to manage tickets",
|
|
@@ -1193,7 +1351,7 @@ function TicketCenterAuthed({
|
|
|
1193
1351
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3 text-xs text-ods-text-secondary", children: [
|
|
1194
1352
|
lastUpdatedAt && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
|
|
1195
1353
|
"Updated ",
|
|
1196
|
-
|
|
1354
|
+
_chunkD4MNFY67cjs.formatRelativeTime.call(void 0, new Date(lastUpdatedAt))
|
|
1197
1355
|
] }),
|
|
1198
1356
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1199
1357
|
_chunkUXZ3ZJ3Mcjs.Button,
|
|
@@ -1209,15 +1367,15 @@ function TicketCenterAuthed({
|
|
|
1209
1367
|
)
|
|
1210
1368
|
] })
|
|
1211
1369
|
] }),
|
|
1212
|
-
isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketListSkeleton, {}) : merged.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1213
|
-
|
|
1370
|
+
isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketListSkeleton, {}) : merged.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.Card, { className: "p-6", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1371
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1214
1372
|
{
|
|
1215
1373
|
type: "generic",
|
|
1216
1374
|
title: "No tickets yet",
|
|
1217
1375
|
description: "Open one above to start the conversation.",
|
|
1218
1376
|
showCTA: false
|
|
1219
1377
|
}
|
|
1220
|
-
) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1378
|
+
) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.Card, { className: "overflow-hidden", children: merged.map((ticket) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1221
1379
|
TicketRow,
|
|
1222
1380
|
{
|
|
1223
1381
|
ticket,
|
|
@@ -1237,7 +1395,7 @@ function TicketCenterAuthed({
|
|
|
1237
1395
|
}
|
|
1238
1396
|
function TicketCenterSkeleton() {
|
|
1239
1397
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-6", children: [
|
|
1240
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
1398
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkD4MNFY67cjs.Card, { className: "p-6", children: [
|
|
1241
1399
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-7 w-48 mb-4" }),
|
|
1242
1400
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-10 w-full mb-3" }),
|
|
1243
1401
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-24 w-full" })
|
|
@@ -1246,7 +1404,7 @@ function TicketCenterSkeleton() {
|
|
|
1246
1404
|
] });
|
|
1247
1405
|
}
|
|
1248
1406
|
function TicketListSkeleton() {
|
|
1249
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1407
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.Card, { className: "overflow-hidden", children: [0, 1, 2].map((i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "h-20 px-4 flex items-center gap-4 border-b border-ods-border last:border-b-0", children: [
|
|
1250
1408
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 flex flex-col gap-2", children: [
|
|
1251
1409
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-4 w-2/3" }),
|
|
1252
1410
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-3 w-full" })
|
|
@@ -1259,7 +1417,7 @@ function TicketListSkeleton() {
|
|
|
1259
1417
|
// src/components/tickets/help-center-list.tsx
|
|
1260
1418
|
|
|
1261
1419
|
|
|
1262
|
-
|
|
1420
|
+
_chunk2G3NXF6Jcjs.init_unified_pagination.call(void 0, );
|
|
1263
1421
|
|
|
1264
1422
|
// src/components/tickets/help-center-card.tsx
|
|
1265
1423
|
|
|
@@ -1274,12 +1432,14 @@ function HelpCenterCard({
|
|
|
1274
1432
|
onSendMessage,
|
|
1275
1433
|
onClose,
|
|
1276
1434
|
onReopen,
|
|
1277
|
-
onActionCollapsed
|
|
1435
|
+
onActionCollapsed,
|
|
1436
|
+
replyError,
|
|
1437
|
+
onClearReplyError
|
|
1278
1438
|
}) {
|
|
1279
1439
|
const optimistic = isOptimistic(ticket);
|
|
1280
1440
|
const rawStatus = (_nullishCoalesce(ticket.status, () => ( "OPEN"))).toUpperCase();
|
|
1281
1441
|
const priority = (_nullishCoalesce(ticket.priority, () => ( ""))).toUpperCase();
|
|
1282
|
-
const relativeUpdated = ticket.hubspot_updated_at ?
|
|
1442
|
+
const relativeUpdated = ticket.hubspot_updated_at ? _chunkD4MNFY67cjs.formatRelativeTime.call(void 0, ticket.hubspot_updated_at) : "recently";
|
|
1283
1443
|
const title = (ticket.subject || "").trim() || "(untitled)";
|
|
1284
1444
|
const subtitle = `UPDATED ${relativeUpdated}, #${ticket.external_id || "\u2014"}${ticket.pipeline_stage_label ? `, ${ticket.pipeline_stage_label}` : ""}`;
|
|
1285
1445
|
const description = _nullishCoalesce(_nullishCoalesce(ticket.preview, () => ( ticket.body)), () => ( ""));
|
|
@@ -1288,7 +1448,7 @@ function HelpCenterCard({
|
|
|
1288
1448
|
const rowRef = _react.useRef.call(void 0, null);
|
|
1289
1449
|
const handleClick = _react.useCallback.call(void 0, () => {
|
|
1290
1450
|
onToggle(ticket.id);
|
|
1291
|
-
|
|
1451
|
+
_chunkD4MNFY67cjs.scrollElementIntoView.call(void 0, rowRef.current, {
|
|
1292
1452
|
headerOffset: STICKY_HEADER_OFFSET_PX,
|
|
1293
1453
|
adjustTargetY: (raw) => {
|
|
1294
1454
|
if (!rowRef.current) return raw;
|
|
@@ -1305,16 +1465,16 @@ function HelpCenterCard({
|
|
|
1305
1465
|
}, [onToggle, ticket.id]);
|
|
1306
1466
|
const rightBadges = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1307
1467
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1308
|
-
|
|
1468
|
+
_chunkD4MNFY67cjs.StatusBadge,
|
|
1309
1469
|
{
|
|
1310
1470
|
text: rawStatus,
|
|
1311
|
-
colorScheme:
|
|
1471
|
+
colorScheme: _chunkD4MNFY67cjs.getStatusColorScheme.call(void 0, rawStatus),
|
|
1312
1472
|
variant: "card",
|
|
1313
1473
|
className: "border border-ods-border"
|
|
1314
1474
|
}
|
|
1315
1475
|
),
|
|
1316
1476
|
priority && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1317
|
-
|
|
1477
|
+
_chunkD4MNFY67cjs.StatusBadge,
|
|
1318
1478
|
{
|
|
1319
1479
|
text: priority,
|
|
1320
1480
|
colorScheme: mapPriorityScheme(priority),
|
|
@@ -1341,7 +1501,7 @@ function HelpCenterCard({
|
|
|
1341
1501
|
"aria-controls": isExpanded ? `help-center-drawer-${ticket.id}` : void 0,
|
|
1342
1502
|
className: "w-full text-left p-[12px] md:p-[16px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-accent focus-visible:ring-inset disabled:cursor-default",
|
|
1343
1503
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1344
|
-
|
|
1504
|
+
_chunk2G3NXF6Jcjs.DevCardRowContent,
|
|
1345
1505
|
{
|
|
1346
1506
|
title,
|
|
1347
1507
|
subtitle,
|
|
@@ -1361,7 +1521,9 @@ function HelpCenterCard({
|
|
|
1361
1521
|
onSendMessage,
|
|
1362
1522
|
onClose,
|
|
1363
1523
|
onReopen,
|
|
1364
|
-
onActionCollapsed
|
|
1524
|
+
onActionCollapsed,
|
|
1525
|
+
replyError,
|
|
1526
|
+
onClearReplyError
|
|
1365
1527
|
}
|
|
1366
1528
|
) })
|
|
1367
1529
|
]
|
|
@@ -1414,7 +1576,7 @@ function HelpCenterCreateForm({
|
|
|
1414
1576
|
const [subject, setSubject] = _react.useState.call(void 0, "");
|
|
1415
1577
|
const [subjectError, setSubjectError] = _react.useState.call(void 0, null);
|
|
1416
1578
|
const subjectField = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col", children: [
|
|
1417
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
1579
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkD4MNFY67cjs.Label, { htmlFor: "help-center-subject", children: [
|
|
1418
1580
|
"Subject",
|
|
1419
1581
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-accent", children: "*" })
|
|
1420
1582
|
] }),
|
|
@@ -1446,7 +1608,7 @@ function HelpCenterCreateForm({
|
|
|
1446
1608
|
)
|
|
1447
1609
|
] });
|
|
1448
1610
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1449
|
-
|
|
1611
|
+
_chunkNGFP4RVLcjs.ContactForm,
|
|
1450
1612
|
{
|
|
1451
1613
|
title: "Open a new ticket",
|
|
1452
1614
|
footerText: "The support team typically responds within one business day.",
|
|
@@ -1484,7 +1646,7 @@ function HelpCenterCreateForm({
|
|
|
1484
1646
|
// src/components/tickets/help-center-list.tsx
|
|
1485
1647
|
|
|
1486
1648
|
function HelpCenterList({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
1487
|
-
const identity =
|
|
1649
|
+
const identity = _chunkD4MNFY67cjs.useChatIdentity.call(void 0, );
|
|
1488
1650
|
const searchParams = _chunkG7UE6RKVcjs.useSearchParams.call(void 0, );
|
|
1489
1651
|
const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
|
|
1490
1652
|
const pathname = _chunkG7UE6RKVcjs.usePathname.call(void 0, );
|
|
@@ -1493,11 +1655,11 @@ function HelpCenterList({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
|
1493
1655
|
const rawPage = Number(searchParams.get("page"));
|
|
1494
1656
|
const page = Number.isFinite(rawPage) && rawPage > 0 ? Math.floor(rawPage) : 1;
|
|
1495
1657
|
if (identity.isLoading) {
|
|
1496
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1658
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevSectionPage, { sectionKey: "tickets", preControls: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpCenterCreateFormSkeleton, {}), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevCardRowSkeletonList, {}) });
|
|
1497
1659
|
}
|
|
1498
|
-
if (identity.authTier === "anon" || !_optionalChain([identity, 'access',
|
|
1499
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1500
|
-
|
|
1660
|
+
if (identity.authTier === "anon" || !_optionalChain([identity, 'access', _56 => _56.user, 'optionalAccess', _57 => _57.email])) {
|
|
1661
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevSectionPage, { sectionKey: "tickets", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1662
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1501
1663
|
{
|
|
1502
1664
|
type: "generic",
|
|
1503
1665
|
title: "Sign in to manage tickets",
|
|
@@ -1506,7 +1668,7 @@ function HelpCenterList({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
|
1506
1668
|
}
|
|
1507
1669
|
) });
|
|
1508
1670
|
}
|
|
1509
|
-
const sessionName = [_optionalChain([identity, 'access',
|
|
1671
|
+
const sessionName = [_optionalChain([identity, 'access', _58 => _58.user, 'optionalAccess', _59 => _59.firstName]), _optionalChain([identity, 'access', _60 => _60.user, 'optionalAccess', _61 => _61.lastName])].filter(Boolean).join(" ").trim() || _optionalChain([identity, 'access', _62 => _62.user, 'optionalAccess', _63 => _63.email, 'optionalAccess', _64 => _64.split, 'call', _65 => _65("@"), 'access', _66 => _66[0]]) || "Customer";
|
|
1510
1672
|
const sessionEmail = identity.user.email;
|
|
1511
1673
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1512
1674
|
HelpCenterListAuthed,
|
|
@@ -1597,15 +1759,15 @@ function HelpCenterListAuthed({
|
|
|
1597
1759
|
] }),
|
|
1598
1760
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Button, { type: "button", variant: "accent", onClick: () => refetch(), children: "Retry" })
|
|
1599
1761
|
] }),
|
|
1600
|
-
!error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1762
|
+
!error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevCardRowSkeletonList, {}) : !hasResults && isFetching ? (
|
|
1601
1763
|
// Bridge state — background refetch in flight and the
|
|
1602
1764
|
// optimistic placeholder was just removed by the mutation
|
|
1603
1765
|
// callback. Without this branch "No tickets yet" would flash
|
|
1604
1766
|
// for ~50ms between `removeOptimistic` and the server
|
|
1605
1767
|
// response landing.
|
|
1606
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1768
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevCardRowSkeletonList, { rows: 1 })
|
|
1607
1769
|
) : !hasResults ? hasActiveFilters ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1608
|
-
|
|
1770
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1609
1771
|
{
|
|
1610
1772
|
type: "search",
|
|
1611
1773
|
title: "No tickets found",
|
|
@@ -1620,7 +1782,7 @@ function HelpCenterListAuthed({
|
|
|
1620
1782
|
}
|
|
1621
1783
|
}
|
|
1622
1784
|
) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1623
|
-
|
|
1785
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1624
1786
|
{
|
|
1625
1787
|
type: "generic",
|
|
1626
1788
|
title: "No tickets yet",
|
|
@@ -1647,14 +1809,16 @@ function HelpCenterListAuthed({
|
|
|
1647
1809
|
onSendMessage: actions.sendMessage,
|
|
1648
1810
|
onClose: actions.closeTicket,
|
|
1649
1811
|
onReopen: actions.reopenTicket,
|
|
1650
|
-
onActionCollapsed: () => setExpandedTicketId(null)
|
|
1812
|
+
onActionCollapsed: () => setExpandedTicketId(null),
|
|
1813
|
+
replyError: actions.replyErrorFor(ticket.external_id),
|
|
1814
|
+
onClearReplyError: () => actions.clearReplyError(ticket.external_id)
|
|
1651
1815
|
},
|
|
1652
1816
|
ticket.id
|
|
1653
1817
|
)) })
|
|
1654
1818
|
) }),
|
|
1655
|
-
!error && totalPages > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1819
|
+
!error && totalPages > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.UnifiedPagination, { currentPage: page, totalPages })
|
|
1656
1820
|
] });
|
|
1657
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1821
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevSectionPage, { sectionKey: "tickets", preControls: form, children: body });
|
|
1658
1822
|
}
|
|
1659
1823
|
|
|
1660
1824
|
|