@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.
Files changed (54) hide show
  1. package/dist/admin/booking-contract-dialog.d.ts.map +1 -1
  2. package/dist/admin/booking-contract-dialog.js +11 -1
  3. package/dist/admin/use-booking-action-ledger-events.d.ts.map +1 -1
  4. package/dist/admin/use-booking-action-ledger-events.js +18 -3
  5. package/dist/components/booking-activity-timeline.d.ts.map +1 -1
  6. package/dist/components/booking-activity-timeline.js +4 -1
  7. package/dist/components/booking-document-dialog.d.ts.map +1 -1
  8. package/dist/components/booking-document-dialog.js +10 -2
  9. package/dist/components/booking-payment-reconciliation-banner.d.ts.map +1 -1
  10. package/dist/components/booking-payments-summary.d.ts +9 -1
  11. package/dist/components/booking-payments-summary.d.ts.map +1 -1
  12. package/dist/components/booking-payments-summary.js +57 -32
  13. package/dist/components/file-dropzone.d.ts +3 -1
  14. package/dist/components/file-dropzone.d.ts.map +1 -1
  15. package/dist/components/file-dropzone.js +2 -1
  16. package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts +3 -3
  17. package/dist/extras/hooks/use-slot-extra-manifest.d.ts +1 -1
  18. package/dist/extras/query-options.d.ts +4 -4
  19. package/dist/extras/schemas.d.ts +3 -3
  20. package/dist/hooks/use-booking-action-ledger.d.ts +1 -1
  21. package/dist/hooks/use-booking-documents.d.ts.map +1 -1
  22. package/dist/hooks/use-booking-documents.js +3 -0
  23. package/dist/hooks/use-booking-item-mutation.d.ts.map +1 -1
  24. package/dist/hooks/use-booking-item-mutation.js +13 -6
  25. package/dist/hooks/use-booking-note-mutation.d.ts.map +1 -1
  26. package/dist/hooks/use-booking-note-mutation.js +3 -0
  27. package/dist/hooks/use-supplier-status-mutation.d.ts +2 -2
  28. package/dist/hooks/use-supplier-status-mutation.d.ts.map +1 -1
  29. package/dist/hooks/use-supplier-status-mutation.js +10 -12
  30. package/dist/hooks/use-supplier-statuses.d.ts +1 -1
  31. package/dist/hooks/use-traveler-mutation.d.ts.map +1 -1
  32. package/dist/hooks/use-traveler-mutation.js +10 -12
  33. package/dist/hooks/use-traveler-with-travel-details-mutation.d.ts.map +1 -1
  34. package/dist/hooks/use-traveler-with-travel-details-mutation.js +3 -0
  35. package/dist/i18n/en-sections.d.ts +1 -0
  36. package/dist/i18n/en-sections.d.ts.map +1 -1
  37. package/dist/i18n/en-sections.js +1 -0
  38. package/dist/i18n/en.d.ts +1 -0
  39. package/dist/i18n/en.d.ts.map +1 -1
  40. package/dist/i18n/messages-sections.d.ts +1 -0
  41. package/dist/i18n/messages-sections.d.ts.map +1 -1
  42. package/dist/i18n/provider.d.ts +2 -0
  43. package/dist/i18n/provider.d.ts.map +1 -1
  44. package/dist/i18n/ro-sections.d.ts +1 -0
  45. package/dist/i18n/ro-sections.d.ts.map +1 -1
  46. package/dist/i18n/ro-sections.js +1 -0
  47. package/dist/i18n/ro.d.ts +1 -0
  48. package/dist/i18n/ro.d.ts.map +1 -1
  49. package/dist/query-options.d.ts +4 -4
  50. package/dist/requirements/hooks/use-booking-questions.d.ts +1 -1
  51. package/dist/requirements/query-options.d.ts +4 -4
  52. package/dist/requirements/schemas.d.ts +3 -3
  53. package/dist/schemas.d.ts +6 -6
  54. 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":"AA0BA,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,+BA8N5B"}
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" })) : null }), preview.data?.templateName ? (_jsxs("p", { className: "text-muted-foreground text-xs", children: [t.previewTemplateLabel, " ", preview.data.templateName] })) : 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) => {
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,EAAE,MAAM,4CAA4C,CAAA;AAO/E;;;;;;;;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,CAgDA"}
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: "action",
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: ScrollText,
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,qBAuJ9B"}
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: messages.bookingActivityTimeline.activityTitles[entry.activityType] ?? entry.description,
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":"AAkDA,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,+BAyK5B"}
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.string().url(messages.bookingDocumentDialog.validation.fileUrlInvalid),
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: create.isPending, children: [create.isPending && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), messages.bookingDocumentDialog.actions.addDocument] })] })] })] }) }));
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;AAID,wBAAgB,kCAAkC,CAAC,EACjD,SAAS,GACV,EAAE,uCAAuC,+BA4FzC"}
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 BookingPaymentsSummaryRow {
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,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,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,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,qBAwQ7B"}
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
- id: payment.id,
55
- invoiceId: payment.invoiceId,
56
- invoiceNumber: payment.invoiceNumber,
57
- invoiceType: payment.invoiceType,
58
- amountCents: payment.amountCents,
59
- currency: payment.currency,
60
- baseCurrency: payment.baseCurrency ?? null,
61
- baseAmountCents: payment.baseAmountCents ?? null,
62
- status: payment.status,
63
- paymentMethod: payment.paymentMethod,
64
- paymentDate: payment.paymentDate,
65
- referenceNumber: payment.referenceNumber,
66
- notes: payment.notes,
67
- })), [payments]);
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(row.original.invoiceId, row.original);
116
- }, className: "inline-flex items-center gap-1 font-mono text-primary text-xs hover:underline", children: [row.original.invoiceNumber, _jsx(ArrowUpRight, { className: "h-3 w-3" })] }));
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(row.original), onClick: (e) => e.stopPropagation(), className: "inline-flex items-center gap-1 font-mono text-primary text-xs hover:underline", children: [row.original.invoiceNumber, _jsx(ArrowUpRight, { className: "h-3 w-3" })] }));
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: row.original.invoiceNumber });
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 }) => (_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) => {
130
- e.stopPropagation();
131
- onViewPayment(row.original);
132
- } })) : null, onConvertProforma && row.original.invoiceType === "proforma" ? (_jsx(IconActionButton, { label: card.actions.convertToInvoice, icon: _jsx(ArrowUpRight, { className: "h-3.5 w-3.5" }), onClick: (e) => {
133
- e.stopPropagation();
134
- void onConvertProforma(row.original);
135
- } })) : null, onEditPayment ? (_jsx(IconActionButton, { label: card.actions.edit, icon: _jsx(Pencil, { className: "h-3.5 w-3.5" }), onClick: (e) => {
136
- e.stopPropagation();
137
- onEditPayment(row.original);
138
- } })) : 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) => {
139
- e.stopPropagation();
140
- setDeleteTarget(row.original);
141
- } })) : null] })),
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,qBA8KnB"}
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?: "pending" | "not_required" | "collected" | "waived" | "refunded" | undefined;
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?: "pending" | "not_required" | "collected" | "waived" | "refunded" | undefined;
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: "pending" | "not_required" | "collected" | "waived" | "refunded";
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: "pending" | "not_required" | "collected" | "waived" | "refunded";
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: "pending" | "not_required" | "collected" | "waived" | "refunded";
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: "pending" | "not_required" | "collected" | "waived" | "refunded";
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: "pending" | "not_required" | "collected" | "waived" | "refunded";
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: "pending" | "not_required" | "collected" | "waived" | "refunded";
442
+ collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
443
443
  collectionCurrency: string | null;
444
444
  collectionAmountCents: number | null;
445
445
  collectedAt: string | null;
@@ -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: "high" | "low" | "medium" | "critical";
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;;;;;;;;;;;;;;;EA6CnE"}
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;AAE5E,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAuBZ,MAAM;eAAS,sBAAsB;;;;;EAgChF"}
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
- void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.items(bookingId) });
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
- void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.items(bookingId) });
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
- void queryClient.invalidateQueries({ queryKey: bookingsQueryKeys.items(bookingId) });
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoDvD"}
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) => {