@flamingo-stack/openframe-frontend-core 0.0.214 → 0.0.215-snapshot.20260529010429
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 +254 -103
- package/dist/components/tickets/index.cjs.map +1 -1
- package/dist/components/tickets/index.js +184 -33
- 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 +139 -5
- 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);
|
|
@@ -974,12 +1069,13 @@ function useTicketActions(options) {
|
|
|
974
1069
|
[setRowBusy, enqueue, executeTicketAction, queryClient, toast2, surfaceError, removeTicketFromCache]
|
|
975
1070
|
);
|
|
976
1071
|
const sendMessage = _react.useCallback.call(void 0,
|
|
977
|
-
(ticket, text, attachments) => {
|
|
1072
|
+
async (ticket, text, attachments) => {
|
|
978
1073
|
const trimmed = text.trim();
|
|
979
1074
|
const hasText = trimmed.length > 0;
|
|
980
1075
|
const hasFiles = attachments.length > 0;
|
|
981
|
-
if (!hasText && !hasFiles) return
|
|
982
|
-
|
|
1076
|
+
if (!hasText && !hasFiles) return false;
|
|
1077
|
+
lastUpdateErrorRef.current = null;
|
|
1078
|
+
const ok = await updateTicket(
|
|
983
1079
|
ticket,
|
|
984
1080
|
{
|
|
985
1081
|
...hasText ? { content_addendum: trimmed } : {},
|
|
@@ -988,15 +1084,25 @@ function useTicketActions(options) {
|
|
|
988
1084
|
TOAST_COPY.comment_success,
|
|
989
1085
|
"send message"
|
|
990
1086
|
);
|
|
1087
|
+
if (ok) {
|
|
1088
|
+
clearReplyError(ticket.external_id);
|
|
1089
|
+
} else {
|
|
1090
|
+
const mapped = lastUpdateErrorRef.current;
|
|
1091
|
+
if (mapped && REPLY_BANNER_CODES.has(mapped.code)) {
|
|
1092
|
+
setReplyError(ticket.external_id, mapped);
|
|
1093
|
+
}
|
|
1094
|
+
lastUpdateErrorRef.current = null;
|
|
1095
|
+
}
|
|
1096
|
+
return ok;
|
|
991
1097
|
},
|
|
992
|
-
[updateTicket]
|
|
1098
|
+
[updateTicket, clearReplyError, setReplyError]
|
|
993
1099
|
);
|
|
994
1100
|
const closeTicket = _react.useCallback.call(void 0,
|
|
995
1101
|
(ticket, resolution) => updateTicket(
|
|
996
1102
|
ticket,
|
|
997
1103
|
{
|
|
998
1104
|
status: "CLOSED",
|
|
999
|
-
..._optionalChain([resolution, 'optionalAccess',
|
|
1105
|
+
..._optionalChain([resolution, 'optionalAccess', _48 => _48.trim, 'call', _49 => _49()]) ? { resolution: resolution.trim() } : {}
|
|
1000
1106
|
},
|
|
1001
1107
|
TOAST_COPY.close_success,
|
|
1002
1108
|
"close ticket"
|
|
@@ -1014,9 +1120,20 @@ function useTicketActions(options) {
|
|
|
1014
1120
|
closeTicket,
|
|
1015
1121
|
reopenTicket,
|
|
1016
1122
|
isSubmittingForm,
|
|
1017
|
-
isRowBusy
|
|
1123
|
+
isRowBusy,
|
|
1124
|
+
replyErrorFor,
|
|
1125
|
+
clearReplyError
|
|
1018
1126
|
}),
|
|
1019
|
-
[
|
|
1127
|
+
[
|
|
1128
|
+
submitTicket,
|
|
1129
|
+
sendMessage,
|
|
1130
|
+
closeTicket,
|
|
1131
|
+
reopenTicket,
|
|
1132
|
+
isSubmittingForm,
|
|
1133
|
+
isRowBusy,
|
|
1134
|
+
replyErrorFor,
|
|
1135
|
+
clearReplyError
|
|
1136
|
+
]
|
|
1020
1137
|
);
|
|
1021
1138
|
}
|
|
1022
1139
|
var TicketActionFailure = class extends Error {
|
|
@@ -1058,7 +1175,7 @@ function mapTicketActionError(err) {
|
|
|
1058
1175
|
removeRowFromCache: false
|
|
1059
1176
|
};
|
|
1060
1177
|
case "RATE_LIMITED": {
|
|
1061
|
-
const retryAfterRaw = _optionalChain([err, 'access',
|
|
1178
|
+
const retryAfterRaw = _optionalChain([err, 'access', _50 => _50.response, 'optionalAccess', _51 => _51.headers, 'access', _52 => _52.get, 'call', _53 => _53("Retry-After")]);
|
|
1062
1179
|
const retryAfterSeconds = retryAfterRaw ? parseInt(retryAfterRaw, 10) : void 0;
|
|
1063
1180
|
return {
|
|
1064
1181
|
code: err.code,
|
|
@@ -1075,6 +1192,34 @@ function mapTicketActionError(err) {
|
|
|
1075
1192
|
supportSystemDown: false,
|
|
1076
1193
|
removeRowFromCache: false
|
|
1077
1194
|
};
|
|
1195
|
+
case "HUBSPOT_5XX":
|
|
1196
|
+
return {
|
|
1197
|
+
code: err.code,
|
|
1198
|
+
message: "We couldn't reach the support system. Your reply wasn't sent \u2014 please retry in a moment.",
|
|
1199
|
+
supportSystemDown: false,
|
|
1200
|
+
removeRowFromCache: false
|
|
1201
|
+
};
|
|
1202
|
+
case "HUBSPOT_400_VALIDATION":
|
|
1203
|
+
return {
|
|
1204
|
+
code: err.code,
|
|
1205
|
+
message: "Your reply was rejected. Please rephrase or remove unsupported content and try again.",
|
|
1206
|
+
supportSystemDown: false,
|
|
1207
|
+
removeRowFromCache: false
|
|
1208
|
+
};
|
|
1209
|
+
case "HUBSPOT_404_THREAD":
|
|
1210
|
+
return {
|
|
1211
|
+
code: err.code,
|
|
1212
|
+
message: "This conversation is no longer accepting replies. Open a new ticket to continue.",
|
|
1213
|
+
supportSystemDown: false,
|
|
1214
|
+
removeRowFromCache: false
|
|
1215
|
+
};
|
|
1216
|
+
case "HUBSPOT_REPLY_UNKNOWN":
|
|
1217
|
+
return {
|
|
1218
|
+
code: err.code,
|
|
1219
|
+
message: "Your reply didn't go through. Please retry.",
|
|
1220
|
+
supportSystemDown: false,
|
|
1221
|
+
removeRowFromCache: false
|
|
1222
|
+
};
|
|
1078
1223
|
default:
|
|
1079
1224
|
return {
|
|
1080
1225
|
code: "UNKNOWN",
|
|
@@ -1116,13 +1261,13 @@ function resolveErrorCode(bodyCode, status) {
|
|
|
1116
1261
|
// src/components/tickets/ticket-center.tsx
|
|
1117
1262
|
|
|
1118
1263
|
function TicketCenter({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
1119
|
-
const identity =
|
|
1264
|
+
const identity = _chunkD4MNFY67cjs.useChatIdentity.call(void 0, );
|
|
1120
1265
|
if (identity.isLoading) {
|
|
1121
1266
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketCenterSkeleton, {});
|
|
1122
1267
|
}
|
|
1123
|
-
if (identity.authTier === "anon" || !_optionalChain([identity, 'access',
|
|
1268
|
+
if (identity.authTier === "anon" || !_optionalChain([identity, 'access', _54 => _54.user, 'optionalAccess', _55 => _55.email])) {
|
|
1124
1269
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1125
|
-
|
|
1270
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1126
1271
|
{
|
|
1127
1272
|
type: "generic",
|
|
1128
1273
|
title: "Sign in to manage tickets",
|
|
@@ -1193,7 +1338,7 @@ function TicketCenterAuthed({
|
|
|
1193
1338
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3 text-xs text-ods-text-secondary", children: [
|
|
1194
1339
|
lastUpdatedAt && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
|
|
1195
1340
|
"Updated ",
|
|
1196
|
-
|
|
1341
|
+
_chunkD4MNFY67cjs.formatRelativeTime.call(void 0, new Date(lastUpdatedAt))
|
|
1197
1342
|
] }),
|
|
1198
1343
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1199
1344
|
_chunkUXZ3ZJ3Mcjs.Button,
|
|
@@ -1209,15 +1354,15 @@ function TicketCenterAuthed({
|
|
|
1209
1354
|
)
|
|
1210
1355
|
] })
|
|
1211
1356
|
] }),
|
|
1212
|
-
isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TicketListSkeleton, {}) : merged.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1213
|
-
|
|
1357
|
+
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,
|
|
1358
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1214
1359
|
{
|
|
1215
1360
|
type: "generic",
|
|
1216
1361
|
title: "No tickets yet",
|
|
1217
1362
|
description: "Open one above to start the conversation.",
|
|
1218
1363
|
showCTA: false
|
|
1219
1364
|
}
|
|
1220
|
-
) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1365
|
+
) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkD4MNFY67cjs.Card, { className: "overflow-hidden", children: merged.map((ticket) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1221
1366
|
TicketRow,
|
|
1222
1367
|
{
|
|
1223
1368
|
ticket,
|
|
@@ -1237,7 +1382,7 @@ function TicketCenterAuthed({
|
|
|
1237
1382
|
}
|
|
1238
1383
|
function TicketCenterSkeleton() {
|
|
1239
1384
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-6", children: [
|
|
1240
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
1385
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkD4MNFY67cjs.Card, { className: "p-6", children: [
|
|
1241
1386
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-7 w-48 mb-4" }),
|
|
1242
1387
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-10 w-full mb-3" }),
|
|
1243
1388
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-24 w-full" })
|
|
@@ -1246,7 +1391,7 @@ function TicketCenterSkeleton() {
|
|
|
1246
1391
|
] });
|
|
1247
1392
|
}
|
|
1248
1393
|
function TicketListSkeleton() {
|
|
1249
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1394
|
+
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
1395
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 flex flex-col gap-2", children: [
|
|
1251
1396
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-4 w-2/3" }),
|
|
1252
1397
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Skeleton, { className: "h-3 w-full" })
|
|
@@ -1259,7 +1404,7 @@ function TicketListSkeleton() {
|
|
|
1259
1404
|
// src/components/tickets/help-center-list.tsx
|
|
1260
1405
|
|
|
1261
1406
|
|
|
1262
|
-
|
|
1407
|
+
_chunk2G3NXF6Jcjs.init_unified_pagination.call(void 0, );
|
|
1263
1408
|
|
|
1264
1409
|
// src/components/tickets/help-center-card.tsx
|
|
1265
1410
|
|
|
@@ -1274,12 +1419,14 @@ function HelpCenterCard({
|
|
|
1274
1419
|
onSendMessage,
|
|
1275
1420
|
onClose,
|
|
1276
1421
|
onReopen,
|
|
1277
|
-
onActionCollapsed
|
|
1422
|
+
onActionCollapsed,
|
|
1423
|
+
replyError,
|
|
1424
|
+
onClearReplyError
|
|
1278
1425
|
}) {
|
|
1279
1426
|
const optimistic = isOptimistic(ticket);
|
|
1280
1427
|
const rawStatus = (_nullishCoalesce(ticket.status, () => ( "OPEN"))).toUpperCase();
|
|
1281
1428
|
const priority = (_nullishCoalesce(ticket.priority, () => ( ""))).toUpperCase();
|
|
1282
|
-
const relativeUpdated = ticket.hubspot_updated_at ?
|
|
1429
|
+
const relativeUpdated = ticket.hubspot_updated_at ? _chunkD4MNFY67cjs.formatRelativeTime.call(void 0, ticket.hubspot_updated_at) : "recently";
|
|
1283
1430
|
const title = (ticket.subject || "").trim() || "(untitled)";
|
|
1284
1431
|
const subtitle = `UPDATED ${relativeUpdated}, #${ticket.external_id || "\u2014"}${ticket.pipeline_stage_label ? `, ${ticket.pipeline_stage_label}` : ""}`;
|
|
1285
1432
|
const description = _nullishCoalesce(_nullishCoalesce(ticket.preview, () => ( ticket.body)), () => ( ""));
|
|
@@ -1288,7 +1435,7 @@ function HelpCenterCard({
|
|
|
1288
1435
|
const rowRef = _react.useRef.call(void 0, null);
|
|
1289
1436
|
const handleClick = _react.useCallback.call(void 0, () => {
|
|
1290
1437
|
onToggle(ticket.id);
|
|
1291
|
-
|
|
1438
|
+
_chunkD4MNFY67cjs.scrollElementIntoView.call(void 0, rowRef.current, {
|
|
1292
1439
|
headerOffset: STICKY_HEADER_OFFSET_PX,
|
|
1293
1440
|
adjustTargetY: (raw) => {
|
|
1294
1441
|
if (!rowRef.current) return raw;
|
|
@@ -1305,16 +1452,16 @@ function HelpCenterCard({
|
|
|
1305
1452
|
}, [onToggle, ticket.id]);
|
|
1306
1453
|
const rightBadges = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1307
1454
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1308
|
-
|
|
1455
|
+
_chunkD4MNFY67cjs.StatusBadge,
|
|
1309
1456
|
{
|
|
1310
1457
|
text: rawStatus,
|
|
1311
|
-
colorScheme:
|
|
1458
|
+
colorScheme: _chunkD4MNFY67cjs.getStatusColorScheme.call(void 0, rawStatus),
|
|
1312
1459
|
variant: "card",
|
|
1313
1460
|
className: "border border-ods-border"
|
|
1314
1461
|
}
|
|
1315
1462
|
),
|
|
1316
1463
|
priority && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1317
|
-
|
|
1464
|
+
_chunkD4MNFY67cjs.StatusBadge,
|
|
1318
1465
|
{
|
|
1319
1466
|
text: priority,
|
|
1320
1467
|
colorScheme: mapPriorityScheme(priority),
|
|
@@ -1341,7 +1488,7 @@ function HelpCenterCard({
|
|
|
1341
1488
|
"aria-controls": isExpanded ? `help-center-drawer-${ticket.id}` : void 0,
|
|
1342
1489
|
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
1490
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1344
|
-
|
|
1491
|
+
_chunk2G3NXF6Jcjs.DevCardRowContent,
|
|
1345
1492
|
{
|
|
1346
1493
|
title,
|
|
1347
1494
|
subtitle,
|
|
@@ -1361,7 +1508,9 @@ function HelpCenterCard({
|
|
|
1361
1508
|
onSendMessage,
|
|
1362
1509
|
onClose,
|
|
1363
1510
|
onReopen,
|
|
1364
|
-
onActionCollapsed
|
|
1511
|
+
onActionCollapsed,
|
|
1512
|
+
replyError,
|
|
1513
|
+
onClearReplyError
|
|
1365
1514
|
}
|
|
1366
1515
|
) })
|
|
1367
1516
|
]
|
|
@@ -1414,7 +1563,7 @@ function HelpCenterCreateForm({
|
|
|
1414
1563
|
const [subject, setSubject] = _react.useState.call(void 0, "");
|
|
1415
1564
|
const [subjectError, setSubjectError] = _react.useState.call(void 0, null);
|
|
1416
1565
|
const subjectField = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col", children: [
|
|
1417
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
1566
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkD4MNFY67cjs.Label, { htmlFor: "help-center-subject", children: [
|
|
1418
1567
|
"Subject",
|
|
1419
1568
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-accent", children: "*" })
|
|
1420
1569
|
] }),
|
|
@@ -1446,7 +1595,7 @@ function HelpCenterCreateForm({
|
|
|
1446
1595
|
)
|
|
1447
1596
|
] });
|
|
1448
1597
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1449
|
-
|
|
1598
|
+
_chunkNGFP4RVLcjs.ContactForm,
|
|
1450
1599
|
{
|
|
1451
1600
|
title: "Open a new ticket",
|
|
1452
1601
|
footerText: "The support team typically responds within one business day.",
|
|
@@ -1484,7 +1633,7 @@ function HelpCenterCreateForm({
|
|
|
1484
1633
|
// src/components/tickets/help-center-list.tsx
|
|
1485
1634
|
|
|
1486
1635
|
function HelpCenterList({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
1487
|
-
const identity =
|
|
1636
|
+
const identity = _chunkD4MNFY67cjs.useChatIdentity.call(void 0, );
|
|
1488
1637
|
const searchParams = _chunkG7UE6RKVcjs.useSearchParams.call(void 0, );
|
|
1489
1638
|
const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
|
|
1490
1639
|
const pathname = _chunkG7UE6RKVcjs.usePathname.call(void 0, );
|
|
@@ -1493,11 +1642,11 @@ function HelpCenterList({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
|
1493
1642
|
const rawPage = Number(searchParams.get("page"));
|
|
1494
1643
|
const page = Number.isFinite(rawPage) && rawPage > 0 ? Math.floor(rawPage) : 1;
|
|
1495
1644
|
if (identity.isLoading) {
|
|
1496
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1645
|
+
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
1646
|
}
|
|
1498
|
-
if (identity.authTier === "anon" || !_optionalChain([identity, 'access',
|
|
1499
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1500
|
-
|
|
1647
|
+
if (identity.authTier === "anon" || !_optionalChain([identity, 'access', _56 => _56.user, 'optionalAccess', _57 => _57.email])) {
|
|
1648
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevSectionPage, { sectionKey: "tickets", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1649
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1501
1650
|
{
|
|
1502
1651
|
type: "generic",
|
|
1503
1652
|
title: "Sign in to manage tickets",
|
|
@@ -1506,7 +1655,7 @@ function HelpCenterList({ toast: toast2 = _chunkWT5JV2GScjs.toast } = {}) {
|
|
|
1506
1655
|
}
|
|
1507
1656
|
) });
|
|
1508
1657
|
}
|
|
1509
|
-
const sessionName = [_optionalChain([identity, 'access',
|
|
1658
|
+
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
1659
|
const sessionEmail = identity.user.email;
|
|
1511
1660
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1512
1661
|
HelpCenterListAuthed,
|
|
@@ -1597,15 +1746,15 @@ function HelpCenterListAuthed({
|
|
|
1597
1746
|
] }),
|
|
1598
1747
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUXZ3ZJ3Mcjs.Button, { type: "button", variant: "accent", onClick: () => refetch(), children: "Retry" })
|
|
1599
1748
|
] }),
|
|
1600
|
-
!error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1749
|
+
!error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevCardRowSkeletonList, {}) : !hasResults && isFetching ? (
|
|
1601
1750
|
// Bridge state — background refetch in flight and the
|
|
1602
1751
|
// optimistic placeholder was just removed by the mutation
|
|
1603
1752
|
// callback. Without this branch "No tickets yet" would flash
|
|
1604
1753
|
// for ~50ms between `removeOptimistic` and the server
|
|
1605
1754
|
// response landing.
|
|
1606
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1755
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevCardRowSkeletonList, { rows: 1 })
|
|
1607
1756
|
) : !hasResults ? hasActiveFilters ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1608
|
-
|
|
1757
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1609
1758
|
{
|
|
1610
1759
|
type: "search",
|
|
1611
1760
|
title: "No tickets found",
|
|
@@ -1620,7 +1769,7 @@ function HelpCenterListAuthed({
|
|
|
1620
1769
|
}
|
|
1621
1770
|
}
|
|
1622
1771
|
) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1623
|
-
|
|
1772
|
+
_chunk2G3NXF6Jcjs.EmptyState,
|
|
1624
1773
|
{
|
|
1625
1774
|
type: "generic",
|
|
1626
1775
|
title: "No tickets yet",
|
|
@@ -1647,14 +1796,16 @@ function HelpCenterListAuthed({
|
|
|
1647
1796
|
onSendMessage: actions.sendMessage,
|
|
1648
1797
|
onClose: actions.closeTicket,
|
|
1649
1798
|
onReopen: actions.reopenTicket,
|
|
1650
|
-
onActionCollapsed: () => setExpandedTicketId(null)
|
|
1799
|
+
onActionCollapsed: () => setExpandedTicketId(null),
|
|
1800
|
+
replyError: actions.replyErrorFor(ticket.external_id),
|
|
1801
|
+
onClearReplyError: () => actions.clearReplyError(ticket.external_id)
|
|
1651
1802
|
},
|
|
1652
1803
|
ticket.id
|
|
1653
1804
|
)) })
|
|
1654
1805
|
) }),
|
|
1655
|
-
!error && totalPages > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1806
|
+
!error && totalPages > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.UnifiedPagination, { currentPage: page, totalPages })
|
|
1656
1807
|
] });
|
|
1657
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1808
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2G3NXF6Jcjs.DevSectionPage, { sectionKey: "tickets", preControls: form, children: body });
|
|
1658
1809
|
}
|
|
1659
1810
|
|
|
1660
1811
|
|