@voyant-travel/bookings-react 0.198.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.
- package/dist/admin/booking-detail-skeleton.js +1 -1
- package/dist/admin/bookings-list-skeleton.js +1 -1
- package/dist/admin/pages/booking-journey-page.js +1 -1
- package/dist/admin/pages/booking-new-page.js +1 -1
- package/dist/components/booking-billing-dialog.js +4 -4
- package/dist/components/booking-cancellation-dialog.js +2 -2
- package/dist/components/booking-create-page.js +1 -1
- package/dist/components/booking-detail-page.js +4 -4
- package/dist/components/booking-dialog.js +3 -3
- package/dist/components/booking-document-dialog.js +1 -1
- package/dist/components/booking-document-list.js +6 -3
- package/dist/components/booking-group-section.js +5 -2
- package/dist/components/booking-guarantee-dialog.js +5 -5
- package/dist/components/booking-item-dialog.js +5 -5
- package/dist/components/booking-item-travelers.js +6 -3
- package/dist/components/booking-payment-schedule-dialog.js +2 -2
- package/dist/components/booking-quick-view-sheet.js +2 -2
- package/dist/components/bookings-page.js +1 -1
- package/dist/components/payment-schedule-section.js +1 -1
- package/dist/components/supplier-status-dialog.js +1 -1
- package/dist/components/traveler-dialog.js +5 -5
- package/dist/extras/i18n/en.js +9 -7
- package/dist/extras/i18n/ro.js +9 -7
- package/dist/i18n/en-base.js +3 -3
- package/dist/i18n/en-create-list.js +14 -14
- package/dist/i18n/en-journey.js +15 -15
- package/dist/i18n/en-operations.js +11 -11
- package/dist/i18n/en-sections.js +3 -3
- package/dist/i18n/ro-base.js +3 -3
- package/dist/i18n/ro-create-list.js +13 -13
- package/dist/i18n/ro-journey.js +10 -10
- package/dist/i18n/ro-operations.js +11 -11
- package/dist/i18n/ro-sections.js +3 -3
- package/dist/requirements/i18n/en.js +8 -8
- package/dist/requirements/i18n/ro.js +7 -7
- package/package.json +36 -36
|
@@ -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
|
|
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
|
|
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
|
}
|
|
@@ -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: "
|
|
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
|
|
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,
|
|
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(
|
|
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(
|
|
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
|
|
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}
|
|
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
|
|
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) ? (
|
|
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,
|
|
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(
|
|
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(
|
|
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 (
|
|
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 (!
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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 (
|
|
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-
|
|
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-
|
|
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
|
|
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] })] }))] }));
|
|
@@ -86,7 +86,7 @@ export function SupplierStatusDialog({ open, onOpenChange, bookingId, supplierSt
|
|
|
86
86
|
const isSubmitting = create.isPending || update.isPending;
|
|
87
87
|
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing
|
|
88
88
|
? messages.supplierStatusDialog.titles.edit
|
|
89
|
-
: messages.supplierStatusDialog.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.supplierStatusDialog.fields.serviceName }), _jsx(Input, { ...form.register("serviceName"), placeholder: messages.supplierStatusDialog.placeholders.serviceName, disabled: isEditing }), form.formState.errors.serviceName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.serviceName.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.supplierStatusDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (value) => form.setValue("status", value), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: CONFIRMATION_STATUSES.map((status) => (_jsx(SelectItem, { value: status.value, children: messages.common.supplierStatusLabels[status.value] }, status.value))) })] })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.supplierStatusDialog.fields.costCurrency }), _jsx(CurrencyCombobox, { value: form.watch("costCurrency") || null, onChange: (next) => form.setValue("costCurrency", next ?? DEFAULT_CURRENCY, {
|
|
89
|
+
: messages.supplierStatusDialog.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.supplierStatusDialog.fields.serviceName }), _jsx(Input, { ...form.register("serviceName"), placeholder: messages.supplierStatusDialog.placeholders.serviceName, disabled: isEditing }), form.formState.errors.serviceName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.serviceName.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.supplierStatusDialog.fields.status }), _jsxs(Select, { items: statusItems, value: form.watch("status"), onValueChange: (value) => form.setValue("status", value), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: CONFIRMATION_STATUSES.map((status) => (_jsx(SelectItem, { value: status.value, children: messages.common.supplierStatusLabels[status.value] }, status.value))) })] })] })] }), _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.supplierStatusDialog.fields.costCurrency }), _jsx(CurrencyCombobox, { value: form.watch("costCurrency") || null, onChange: (next) => form.setValue("costCurrency", next ?? DEFAULT_CURRENCY, {
|
|
90
90
|
shouldValidate: true,
|
|
91
91
|
shouldDirty: true,
|
|
92
92
|
}) })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.supplierStatusDialog.fields.costAmountCents }), _jsx(CurrencyInput, { value: form.watch("costAmountCents"), onChange: (next) => form.setValue("costAmountCents", next ?? 0, {
|