@voyant-travel/bookings-react 0.138.1 → 0.138.3
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/admin/booking-contract-dialog.d.ts.map +1 -1
- package/dist/admin/booking-contract-dialog.js +11 -1
- package/dist/admin/use-booking-action-ledger-events.d.ts.map +1 -1
- package/dist/admin/use-booking-action-ledger-events.js +18 -3
- package/dist/components/booking-activity-timeline.d.ts.map +1 -1
- package/dist/components/booking-activity-timeline.js +4 -1
- package/dist/components/booking-document-dialog.d.ts.map +1 -1
- package/dist/components/booking-document-dialog.js +10 -2
- package/dist/components/booking-payment-reconciliation-banner.d.ts.map +1 -1
- package/dist/components/booking-payments-summary.d.ts +9 -1
- package/dist/components/booking-payments-summary.d.ts.map +1 -1
- package/dist/components/booking-payments-summary.js +57 -32
- package/dist/components/file-dropzone.d.ts +3 -1
- package/dist/components/file-dropzone.d.ts.map +1 -1
- package/dist/components/file-dropzone.js +2 -1
- package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts +3 -3
- package/dist/extras/hooks/use-slot-extra-manifest.d.ts +1 -1
- package/dist/extras/query-options.d.ts +4 -4
- package/dist/extras/schemas.d.ts +3 -3
- package/dist/hooks/use-booking-action-ledger.d.ts +1 -1
- package/dist/hooks/use-booking-documents.d.ts.map +1 -1
- package/dist/hooks/use-booking-documents.js +3 -0
- package/dist/hooks/use-booking-item-mutation.d.ts.map +1 -1
- package/dist/hooks/use-booking-item-mutation.js +13 -6
- package/dist/hooks/use-booking-note-mutation.d.ts.map +1 -1
- package/dist/hooks/use-booking-note-mutation.js +3 -0
- package/dist/hooks/use-supplier-status-mutation.d.ts +2 -2
- package/dist/hooks/use-supplier-status-mutation.d.ts.map +1 -1
- package/dist/hooks/use-supplier-status-mutation.js +10 -12
- package/dist/hooks/use-supplier-statuses.d.ts +1 -1
- package/dist/hooks/use-traveler-mutation.d.ts.map +1 -1
- package/dist/hooks/use-traveler-mutation.js +10 -12
- package/dist/hooks/use-traveler-with-travel-details-mutation.d.ts.map +1 -1
- package/dist/hooks/use-traveler-with-travel-details-mutation.js +3 -0
- package/dist/i18n/en-sections.d.ts +1 -0
- package/dist/i18n/en-sections.d.ts.map +1 -1
- package/dist/i18n/en-sections.js +1 -0
- package/dist/i18n/en.d.ts +1 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/messages-sections.d.ts +1 -0
- package/dist/i18n/messages-sections.d.ts.map +1 -1
- package/dist/i18n/provider.d.ts +2 -0
- package/dist/i18n/provider.d.ts.map +1 -1
- package/dist/i18n/ro-sections.d.ts +1 -0
- package/dist/i18n/ro-sections.d.ts.map +1 -1
- package/dist/i18n/ro-sections.js +1 -0
- package/dist/i18n/ro.d.ts +1 -0
- package/dist/i18n/ro.d.ts.map +1 -1
- package/dist/query-options.d.ts +4 -4
- package/dist/requirements/hooks/use-booking-questions.d.ts +1 -1
- package/dist/requirements/query-options.d.ts +4 -4
- package/dist/requirements/schemas.d.ts +3 -3
- package/dist/schemas.d.ts +6 -6
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booking-contract-dialog.d.ts","sourceRoot":"","sources":["../../src/admin/booking-contract-dialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"booking-contract-dialog.d.ts","sourceRoot":"","sources":["../../src/admin/booking-contract-dialog.tsx"],"names":[],"mappings":"AA2BA,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,aAAa,EACb,SAAS,GACV,EAAE,0BAA0B,+BA8O5B"}
|
|
@@ -6,6 +6,7 @@ import { legalQueryKeys, useLegalContractAttachmentMutation, useLegalContractMut
|
|
|
6
6
|
import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, Input, Label, Skeleton, } from "@voyant-travel/ui/components";
|
|
7
7
|
import { FileText, Loader2, Paperclip, X } from "lucide-react";
|
|
8
8
|
import { useEffect, useState } from "react";
|
|
9
|
+
import { VoyantApiError } from "../client.js";
|
|
9
10
|
import { useBookingContractGenerationMutation } from "../index.js";
|
|
10
11
|
/**
|
|
11
12
|
* "Add contract" dialog for a booking. Two modes:
|
|
@@ -29,6 +30,7 @@ export function BookingContractDialog({ open, onOpenChange, bookingId, bookingNu
|
|
|
29
30
|
const [mode, setMode] = useState("generate");
|
|
30
31
|
const [uploading, setUploading] = useState(false);
|
|
31
32
|
const [error, setError] = useState(null);
|
|
33
|
+
const [previewRequested, setPreviewRequested] = useState(false);
|
|
32
34
|
// Upload form state
|
|
33
35
|
const [title, setTitle] = useState("");
|
|
34
36
|
const [file, setFile] = useState(null);
|
|
@@ -43,6 +45,7 @@ export function BookingContractDialog({ open, onOpenChange, bookingId, bookingNu
|
|
|
43
45
|
setFile(null);
|
|
44
46
|
setError(null);
|
|
45
47
|
setUploading(false);
|
|
48
|
+
setPreviewRequested(false);
|
|
46
49
|
resetPreview();
|
|
47
50
|
}, [open, resetPreview]);
|
|
48
51
|
// Fetch preview HTML every time the dialog opens (or the mode flips
|
|
@@ -52,6 +55,7 @@ export function BookingContractDialog({ open, onOpenChange, bookingId, bookingNu
|
|
|
52
55
|
useEffect(() => {
|
|
53
56
|
if (!open || mode !== "generate")
|
|
54
57
|
return;
|
|
58
|
+
setPreviewRequested(true);
|
|
55
59
|
fetchPreview();
|
|
56
60
|
}, [open, mode, fetchPreview]);
|
|
57
61
|
const handleGenerate = async () => {
|
|
@@ -102,10 +106,16 @@ export function BookingContractDialog({ open, onOpenChange, bookingId, bookingNu
|
|
|
102
106
|
const submitting = generate.isPending || uploading;
|
|
103
107
|
const previewReady = preview.data != null;
|
|
104
108
|
const canSubmit = mode === "generate" ? previewReady && !submitting : file != null && !submitting;
|
|
109
|
+
const previewSetupMissing = preview.error instanceof VoyantApiError && preview.error.status === 404;
|
|
110
|
+
const showPreviewSetupHint = mode === "generate" &&
|
|
111
|
+
previewRequested &&
|
|
112
|
+
!preview.isPending &&
|
|
113
|
+
!preview.data &&
|
|
114
|
+
(!preview.isError || previewSetupMissing);
|
|
105
115
|
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "w-full! max-w-4xl! gap-0 p-0", children: [_jsxs(DialogHeader, { className: "shrink-0 border-b px-6 py-4", children: [_jsx(DialogTitle, { children: t.title }), _jsx(DialogDescription, { children: t.description })] }), _jsx("div", { className: "max-h-[70vh] overflow-y-auto", children: _jsxs("div", { className: "flex flex-col gap-4 px-6 py-5", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: t.modeLabel }), _jsx(SegmentedChoice, { value: mode, onChange: setMode, options: [
|
|
106
116
|
{ value: "generate", label: t.modeGenerate },
|
|
107
117
|
{ value: "upload", label: t.modeUpload },
|
|
108
|
-
] })] }), mode === "generate" ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: t.previewLabel }), _jsx("div", { className: "overflow-hidden rounded-md border bg-muted/30", children: preview.isPending ? (_jsxs("div", { className: "flex flex-col gap-3 p-6", children: [_jsx(Skeleton, { className: "h-6 w-1/2" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-5/6" }), _jsx(Skeleton, { className: "h-4 w-4/5" }), _jsx(Skeleton, { className: "h-4 w-full" })] })) : preview.isError ? (_jsxs("p", { className: "p-6 text-destructive text-sm", children: [t.previewErrorPrefix, " ", preview.error instanceof Error ? preview.error.message : t.previewFailed] })) : preview.data ? (_jsx("iframe", { title: preview.data.templateName || t.previewIframeFallback, srcDoc: wrapPreviewHtml(preview.data.html), sandbox: "", className: "h-[60vh] w-full border-0 bg-white" })) :
|
|
118
|
+
] })] }), mode === "generate" ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: t.previewLabel }), _jsx("div", { className: "overflow-hidden rounded-md border bg-muted/30", children: preview.isPending ? (_jsxs("div", { className: "flex flex-col gap-3 p-6", children: [_jsx(Skeleton, { className: "h-6 w-1/2" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-5/6" }), _jsx(Skeleton, { className: "h-4 w-4/5" }), _jsx(Skeleton, { className: "h-4 w-full" })] })) : preview.isError && !previewSetupMissing ? (_jsxs("p", { className: "p-6 text-destructive text-sm", children: [t.previewErrorPrefix, " ", preview.error instanceof Error ? preview.error.message : t.previewFailed] })) : preview.data ? (_jsx("iframe", { title: preview.data.templateName || t.previewIframeFallback, srcDoc: wrapPreviewHtml(preview.data.html), sandbox: "", className: "h-[60vh] w-full border-0 bg-white" })) : (_jsx("div", { className: "p-6 text-muted-foreground text-sm", children: t.previewUnavailable })) }), preview.data?.templateName ? (_jsxs("p", { className: "text-muted-foreground text-xs", children: [t.previewTemplateLabel, " ", preview.data.templateName] })) : null, showPreviewSetupHint ? (_jsx("p", { className: "text-muted-foreground text-xs", children: t.previewSetupHint })) : null] })) : (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: t.uploadTitleLabel }), _jsx(Input, { value: title, onChange: (e) => setTitle(e.target.value), placeholder: bookingNumber ? `Contract ${bookingNumber}` : t.uploadTitlePlaceholder }), _jsx("p", { className: "text-muted-foreground text-xs", children: t.uploadTitleHint })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: t.uploadFileLabel }), _jsx("input", { type: "file", accept: "application/pdf", onChange: (e) => {
|
|
109
119
|
const next = e.target.files?.[0] ?? null;
|
|
110
120
|
setFile(next);
|
|
111
121
|
}, className: "block w-full text-sm file:mr-3 file:rounded-md file:border file:bg-muted file:px-3 file:py-1.5 file:text-sm file:font-medium hover:file:bg-muted/70" }), file ? (_jsxs("div", { className: "flex items-center justify-between gap-2 rounded-md border bg-background px-3 py-1.5 text-sm", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx(Paperclip, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "truncate", children: file.name })] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: () => setFile(null), children: _jsx(X, { className: "h-3.5 w-3.5" }) })] })) : null] })] })), error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null] }) }), _jsxs("div", { className: "flex shrink-0 items-center justify-end gap-2 border-t px-6 py-4", children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: submitting, children: t.cancel }), _jsxs(Button, { type: "button", disabled: !canSubmit, onClick: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-booking-action-ledger-events.d.ts","sourceRoot":"","sources":["../../src/admin/use-booking-action-ledger-events.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"use-booking-action-ledger-events.d.ts","sourceRoot":"","sources":["../../src/admin/use-booking-action-ledger-events.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,4CAA4C,CAAA;AAO/F;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG;IAC/D,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,MAAM,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAA;CAC/B,CAiDA"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useOperatorAdminMessages } from "@voyant-travel/admin";
|
|
4
4
|
import { Button } from "@voyant-travel/ui/components/button";
|
|
5
|
-
import { ScrollText } from "lucide-react";
|
|
5
|
+
import { CreditCard, FileText, ScrollText } from "lucide-react";
|
|
6
6
|
import { useMemo } from "react";
|
|
7
7
|
import { useBookingActionLedger, } from "../index.js";
|
|
8
8
|
/**
|
|
@@ -25,14 +25,15 @@ export function useBookingActionLedgerEvents(bookingId) {
|
|
|
25
25
|
for (const page of pages) {
|
|
26
26
|
for (const entry of page.data) {
|
|
27
27
|
const traveler = travelersById.get(entry.targetId) ?? null;
|
|
28
|
+
const presentation = getLedgerTimelinePresentation(entry.actionName);
|
|
28
29
|
all.push({
|
|
29
30
|
id: `action:${entry.id}`,
|
|
30
|
-
source:
|
|
31
|
+
source: presentation.source,
|
|
31
32
|
title: formatActionName(entry.actionName),
|
|
32
33
|
description: formatLedgerDescription(entry, traveler, t.travelerFallback, t.targetBooking),
|
|
33
34
|
actorId: entry.principalId,
|
|
34
35
|
timestamp: entry.occurredAt,
|
|
35
|
-
icon:
|
|
36
|
+
icon: presentation.icon,
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -44,6 +45,20 @@ export function useBookingActionLedgerEvents(bookingId) {
|
|
|
44
45
|
function formatActionName(value) {
|
|
45
46
|
return value.replaceAll(".", " / ").replaceAll("_", " ");
|
|
46
47
|
}
|
|
48
|
+
function getLedgerTimelinePresentation(actionName) {
|
|
49
|
+
if (actionName.startsWith("finance.invoice.") ||
|
|
50
|
+
actionName.startsWith("finance.invoice_line_item.") ||
|
|
51
|
+
actionName.startsWith("finance.credit_note.") ||
|
|
52
|
+
actionName.startsWith("finance.credit_note_line_item.")) {
|
|
53
|
+
return { source: "document", icon: FileText };
|
|
54
|
+
}
|
|
55
|
+
if (actionName.startsWith("finance.payment") ||
|
|
56
|
+
actionName.startsWith("finance.booking_payment") ||
|
|
57
|
+
actionName.startsWith("finance.booking_guarantee")) {
|
|
58
|
+
return { source: "payment", icon: CreditCard };
|
|
59
|
+
}
|
|
60
|
+
return { source: "action", icon: ScrollText };
|
|
61
|
+
}
|
|
47
62
|
function formatTarget(entry, traveler, travelerFallback, bookingFallback) {
|
|
48
63
|
if (traveler) {
|
|
49
64
|
return [traveler.firstName, traveler.lastName].filter(Boolean).join(" ") || travelerFallback;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booking-activity-timeline.d.ts","sourceRoot":"","sources":["../../src/components/booking-activity-timeline.tsx"],"names":[],"mappings":"AAYA,OAAO,EAML,KAAK,UAAU,EAKhB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;IAC3C,0FAA0F;IAC1F,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3E,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACvC,CAAA;AA6BD,wBAAgB,uBAAuB,CAAC,EACtC,SAAS,EACT,eAA0B,EAC1B,gBAAgB,EAChB,MAAM,EACN,QAAa,GACd,EAAE,4BAA4B,
|
|
1
|
+
{"version":3,"file":"booking-activity-timeline.d.ts","sourceRoot":"","sources":["../../src/components/booking-activity-timeline.tsx"],"names":[],"mappings":"AAYA,OAAO,EAML,KAAK,UAAU,EAKhB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;IAC3C,0FAA0F;IAC1F,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3E,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACvC,CAAA;AA6BD,wBAAgB,uBAAuB,CAAC,EACtC,SAAS,EACT,eAA0B,EAC1B,gBAAgB,EAChB,MAAM,EACN,QAAa,GACd,EAAE,4BAA4B,qBA0J9B"}
|
|
@@ -56,7 +56,10 @@ export function BookingActivityTimeline({ bookingId, paymentsVariant = "public",
|
|
|
56
56
|
merged.push({
|
|
57
57
|
id: `activity:${entry.id}`,
|
|
58
58
|
source: "activity",
|
|
59
|
-
title:
|
|
59
|
+
title: entry.activityType === "note_added"
|
|
60
|
+
? entry.description
|
|
61
|
+
: (messages.bookingActivityTimeline.activityTitles[entry.activityType] ??
|
|
62
|
+
entry.description),
|
|
60
63
|
description: entry.description,
|
|
61
64
|
// Prefer the hydrated display name; fall back to email then raw
|
|
62
65
|
// id (system actors stay null and skip the "By …" render).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booking-document-dialog.d.ts","sourceRoot":"","sources":["../../src/components/booking-document-dialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"booking-document-dialog.d.ts","sourceRoot":"","sources":["../../src/components/booking-document-dialog.tsx"],"names":[],"mappings":"AAqDA,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,GACV,EAAE,0BAA0B,+BA+K5B"}
|
|
@@ -19,7 +19,10 @@ function createDocumentFormSchema(messages) {
|
|
|
19
19
|
.string()
|
|
20
20
|
.min(1, messages.bookingDocumentDialog.validation.fileNameRequired)
|
|
21
21
|
.max(500),
|
|
22
|
-
fileUrl: z
|
|
22
|
+
fileUrl: z
|
|
23
|
+
.string()
|
|
24
|
+
.min(1, messages.bookingDocumentDialog.validation.fileRequired)
|
|
25
|
+
.url(messages.bookingDocumentDialog.validation.fileUrlInvalid),
|
|
23
26
|
travelerId: z.string().optional().nullable(),
|
|
24
27
|
expiresAt: z.string().optional().nullable(),
|
|
25
28
|
notes: z.string().optional().nullable(),
|
|
@@ -73,11 +76,16 @@ export function BookingDocumentDialog({ open, onOpenChange, bookingId, onSuccess
|
|
|
73
76
|
onOpenChange(false);
|
|
74
77
|
onSuccess?.();
|
|
75
78
|
};
|
|
79
|
+
const uploadedFileUrl = form.watch("fileUrl");
|
|
80
|
+
const canSubmit = Boolean(uploadedFileUrl) && !create.isPending;
|
|
76
81
|
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: messages.bookingDocumentDialog.title }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-1 flex-col overflow-hidden", children: [_jsxs(DialogBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDocumentDialog.fields.type }), _jsxs(Select, { items: typeItems, value: form.watch("type"), onValueChange: (v) => form.setValue("type", (v ?? "other")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: documentTypes.map((t) => (_jsx(SelectItem, { value: t, children: messages.bookingDocumentDialog.documentTypeLabels[t] }, t))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDocumentDialog.fields.traveler }), _jsxs(Select, { items: travelerItems, value: form.watch("travelerId") ?? UNASSIGNED, onValueChange: (v) => form.setValue("travelerId", v ?? UNASSIGNED), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: UNASSIGNED, children: messages.bookingDocumentDialog.placeholders.travelerUnassigned }), travelers.map((traveler) => (_jsxs(SelectItem, { value: traveler.id, children: [traveler.firstName, " ", traveler.lastName] }, traveler.id)))] })] })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDocumentDialog.fields.file }), _jsx(FileDropzone, { accept: "application/pdf,image/*", maxSize: 10 * 1024 * 1024, onUploaded: (upload) => {
|
|
77
82
|
form.setValue("fileUrl", upload.url, { shouldValidate: true });
|
|
78
83
|
form.setValue("fileName", upload.name, { shouldValidate: true });
|
|
84
|
+
}, onCleared: () => {
|
|
85
|
+
form.setValue("fileUrl", "", { shouldDirty: true, shouldValidate: true });
|
|
86
|
+
form.setValue("fileName", "", { shouldDirty: true, shouldValidate: true });
|
|
79
87
|
}, helperText: messages.bookingDocumentDialog.placeholders.helperText }), form.formState.errors.fileUrl && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.fileUrl.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDocumentDialog.fields.expiresAt }), _jsx(DatePicker, { value: form.watch("expiresAt") || null, onChange: (next) => form.setValue("expiresAt", next ?? "", {
|
|
80
88
|
shouldValidate: true,
|
|
81
89
|
shouldDirty: true,
|
|
82
|
-
}), placeholder: messages.bookingDocumentDialog.placeholders.expiresAt, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDocumentDialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: messages.bookingDocumentDialog.placeholders.notes })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled:
|
|
90
|
+
}), placeholder: messages.bookingDocumentDialog.placeholders.expiresAt, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDocumentDialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: messages.bookingDocumentDialog.placeholders.notes })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: !canSubmit, children: [create.isPending && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), messages.bookingDocumentDialog.actions.addDocument] })] })] })] }) }));
|
|
83
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booking-payment-reconciliation-banner.d.ts","sourceRoot":"","sources":["../../src/components/booking-payment-reconciliation-banner.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,uCAAuC;IACtD,SAAS,EAAE,MAAM,CAAA;CAClB;
|
|
1
|
+
{"version":3,"file":"booking-payment-reconciliation-banner.d.ts","sourceRoot":"","sources":["../../src/components/booking-payment-reconciliation-banner.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,uCAAuC;IACtD,SAAS,EAAE,MAAM,CAAA;CAClB;AASD,wBAAgB,kCAAkC,CAAC,EACjD,SAAS,GACV,EAAE,uCAAuC,+BA4FzC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type PaymentMethod, type PaymentStatus } from "@voyant-travel/finance-react";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
export interface
|
|
3
|
+
export interface BookingPaymentSummaryPaymentRow {
|
|
4
4
|
id: string;
|
|
5
|
+
source: "payment";
|
|
5
6
|
invoiceId: string;
|
|
6
7
|
invoiceNumber: string;
|
|
7
8
|
invoiceType?: "invoice" | "proforma" | "credit_note";
|
|
@@ -16,6 +17,13 @@ export interface BookingPaymentsSummaryRow {
|
|
|
16
17
|
referenceNumber: string | null;
|
|
17
18
|
notes: string | null;
|
|
18
19
|
}
|
|
20
|
+
export interface BookingPaymentSummaryVoucherRedemptionRow extends Omit<BookingPaymentSummaryPaymentRow, "source" | "invoiceId" | "invoiceNumber" | "invoiceType"> {
|
|
21
|
+
source: "voucher_redemption";
|
|
22
|
+
invoiceId: null;
|
|
23
|
+
invoiceNumber: null;
|
|
24
|
+
invoiceType: null;
|
|
25
|
+
}
|
|
26
|
+
export type BookingPaymentsSummaryRow = BookingPaymentSummaryPaymentRow | BookingPaymentSummaryVoucherRedemptionRow;
|
|
19
27
|
export interface BookingPaymentsSummaryProps {
|
|
20
28
|
bookingId: string;
|
|
21
29
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booking-payments-summary.d.ts","sourceRoot":"","sources":["../../src/components/booking-payments-summary.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAGnB,MAAM,8BAA8B,CAAA;AAarC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"booking-payments-summary.d.ts","sourceRoot":"","sources":["../../src/components/booking-payments-summary.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAGnB,MAAM,8BAA8B,CAAA;AAarC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,WAAW,+BAA+B;IAC9C,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,SAAS,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,MAAM,EAAE,aAAa,CAAA;IACrB,aAAa,EAAE,aAAa,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,yCACf,SAAQ,IAAI,CACV,+BAA+B,EAC/B,QAAQ,GAAG,WAAW,GAAG,eAAe,GAAG,aAAa,CACzD;IACD,MAAM,EAAE,oBAAoB,CAAA;IAC5B,SAAS,EAAE,IAAI,CAAA;IACf,aAAa,EAAE,IAAI,CAAA;IACnB,WAAW,EAAE,IAAI,CAAA;CAClB;AAED,MAAM,MAAM,yBAAyB,GACjC,+BAA+B,GAC/B,yCAAyC,CAAA;AAmB7C,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,yBAAyB,KAAK,IAAI,CAAA;IAC3E;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,yBAAyB,KAAK,MAAM,CAAA;IAC3D;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,yBAAyB,KAAK,IAAI,CAAA;IACxD,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,yBAAyB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;IAClF,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,yBAAyB,KAAK,IAAI,CAAA;IACxD;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC1E;;;;OAIG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,SAAS,EACT,OAAkB,EAClB,aAAa,EACb,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,YAAY,GACb,EAAE,2BAA2B,qBAqS7B"}
|
|
@@ -50,21 +50,37 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
|
|
|
50
50
|
setDeletePending(false);
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
|
-
const paymentRows = React.useMemo(() => payments.map((payment) =>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
const paymentRows = React.useMemo(() => payments.map((payment) => {
|
|
54
|
+
const base = {
|
|
55
|
+
id: payment.id,
|
|
56
|
+
amountCents: payment.amountCents,
|
|
57
|
+
currency: payment.currency,
|
|
58
|
+
baseCurrency: payment.baseCurrency ?? null,
|
|
59
|
+
baseAmountCents: payment.baseAmountCents ?? null,
|
|
60
|
+
status: payment.status,
|
|
61
|
+
paymentMethod: payment.paymentMethod,
|
|
62
|
+
paymentDate: payment.paymentDate,
|
|
63
|
+
referenceNumber: payment.referenceNumber,
|
|
64
|
+
notes: payment.notes,
|
|
65
|
+
};
|
|
66
|
+
const source = payment.source ?? "payment";
|
|
67
|
+
if (source === "voucher_redemption") {
|
|
68
|
+
return {
|
|
69
|
+
...base,
|
|
70
|
+
source: "voucher_redemption",
|
|
71
|
+
invoiceId: null,
|
|
72
|
+
invoiceNumber: null,
|
|
73
|
+
invoiceType: null,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
...base,
|
|
78
|
+
source: "payment",
|
|
79
|
+
invoiceId: payment.invoiceId ?? "",
|
|
80
|
+
invoiceNumber: payment.invoiceNumber ?? "",
|
|
81
|
+
invoiceType: payment.invoiceType ?? undefined,
|
|
82
|
+
};
|
|
83
|
+
}), [payments]);
|
|
68
84
|
const columns = React.useMemo(() => {
|
|
69
85
|
const cols = [
|
|
70
86
|
{
|
|
@@ -109,16 +125,20 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
|
|
|
109
125
|
accessorKey: "invoiceNumber",
|
|
110
126
|
header: card.columns.invoice,
|
|
111
127
|
cell: ({ row }) => {
|
|
128
|
+
const payment = row.original;
|
|
129
|
+
if (payment.source !== "payment") {
|
|
130
|
+
return _jsx("span", { className: "text-muted-foreground", children: "\u2014" });
|
|
131
|
+
}
|
|
112
132
|
if (onInvoiceOpen) {
|
|
113
133
|
return (_jsxs("button", { type: "button", onClick: (e) => {
|
|
114
134
|
e.stopPropagation();
|
|
115
|
-
onInvoiceOpen(
|
|
116
|
-
}, className: "inline-flex items-center gap-1 font-mono text-primary text-xs hover:underline", children: [
|
|
135
|
+
onInvoiceOpen(payment.invoiceId, payment);
|
|
136
|
+
}, className: "inline-flex items-center gap-1 font-mono text-primary text-xs hover:underline", children: [payment.invoiceNumber, _jsx(ArrowUpRight, { className: "h-3 w-3" })] }));
|
|
117
137
|
}
|
|
118
138
|
if (getInvoiceHref) {
|
|
119
|
-
return (_jsxs("a", { href: getInvoiceHref(
|
|
139
|
+
return (_jsxs("a", { href: getInvoiceHref(payment), onClick: (e) => e.stopPropagation(), className: "inline-flex items-center gap-1 font-mono text-primary text-xs hover:underline", children: [payment.invoiceNumber, _jsx(ArrowUpRight, { className: "h-3 w-3" })] }));
|
|
120
140
|
}
|
|
121
|
-
return _jsx("span", { className: "font-mono text-xs", children:
|
|
141
|
+
return _jsx("span", { className: "font-mono text-xs", children: payment.invoiceNumber });
|
|
122
142
|
},
|
|
123
143
|
},
|
|
124
144
|
];
|
|
@@ -126,19 +146,24 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
|
|
|
126
146
|
cols.push({
|
|
127
147
|
id: "actions",
|
|
128
148
|
header: () => _jsx("span", { className: "sr-only", children: card.columns.actions }),
|
|
129
|
-
cell: ({ row }) =>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
149
|
+
cell: ({ row }) => {
|
|
150
|
+
if (row.original.source !== "payment") {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
return (_jsxs("div", { className: "flex items-center justify-end gap-1", children: [onViewPayment ? (_jsx(IconActionButton, { label: card.actions.view, icon: _jsx(Eye, { className: "h-3.5 w-3.5" }), onClick: (e) => {
|
|
154
|
+
e.stopPropagation();
|
|
155
|
+
onViewPayment(row.original);
|
|
156
|
+
} })) : null, onConvertProforma && row.original.invoiceType === "proforma" ? (_jsx(IconActionButton, { label: card.actions.convertToInvoice, icon: _jsx(ArrowUpRight, { className: "h-3.5 w-3.5" }), onClick: (e) => {
|
|
157
|
+
e.stopPropagation();
|
|
158
|
+
void onConvertProforma(row.original);
|
|
159
|
+
} })) : null, onEditPayment ? (_jsx(IconActionButton, { label: card.actions.edit, icon: _jsx(Pencil, { className: "h-3.5 w-3.5" }), onClick: (e) => {
|
|
160
|
+
e.stopPropagation();
|
|
161
|
+
onEditPayment(row.original);
|
|
162
|
+
} })) : null, onDeletePayment ? (_jsx(IconActionButton, { label: card.actions.delete, icon: _jsx(Trash2, { className: "h-3.5 w-3.5" }), className: "text-muted-foreground hover:bg-destructive/10 hover:text-destructive", onClick: (e) => {
|
|
163
|
+
e.stopPropagation();
|
|
164
|
+
setDeleteTarget(row.original);
|
|
165
|
+
} })) : null] }));
|
|
166
|
+
},
|
|
142
167
|
});
|
|
143
168
|
}
|
|
144
169
|
return cols;
|
|
@@ -15,6 +15,8 @@ export interface FileDropzoneProps {
|
|
|
15
15
|
maxSize?: number;
|
|
16
16
|
/** Called after a successful upload. */
|
|
17
17
|
onUploaded: (file: UploadedFile) => void;
|
|
18
|
+
/** Called after a previously uploaded file is cleared from the dropzone. */
|
|
19
|
+
onCleared?: () => void;
|
|
18
20
|
/** Called when an error occurs (validation, upload failure). */
|
|
19
21
|
onError?: (message: string) => void;
|
|
20
22
|
/** Helper text shown in the idle state. */
|
|
@@ -22,5 +24,5 @@ export interface FileDropzoneProps {
|
|
|
22
24
|
/** Disable interaction. */
|
|
23
25
|
disabled?: boolean;
|
|
24
26
|
}
|
|
25
|
-
export declare function FileDropzone({ uploadUrl, accept, maxSize, onUploaded, onError, helperText, disabled, }: FileDropzoneProps): React.JSX.Element;
|
|
27
|
+
export declare function FileDropzone({ uploadUrl, accept, maxSize, onUploaded, onCleared, onError, helperText, disabled, }: FileDropzoneProps): React.JSX.Element;
|
|
26
28
|
//# sourceMappingURL=file-dropzone.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-dropzone.d.ts","sourceRoot":"","sources":["../../src/components/file-dropzone.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IACxC,gEAAgE;IAChE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,YAAY,CAAC,EAC3B,SAAmC,EACnC,MAAM,EACN,OAAO,EACP,UAAU,EACV,OAAO,EACP,UAAU,EACV,QAAQ,GACT,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"file-dropzone.d.ts","sourceRoot":"","sources":["../../src/components/file-dropzone.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IACxC,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,gEAAgE;IAChE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,YAAY,CAAC,EAC3B,SAAmC,EACnC,MAAM,EACN,OAAO,EACP,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,QAAQ,GACT,EAAE,iBAAiB,qBA+KnB"}
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import { File as FileIcon, Loader2, Upload, X } from "lucide-react";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider.js";
|
|
6
|
-
export function FileDropzone({ uploadUrl = "/api/v1/admin/uploads", accept, maxSize, onUploaded, onError, helperText, disabled, }) {
|
|
6
|
+
export function FileDropzone({ uploadUrl = "/api/v1/admin/uploads", accept, maxSize, onUploaded, onCleared, onError, helperText, disabled, }) {
|
|
7
7
|
const inputRef = React.useRef(null);
|
|
8
8
|
const [isDragging, setIsDragging] = React.useState(false);
|
|
9
9
|
const [isUploading, setIsUploading] = React.useState(false);
|
|
@@ -94,6 +94,7 @@ export function FileDropzone({ uploadUrl = "/api/v1/admin/uploads", accept, maxS
|
|
|
94
94
|
const reset = () => {
|
|
95
95
|
setUploaded(null);
|
|
96
96
|
setError(null);
|
|
97
|
+
onCleared?.();
|
|
97
98
|
};
|
|
98
99
|
if (uploaded) {
|
|
99
100
|
return (_jsxs("div", { className: "flex items-center justify-between gap-3 rounded-md border bg-muted/30 p-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(FileIcon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-medium", children: uploaded.name }), _jsxs("p", { className: "text-xs text-muted-foreground", children: [formatSize(uploaded.size), " \u00B7 ", uploaded.mimeType] })] })] }), _jsx("button", { type: "button", onClick: reset, className: "text-muted-foreground hover:text-destructive", "aria-label": messages.fileDropzone.removeFileAriaLabel, children: _jsx(X, { className: "h-4 w-4" }) })] }));
|
|
@@ -12,7 +12,7 @@ export declare function useSlotExtraManifestMutation(slotId: string): {
|
|
|
12
12
|
productExtraId: string;
|
|
13
13
|
optionExtraConfigId?: string | null | undefined;
|
|
14
14
|
status?: "selected" | "cancelled" | "fulfilled" | "no_show" | undefined;
|
|
15
|
-
collectionStatus?: "
|
|
15
|
+
collectionStatus?: "not_required" | "pending" | "collected" | "waived" | "refunded" | undefined;
|
|
16
16
|
collectionCurrency?: string | null | undefined;
|
|
17
17
|
collectionAmountCents?: number | null | undefined;
|
|
18
18
|
notes?: string | null | undefined;
|
|
@@ -27,7 +27,7 @@ export declare function useSlotExtraManifestMutation(slotId: string): {
|
|
|
27
27
|
productExtraId: string;
|
|
28
28
|
optionExtraConfigId?: string | null | undefined;
|
|
29
29
|
status?: "selected" | "cancelled" | "fulfilled" | "no_show" | undefined;
|
|
30
|
-
collectionStatus?: "
|
|
30
|
+
collectionStatus?: "not_required" | "pending" | "collected" | "waived" | "refunded" | undefined;
|
|
31
31
|
collectionCurrency?: string | null | undefined;
|
|
32
32
|
collectionAmountCents?: number | null | undefined;
|
|
33
33
|
notes?: string | null | undefined;
|
|
@@ -39,7 +39,7 @@ export declare function useSlotExtraManifestMutation(slotId: string): {
|
|
|
39
39
|
}, Error, {
|
|
40
40
|
productExtraId: string;
|
|
41
41
|
travelerIds: string[];
|
|
42
|
-
collectionStatus: "
|
|
42
|
+
collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
|
|
43
43
|
collectionCurrency?: string | null | undefined;
|
|
44
44
|
collectionAmountCents?: number | null | undefined;
|
|
45
45
|
notes?: string | null | undefined;
|
|
@@ -55,7 +55,7 @@ export declare function useSlotExtraManifest(slotId: string | null | undefined,
|
|
|
55
55
|
status: "selected" | "cancelled" | "fulfilled" | "no_show";
|
|
56
56
|
selected: boolean;
|
|
57
57
|
collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
|
|
58
|
-
collectionStatus: "
|
|
58
|
+
collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
|
|
59
59
|
collectionCurrency: string | null;
|
|
60
60
|
collectionAmountCents: number | null;
|
|
61
61
|
collectedAt: string | null;
|
|
@@ -243,7 +243,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
|
|
|
243
243
|
status: "selected" | "cancelled" | "fulfilled" | "no_show";
|
|
244
244
|
selected: boolean;
|
|
245
245
|
collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
|
|
246
|
-
collectionStatus: "
|
|
246
|
+
collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
|
|
247
247
|
collectionCurrency: string | null;
|
|
248
248
|
collectionAmountCents: number | null;
|
|
249
249
|
collectedAt: string | null;
|
|
@@ -307,7 +307,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
|
|
|
307
307
|
status: "selected" | "cancelled" | "fulfilled" | "no_show";
|
|
308
308
|
selected: boolean;
|
|
309
309
|
collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
|
|
310
|
-
collectionStatus: "
|
|
310
|
+
collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
|
|
311
311
|
collectionCurrency: string | null;
|
|
312
312
|
collectionAmountCents: number | null;
|
|
313
313
|
collectedAt: string | null;
|
|
@@ -372,7 +372,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
|
|
|
372
372
|
status: "selected" | "cancelled" | "fulfilled" | "no_show";
|
|
373
373
|
selected: boolean;
|
|
374
374
|
collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
|
|
375
|
-
collectionStatus: "
|
|
375
|
+
collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
|
|
376
376
|
collectionCurrency: string | null;
|
|
377
377
|
collectionAmountCents: number | null;
|
|
378
378
|
collectedAt: string | null;
|
|
@@ -439,7 +439,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
|
|
|
439
439
|
status: "selected" | "cancelled" | "fulfilled" | "no_show";
|
|
440
440
|
selected: boolean;
|
|
441
441
|
collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
|
|
442
|
-
collectionStatus: "
|
|
442
|
+
collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
|
|
443
443
|
collectionCurrency: string | null;
|
|
444
444
|
collectionAmountCents: number | null;
|
|
445
445
|
collectedAt: string | null;
|
package/dist/extras/schemas.d.ts
CHANGED
|
@@ -175,8 +175,8 @@ export declare const slotExtraManifestSelectionSchema: z.ZodObject<{
|
|
|
175
175
|
booking_total: "booking_total";
|
|
176
176
|
}>;
|
|
177
177
|
collectionStatus: z.ZodEnum<{
|
|
178
|
-
pending: "pending";
|
|
179
178
|
not_required: "not_required";
|
|
179
|
+
pending: "pending";
|
|
180
180
|
collected: "collected";
|
|
181
181
|
waived: "waived";
|
|
182
182
|
refunded: "refunded";
|
|
@@ -278,8 +278,8 @@ export declare const slotExtraManifestSchema: z.ZodObject<{
|
|
|
278
278
|
booking_total: "booking_total";
|
|
279
279
|
}>;
|
|
280
280
|
collectionStatus: z.ZodEnum<{
|
|
281
|
-
pending: "pending";
|
|
282
281
|
not_required: "not_required";
|
|
282
|
+
pending: "pending";
|
|
283
283
|
collected: "collected";
|
|
284
284
|
waived: "waived";
|
|
285
285
|
refunded: "refunded";
|
|
@@ -383,8 +383,8 @@ export declare const slotExtraManifestResponse: z.ZodObject<{
|
|
|
383
383
|
booking_total: "booking_total";
|
|
384
384
|
}>;
|
|
385
385
|
collectionStatus: z.ZodEnum<{
|
|
386
|
-
pending: "pending";
|
|
387
386
|
not_required: "not_required";
|
|
387
|
+
pending: "pending";
|
|
388
388
|
collected: "collected";
|
|
389
389
|
waived: "waived";
|
|
390
390
|
refunded: "refunded";
|
|
@@ -18,7 +18,7 @@ export declare function useBookingActionLedger(bookingId: string | null | undefi
|
|
|
18
18
|
actionVersion: string;
|
|
19
19
|
actionKind: "reverse" | "read" | "create" | "update" | "delete" | "execute" | "approve" | "reject" | "compensate" | "duplicate";
|
|
20
20
|
status: "cancelled" | "expired" | "requested" | "awaiting_approval" | "approved" | "denied" | "succeeded" | "failed" | "reversed" | "compensated" | "superseded";
|
|
21
|
-
evaluatedRisk: "
|
|
21
|
+
evaluatedRisk: "low" | "medium" | "high" | "critical";
|
|
22
22
|
actorType: string | null;
|
|
23
23
|
principalType: "user" | "api_key" | "agent" | "workflow" | "system";
|
|
24
24
|
principalId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-booking-documents.d.ts","sourceRoot":"","sources":["../../src/hooks/use-booking-documents.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,kCAAkC;IACjD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,OAAO,GAAE,kCAAuC;;;;;;;;;;;;WASjD;AAED,MAAM,WAAW,kCAAkC;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,wBAAgB,kCAAkC,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"use-booking-documents.d.ts","sourceRoot":"","sources":["../../src/hooks/use-booking-documents.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,kCAAkC;IACjD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,OAAO,GAAE,kCAAuC;;;;;;;;;;;;WASjD;AAED,MAAM,WAAW,kCAAkC;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,wBAAgB,kCAAkC,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;EAgDnE"}
|
|
@@ -17,7 +17,10 @@ export function useBookingTravelerDocumentMutation(bookingId) {
|
|
|
17
17
|
const { baseUrl, fetcher } = useVoyantBookingsContext();
|
|
18
18
|
const queryClient = useQueryClient();
|
|
19
19
|
const invalidate = () => {
|
|
20
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.booking(bookingId) });
|
|
21
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.bookings() });
|
|
20
22
|
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.documents(bookingId) });
|
|
23
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.activity(bookingId) });
|
|
21
24
|
};
|
|
22
25
|
const create = useMutation({
|
|
23
26
|
mutationFn: async (input) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-booking-item-mutation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-booking-item-mutation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAW5B,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAC5E,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"use-booking-item-mutation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-booking-item-mutation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAW5B,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAC5E,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAgB5E,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAsBZ,MAAM;eAAS,sBAAsB;;;;;EA8BhF"}
|
|
@@ -4,6 +4,16 @@ import { fetchWithValidation } from "../client.js";
|
|
|
4
4
|
import { useVoyantBookingsContext } from "../provider.js";
|
|
5
5
|
import { bookingsQueryKeys } from "../query-keys.js";
|
|
6
6
|
import { bookingItemsResponse, bookingSingleResponse, successEnvelope } from "../schemas.js";
|
|
7
|
+
function invalidateBookingItemMutationQueries(queryClient, bookingId) {
|
|
8
|
+
void queryClient.invalidateQueries({
|
|
9
|
+
queryKey: bookingsQueryKeys.booking(bookingId),
|
|
10
|
+
exact: true,
|
|
11
|
+
});
|
|
12
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.bookings() });
|
|
13
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.items(bookingId) });
|
|
14
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.activity(bookingId) });
|
|
15
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.actionLedger(bookingId) });
|
|
16
|
+
}
|
|
7
17
|
export function useBookingItemMutation(bookingId) {
|
|
8
18
|
const { baseUrl, fetcher } = useVoyantBookingsContext();
|
|
9
19
|
const queryClient = useQueryClient();
|
|
@@ -15,8 +25,7 @@ export function useBookingItemMutation(bookingId) {
|
|
|
15
25
|
return data;
|
|
16
26
|
},
|
|
17
27
|
onSuccess: () => {
|
|
18
|
-
|
|
19
|
-
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.activity(bookingId) });
|
|
28
|
+
invalidateBookingItemMutationQueries(queryClient, bookingId);
|
|
20
29
|
},
|
|
21
30
|
});
|
|
22
31
|
const update = useMutation({
|
|
@@ -27,15 +36,13 @@ export function useBookingItemMutation(bookingId) {
|
|
|
27
36
|
return data;
|
|
28
37
|
},
|
|
29
38
|
onSuccess: () => {
|
|
30
|
-
|
|
31
|
-
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.activity(bookingId) });
|
|
39
|
+
invalidateBookingItemMutationQueries(queryClient, bookingId);
|
|
32
40
|
},
|
|
33
41
|
});
|
|
34
42
|
const remove = useMutation({
|
|
35
43
|
mutationFn: async (itemId) => fetchWithValidation(`/v1/admin/bookings/${bookingId}/items/${itemId}`, successEnvelope, { baseUrl, fetcher }, { method: "DELETE" }),
|
|
36
44
|
onSuccess: () => {
|
|
37
|
-
|
|
38
|
-
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.activity(bookingId) });
|
|
45
|
+
invalidateBookingItemMutationQueries(queryClient, bookingId);
|
|
39
46
|
},
|
|
40
47
|
});
|
|
41
48
|
return { create, update, remove };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-booking-note-mutation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-booking-note-mutation.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;CAChB;AAQD,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"use-booking-note-mutation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-booking-note-mutation.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;CAChB;AAQD,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuDvD"}
|
|
@@ -13,8 +13,11 @@ export function useBookingNoteMutation(bookingId) {
|
|
|
13
13
|
const { baseUrl, fetcher } = useVoyantBookingsContext();
|
|
14
14
|
const queryClient = useQueryClient();
|
|
15
15
|
const invalidate = () => {
|
|
16
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.booking(bookingId) });
|
|
17
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.bookings() });
|
|
16
18
|
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.notes(bookingId) });
|
|
17
19
|
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.activity(bookingId) });
|
|
20
|
+
void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.actionLedger(bookingId) });
|
|
18
21
|
};
|
|
19
22
|
const create = useMutation({
|
|
20
23
|
mutationFn: async (input) => {
|