@voyant-travel/bookings-react 0.197.0 → 0.198.1

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 (38) hide show
  1. package/dist/admin/booking-detail-skeleton.js +1 -1
  2. package/dist/admin/bookings-list-skeleton.js +1 -1
  3. package/dist/admin/index.d.ts +4 -4
  4. package/dist/admin/pages/booking-journey-page.js +1 -1
  5. package/dist/admin/pages/booking-new-page.js +1 -1
  6. package/dist/components/booking-billing-dialog.js +4 -4
  7. package/dist/components/booking-cancellation-dialog.js +2 -2
  8. package/dist/components/booking-create-page.js +1 -1
  9. package/dist/components/booking-detail-page.js +4 -4
  10. package/dist/components/booking-dialog.js +3 -3
  11. package/dist/components/booking-document-dialog.js +1 -1
  12. package/dist/components/booking-document-list.js +6 -3
  13. package/dist/components/booking-group-section.js +5 -2
  14. package/dist/components/booking-guarantee-dialog.js +5 -5
  15. package/dist/components/booking-item-dialog.js +5 -5
  16. package/dist/components/booking-item-travelers.js +6 -3
  17. package/dist/components/booking-payment-schedule-dialog.js +2 -2
  18. package/dist/components/booking-quick-view-sheet.js +2 -2
  19. package/dist/components/bookings-page.js +1 -1
  20. package/dist/components/payment-schedule-section.js +1 -1
  21. package/dist/components/supplier-status-dialog.js +1 -1
  22. package/dist/components/traveler-dialog.js +5 -5
  23. package/dist/extras/i18n/en.js +9 -7
  24. package/dist/extras/i18n/ro.js +9 -7
  25. package/dist/i18n/en-base.js +3 -3
  26. package/dist/i18n/en-create-list.js +14 -14
  27. package/dist/i18n/en-journey.js +15 -15
  28. package/dist/i18n/en-operations.js +11 -11
  29. package/dist/i18n/en-sections.js +3 -3
  30. package/dist/i18n/ro-base.js +3 -3
  31. package/dist/i18n/ro-create-list.js +13 -13
  32. package/dist/i18n/ro-journey.js +10 -10
  33. package/dist/i18n/ro-operations.js +11 -11
  34. package/dist/i18n/ro-sections.js +3 -3
  35. package/dist/requirements/i18n/en.js +8 -8
  36. package/dist/requirements/i18n/ro.js +7 -7
  37. package/dist/storefront/storefront-checkout-bodies.d.ts +1 -1
  38. package/package.json +39 -39
@@ -7,7 +7,7 @@ import { Skeleton } from "@voyant-travel/ui/components/skeleton";
7
7
  * bar, two list cards) so the pending state doesn't shift the page.
8
8
  */
9
9
  export function BookingDetailSkeleton() {
10
- return (_jsxs("div", { className: "flex flex-col gap-6 p-6", children: [_jsx(Header, {}), _jsx(SummaryCard, {}), _jsx(TabsBar, {}), _jsx(ListCard, { titleWidth: "w-32", rows: 3 }), _jsx(ListCard, { titleWidth: "w-28", rows: 2 })] }));
10
+ return (_jsxs("div", { className: "flex flex-col gap-6", children: [_jsx(Header, {}), _jsx(SummaryCard, {}), _jsx(TabsBar, {}), _jsx(ListCard, { titleWidth: "w-32", rows: 3 }), _jsx(ListCard, { titleWidth: "w-28", rows: 2 })] }));
11
11
  }
12
12
  function Header() {
13
13
  return (_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "h-7 w-44" }), _jsx(Skeleton, { className: "h-5 w-20 rounded-full" })] }), _jsx(Skeleton, { className: "h-8 w-8 rounded-md" })] }));
@@ -12,7 +12,7 @@ const HEADER_WIDTHS = ["w-20", "w-14", "w-20", "w-8", "w-20"];
12
12
  * - Pagination bar
13
13
  */
14
14
  export function BookingsListSkeleton() {
15
- return (_jsxs("div", { className: "flex flex-col gap-6 p-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-7 w-28" }), _jsx(Skeleton, { className: "h-4 w-80" })] }), _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx(Skeleton, { className: "h-9 w-full max-w-sm" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Skeleton, { className: "h-9 w-32" }), _jsx(Skeleton, { className: "h-9 w-36" })] })] }), _jsx("div", { className: "rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: HEADER_WIDTHS.map((width, column) => (_jsx(TableHead
15
+ return (_jsxs("div", { className: "flex flex-col gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-7 w-28" }), _jsx(Skeleton, { className: "h-4 w-80" })] }), _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx(Skeleton, { className: "h-9 w-full max-w-sm" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Skeleton, { className: "h-9 w-32" }), _jsx(Skeleton, { className: "h-9 w-36" })] })] }), _jsx("div", { className: "rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: HEADER_WIDTHS.map((width, column) => (_jsx(TableHead
16
16
  // biome-ignore lint/suspicious/noArrayIndexKey: stable placeholders -- owner: bookings-react; existing suppression is intentional pending typed cleanup.
17
17
  , { children: _jsx(Skeleton, { className: `h-3.5 ${width}` }) }, column))) }) }), _jsx(SkeletonRows, { rows: 8, widths: ["w-28", "w-20", "w-24", "w-6", "w-24"] })] }) }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Skeleton, { className: "h-4 w-40" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Skeleton, { className: "h-8 w-20" }), _jsx(Skeleton, { className: "h-4 w-20" }), _jsx(Skeleton, { className: "h-8 w-16" })] })] })] }));
18
18
  }
@@ -135,9 +135,9 @@ export declare const bookingDetailTabSchema: z.ZodEnum<{
135
135
  travelers: "travelers";
136
136
  activity: "activity";
137
137
  documents: "documents";
138
- finance: "finance";
139
- invoices: "invoices";
140
138
  suppliers: "suppliers";
139
+ invoices: "invoices";
140
+ finance: "finance";
141
141
  }>;
142
142
  /**
143
143
  * Search contract for the booking detail page. `productId`/`slotId` only
@@ -153,9 +153,9 @@ export declare const bookingDetailSearchSchema: z.ZodObject<{
153
153
  travelers: "travelers";
154
154
  activity: "activity";
155
155
  documents: "documents";
156
- finance: "finance";
157
- invoices: "invoices";
158
156
  suppliers: "suppliers";
157
+ invoices: "invoices";
158
+ finance: "finance";
159
159
  }>>;
160
160
  }, z.core.$strip>;
161
161
  export type BookingDetailSearchParams = z.infer<typeof bookingDetailSearchSchema>;
@@ -16,7 +16,7 @@ export default function BookingJourneyPage({ params, search }) {
16
16
  // Stable draft id — refresh-safe when carried in the URL; generated once
17
17
  // per mount otherwise.
18
18
  const draftId = useMemo(() => journeySearch.draftId ?? generateDraftId(), [journeySearch.draftId]);
19
- return (_jsx("div", { className: "container mx-auto py-6", children: _jsx(BookingJourneyHost, { entityModule: params.entityModule ?? "", entityId: params.entityId ?? "", sourceKind: journeySearch.sourceKind, sourceConnectionId: journeySearch.sourceConnectionId, sourceRef: journeySearch.sourceRef, departureId: journeySearch.departureId, departureDate: journeySearch.departureDate, optionId: journeySearch.optionId, roomTypeId: journeySearch.roomTypeId, ratePlanId: journeySearch.ratePlanId, board: journeySearch.board, entityName: journeySearch.entityName, entityImageUrl: journeySearch.entityImageUrl, draftId: draftId }) }));
19
+ return (_jsx("div", { className: "mx-auto", children: _jsx(BookingJourneyHost, { entityModule: params.entityModule ?? "", entityId: params.entityId ?? "", sourceKind: journeySearch.sourceKind, sourceConnectionId: journeySearch.sourceConnectionId, sourceRef: journeySearch.sourceRef, departureId: journeySearch.departureId, departureDate: journeySearch.departureDate, optionId: journeySearch.optionId, roomTypeId: journeySearch.roomTypeId, ratePlanId: journeySearch.ratePlanId, board: journeySearch.board, entityName: journeySearch.entityName, entityImageUrl: journeySearch.entityImageUrl, draftId: draftId }) }));
20
20
  }
21
21
  function generateDraftId() {
22
22
  if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.randomUUID) {
@@ -35,7 +35,7 @@ export default function BookingNewPage({ search }) {
35
35
  }, [productId, slotId, navigate]);
36
36
  if (productId)
37
37
  return null;
38
- return (_jsxs("main", { className: "mx-auto flex w-full max-w-screen-md flex-col gap-6 px-4 py-6 sm:px-6 lg:px-8", children: [_jsxs("header", { className: "flex flex-col gap-1", children: [_jsx("h1", { className: "font-semibold text-2xl tracking-normal", children: messages.bookingCreatePage.title }), _jsx("p", { className: "text-muted-foreground text-sm", children: messages.bookingCreatePage.description })] }), _jsx(ProductPickerSection, { value: { productId: "", optionId: null }, enabled: true, lockProduct: false, showOptionPicker: false,
38
+ return (_jsxs("main", { className: "mx-auto flex w-full max-w-screen-md flex-col gap-6", children: [_jsxs("header", { className: "flex flex-col gap-1", children: [_jsx("h1", { className: "font-semibold text-2xl tracking-normal", children: messages.bookingCreatePage.title }), _jsx("p", { className: "text-muted-foreground text-sm", children: messages.bookingCreatePage.description })] }), _jsx(ProductPickerSection, { value: { productId: "", optionId: null }, enabled: true, lockProduct: false, showOptionPicker: false,
39
39
  // Owned pick -> journey with `owned` provenance. Clearing the field
40
40
  // yields an empty productId, which we ignore.
41
41
  onChange: (value) => {
@@ -3,7 +3,7 @@
3
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  import { useAddresses } from "@voyant-travel/identity-react";
5
5
  import { useOrganization, useOrganizations, usePeople, usePerson, } from "@voyant-travel/relationships-react";
6
- import { Button, ButtonGroup, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, } from "@voyant-travel/ui/components";
6
+ import { Button, ButtonGroup, Input, Label, Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader, SheetTitle, } from "@voyant-travel/ui/components";
7
7
  import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyant-travel/ui/components/combobox";
8
8
  import { CountryCombobox } from "@voyant-travel/ui/components/country-combobox";
9
9
  import { PhoneInput } from "@voyant-travel/ui/components/phone-input";
@@ -259,7 +259,7 @@ export function BookingBillingDialog({ open, onOpenChange, booking, onSuccess, }
259
259
  onOpenChange(false);
260
260
  onSuccess?.();
261
261
  };
262
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: messages.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: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.partyType }), _jsxs(ButtonGroup, { children: [_jsxs(Button, { type: "button", variant: partyType === "individual" ? "secondary" : "outline", size: "sm", "aria-pressed": partyType === "individual", onClick: () => setPartyType("individual"), children: [_jsx(User, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }), messages.partyTypeLabels.individual] }), _jsxs(Button, { type: "button", variant: partyType === "company" ? "secondary" : "outline", size: "sm", "aria-pressed": partyType === "company", onClick: () => setPartyType("company"), children: [_jsx(Building2, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }), messages.partyTypeLabels.company] })] })] }), _jsxs("div", { className: "rounded-md border p-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(Label, { children: messages.crmPicker.label }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setCrmPickerOpen((current) => !current), children: [_jsx(Search, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }), crmPickerOpen ? messages.actions.hideCrmPicker : messages.actions.selectFromCrm] })] }), crmPickerOpen ? (_jsx("div", { className: "mt-3", children: partyType === "company" ? (_jsxs(Combobox, { items: organizations.map((organization) => organization.id), value: selectedOrganizationId, inputValue: organizationInputValue, autoHighlight: true, itemToStringLabel: (id) => organizationsMap.get(id)?.name ??
262
+ return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", size: "lg", children: [_jsx(SheetHeader, { children: _jsx(SheetTitle, { children: messages.title }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-1 flex-col overflow-hidden", children: [_jsxs(SheetBody, { className: "grid gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.partyType }), _jsxs(ButtonGroup, { children: [_jsxs(Button, { type: "button", variant: partyType === "individual" ? "secondary" : "outline", size: "sm", "aria-pressed": partyType === "individual", onClick: () => setPartyType("individual"), children: [_jsx(User, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }), messages.partyTypeLabels.individual] }), _jsxs(Button, { type: "button", variant: partyType === "company" ? "secondary" : "outline", size: "sm", "aria-pressed": partyType === "company", onClick: () => setPartyType("company"), children: [_jsx(Building2, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }), messages.partyTypeLabels.company] })] })] }), _jsxs("div", { className: "rounded-md border p-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(Label, { children: messages.crmPicker.label }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setCrmPickerOpen((current) => !current), children: [_jsx(Search, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }), crmPickerOpen ? messages.actions.hideCrmPicker : messages.actions.selectFromCrm] })] }), crmPickerOpen ? (_jsx("div", { className: "mt-3", children: partyType === "company" ? (_jsxs(Combobox, { items: organizations.map((organization) => organization.id), value: selectedOrganizationId, inputValue: organizationInputValue, autoHighlight: true, itemToStringLabel: (id) => organizationsMap.get(id)?.name ??
263
263
  cachedOrganizationsRef.current.get(id)?.name ??
264
264
  id, itemToStringValue: (id) => id, onInputValueChange: (next) => {
265
265
  setOrganizationInputValue(next);
@@ -297,10 +297,10 @@ export function BookingBillingDialog({ open, onOpenChange, booking, onSuccess, }
297
297
  return (_jsx(ComboboxItem, { value: person.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: formatPersonName(person) }), person.email ? (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: person.email })) : null] }) }, person.id));
298
298
  } }) })] })] })) })) : null] }), _jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: partyType === "company"
299
299
  ? messages.fields.companyName
300
- : messages.fields.firstName }), _jsx(Input, { ...form.register("contactFirstName") })] }), partyType === "company" ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.taxId }), _jsx(Input, { ...form.register("contactTaxId") })] })) : (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.lastName }), _jsx(Input, { ...form.register("contactLastName") })] }))] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.email }), _jsx(Input, { type: "email", ...form.register("contactEmail") }), form.formState.errors.contactEmail ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.contactEmail.message })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.phone }), _jsx(PhoneInput, { value: form.watch("contactPhone") ?? "", onChange: (next) => form.setValue("contactPhone", next, { shouldDirty: true }) })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.addressLine1 }), _jsx(Input, { ...form.register("contactAddressLine1") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.addressLine2 }), _jsx(Input, { ...form.register("contactAddressLine2") })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.city }), _jsx(Input, { ...form.register("contactCity") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.region }), _jsx(Input, { ...form.register("contactRegion") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.postalCode }), _jsx(Input, { ...form.register("contactPostalCode") })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.country }), _jsx(CountryCombobox, { value: form.watch("contactCountry") || null, onChange: (next) => form.setValue("contactCountry", next ?? "", {
300
+ : messages.fields.firstName }), _jsx(Input, { ...form.register("contactFirstName") })] }), partyType === "company" ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.taxId }), _jsx(Input, { ...form.register("contactTaxId") })] })) : (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.lastName }), _jsx(Input, { ...form.register("contactLastName") })] }))] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.email }), _jsx(Input, { type: "email", ...form.register("contactEmail") }), form.formState.errors.contactEmail ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.contactEmail.message })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.phone }), _jsx(PhoneInput, { value: form.watch("contactPhone") ?? "", onChange: (next) => form.setValue("contactPhone", next, { shouldDirty: true }) })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.addressLine1 }), _jsx(Input, { ...form.register("contactAddressLine1") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.addressLine2 }), _jsx(Input, { ...form.register("contactAddressLine2") })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.city }), _jsx(Input, { ...form.register("contactCity") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.region }), _jsx(Input, { ...form.register("contactRegion") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.postalCode }), _jsx(Input, { ...form.register("contactPostalCode") })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.fields.country }), _jsx(CountryCombobox, { value: form.watch("contactCountry") || null, onChange: (next) => form.setValue("contactCountry", next ?? "", {
301
301
  shouldDirty: true,
302
302
  shouldValidate: true,
303
- }) })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.actions.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: update.isPending, children: [update.isPending ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null, messages.actions.save] })] })] })] }) }));
303
+ }) })] })] }), _jsxs(SheetFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.actions.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: update.isPending, children: [update.isPending ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null, messages.actions.save] })] })] })] }) }));
304
304
  }
305
305
  function formatPersonName(person) {
306
306
  if (!person)
@@ -67,9 +67,9 @@ export function BookingCancellationDialog({ open, onOpenChange, booking, paidAmo
67
67
  const formatPercent = React.useCallback((basisPoints) => `${formatNumber(basisPoints / 100, {
68
68
  maximumFractionDigits: 0,
69
69
  })}%`, [formatNumber]);
70
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsxs(DialogTitle, { className: "flex items-center gap-2", children: [_jsx(AlertTriangle, { className: "h-4 w-4 text-destructive" }), messages.bookingCancellationDialog.title] }) }), _jsxs(DialogBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4 rounded-md border bg-muted/30 p-3 text-sm", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.booking }), _jsx("div", { className: "font-mono text-xs", children: booking.bookingNumber })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.startDate }), _jsx("div", { children: booking.startDate ?? messages.bookingCancellationDialog.values.startDateTbd })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.total }), _jsx("div", { className: "font-mono", children: total != null
70
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsxs(DialogTitle, { className: "flex items-center gap-2", children: [_jsx(AlertTriangle, { className: "h-4 w-4 text-destructive" }), messages.bookingCancellationDialog.title] }) }), _jsxs(DialogBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4 rounded-md border bg-muted/30 p-3 text-sm", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.booking }), _jsx("div", { className: "font-mono text-xs", children: booking.bookingNumber })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.startDate }), _jsx("div", { children: booking.startDate ?? messages.bookingCancellationDialog.values.startDateTbd })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.total }), _jsx("div", { className: "font-mono", children: total != null
71
71
  ? formatAmount(total, booking.sellCurrency)
72
- : messages.bookingCancellationDialog.values.amountUnavailable })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.daysBeforeDeparture }), _jsx("div", { children: daysBeforeDeparture })] })] }), resolveLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), messages.bookingCancellationDialog.policy.resolving] })) : !policy ? (_jsxs("div", { className: "rounded-md border border-dashed p-3 text-sm text-muted-foreground", children: [messages.bookingCancellationDialog.policy.missing, " ", messages.bookingCancellationDialog.policy.missingHint] })) : (_jsxs("div", { className: "space-y-2 rounded-md border p-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.applicablePolicy }), _jsx("div", { className: "text-sm font-medium", children: policy.policy.name })] }), evaluation && (_jsx(Badge, { variant: refundTypeVariant[evaluation.refundType] ?? "secondary", children: messages.bookingCancellationDialog.refundTypeLabels[evaluation.refundType] ?? evaluation.refundType }))] }), evaluationLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), messages.bookingCancellationDialog.policy.calculating] })) : evaluation && total != null ? (_jsxs("div", { className: "grid grid-cols-3 gap-3 border-t pt-3 text-sm", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.refund }), _jsx("div", { className: "font-mono font-medium", children: formatAmount(evaluation.refundCents, booking.sellCurrency) }), _jsxs("div", { className: "text-xs text-muted-foreground", children: ["(", formatPercent(evaluation.refundPercent), ")"] })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.penalty }), _jsx("div", { className: "font-mono font-medium text-destructive", children: formatAmount(penalty, booking.sellCurrency) })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.rule }), _jsx("div", { className: "text-xs", children: evaluation.appliedRule?.label ??
72
+ : messages.bookingCancellationDialog.values.amountUnavailable })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.summary.daysBeforeDeparture }), _jsx("div", { children: daysBeforeDeparture })] })] }), resolveLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), messages.bookingCancellationDialog.policy.resolving] })) : !policy ? (_jsxs("div", { className: "rounded-md border border-dashed p-3 text-sm text-muted-foreground", children: [messages.bookingCancellationDialog.policy.missing, " ", messages.bookingCancellationDialog.policy.missingHint] })) : (_jsxs("div", { className: "space-y-2 rounded-md border p-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.applicablePolicy }), _jsx("div", { className: "text-sm font-medium", children: policy.policy.name })] }), evaluation && (_jsx(Badge, { variant: refundTypeVariant[evaluation.refundType] ?? "secondary", children: messages.bookingCancellationDialog.refundTypeLabels[evaluation.refundType] ?? evaluation.refundType }))] }), evaluationLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), messages.bookingCancellationDialog.policy.calculating] })) : evaluation && total != null ? (_jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 border-t pt-3 text-sm", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.refund }), _jsx("div", { className: "font-mono font-medium", children: formatAmount(evaluation.refundCents, booking.sellCurrency) }), _jsxs("div", { className: "text-xs text-muted-foreground", children: ["(", formatPercent(evaluation.refundPercent), ")"] })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.penalty }), _jsx("div", { className: "font-mono font-medium text-destructive", children: formatAmount(penalty, booking.sellCurrency) })] }), _jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: messages.bookingCancellationDialog.policy.rule }), _jsx("div", { className: "text-xs", children: evaluation.appliedRule?.label ??
73
73
  (evaluation.appliedRule?.daysBeforeDeparture != null
74
74
  ? formatMessage(messages.bookingCancellationDialog.values.ruleDaysBeforeDeparture, {
75
75
  days: evaluation.appliedRule.daysBeforeDeparture,
@@ -7,5 +7,5 @@ import { BookingCreateForm } from "./booking-create-sheet.js";
7
7
  */
8
8
  export function BookingCreatePage({ onCreated, onCancel, defaultProductId, defaultSlotId, }) {
9
9
  const messages = useBookingsUiMessagesOrDefault();
10
- return (_jsxs("main", { className: "mx-auto flex w-full max-w-screen-2xl flex-col gap-6 px-4 py-6 sm:px-6 lg:px-8", children: [_jsxs("header", { className: "flex flex-col gap-1", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-normal", children: messages.bookingCreatePage.title }), _jsx("p", { className: "text-sm text-muted-foreground", children: messages.bookingCreatePage.description })] }), _jsx("section", { className: "flex flex-col gap-4", children: _jsx(BookingCreateForm, { onCreated: onCreated, onCancel: onCancel, defaultProductId: defaultProductId, defaultSlotId: defaultSlotId }) })] }));
10
+ return (_jsxs("main", { className: "mx-auto flex w-full max-w-screen-2xl flex-col gap-6", children: [_jsxs("header", { className: "flex flex-col gap-1", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-normal", children: messages.bookingCreatePage.title }), _jsx("p", { className: "text-sm text-muted-foreground", children: messages.bookingCreatePage.description })] }), _jsx("section", { className: "flex flex-col gap-4", children: _jsx(BookingCreateForm, { onCreated: onCreated, onCancel: onCancel, defaultProductId: defaultProductId, defaultSlotId: defaultSlotId }) })] }));
11
11
  }
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  import { useOrganization, usePerson } from "@voyant-travel/relationships-react";
5
- import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Card, CardContent, cn, } from "@voyant-travel/ui/components";
5
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Card, CardContent, CardHeader, CardTitle, cn, } from "@voyant-travel/ui/components";
6
6
  import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@voyant-travel/ui/components/collapsible";
7
7
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@voyant-travel/ui/components/tabs";
8
8
  import { Tooltip, TooltipContent, TooltipTrigger } from "@voyant-travel/ui/components/tooltip";
@@ -77,7 +77,7 @@ export function BookingDetailPage({ id, className, locale, hideBreadcrumb, onBac
77
77
  const headerDateRange = booking.startDate
78
78
  ? `${formatDate(booking.startDate, resolvedLocale, detailMessages.noValue)} - ${formatDate(booking.endDate, resolvedLocale, detailMessages.noValue)}`
79
79
  : null;
80
- const headerPax = booking.pax != null ? `${booking.pax} PAX` : null;
80
+ const headerPax = booking.pax != null ? `${booking.pax} ${messages.bookingQuickViewSheet.paxSuffix}` : null;
81
81
  const headerProductTitle = primaryItem?.productNameSnapshot ?? primaryItem?.title ?? null;
82
82
  const headerProductId = primaryItem?.productId ?? null;
83
83
  const headerSlotId = primaryItem?.availabilitySlotId ?? null;
@@ -87,13 +87,13 @@ export function BookingDetailPage({ id, className, locale, hideBreadcrumb, onBac
87
87
  headerDateRange ? (headerSlotId && onItemResourceOpen ? (_jsx("button", { type: "button", onClick: () => onItemResourceOpen("availabilitySlot", headerSlotId), className: "hover:text-foreground hover:underline", children: headerDateRange }, "dates")) : (_jsx("span", { children: headerDateRange }, "dates"))) : null,
88
88
  headerPax ? _jsx("span", { children: headerPax }, "pax") : null,
89
89
  ].filter(Boolean);
90
- return (_jsxs("div", { "data-slot": "booking-detail-page", className: cn("flex flex-col gap-6 p-6", className), children: [hideBreadcrumb ? null : (_jsxs("div", { className: "flex items-center gap-1.5 text-sm text-muted-foreground", children: [onBack ? (_jsx("button", { type: "button", onClick: onBack, className: "transition-colors hover:text-foreground", children: detailMessages.breadcrumbBookings })) : (_jsx("span", { children: detailMessages.breadcrumbBookings })), _jsx(ChevronRight, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), _jsx("span", { className: "font-normal text-foreground", children: booking.bookingNumber })] })), _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: booking.bookingNumber }), _jsx(StatusBadge, { status: booking.status, children: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels) })] }), headerSubtitleParts.length > 0 ? (_jsx("div", { className: "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground", children: headerSubtitleParts.map((part, idx) => (_jsxs(Fragment, { children: [idx > 0 ? _jsx("span", { className: "text-muted-foreground/60", children: "/" }) : null, part] }, idx))) })) : null] }), isCancelled ? null : (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setEditOpen(true), children: [_jsx(Pencil, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.editAction] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setStatusDialogOpen(true), children: [_jsx(RefreshCw, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.changeStatusAction] }), canCancel ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setCancelDialogOpen(true), children: [_jsx(Ban, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.cancelBookingAction] })) : null, _jsxs(Button, { variant: "outline", size: "sm", className: "text-destructive hover:bg-destructive/10 hover:text-destructive", disabled: remove.isPending, onClick: () => setDeleteDialogOpen(true), children: [_jsx(Trash2, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.deleteAction] })] }))] }), slots?.header?.(booking), _jsxs("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-4", children: [_jsx(StatCard, { label: detailMessages.summaryTotal, hint: sellHint, children: formatAmount(booking.sellAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryPaid, badge: paidAmountCents != null && booking.sellAmountCents
90
+ return (_jsxs("div", { "data-slot": "booking-detail-page", className: cn("flex flex-col gap-6", className), children: [hideBreadcrumb ? null : (_jsxs("div", { className: "flex items-center gap-1.5 text-sm text-muted-foreground", children: [onBack ? (_jsx("button", { type: "button", onClick: onBack, className: "transition-colors hover:text-foreground", children: detailMessages.breadcrumbBookings })) : (_jsx("span", { children: detailMessages.breadcrumbBookings })), _jsx(ChevronRight, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), _jsx("span", { className: "font-normal text-foreground", children: booking.bookingNumber })] })), _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: booking.bookingNumber }), _jsx(StatusBadge, { status: booking.status, children: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels) })] }), headerSubtitleParts.length > 0 ? (_jsx("div", { className: "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground", children: headerSubtitleParts.map((part, idx) => (_jsxs(Fragment, { children: [idx > 0 ? _jsx("span", { className: "text-muted-foreground/60", children: "/" }) : null, part] }, idx))) })) : null] }), isCancelled ? null : (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setEditOpen(true), children: [_jsx(Pencil, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.editAction] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setStatusDialogOpen(true), children: [_jsx(RefreshCw, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.changeStatusAction] }), canCancel ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setCancelDialogOpen(true), children: [_jsx(Ban, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.cancelBookingAction] })) : null, _jsxs(Button, { variant: "outline", size: "sm", className: "text-destructive hover:bg-destructive/10 hover:text-destructive", disabled: remove.isPending, onClick: () => setDeleteDialogOpen(true), children: [_jsx(Trash2, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.deleteAction] })] }))] }), slots?.header?.(booking), _jsxs("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-4", children: [_jsx(StatCard, { label: detailMessages.summaryTotal, hint: sellHint, children: formatAmount(booking.sellAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryPaid, badge: paidAmountCents != null && booking.sellAmountCents
91
91
  ? renderPercentBadge(Math.round((paidAmountCents / booking.sellAmountCents) * 100), paidBadgeClass)
92
92
  : null, children: paidAmountCents != null
93
93
  ? formatAmount(paidAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue)
94
94
  : detailMessages.noValue }), _jsx(StatCard, { label: detailMessages.summaryCostMargin, badge: booking.marginPercent != null
95
95
  ? renderPercentBadge(booking.marginPercent, marginBadgeClass)
96
- : null, children: formatAmount(booking.costAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryCreated, children: formatDate(booking.createdAt, resolvedLocale, detailMessages.noValue) })] }), slots?.afterSummary?.(booking), _jsxs(Tabs, { defaultValue: "items", value: activeTab, onValueChange: (value) => onTabChange?.(String(value)), children: [_jsxs(TabsList, { className: "w-full justify-start", children: [_jsx(TabsTrigger, { value: "items", children: detailMessages.tabOverview }), _jsx(TabsTrigger, { value: "travelers", children: detailMessages.tabTravelers }), _jsx(TabsTrigger, { value: "finance", children: detailMessages.tabFinance }), slots?.invoicesTab ? (_jsx(TabsTrigger, { value: "invoices", children: slots.invoicesTab.label ?? detailMessages.tabInvoices })) : null, _jsx(TabsTrigger, { value: "documents", children: detailMessages.tabDocuments }), _jsx(TabsTrigger, { value: "suppliers", children: detailMessages.tabSuppliers }), _jsx(TabsTrigger, { value: "activity", children: detailMessages.tabActivity }), _jsx(TabsTrigger, { value: "metadata", children: detailMessages.tabMetadata })] }), _jsxs(TabsContent, { value: "items", className: "mt-4 flex flex-col gap-6", children: [slots?.overviewStart?.(booking), _jsx(BookingItemList, { bookingId: id, onResourceOpen: onItemResourceOpen, readOnly: isCancelled }), _jsx(BookingGroupSection, { bookingId: id }), visibleInternalNotes(booking.internalNotes) ? (_jsx(Card, { children: _jsxs(CardContent, { className: "py-5", children: [_jsx("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: detailMessages.internalNotesLabel }), _jsx("p", { className: "whitespace-pre-wrap text-sm", children: visibleInternalNotes(booking.internalNotes) })] }) })) : null, slots?.overviewEnd?.(booking)] }), _jsxs(TabsContent, { value: "travelers", className: "mt-4 flex flex-col gap-6", children: [slots?.travelersStart?.(booking), _jsx(BookingBillingContextCard, { booking: booking, onPersonOpen: onPersonOpen, onOrganizationOpen: onOrganizationOpen }), _jsx(TravelerList, { bookingId: id, autoReveal: true })] }), _jsxs(TabsContent, { value: "finance", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingPaymentScheduleList, { bookingId: id, addScheduleDisabledReason: addScheduleDisabledReason ?? null }), slots?.paymentsContent ? (renderDetailSlot(slots.paymentsContent, booking)) : (_jsx(BookingPaymentsSummary, { bookingId: id, variant: "admin", onViewPayment: onViewPayment, onInvoiceOpen: onInvoiceOpen, onEditPayment: onEditPayment, onDeletePayment: onDeletePayment, headerAction: onRecordPayment ? (_jsx(RecordPaymentHeaderButton, { label: detailMessages.recordPaymentAction, disabledReason: recordPaymentDisabledReason ?? null, onClick: () => onRecordPayment(booking) })) : null })), slots?.financeStart?.(booking), _jsxs(Collapsible, { children: [_jsxs(CollapsibleTrigger, { className: "group flex w-full items-center justify-between rounded-md border bg-background px-4 py-3 text-sm font-semibold hover:bg-muted/30", children: [messages.bookingGuaranteeList.title, _jsx(ChevronDown, { className: "h-4 w-4 transition-transform group-data-panel-open:rotate-180" })] }), _jsx(CollapsibleContent, { className: "mt-3", children: _jsx(BookingGuaranteeList, { bookingId: id }) })] }), slots?.financeEnd?.(booking)] }), slots?.invoicesTab ? (_jsx(TabsContent, { value: "invoices", className: "mt-4 flex flex-col gap-6", children: renderDetailSlot(slots.invoicesTab.content, booking) })) : null, _jsx(TabsContent, { value: "documents", className: "mt-4 flex flex-col gap-4", children: slots?.documents ? (slots.documents(booking)) : (_jsx("p", { className: "rounded-md border border-dashed p-4 text-sm text-muted-foreground", children: detailMessages.documentsSlotEmpty })) }), _jsx(TabsContent, { value: "suppliers", className: "mt-4", children: _jsx(SupplierStatusList, { bookingId: id }) }), _jsxs(TabsContent, { value: "activity", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingNotes, { bookingId: id }), _jsx(BookingActivityTimeline, { bookingId: id, paymentsVariant: "admin", additionalEvents: slots?.activityExtraEvents, footer: slots?.activityTimelineFooter }), slots?.activityEnd?.(booking)] }), _jsx(TabsContent, { value: "metadata", className: "mt-4", children: _jsx(BookingMetadataList, { booking: booking, messages: detailMessages.metadataSection, statusLabel: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels), formatDateTime: i18n.formatDateTime, noValue: detailMessages.noValue }) })] }), _jsx(BookingDialog, { open: editOpen, onOpenChange: setEditOpen, booking: booking }), _jsx(StatusChangeDialog, { open: statusDialogOpen, onOpenChange: setStatusDialogOpen, bookingId: id, currentStatus: booking.status }), _jsx(BookingCancellationDialog, { open: cancelDialogOpen, onOpenChange: setCancelDialogOpen, booking: booking, paidAmountCents: paidAmountCents, hasRecordedPayment: hasRecordedPayment }), _jsx(AlertDialog, { open: deleteDialogOpen, onOpenChange: (next) => {
96
+ : null, children: formatAmount(booking.costAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryCreated, children: formatDate(booking.createdAt, resolvedLocale, detailMessages.noValue) })] }), slots?.afterSummary?.(booking), _jsxs(Tabs, { defaultValue: "items", value: activeTab, onValueChange: (value) => onTabChange?.(String(value)), children: [_jsxs(TabsList, { className: "w-full justify-start", children: [_jsx(TabsTrigger, { value: "items", children: detailMessages.tabOverview }), _jsx(TabsTrigger, { value: "travelers", children: detailMessages.tabTravelers }), _jsx(TabsTrigger, { value: "finance", children: detailMessages.tabFinance }), slots?.invoicesTab ? (_jsx(TabsTrigger, { value: "invoices", children: slots.invoicesTab.label ?? detailMessages.tabInvoices })) : null, _jsx(TabsTrigger, { value: "documents", children: detailMessages.tabDocuments }), _jsx(TabsTrigger, { value: "suppliers", children: detailMessages.tabSuppliers }), _jsx(TabsTrigger, { value: "activity", children: detailMessages.tabActivity }), _jsx(TabsTrigger, { value: "metadata", children: detailMessages.tabMetadata })] }), _jsxs(TabsContent, { value: "items", className: "mt-4 flex flex-col gap-6", children: [slots?.overviewStart?.(booking), _jsx(BookingItemList, { bookingId: id, onResourceOpen: onItemResourceOpen, readOnly: isCancelled }), _jsx(BookingGroupSection, { bookingId: id }), visibleInternalNotes(booking.internalNotes) ? (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: detailMessages.internalNotesLabel }) }), _jsx(CardContent, { children: _jsx("p", { className: "whitespace-pre-wrap text-sm", children: visibleInternalNotes(booking.internalNotes) }) })] })) : null, slots?.overviewEnd?.(booking)] }), _jsxs(TabsContent, { value: "travelers", className: "mt-4 flex flex-col gap-6", children: [slots?.travelersStart?.(booking), _jsx(BookingBillingContextCard, { booking: booking, onPersonOpen: onPersonOpen, onOrganizationOpen: onOrganizationOpen }), _jsx(TravelerList, { bookingId: id, autoReveal: true })] }), _jsxs(TabsContent, { value: "finance", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingPaymentScheduleList, { bookingId: id, addScheduleDisabledReason: addScheduleDisabledReason ?? null }), slots?.paymentsContent ? (renderDetailSlot(slots.paymentsContent, booking)) : (_jsx(BookingPaymentsSummary, { bookingId: id, variant: "admin", onViewPayment: onViewPayment, onInvoiceOpen: onInvoiceOpen, onEditPayment: onEditPayment, onDeletePayment: onDeletePayment, headerAction: onRecordPayment ? (_jsx(RecordPaymentHeaderButton, { label: detailMessages.recordPaymentAction, disabledReason: recordPaymentDisabledReason ?? null, onClick: () => onRecordPayment(booking) })) : null })), slots?.financeStart?.(booking), _jsxs(Collapsible, { children: [_jsxs(CollapsibleTrigger, { className: "group flex w-full items-center justify-between rounded-md border bg-background px-4 py-3 text-sm font-semibold hover:bg-muted/30", children: [messages.bookingGuaranteeList.title, _jsx(ChevronDown, { className: "h-4 w-4 transition-transform group-data-panel-open:rotate-180" })] }), _jsx(CollapsibleContent, { className: "mt-3", children: _jsx(BookingGuaranteeList, { bookingId: id }) })] }), slots?.financeEnd?.(booking)] }), slots?.invoicesTab ? (_jsx(TabsContent, { value: "invoices", className: "mt-4 flex flex-col gap-6", children: renderDetailSlot(slots.invoicesTab.content, booking) })) : null, _jsx(TabsContent, { value: "documents", className: "mt-4 flex flex-col gap-4", children: slots?.documents ? (slots.documents(booking)) : (_jsx("p", { className: "rounded-md border border-dashed p-4 text-sm text-muted-foreground", children: detailMessages.documentsSlotEmpty })) }), _jsx(TabsContent, { value: "suppliers", className: "mt-4", children: _jsx(SupplierStatusList, { bookingId: id }) }), _jsxs(TabsContent, { value: "activity", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingNotes, { bookingId: id }), _jsx(BookingActivityTimeline, { bookingId: id, paymentsVariant: "admin", additionalEvents: slots?.activityExtraEvents, footer: slots?.activityTimelineFooter }), slots?.activityEnd?.(booking)] }), _jsx(TabsContent, { value: "metadata", className: "mt-4", children: _jsx(BookingMetadataList, { booking: booking, messages: detailMessages.metadataSection, statusLabel: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels), formatDateTime: i18n.formatDateTime, noValue: detailMessages.noValue }) })] }), _jsx(BookingDialog, { open: editOpen, onOpenChange: setEditOpen, booking: booking }), _jsx(StatusChangeDialog, { open: statusDialogOpen, onOpenChange: setStatusDialogOpen, bookingId: id, currentStatus: booking.status }), _jsx(BookingCancellationDialog, { open: cancelDialogOpen, onOpenChange: setCancelDialogOpen, booking: booking, paidAmountCents: paidAmountCents, hasRecordedPayment: hasRecordedPayment }), _jsx(AlertDialog, { open: deleteDialogOpen, onOpenChange: (next) => {
97
97
  if (!next && !remove.isPending)
98
98
  setDeleteDialogOpen(false);
99
99
  }, children: _jsxs(AlertDialogContent, { size: "sm", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: detailMessages.deleteConfirm }), _jsx(AlertDialogDescription, { children: booking.bookingNumber
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea, } from "@voyant-travel/ui/components";
3
+ import { Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader, SheetTitle, Textarea, } from "@voyant-travel/ui/components";
4
4
  import { CurrencyCombobox } from "@voyant-travel/ui/components/currency-combobox";
5
5
  import { CurrencyInput } from "@voyant-travel/ui/components/currency-input";
6
6
  import { DateRangePicker } from "@voyant-travel/ui/components/date-picker";
@@ -100,7 +100,7 @@ function BookingEditDialog({ open, onOpenChange, booking, onSuccess }) {
100
100
  onSuccess?.(saved);
101
101
  };
102
102
  const isSubmitting = update.isPending;
103
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: messages.bookingDialog.editTitle }) }), _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.bookingDialog.fields.bookingNumber }), _jsx(Input, { ...form.register("bookingNumber"), placeholder: messages.bookingDialog.placeholders.bookingNumber }), form.formState.errors.bookingNumber && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.bookingNumber.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.status }), _jsxs(Select, { value: form.watch("status"), onValueChange: (value) => form.setValue("status", value), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: BOOKING_STATUS_VALUES.map((status) => (_jsx(SelectItem, { value: status, children: messages.common.bookingStatusLabels[status] }, status))) })] })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.sellCurrency }), _jsx(CurrencyCombobox, { value: form.watch("sellCurrency") || null, onChange: (next) => form.setValue("sellCurrency", next ?? DEFAULT_CURRENCY, {
103
+ return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", size: "lg", children: [_jsx(SheetHeader, { children: _jsx(SheetTitle, { children: messages.bookingDialog.editTitle }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-1 flex-col overflow-hidden", children: [_jsxs(SheetBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.bookingNumber }), _jsx(Input, { ...form.register("bookingNumber"), placeholder: messages.bookingDialog.placeholders.bookingNumber }), form.formState.errors.bookingNumber && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.bookingNumber.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.status }), _jsxs(Select, { value: form.watch("status"), onValueChange: (value) => form.setValue("status", value), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: BOOKING_STATUS_VALUES.map((status) => (_jsx(SelectItem, { value: status, children: messages.common.bookingStatusLabels[status] }, status))) })] })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.sellCurrency }), _jsx(CurrencyCombobox, { value: form.watch("sellCurrency") || null, onChange: (next) => form.setValue("sellCurrency", next ?? DEFAULT_CURRENCY, {
104
104
  shouldValidate: true,
105
105
  shouldDirty: true,
106
106
  }) })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.travelDates }), _jsx(DateRangePicker, { value: {
@@ -109,5 +109,5 @@ function BookingEditDialog({ open, onOpenChange, booking, onSuccess }) {
109
109
  }, onChange: (nextValue) => {
110
110
  form.setValue("startDate", nextValue?.from ?? "", { shouldDirty: true });
111
111
  form.setValue("endDate", nextValue?.to ?? "", { shouldDirty: true });
112
- }, placeholder: messages.bookingDialog.placeholders.travelDates, className: "w-full" })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.sellAmountCents }), _jsx(CurrencyInput, { value: booking.sellAmountCents, onChange: noopCurrencyChange, currency: form.watch("sellCurrency"), disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.costAmountCents }), _jsx(CurrencyInput, { value: booking.costAmountCents, onChange: noopCurrencyChange, currency: form.watch("sellCurrency"), disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.pax }), _jsx(Input, { ...form.register("pax"), type: "number", min: "1", placeholder: messages.bookingDialog.placeholders.pax })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.internalNotes }), _jsx(Textarea, { ...form.register("internalNotes"), placeholder: messages.bookingDialog.placeholders.internalNotes })] })] }), _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: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), messages.common.saveChanges] })] })] })] }) }));
112
+ }, placeholder: messages.bookingDialog.placeholders.travelDates, className: "w-full" })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.sellAmountCents }), _jsx(CurrencyInput, { value: booking.sellAmountCents, onChange: noopCurrencyChange, currency: form.watch("sellCurrency"), disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.costAmountCents }), _jsx(CurrencyInput, { value: booking.costAmountCents, onChange: noopCurrencyChange, currency: form.watch("sellCurrency"), disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.pax }), _jsx(Input, { ...form.register("pax"), type: "number", min: "1", placeholder: messages.bookingDialog.placeholders.pax })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.internalNotes }), _jsx(Textarea, { ...form.register("internalNotes"), placeholder: messages.bookingDialog.placeholders.internalNotes })] })] }), _jsxs(SheetFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), messages.common.saveChanges] })] })] })] }) }));
113
113
  }
@@ -78,7 +78,7 @@ export function BookingDocumentDialog({ open, onOpenChange, bookingId, onSuccess
78
78
  };
79
79
  const uploadedFileUrl = form.watch("fileUrl");
80
80
  const canSubmit = Boolean(uploadedFileUrl) && !create.isPending;
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) => {
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-1 sm: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) => {
82
82
  form.setValue("fileUrl", upload.url, { shouldValidate: true });
83
83
  form.setValue("fileName", upload.name, { shouldValidate: true });
84
84
  }, onCleared: () => {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Badge, Button, Card, CardContent, CardHeader, CardTitle, } from "@voyant-travel/ui/components";
3
+ import { Badge, Button, Card, CardContent, CardHeader, CardTitle, confirmDialog, } from "@voyant-travel/ui/components";
4
4
  import { ExternalLink, FileText, Plus, Trash2 } from "lucide-react";
5
5
  import * as React from "react";
6
6
  import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
@@ -34,8 +34,11 @@ export function BookingDocumentList({ bookingId }) {
34
34
  ? doc.travelerId
35
35
  : messages.bookingDocumentList.values.travelerUnavailable }), _jsx("td", { className: "p-2", children: doc.expiresAt
36
36
  ? formatDate(doc.expiresAt)
37
- : messages.bookingDocumentList.values.expiresUnavailable }), _jsx("td", { className: "max-w-[200px] truncate p-2 text-muted-foreground", children: doc.notes ?? messages.bookingDocumentList.values.notesUnavailable }), _jsx("td", { className: "p-2", children: _jsx("button", { type: "button", onClick: () => {
38
- if (confirm(messages.bookingDocumentList.actions.deleteConfirm)) {
37
+ : messages.bookingDocumentList.values.expiresUnavailable }), _jsx("td", { className: "max-w-[200px] truncate p-2 text-muted-foreground", children: doc.notes ?? messages.bookingDocumentList.values.notesUnavailable }), _jsx("td", { className: "p-2", children: _jsx("button", { type: "button", onClick: async () => {
38
+ if (await confirmDialog({
39
+ description: messages.bookingDocumentList.actions.deleteConfirm,
40
+ destructive: true,
41
+ })) {
39
42
  remove.mutate(doc.id);
40
43
  }
41
44
  }, className: "text-muted-foreground hover:text-destructive", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) })] }, doc.id));
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Badge, Button, Card, CardContent, CardHeader, CardTitle, } from "@voyant-travel/ui/components";
3
+ import { Badge, Button, Card, CardContent, CardHeader, CardTitle, confirmDialog, } from "@voyant-travel/ui/components";
4
4
  import { Link2, Unlink, Users } from "lucide-react";
5
5
  import * as React from "react";
6
6
  import { formatMessage, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
@@ -38,7 +38,10 @@ export function BookingGroupSection({ bookingId, productId, optionUnitId, hideWi
38
38
  const handleRemove = async () => {
39
39
  if (!groupId)
40
40
  return;
41
- if (!confirm(messages.bookingGroupSection.actions.removeConfirm))
41
+ if (!(await confirmDialog({
42
+ description: messages.bookingGroupSection.actions.removeConfirm,
43
+ destructive: true,
44
+ })))
42
45
  return;
43
46
  await removeMember.mutateAsync({ groupId, bookingId });
44
47
  };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useBookingGuaranteeMutation, } from "@voyant-travel/finance-react";
4
- import { Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea, } from "@voyant-travel/ui/components";
4
+ import { Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader, SheetTitle, Textarea, } from "@voyant-travel/ui/components";
5
5
  import { CurrencyCombobox } from "@voyant-travel/ui/components/currency-combobox";
6
6
  import { CurrencyInput } from "@voyant-travel/ui/components/currency-input";
7
7
  import { DateTimePicker } from "@voyant-travel/ui/components/date-time-picker";
@@ -106,18 +106,18 @@ export function BookingGuaranteeDialog({ open, onOpenChange, bookingId, guarante
106
106
  onSuccess?.();
107
107
  };
108
108
  const isSubmitting = create.isPending || update.isPending;
109
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing
109
+ return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", size: "lg", children: [_jsx(SheetHeader, { children: _jsx(SheetTitle, { children: isEditing
110
110
  ? messages.bookingGuaranteeDialog.titles.edit
111
- : messages.bookingGuaranteeDialog.titles.create }) }), _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.bookingGuaranteeDialog.fields.type }), _jsxs(Select, { items: typeItems, value: form.watch("guaranteeType"), onValueChange: (v) => form.setValue("guaranteeType", (v ?? "deposit")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: guaranteeTypes.map((t) => (_jsx(SelectItem, { value: t, children: messages.bookingGuaranteeDialog.guaranteeTypeLabels[t] }, t))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (v) => form.setValue("status", (v ?? "pending")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: guaranteeStatuses.map((s) => (_jsx(SelectItem, { value: s, children: messages.bookingGuaranteeDialog.guaranteeStatusLabels[s] }, s))) })] })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.currency }), _jsx(CurrencyCombobox, { value: form.watch("currency") || null, onChange: (next) => form.setValue("currency", next ?? DEFAULT_CURRENCY, {
111
+ : messages.bookingGuaranteeDialog.titles.create }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-1 flex-col overflow-hidden", children: [_jsxs(SheetBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.type }), _jsxs(Select, { items: typeItems, value: form.watch("guaranteeType"), onValueChange: (v) => form.setValue("guaranteeType", (v ?? "deposit")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: guaranteeTypes.map((t) => (_jsx(SelectItem, { value: t, children: messages.bookingGuaranteeDialog.guaranteeTypeLabels[t] }, t))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (v) => form.setValue("status", (v ?? "pending")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: guaranteeStatuses.map((s) => (_jsx(SelectItem, { value: s, children: messages.bookingGuaranteeDialog.guaranteeStatusLabels[s] }, s))) })] })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.currency }), _jsx(CurrencyCombobox, { value: form.watch("currency") || null, onChange: (next) => form.setValue("currency", next ?? DEFAULT_CURRENCY, {
112
112
  shouldValidate: true,
113
113
  shouldDirty: true,
114
114
  }) })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.amountCents }), _jsx(CurrencyInput, { value: form.watch("amountCents"), onChange: (next) => form.setValue("amountCents", next, {
115
115
  shouldDirty: true,
116
116
  shouldValidate: true,
117
- }), currency: form.watch("currency") })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.provider }), _jsx(Input, { ...form.register("provider"), placeholder: messages.bookingGuaranteeDialog.placeholders.provider })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.referenceNumber }), _jsx(Input, { ...form.register("referenceNumber"), placeholder: messages.bookingGuaranteeDialog.placeholders.referenceNumber })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.expiresAt }), _jsx(DateTimePicker, { value: form.watch("expiresAt") || null, onChange: (next) => form.setValue("expiresAt", next ?? "", {
117
+ }), currency: form.watch("currency") })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.provider }), _jsx(Input, { ...form.register("provider"), placeholder: messages.bookingGuaranteeDialog.placeholders.provider })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.referenceNumber }), _jsx(Input, { ...form.register("referenceNumber"), placeholder: messages.bookingGuaranteeDialog.placeholders.referenceNumber })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.expiresAt }), _jsx(DateTimePicker, { value: form.watch("expiresAt") || null, onChange: (next) => form.setValue("expiresAt", next ?? "", {
118
118
  shouldValidate: true,
119
119
  shouldDirty: true,
120
- }), placeholder: messages.bookingGuaranteeDialog.placeholders.expiresAt, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: messages.bookingGuaranteeDialog.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: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), isEditing
120
+ }), placeholder: messages.bookingGuaranteeDialog.placeholders.expiresAt, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingGuaranteeDialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: messages.bookingGuaranteeDialog.placeholders.notes })] })] }), _jsxs(SheetFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), isEditing
121
121
  ? messages.common.saveChanges
122
122
  : messages.bookingGuaranteeDialog.actions.addGuarantee] })] })] })] }) }));
123
123
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea, } from "@voyant-travel/ui/components";
3
+ import { Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader, SheetTitle, Textarea, } from "@voyant-travel/ui/components";
4
4
  import { CurrencyCombobox } from "@voyant-travel/ui/components/currency-combobox";
5
5
  import { CurrencyInput } from "@voyant-travel/ui/components/currency-input";
6
6
  import { DatePicker } from "@voyant-travel/ui/components/date-picker";
@@ -139,9 +139,9 @@ export function BookingItemDialog({ open, onOpenChange, bookingId, item, onSucce
139
139
  onSuccess?.();
140
140
  };
141
141
  const isSubmitting = create.isPending || update.isPending;
142
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing
142
+ return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", size: "lg", children: [_jsx(SheetHeader, { children: _jsx(SheetTitle, { children: isEditing
143
143
  ? messages.bookingItemDialog.titles.edit
144
- : messages.bookingItemDialog.titles.create }) }), _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: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.title }), _jsx(Input, { ...form.register("title"), placeholder: messages.bookingItemDialog.placeholders.title }), form.formState.errors.title && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.title.message }))] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.type }), _jsxs(Select, { items: typeItems, value: form.watch("itemType"), onValueChange: (v) => form.setValue("itemType", v), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: itemTypes.map((t) => (_jsx(SelectItem, { value: t, children: messages.bookingItemDialog.itemTypeLabels[t] }, t))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (v) => form.setValue("status", v), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: itemStatuses.map((s) => (_jsx(SelectItem, { value: s, children: messages.bookingItemDialog.itemStatusLabels[s] }, s))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.quantity }), _jsx(Input, { ...form.register("quantity"), type: "number", min: 1 })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.sellCurrency }), _jsx(CurrencyCombobox, { value: form.watch("sellCurrency") || null, onChange: (next) => form.setValue("sellCurrency", next ?? DEFAULT_CURRENCY, {
144
+ : messages.bookingItemDialog.titles.create }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-1 flex-col overflow-hidden", children: [_jsxs(SheetBody, { className: "grid gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.title }), _jsx(Input, { ...form.register("title"), placeholder: messages.bookingItemDialog.placeholders.title }), form.formState.errors.title && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.title.message }))] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.type }), _jsxs(Select, { items: typeItems, value: form.watch("itemType"), onValueChange: (v) => form.setValue("itemType", v), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: itemTypes.map((t) => (_jsx(SelectItem, { value: t, children: messages.bookingItemDialog.itemTypeLabels[t] }, t))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (v) => form.setValue("status", v), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: itemStatuses.map((s) => (_jsx(SelectItem, { value: s, children: messages.bookingItemDialog.itemStatusLabels[s] }, s))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.quantity }), _jsx(Input, { ...form.register("quantity"), type: "number", min: 1 })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.sellCurrency }), _jsx(CurrencyCombobox, { value: form.watch("sellCurrency") || null, onChange: (next) => form.setValue("sellCurrency", next ?? DEFAULT_CURRENCY, {
145
145
  shouldValidate: true,
146
146
  shouldDirty: true,
147
147
  }) })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.unitSellAmountCents }), _jsx(CurrencyInput, { value: form.watch("unitSellAmountCents"), onChange: (next) => form.setValue("unitSellAmountCents", next, {
@@ -150,7 +150,7 @@ export function BookingItemDialog({ open, onOpenChange, bookingId, item, onSucce
150
150
  }), currency: form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.unitSellAmountCents })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.totalSellAmountCents }), _jsx(CurrencyInput, { value: form.watch("totalSellAmountCents"), onChange: (next) => form.setValue("totalSellAmountCents", next, {
151
151
  shouldDirty: true,
152
152
  shouldValidate: true,
153
- }), currency: form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.totalSellAmountCents })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.costCurrency }), _jsx(CurrencyCombobox, { value: form.watch("costCurrency") || null, onChange: (next) => form.setValue("costCurrency", next ?? null, {
153
+ }), currency: form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.totalSellAmountCents })] })] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.costCurrency }), _jsx(CurrencyCombobox, { value: form.watch("costCurrency") || null, onChange: (next) => form.setValue("costCurrency", next ?? null, {
154
154
  shouldValidate: true,
155
155
  shouldDirty: true,
156
156
  }) }), form.formState.errors.costCurrency && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.costCurrency.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.unitCostAmountCents }), _jsx(CurrencyInput, { value: form.watch("unitCostAmountCents"), onChange: (next) => form.setValue("unitCostAmountCents", next, {
@@ -162,5 +162,5 @@ export function BookingItemDialog({ open, onOpenChange, bookingId, item, onSucce
162
162
  }), currency: form.watch("costCurrency"), placeholder: messages.bookingItemDialog.placeholders.totalCostAmountCents })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.serviceDate }), _jsx(DatePicker, { value: form.watch("serviceDate") || null, onChange: (next) => form.setValue("serviceDate", next ?? "", {
163
163
  shouldValidate: true,
164
164
  shouldDirty: true,
165
- }), placeholder: messages.bookingItemDialog.placeholders.serviceDate, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.description }), _jsx(Textarea, { ...form.register("description"), placeholder: messages.bookingItemDialog.placeholders.description })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: messages.bookingItemDialog.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: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), isEditing ? messages.common.saveChanges : messages.bookingItemDialog.actions.addItem] })] })] })] }) }));
165
+ }), placeholder: messages.bookingItemDialog.placeholders.serviceDate, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.description }), _jsx(Textarea, { ...form.register("description"), placeholder: messages.bookingItemDialog.placeholders.description })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: messages.bookingItemDialog.placeholders.notes })] })] }), _jsxs(SheetFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), isEditing ? messages.common.saveChanges : messages.bookingItemDialog.actions.addItem] })] })] })] }) }));
166
166
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Badge, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyant-travel/ui/components";
3
+ import { Badge, Button, confirmDialog, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyant-travel/ui/components";
4
4
  import { Plus, Trash2, UserCheck } from "lucide-react";
5
5
  import * as React from "react";
6
6
  import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
@@ -48,8 +48,11 @@ export function BookingItemTravelers({ bookingId, itemId }) {
48
48
  };
49
49
  return (_jsxs("div", { className: "space-y-3 rounded-md border bg-muted/30 p-3", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs font-medium text-muted-foreground", children: [_jsx(UserCheck, { className: "h-3.5 w-3.5" }), messages.bookingItemTravelers.title] }), assignedTravelers.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground", children: messages.bookingItemTravelers.empty })) : (_jsx("div", { className: "space-y-1", children: assignedTravelers.map((link) => {
50
50
  const traveler = travelerMap.get(link.travelerId);
51
- return (_jsxs("div", { className: "flex items-center justify-between rounded px-2 py-1 text-sm", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { children: traveler ? `${traveler.firstName} ${traveler.lastName}` : link.travelerId }), _jsx(Badge, { variant: "outline", className: "text-xs", children: messages.bookingItemTravelers.roleLabels[link.role] }), link.isPrimary && (_jsx(Badge, { variant: "default", className: "text-xs", children: messages.bookingItemTravelers.primaryBadge }))] }), _jsx("button", { type: "button", onClick: () => {
52
- if (confirm(messages.bookingItemTravelers.actions.removeConfirm)) {
51
+ return (_jsxs("div", { className: "flex items-center justify-between rounded px-2 py-1 text-sm", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { children: traveler ? `${traveler.firstName} ${traveler.lastName}` : link.travelerId }), _jsx(Badge, { variant: "outline", className: "text-xs", children: messages.bookingItemTravelers.roleLabels[link.role] }), link.isPrimary && (_jsx(Badge, { variant: "default", className: "text-xs", children: messages.bookingItemTravelers.primaryBadge }))] }), _jsx("button", { type: "button", onClick: async () => {
52
+ if (await confirmDialog({
53
+ description: messages.bookingItemTravelers.actions.removeConfirm,
54
+ destructive: true,
55
+ })) {
53
56
  remove.mutate(link.id);
54
57
  }
55
58
  }, className: "text-muted-foreground hover:text-destructive", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] }, link.id));
@@ -102,10 +102,10 @@ export function BookingPaymentScheduleDialog({ open, onOpenChange, bookingId, sc
102
102
  const isSubmitting = create.isPending || update.isPending;
103
103
  return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing
104
104
  ? messages.paymentScheduleDialog.titles.edit
105
- : messages.paymentScheduleDialog.titles.create }) }), _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.paymentScheduleDialog.fields.type }), _jsxs(Select, { items: typeItems, value: form.watch("scheduleType"), onValueChange: (v) => form.setValue("scheduleType", (v ?? "balance")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: scheduleTypes.map((t) => (_jsx(SelectItem, { value: t, children: messages.paymentScheduleDialog.scheduleTypeLabels[t] }, t))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (v) => form.setValue("status", (v ?? "pending")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: scheduleStatuses.map((s) => (_jsx(SelectItem, { value: s, children: messages.paymentScheduleDialog.scheduleStatusLabels[s] }, s))) })] })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.dueDate }), _jsx(DatePicker, { value: form.watch("dueDate") || null, onChange: (next) => form.setValue("dueDate", next ?? "", {
105
+ : messages.paymentScheduleDialog.titles.create }) }), _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-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.type }), _jsxs(Select, { items: typeItems, value: form.watch("scheduleType"), onValueChange: (v) => form.setValue("scheduleType", (v ?? "balance")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: scheduleTypes.map((t) => (_jsx(SelectItem, { value: t, children: messages.paymentScheduleDialog.scheduleTypeLabels[t] }, t))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (v) => form.setValue("status", (v ?? "pending")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: scheduleStatuses.map((s) => (_jsx(SelectItem, { value: s, children: messages.paymentScheduleDialog.scheduleStatusLabels[s] }, s))) })] })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.dueDate }), _jsx(DatePicker, { value: form.watch("dueDate") || null, onChange: (next) => form.setValue("dueDate", next ?? "", {
106
106
  shouldValidate: true,
107
107
  shouldDirty: true,
108
- }), placeholder: messages.paymentScheduleDialog.placeholders.dueDate, className: "w-full" }), form.formState.errors.dueDate && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.dueDate.message }))] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.currency }), _jsx(CurrencyCombobox, { value: form.watch("currency") || null, onChange: (next) => form.setValue("currency", next ?? DEFAULT_CURRENCY, {
108
+ }), placeholder: messages.paymentScheduleDialog.placeholders.dueDate, className: "w-full" }), form.formState.errors.dueDate && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.dueDate.message }))] }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.currency }), _jsx(CurrencyCombobox, { value: form.watch("currency") || null, onChange: (next) => form.setValue("currency", next ?? DEFAULT_CURRENCY, {
109
109
  shouldValidate: true,
110
110
  shouldDirty: true,
111
111
  }) })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.paymentScheduleDialog.fields.amountCents }), _jsx(CurrencyInput, { value: form.watch("amountCents"), onChange: (next) => form.setValue("amountCents", next ?? 0, {
@@ -23,7 +23,7 @@ export function BookingQuickViewSheet({ bookingId, open, onOpenChange, onViewFul
23
23
  // v5, so opening the sheet with no `bookingId` would render an
24
24
  // indefinite loading state. Gate on an active fetch instead.
25
25
  const isLoading = Boolean(bookingId) && query.fetchStatus === "fetching" && !booking;
26
- return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", className: "sm:max-w-md", children: [_jsx(SheetHeader, { className: "border-b", children: booking ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(SheetTitle, { className: "font-mono text-sm", children: booking.bookingNumber }), _jsx(Badge, { variant: bookingStatusBadgeVariant[booking.status], children: messages.common.bookingStatusLabels[booking.status] ?? booking.status })] }), _jsx("div", { className: "text-2xl font-semibold tabular-nums", children: formatAmount(booking.sellAmountCents, booking.sellCurrency, resolvedLocale, detail.noValue) })] })) : (_jsx(SheetTitle, { children: quick.loadingTitle })) }), _jsx(SheetBody, { className: "flex flex-col gap-5", children: isLoading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: messages.common.loading })) : !booking ? (_jsx("p", { className: "text-sm text-muted-foreground", children: detail.notFound })) : (_jsx(QuickViewBody, { booking: booking, locale: resolvedLocale })) }), onViewFull && booking ? (_jsx(SheetFooter, { children: _jsxs(Button, { type: "button", className: "w-full", onClick: () => onViewFull(booking), children: [quick.viewFullAction, _jsx(ArrowRight, { className: "ml-1 h-4 w-4", "aria-hidden": "true" })] }) })) : null] }) }));
26
+ return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", className: "sm:max-w-md", children: [_jsx(SheetHeader, { className: "border-b", children: booking ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(SheetTitle, { className: "font-mono text-sm", children: booking.bookingNumber }), _jsx(Badge, { variant: bookingStatusBadgeVariant[booking.status], children: messages.common.bookingStatusLabels[booking.status] ?? booking.status })] }), _jsx("div", { className: "text-2xl font-semibold tabular-nums", children: formatAmount(booking.sellAmountCents, booking.sellCurrency, resolvedLocale, detail.noValue) })] })) : (_jsx(SheetTitle, { children: quick.loadingTitle })) }), _jsx(SheetBody, { className: "flex flex-col gap-4", children: isLoading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: messages.common.loading })) : !booking ? (_jsx("p", { className: "text-sm text-muted-foreground", children: detail.notFound })) : (_jsx(QuickViewBody, { booking: booking, locale: resolvedLocale })) }), onViewFull && booking ? (_jsx(SheetFooter, { children: _jsxs(Button, { type: "button", className: "w-full", onClick: () => onViewFull(booking), children: [quick.viewFullAction, _jsx(ArrowRight, { className: "ml-1 h-4 w-4", "aria-hidden": "true" })] }) })) : null] }) }));
27
27
  }
28
28
  function QuickViewBody({ booking, locale }) {
29
29
  const messages = useBookingsUiMessagesOrDefault();
@@ -33,7 +33,7 @@ function QuickViewBody({ booking, locale }) {
33
33
  ? `${formatDate(booking.startDate, locale, detail.noValue)} - ${formatDate(booking.endDate, locale, detail.noValue)}`
34
34
  : formatDate(booking.startDate, locale, detail.noValue)
35
35
  : detail.tbd;
36
- return (_jsxs("div", { className: "flex flex-col gap-5", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Calendar, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }), _jsx("span", { children: dateRange })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Users, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }), _jsx("span", { children: booking.pax != null
36
+ return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Calendar, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }), _jsx("span", { children: dateRange })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Users, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }), _jsx("span", { children: booking.pax != null
37
37
  ? `${booking.pax} ${messages.bookingQuickViewSheet.paxSuffix}`
38
38
  : detail.noValue })] })] }), _jsx(ContactSection, { booking: booking }), _jsx(TravelersSection, { bookingId: booking.id, expectedPax: booking.pax, locale: locale }), _jsx(PaymentsSection, { booking: booking, locale: locale }), _jsx(InvoicesSection, { booking: booking }), _jsx(PaymentScheduleSection, { booking: booking, locale: locale }), _jsx(ContractsSection, { bookingId: booking.id })] }));
39
39
  }
@@ -5,5 +5,5 @@ import { useBookingsUiMessagesOrDefault } from "../i18n/index.js";
5
5
  import { BookingList } from "./booking-list.js";
6
6
  export function BookingsPage({ pageSize, onBookingOpen, onCreateBooking, headerActions, className, initialFilters, onFiltersChange, } = {}) {
7
7
  const messages = useBookingsUiMessagesOrDefault().bookingsPage;
8
- return (_jsxs("div", { "data-slot": "bookings-page", className: cn("flex flex-col gap-6 p-6", className), children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: messages.title }), _jsx("p", { className: "text-sm text-muted-foreground", children: messages.description })] }), _jsx(BookingList, { pageSize: pageSize, onSelectBooking: onBookingOpen, onCreateBooking: onCreateBooking, headerActions: headerActions, initialFilters: initialFilters, onFiltersChange: onFiltersChange })] }));
8
+ return (_jsxs("div", { "data-slot": "bookings-page", className: cn("flex flex-col gap-6", className), children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: messages.title }), _jsx("p", { className: "text-sm text-muted-foreground", children: messages.description })] }), _jsx(BookingList, { pageSize: pageSize, onSelectBooking: onBookingOpen, onCreateBooking: onCreateBooking, headerActions: headerActions, initialFilters: initialFilters, onFiltersChange: onFiltersChange })] }));
9
9
  }
@@ -199,7 +199,7 @@ export function PaymentScheduleSection({ value, onChange, totalAmountCents, depa
199
199
  const paymentMethodLabels = messages.bookingPaymentsSummary.paymentMethodLabels;
200
200
  const renderPaidFields = (idx, installment) => {
201
201
  const checkboxId = `payment-schedule-installment-${idx}-already-paid`;
202
- return (_jsxs("div", { className: "flex flex-col gap-2 rounded-md border border-dashed p-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: checkboxId, checked: installment.alreadyPaid, onCheckedChange: (next) => updateInstallment(idx, { alreadyPaid: next === true }) }), _jsx(Label, { htmlFor: checkboxId, className: "cursor-pointer text-xs", children: merged.alreadyPaid })] }), installment.alreadyPaid ? (_jsxs("div", { className: "grid gap-2 sm:grid-cols-3", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.paymentDate }), _jsx(DatePicker, { value: installment.paymentDate ?? "", onChange: (nextValue) => updateInstallment(idx, { paymentDate: nextValue }) })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.paymentMethod }), _jsxs(Select, { value: installment.paymentMethod, onValueChange: (nextValue) => updateInstallment(idx, { paymentMethod: nextValue ?? "bank_transfer" }), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: ["bank_transfer", "credit_card", "cash", "travel_credit", "other"].map((method) => (_jsx(SelectItem, { value: method, children: paymentMethodLabels[method === "credit_card" ? "card" : method] }, method))) })] })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.paymentReference }), _jsx(Input, { value: installment.paymentReference, onChange: (event) => updateInstallment(idx, { paymentReference: event.target.value }) })] })] })) : null] }));
202
+ return (_jsxs("div", { className: "flex flex-col gap-2 rounded-md border border-dashed p-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: checkboxId, checked: installment.alreadyPaid, onCheckedChange: (next) => updateInstallment(idx, { alreadyPaid: next === true }) }), _jsx(Label, { htmlFor: checkboxId, className: "cursor-pointer text-xs", children: merged.alreadyPaid })] }), installment.alreadyPaid ? (_jsxs("div", { className: "grid gap-2 sm:grid-cols-3", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.paymentDate }), _jsx(DatePicker, { value: installment.paymentDate ?? "", onChange: (nextValue) => updateInstallment(idx, { paymentDate: nextValue }) })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.paymentMethod }), _jsxs(Select, { value: installment.paymentMethod, onValueChange: (nextValue) => updateInstallment(idx, { paymentMethod: nextValue ?? "bank_transfer" }), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: ["bank_transfer", "credit_card", "cash", "travel_credit", "other"].map((method) => (_jsx(SelectItem, { value: method, children: paymentMethodLabels[method === "credit_card" ? "card" : method] }, method))) })] })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.paymentReference }), _jsx(Input, { value: installment.paymentReference, onChange: (event) => updateInstallment(idx, { paymentReference: event.target.value }) })] })] })) : null] }));
203
203
  };
204
204
  const fullInstallment = value.installments[0] ?? createInstallment({ dueDate: todayIso() });
205
205
  return (_jsxs("div", { className: "flex flex-col gap-3 rounded-md border p-3", children: [_jsx(Label, { children: merged.heading }), _jsxs("div", { className: "grid gap-2 rounded-md bg-muted/40 p-2 text-xs sm:grid-cols-3", children: [_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground", children: merged.totalDue }), _jsx("span", { className: "font-medium tabular-nums", children: formatAmount(total) })] }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground", children: merged.scheduledTotal }), _jsx("span", { className: "font-medium tabular-nums", children: formatAmount(scheduledTotal) })] }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground", children: merged.remaining }), _jsx("span", { className: "font-medium tabular-nums", children: formatAmount(remaining) })] })] }), _jsx("div", { className: "flex flex-wrap items-center gap-2", children: modes.map((mode) => (_jsx(Button, { type: "button", size: "sm", variant: value.mode === mode.id ? "default" : "ghost", onClick: () => switchMode(mode.id), children: mode.label }, mode.id))) }), value.mode === "full" && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.dueDate }), _jsx(DatePicker, { value: fullInstallment.dueDate ?? "", onChange: (nextValue) => updateInstallment(0, { dueDate: nextValue }) })] }), renderPaidFields(0, fullInstallment)] })), value.mode === "split" && (_jsxs("div", { className: "flex flex-col gap-3", children: [value.installments.map((installment, idx) => (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-xs font-medium", children: merged.firstInstallment.replace(/\b1\b|first|primul|1st/i, String(idx + 1)) }), value.installments.length > 2 ? (_jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": merged.removeInstallment, onClick: () => removeInstallment(idx), children: _jsx(X, { className: "h-3.5 w-3.5" }) })) : null] }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(CurrencyInput, { placeholder: merged.amount, value: installment.amountCents, onChange: (next) => updateInstallment(idx, { amountCents: next }), currency: currency }), _jsx(DatePicker, { value: installment.dueDate ?? "", onChange: (nextValue) => updateInstallment(idx, { dueDate: nextValue }) })] }), renderPaidFields(idx, installment)] }, installment.id))), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: addInstallment, className: "self-start", children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), merged.addInstallment] })] }))] }));