@voyantjs/bookings-ui 0.26.0 → 0.26.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 (51) hide show
  1. package/dist/components/booking-activity-timeline.js +1 -1
  2. package/dist/components/booking-cancellation-dialog.js +1 -1
  3. package/dist/components/booking-create-dialog.js +9 -9
  4. package/dist/components/booking-dialog.js +2 -2
  5. package/dist/components/booking-document-dialog.js +2 -2
  6. package/dist/components/booking-document-list.js +2 -2
  7. package/dist/components/booking-group-link-dialog.js +1 -1
  8. package/dist/components/booking-group-section.js +2 -2
  9. package/dist/components/booking-guarantee-dialog.js +1 -1
  10. package/dist/components/booking-guarantee-list.js +2 -2
  11. package/dist/components/booking-item-dialog.js +1 -1
  12. package/dist/components/booking-item-list.js +3 -3
  13. package/dist/components/booking-item-travelers.js +1 -1
  14. package/dist/components/booking-list.js +2 -2
  15. package/dist/components/booking-notes.js +1 -1
  16. package/dist/components/booking-payment-schedule-dialog.js +1 -1
  17. package/dist/components/booking-payment-schedule-list.js +2 -2
  18. package/dist/components/booking-payments-summary.js +1 -1
  19. package/dist/components/file-dropzone.js +1 -1
  20. package/dist/components/passengers-section.js +1 -1
  21. package/dist/components/payment-schedule-section.js +1 -1
  22. package/dist/components/person-picker-section.js +1 -1
  23. package/dist/components/price-breakdown-section.js +1 -1
  24. package/dist/components/product-picker-section.js +1 -1
  25. package/dist/components/rooms-stepper-section.js +1 -1
  26. package/dist/components/shared-room-section.js +1 -1
  27. package/dist/components/status-change-dialog.js +1 -1
  28. package/dist/components/supplier-status-dialog.js +1 -1
  29. package/dist/components/supplier-status-list.js +2 -2
  30. package/dist/components/traveler-dialog.d.ts.map +1 -1
  31. package/dist/components/traveler-dialog.js +170 -13
  32. package/dist/components/traveler-list.js +2 -2
  33. package/dist/components/voucher-picker-section.js +1 -1
  34. package/dist/i18n/en.d.ts +22 -0
  35. package/dist/i18n/en.d.ts.map +1 -1
  36. package/dist/i18n/en.js +22 -0
  37. package/dist/i18n/index.d.ts +4 -4
  38. package/dist/i18n/index.d.ts.map +1 -1
  39. package/dist/i18n/index.js +3 -3
  40. package/dist/i18n/messages.d.ts +22 -0
  41. package/dist/i18n/messages.d.ts.map +1 -1
  42. package/dist/i18n/provider.d.ts +45 -1
  43. package/dist/i18n/provider.d.ts.map +1 -1
  44. package/dist/i18n/provider.js +2 -2
  45. package/dist/i18n/ro.d.ts +22 -0
  46. package/dist/i18n/ro.d.ts.map +1 -1
  47. package/dist/i18n/ro.js +22 -0
  48. package/dist/index.d.ts +33 -33
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +33 -33
  51. package/package.json +20 -20
@@ -5,7 +5,7 @@ import { usePublicBookingPayments } from "@voyantjs/finance-react";
5
5
  import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
6
6
  import { Activity, Clock, CreditCard, ExternalLink, FileText, Pencil, Plus, RefreshCw, UserPlus, } from "lucide-react";
7
7
  import * as React from "react";
8
- import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider";
8
+ import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider.js";
9
9
  const activityIcons = {
10
10
  booking_created: Plus,
11
11
  booking_reserved: Plus,
@@ -5,7 +5,7 @@ import { useEvaluateCancellation, useResolvePolicy } from "@voyantjs/legal-react
5
5
  import { Badge, Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Label, Textarea, } from "@voyantjs/ui/components";
6
6
  import { AlertTriangle, Loader2 } from "lucide-react";
7
7
  import * as React from "react";
8
- import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider";
8
+ import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider.js";
9
9
  function daysBetween(from, to) {
10
10
  const diffMs = to.getTime() - from.getTime();
11
11
  return Math.max(0, Math.floor(diffMs / (1000 * 60 * 60 * 24)));
@@ -6,15 +6,15 @@ import { usePersonMutation } from "@voyantjs/crm-react";
6
6
  import { Button, Checkbox, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea, } from "@voyantjs/ui/components";
7
7
  import { Loader2 } from "lucide-react";
8
8
  import * as React from "react";
9
- import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider";
10
- import { emptyPassengerListValue, PassengersSection, } from "./passengers-section";
11
- import { emptyPaymentScheduleValue, PaymentScheduleSection, } from "./payment-schedule-section";
12
- import { emptyPersonPickerValue, PersonPickerSection, } from "./person-picker-section";
13
- import { PriceBreakdownSection } from "./price-breakdown-section";
14
- import { ProductPickerSection } from "./product-picker-section";
15
- import { emptyRoomsStepperValue, RoomsStepperSection, } from "./rooms-stepper-section";
16
- import { emptySharedRoomValue, SharedRoomSection, } from "./shared-room-section";
17
- import { emptyVoucherPickerValue, VoucherPickerSection, } from "./voucher-picker-section";
9
+ import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider.js";
10
+ import { emptyPassengerListValue, PassengersSection, } from "./passengers-section.js";
11
+ import { emptyPaymentScheduleValue, PaymentScheduleSection, } from "./payment-schedule-section.js";
12
+ import { emptyPersonPickerValue, PersonPickerSection, } from "./person-picker-section.js";
13
+ import { PriceBreakdownSection } from "./price-breakdown-section.js";
14
+ import { ProductPickerSection } from "./product-picker-section.js";
15
+ import { emptyRoomsStepperValue, RoomsStepperSection, } from "./rooms-stepper-section.js";
16
+ import { emptySharedRoomValue, SharedRoomSection, } from "./shared-room-section.js";
17
+ import { emptyVoucherPickerValue, VoucherPickerSection, } from "./voucher-picker-section.js";
18
18
  function generateBookingNumber() {
19
19
  const now = new Date();
20
20
  const y = now.getFullYear().toString().slice(-2);
@@ -9,8 +9,8 @@ import { Loader2 } from "lucide-react";
9
9
  import { useEffect } from "react";
10
10
  import { useForm } from "react-hook-form";
11
11
  import { z } from "zod/v4";
12
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
13
- import { BookingCreateDialog } from "./booking-create-dialog";
12
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
13
+ import { BookingCreateDialog } from "./booking-create-dialog.js";
14
14
  function createBookingFormSchema(messages) {
15
15
  return z.object({
16
16
  bookingNumber: z.string().min(1, messages.bookingDialog.validation.bookingNumberRequired),
@@ -8,8 +8,8 @@ import { Loader2 } from "lucide-react";
8
8
  import { useEffect } from "react";
9
9
  import { useForm } from "react-hook-form";
10
10
  import { z } from "zod/v4";
11
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
12
- import { FileDropzone } from "./file-dropzone";
11
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
12
+ import { FileDropzone } from "./file-dropzone.js";
13
13
  const documentTypes = ["visa", "insurance", "health", "passport_copy", "other"];
14
14
  const UNASSIGNED = "__unassigned__";
15
15
  function createDocumentFormSchema(messages) {
@@ -4,8 +4,8 @@ import { useBookingTravelerDocumentMutation, useBookingTravelerDocuments, useTra
4
4
  import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { ExternalLink, FileText, Plus, Trash2 } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
8
- import { BookingDocumentDialog } from "./booking-document-dialog";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { BookingDocumentDialog } from "./booking-document-dialog.js";
9
9
  const typeVariant = {
10
10
  visa: "default",
11
11
  insurance: "secondary",
@@ -4,7 +4,7 @@ import { useBookingGroupMemberMutation, useBookingGroupMutation, useBookingGroup
4
4
  import { Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/ui/components";
5
5
  import { Loader2 } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
8
  const JOIN_PLACEHOLDER = "__none__";
9
9
  export function BookingGroupLinkDialog({ open, onOpenChange, bookingId, productId, optionUnitId, onLinked, }) {
10
10
  const [mode, setMode] = React.useState("join");
@@ -4,8 +4,8 @@ import { useBookingGroup, useBookingGroupForBooking, useBookingGroupMemberMutati
4
4
  import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { Link2, Unlink, Users } from "lucide-react";
6
6
  import * as React from "react";
7
- import { formatMessage, useBookingsUiMessagesOrDefault } from "../i18n/provider";
8
- import { BookingGroupLinkDialog } from "./booking-group-link-dialog";
7
+ import { formatMessage, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { BookingGroupLinkDialog } from "./booking-group-link-dialog.js";
9
9
  export function BookingGroupSection({ bookingId, productId, optionUnitId, hideWithoutAccommodation = true, }) {
10
10
  const [linkDialogOpen, setLinkDialogOpen] = React.useState(false);
11
11
  const messages = useBookingsUiMessagesOrDefault();
@@ -9,7 +9,7 @@ import { Loader2 } from "lucide-react";
9
9
  import { useEffect } from "react";
10
10
  import { useForm } from "react-hook-form";
11
11
  import { z } from "zod/v4";
12
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
12
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
13
13
  const guaranteeTypes = [
14
14
  "deposit",
15
15
  "credit_card",
@@ -4,8 +4,8 @@ import { useBookingGuaranteeMutation, useBookingGuarantees, } from "@voyantjs/fi
4
4
  import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { Pencil, Plus, ShieldCheck, Trash2 } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
8
- import { BookingGuaranteeDialog } from "./booking-guarantee-dialog";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { BookingGuaranteeDialog } from "./booking-guarantee-dialog.js";
9
9
  const statusVariant = {
10
10
  pending: "outline",
11
11
  active: "default",
@@ -9,7 +9,7 @@ import { Loader2 } from "lucide-react";
9
9
  import { useEffect } from "react";
10
10
  import { useForm } from "react-hook-form";
11
11
  import { z } from "zod/v4";
12
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
12
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
13
13
  const itemTypes = [
14
14
  "unit",
15
15
  "extra",
@@ -4,9 +4,9 @@ import { useBookingItemMutation, useBookingItems, } from "@voyantjs/bookings-rea
4
4
  import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { Calendar, ChevronDown, ChevronRight, Package, Pencil, Plus, Trash2 } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
8
- import { BookingItemDialog } from "./booking-item-dialog";
9
- import { BookingItemTravelers } from "./booking-item-travelers";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { BookingItemDialog } from "./booking-item-dialog.js";
9
+ import { BookingItemTravelers } from "./booking-item-travelers.js";
10
10
  const statusVariant = {
11
11
  draft: "outline",
12
12
  on_hold: "secondary",
@@ -4,7 +4,7 @@ import { useBookingItemTravelerMutation, useBookingItemTravelers, useTravelers,
4
4
  import { Badge, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/ui/components";
5
5
  import { Plus, Trash2, UserCheck } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
7
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
8
  const roles = [
9
9
  "traveler",
10
10
  "occupant",
@@ -7,8 +7,8 @@ import { Input } from "@voyantjs/ui/components/input";
7
7
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@voyantjs/ui/components/table";
8
8
  import { Loader2, Plus, Search } from "lucide-react";
9
9
  import * as React from "react";
10
- import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider";
11
- import { BookingDialog } from "./booking-dialog";
10
+ import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider.js";
11
+ import { BookingDialog } from "./booking-dialog.js";
12
12
  export function BookingList({ pageSize = 25, onSelectBooking } = {}) {
13
13
  const [search, setSearch] = React.useState("");
14
14
  const [offset, setOffset] = React.useState(0);
@@ -4,7 +4,7 @@ import { useBookingNoteMutation, useBookingNotes } from "@voyantjs/bookings-reac
4
4
  import { Button, Card, CardContent, CardHeader, CardTitle, Textarea } from "@voyantjs/ui/components";
5
5
  import { Loader2 } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
8
  export function BookingNotes({ bookingId }) {
9
9
  const [content, setContent] = React.useState("");
10
10
  const { data } = useBookingNotes(bookingId);
@@ -9,7 +9,7 @@ import { Loader2 } from "lucide-react";
9
9
  import { useEffect } from "react";
10
10
  import { useForm } from "react-hook-form";
11
11
  import { z } from "zod/v4";
12
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
12
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
13
13
  const scheduleTypes = ["deposit", "installment", "balance", "hold", "other"];
14
14
  const scheduleStatuses = ["pending", "due", "paid", "waived", "cancelled", "expired"];
15
15
  const DEFAULT_CURRENCY = "EUR"; // i18n-literal-ok ISO default currency
@@ -4,8 +4,8 @@ import { useBookingPaymentScheduleMutation, useBookingPaymentSchedules, } from "
4
4
  import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { CalendarClock, Pencil, Plus, Trash2 } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
8
- import { BookingPaymentScheduleDialog } from "./booking-payment-schedule-dialog";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { BookingPaymentScheduleDialog } from "./booking-payment-schedule-dialog.js";
9
9
  const statusVariant = {
10
10
  pending: "outline",
11
11
  due: "secondary",
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useAdminBookingPayments, usePublicBookingPayments } from "@voyantjs/finance-react";
4
4
  import { Badge, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { Banknote, CreditCard, Receipt, Ticket, Wallet } from "lucide-react";
6
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
6
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
7
7
  /**
8
8
  * Map payment status to a badge variant — completed/pending visible
9
9
  * positively, failed/refunded surface destructive coloring so an
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { File as FileIcon, Loader2, Upload, X } from "lucide-react";
4
4
  import * as React from "react";
5
- import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider";
5
+ import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider.js";
6
6
  export function FileDropzone({ uploadUrl = "/api/v1/uploads", accept, maxSize, onUploaded, onError, helperText, disabled, }) {
7
7
  const inputRef = React.useRef(null);
8
8
  const [isDragging, setIsDragging] = React.useState(false);
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/ui/components";
4
4
  import { Trash2 } from "lucide-react";
5
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
5
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
6
6
  const ALL_ROLES = ["lead", "adult", "child", "infant"];
7
7
  export const emptyPassengerListValue = { passengers: [] };
8
8
  /** Factory for a blank row — `role` defaults to `adult` unless the list is empty. */
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Button, Input, Label } from "@voyantjs/ui/components";
4
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
4
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
5
5
  export const emptyPaymentScheduleValue = {
6
6
  mode: "unpaid",
7
7
  fullDueDate: null,
@@ -4,7 +4,7 @@ import { useOrganizations, usePeople } from "@voyantjs/crm-react";
4
4
  import { Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/ui/components";
5
5
  import { UserPlus } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
7
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
8
  const ORG_NONE = "__none__";
9
9
  export const emptyNewPerson = {
10
10
  firstName: "",
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { usePricingPreview } from "@voyantjs/bookings-react";
4
4
  import { Label } from "@voyantjs/ui/components";
5
5
  import * as React from "react";
6
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
6
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
7
7
  /**
8
8
  * Picks the tier whose quantity range contains `qty`. Tiers are expected
9
9
  * oldest-to-newest, `minQuantity`-ascending. Ties are broken by first-match —
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useProductOptions, useProducts } from "@voyantjs/products-react";
4
4
  import { Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/ui/components";
5
5
  import * as React from "react";
6
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
6
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
7
7
  const OPTION_NONE = "__none__";
8
8
  /**
9
9
  * Controlled product + option picker. Splits `value` + `onChange` so apps can
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useSlotUnitAvailability } from "@voyantjs/availability-react";
4
4
  import { Button, Label } from "@voyantjs/ui/components";
5
5
  import { Minus, Plus } from "lucide-react";
6
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
6
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
7
7
  export const emptyRoomsStepperValue = { quantities: {} };
8
8
  /**
9
9
  * Rooms / per-unit stepper for booking-create flows. Drives
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useBookingGroups } from "@voyantjs/bookings-react";
4
4
  import { Button, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/ui/components";
5
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
5
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
6
6
  const GROUP_NONE = "__none__";
7
7
  export const emptySharedRoomValue = {
8
8
  enabled: false,
@@ -7,7 +7,7 @@ import { Loader2 } from "lucide-react";
7
7
  import { useEffect } from "react";
8
8
  import { useForm } from "react-hook-form";
9
9
  import { z } from "zod/v4";
10
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
10
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
11
11
  const statusChangeFormSchema = z.object({
12
12
  status: bookingStatusSchema,
13
13
  note: z.string().optional().nullable(),
@@ -8,7 +8,7 @@ import { Loader2 } from "lucide-react";
8
8
  import { useEffect } from "react";
9
9
  import { useForm } from "react-hook-form";
10
10
  import { z } from "zod/v4";
11
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
11
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
12
12
  function createSupplierStatusFormSchema(messages) {
13
13
  return z.object({
14
14
  serviceName: z.string().min(1, messages.supplierStatusDialog.validation.serviceNameRequired),
@@ -4,8 +4,8 @@ import { useSupplierStatuses } from "@voyantjs/bookings-react";
4
4
  import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { Pencil, Plus } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider";
8
- import { SupplierStatusDialog } from "./supplier-status-dialog";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { SupplierStatusDialog } from "./supplier-status-dialog.js";
9
9
  const supplierStatusVariant = {
10
10
  pending: "outline",
11
11
  confirmed: "default",
@@ -1 +1 @@
1
- {"version":3,"file":"traveler-dialog.d.ts","sourceRoot":"","sources":["../../src/components/traveler-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,qBAAqB,EAAuB,MAAM,0BAA0B,CAAA;AAkC1F,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,SAAS,GACV,EAAE,mBAAmB,2CAwIrB"}
1
+ {"version":3,"file":"traveler-dialog.d.ts","sourceRoot":"","sources":["../../src/components/traveler-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,qBAAqB,EAG3B,MAAM,0BAA0B,CAAA;AA0DjC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,SAAS,GACV,EAAE,mBAAmB,2CA2YrB"}
@@ -1,13 +1,14 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useTravelerMutation } from "@voyantjs/bookings-react";
3
+ import { useRevealTraveler, useTravelerWithTravelDetailsMutation, } from "@voyantjs/bookings-react";
4
+ import { usePersonDocumentMutation, usePersonDocuments, usePersonMutation, usePersonTravelSnapshot, } from "@voyantjs/crm-react";
4
5
  import { Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Textarea, } from "@voyantjs/ui/components";
5
6
  import { zodResolver } from "@voyantjs/ui/lib/zod-resolver";
6
- import { Loader2 } from "lucide-react";
7
- import { useEffect } from "react";
7
+ import { Loader2, Sparkles, Upload } from "lucide-react";
8
+ import { useEffect, useMemo, useState } from "react";
8
9
  import { useForm } from "react-hook-form";
9
10
  import { z } from "zod/v4";
10
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
11
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
11
12
  function createTravelerFormSchema(messages) {
12
13
  return z.object({
13
14
  firstName: z.string().min(1, messages.travelerDialog.validation.firstNameRequired),
@@ -15,13 +16,44 @@ function createTravelerFormSchema(messages) {
15
16
  email: z.string().email().optional().or(z.literal("")).nullable(),
16
17
  phone: z.string().optional().nullable(),
17
18
  specialRequests: z.string().optional().nullable(),
19
+ passportNumber: z.string().optional().nullable(),
20
+ passportExpiry: z.string().optional().nullable(),
21
+ passportIssuingCountry: z.string().optional().nullable(),
22
+ passportIssuingAuthority: z.string().optional().nullable(),
23
+ dateOfBirth: z.string().optional().nullable(),
24
+ dietaryRequirements: z.string().optional().nullable(),
25
+ accessibilityNeeds: z.string().optional().nullable(),
18
26
  });
19
27
  }
28
+ const EMPTY_PII_FORM = {
29
+ passportNumber: "",
30
+ passportExpiry: "",
31
+ passportIssuingCountry: "",
32
+ passportIssuingAuthority: "",
33
+ dateOfBirth: "",
34
+ dietaryRequirements: "",
35
+ accessibilityNeeds: "",
36
+ };
20
37
  export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSuccess, }) {
21
38
  const isEditing = Boolean(traveler);
22
- const { create, update } = useTravelerMutation(bookingId);
39
+ const personId = traveler?.personId ?? null;
23
40
  const messages = useBookingsUiMessagesOrDefault();
24
41
  const travelerFormSchema = createTravelerFormSchema(messages);
42
+ const travelerMutation = useTravelerWithTravelDetailsMutation(bookingId);
43
+ const personMutation = usePersonMutation();
44
+ const documentMutation = usePersonDocumentMutation(personId ?? undefined);
45
+ const reveal = useRevealTraveler(bookingId, traveler?.id ?? null, {
46
+ enabled: Boolean(open && isEditing && traveler?.id),
47
+ });
48
+ const snapshotQuery = usePersonTravelSnapshot(personId ?? undefined, {
49
+ enabled: open && Boolean(personId),
50
+ });
51
+ const documentsQuery = usePersonDocuments(personId ?? undefined, {
52
+ enabled: open && Boolean(personId),
53
+ });
54
+ const snapshot = snapshotQuery.data?.data ?? null;
55
+ const revealedTravelDetails = reveal.data?.data.travelDetails ?? null;
56
+ const primaryPassport = useMemo(() => documentsQuery.data?.data.find((row) => row.type === "passport" && row.isPrimary) ?? null, [documentsQuery.data]);
25
57
  const form = useForm({
26
58
  resolver: zodResolver(travelerFormSchema),
27
59
  defaultValues: {
@@ -30,23 +62,63 @@ export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSucc
30
62
  email: "",
31
63
  phone: "",
32
64
  specialRequests: "",
65
+ ...EMPTY_PII_FORM,
33
66
  },
34
67
  });
68
+ const [savedToProfileMessage, setSavedToProfileMessage] = useState(false);
69
+ const [prefilledNotice, setPrefilledNotice] = useState(false);
35
70
  useEffect(() => {
36
- if (open && traveler) {
71
+ setSavedToProfileMessage(false);
72
+ setPrefilledNotice(false);
73
+ if (!open)
74
+ return;
75
+ if (traveler) {
37
76
  form.reset({
38
77
  firstName: traveler.firstName,
39
78
  lastName: traveler.lastName,
40
79
  email: traveler.email ?? "",
41
80
  phone: traveler.phone ?? "",
42
81
  specialRequests: traveler.specialRequests ?? "",
82
+ passportNumber: revealedTravelDetails?.passportNumber ?? "",
83
+ passportExpiry: revealedTravelDetails?.passportExpiry ?? "",
84
+ passportIssuingCountry: revealedTravelDetails?.passportIssuingCountry ?? "",
85
+ passportIssuingAuthority: revealedTravelDetails?.passportIssuingAuthority ?? "",
86
+ dateOfBirth: revealedTravelDetails?.dateOfBirth ?? "",
87
+ dietaryRequirements: revealedTravelDetails?.dietaryRequirements ?? "",
88
+ accessibilityNeeds: revealedTravelDetails?.accessibilityNeeds ?? "",
43
89
  });
44
90
  }
45
- else if (open) {
46
- form.reset();
91
+ else {
92
+ form.reset({
93
+ firstName: "",
94
+ lastName: "",
95
+ email: "",
96
+ phone: "",
97
+ specialRequests: "",
98
+ ...EMPTY_PII_FORM,
99
+ });
47
100
  }
48
- }, [form, open, traveler]);
101
+ }, [form, open, traveler, revealedTravelDetails]);
102
+ const prefillFromProfile = () => {
103
+ if (!snapshot)
104
+ return;
105
+ form.setValue("passportNumber", snapshot.passportNumber ?? "");
106
+ form.setValue("passportExpiry", snapshot.passportExpiry ?? "");
107
+ form.setValue("passportIssuingCountry", snapshot.passportIssuingCountry ?? "");
108
+ form.setValue("passportIssuingAuthority", snapshot.passportIssuingAuthority ?? "");
109
+ form.setValue("dateOfBirth", snapshot.dateOfBirth ?? "");
110
+ form.setValue("dietaryRequirements", snapshot.dietaryRequirements ?? "");
111
+ form.setValue("accessibilityNeeds", snapshot.accessibilityNeeds ?? "");
112
+ setPrefilledNotice(true);
113
+ setSavedToProfileMessage(false);
114
+ };
49
115
  const onSubmit = async (values) => {
116
+ const trimOrNull = (value) => {
117
+ if (value === null || value === undefined)
118
+ return null;
119
+ const trimmed = value.trim();
120
+ return trimmed === "" ? null : trimmed;
121
+ };
50
122
  const payload = {
51
123
  firstName: values.firstName,
52
124
  lastName: values.lastName,
@@ -54,20 +126,105 @@ export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSucc
54
126
  phone: values.phone || null,
55
127
  specialRequests: values.specialRequests || null,
56
128
  isPrimary: traveler?.isPrimary ?? false,
129
+ participantType: "traveler",
130
+ passportNumber: trimOrNull(values.passportNumber),
131
+ passportExpiry: trimOrNull(values.passportExpiry),
132
+ passportIssuingCountry: trimOrNull(values.passportIssuingCountry),
133
+ passportIssuingAuthority: trimOrNull(values.passportIssuingAuthority),
134
+ dateOfBirth: trimOrNull(values.dateOfBirth),
135
+ dietaryRequirements: trimOrNull(values.dietaryRequirements),
136
+ accessibilityNeeds: trimOrNull(values.accessibilityNeeds),
57
137
  };
58
138
  if (isEditing) {
59
- await update.mutateAsync({ id: traveler.id, input: payload });
139
+ await travelerMutation.update.mutateAsync({ travelerId: traveler.id, input: payload });
60
140
  }
61
141
  else {
62
- await create.mutateAsync(payload);
142
+ await travelerMutation.create.mutateAsync(payload);
63
143
  }
64
144
  onOpenChange(false);
65
145
  onSuccess?.();
66
146
  };
67
- const isSubmitting = create.isPending || update.isPending;
147
+ /**
148
+ * Pushes diverging dietary / accessibility / passport values from
149
+ * the form back to the linked person record. Dietary + accessibility
150
+ * land on `crm.people` via the profile-pii endpoint. Passport
151
+ * diffs update the existing primary passport if there is one,
152
+ * otherwise create a new primary passport doc.
153
+ */
154
+ const saveBackToProfile = async () => {
155
+ if (!personId)
156
+ return;
157
+ const values = form.getValues();
158
+ const trim = (value) => {
159
+ if (value === null || value === undefined)
160
+ return null;
161
+ const trimmed = value.trim();
162
+ return trimmed === "" ? null : trimmed;
163
+ };
164
+ const formDietary = trim(values.dietaryRequirements);
165
+ const formAccessibility = trim(values.accessibilityNeeds);
166
+ const formPassportNumber = trim(values.passportNumber);
167
+ const formPassportExpiry = trim(values.passportExpiry);
168
+ const formPassportCountry = trim(values.passportIssuingCountry);
169
+ const formPassportAuthority = trim(values.passportIssuingAuthority);
170
+ const piiUpdate = {};
171
+ if (formDietary !== (snapshot?.dietaryRequirements ?? null)) {
172
+ piiUpdate.dietary = formDietary;
173
+ }
174
+ if (formAccessibility !== (snapshot?.accessibilityNeeds ?? null)) {
175
+ piiUpdate.accessibility = formAccessibility;
176
+ }
177
+ if (Object.keys(piiUpdate).length > 0) {
178
+ await personMutation.updateProfilePii.mutateAsync({ personId, input: piiUpdate });
179
+ }
180
+ const passportDiverged = formPassportNumber !== (snapshot?.passportNumber ?? null) ||
181
+ formPassportExpiry !== (snapshot?.passportExpiry ?? null) ||
182
+ formPassportCountry !== (snapshot?.passportIssuingCountry ?? null) ||
183
+ formPassportAuthority !== (snapshot?.passportIssuingAuthority ?? null);
184
+ if (passportDiverged) {
185
+ const passportPayload = {
186
+ type: "passport",
187
+ number: formPassportNumber,
188
+ issuingCountry: formPassportCountry,
189
+ issuingAuthority: formPassportAuthority,
190
+ expiryDate: formPassportExpiry,
191
+ isPrimary: true,
192
+ };
193
+ if (primaryPassport) {
194
+ await documentMutation.updateFromPlaintext.mutateAsync({
195
+ id: primaryPassport.id,
196
+ input: passportPayload,
197
+ });
198
+ }
199
+ else {
200
+ await documentMutation.createFromPlaintext.mutateAsync(passportPayload);
201
+ }
202
+ }
203
+ setSavedToProfileMessage(true);
204
+ setPrefilledNotice(false);
205
+ };
206
+ const isSubmitting = travelerMutation.create.isPending || travelerMutation.update.isPending;
207
+ const isSavingProfile = personMutation.updateProfilePii.isPending ||
208
+ documentMutation.updateFromPlaintext.isPending ||
209
+ documentMutation.createFromPlaintext.isPending;
210
+ const watched = form.watch();
211
+ const hasDivergence = Boolean(personId) &&
212
+ snapshot &&
213
+ [
214
+ ["dietaryRequirements", "dietaryRequirements"],
215
+ ["accessibilityNeeds", "accessibilityNeeds"],
216
+ ["passportNumber", "passportNumber"],
217
+ ["passportExpiry", "passportExpiry"],
218
+ ["passportIssuingCountry", "passportIssuingCountry"],
219
+ ["passportIssuingAuthority", "passportIssuingAuthority"],
220
+ ].some(([formKey, snapKey]) => {
221
+ const formValue = watched[formKey] ?? "";
222
+ const snapValue = snapshot[snapKey] ?? "";
223
+ return String(formValue ?? "").trim() !== String(snapValue ?? "").trim();
224
+ });
68
225
  return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing
69
226
  ? messages.travelerDialog.titles.edit
70
- : messages.travelerDialog.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.travelerDialog.fields.firstName }), _jsx(Input, { ...form.register("firstName"), placeholder: messages.travelerDialog.placeholders.firstName }), form.formState.errors.firstName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.firstName.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.lastName }), _jsx(Input, { ...form.register("lastName"), placeholder: messages.travelerDialog.placeholders.lastName }), form.formState.errors.lastName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.lastName.message }))] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.email }), _jsx(Input, { ...form.register("email"), type: "email", placeholder: messages.travelerDialog.placeholders.email })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.phone }), _jsx(Input, { ...form.register("phone"), placeholder: messages.travelerDialog.placeholders.phone })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.specialRequests }), _jsx(Textarea, { ...form.register("specialRequests"), placeholder: messages.travelerDialog.placeholders.specialRequests })] })] }), _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
227
+ : messages.travelerDialog.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.travelerDialog.fields.firstName }), _jsx(Input, { ...form.register("firstName"), placeholder: messages.travelerDialog.placeholders.firstName }), form.formState.errors.firstName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.firstName.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.lastName }), _jsx(Input, { ...form.register("lastName"), placeholder: messages.travelerDialog.placeholders.lastName }), form.formState.errors.lastName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.lastName.message }))] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.email }), _jsx(Input, { ...form.register("email"), type: "email", placeholder: messages.travelerDialog.placeholders.email })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.phone }), _jsx(Input, { ...form.register("phone"), placeholder: messages.travelerDialog.placeholders.phone })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.specialRequests }), _jsx(Textarea, { ...form.register("specialRequests"), placeholder: messages.travelerDialog.placeholders.specialRequests })] }), _jsxs("div", { className: "flex flex-col gap-3 border-t pt-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("h3", { className: "text-sm font-semibold", children: messages.travelerDialog.fields.travelDetailsHeading }), personId ? (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", disabled: !snapshot || snapshotQuery.isLoading, onClick: prefillFromProfile, children: [_jsx(Sparkles, { className: "mr-2 h-3.5 w-3.5" }), messages.travelerDialog.actions.prefillFromProfile] })) : null] }), prefilledNotice ? (_jsx("p", { className: "text-xs text-muted-foreground", children: messages.travelerDialog.hints.prefilledFromProfile })) : null, _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.passportNumber }), _jsx(Input, { ...form.register("passportNumber"), placeholder: messages.travelerDialog.placeholders.passportNumber })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.passportExpiry }), _jsx(Input, { ...form.register("passportExpiry"), type: "date", placeholder: messages.travelerDialog.placeholders.passportExpiry })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.passportIssuingCountry }), _jsx(Input, { ...form.register("passportIssuingCountry"), placeholder: messages.travelerDialog.placeholders.passportIssuingCountry })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.passportIssuingAuthority }), _jsx(Input, { ...form.register("passportIssuingAuthority"), placeholder: messages.travelerDialog.placeholders.passportIssuingAuthority })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.dateOfBirth }), _jsx(Input, { ...form.register("dateOfBirth"), type: "date", placeholder: messages.travelerDialog.placeholders.dateOfBirth })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.dietaryRequirements }), _jsx(Textarea, { ...form.register("dietaryRequirements"), placeholder: messages.travelerDialog.placeholders.dietaryRequirements })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.accessibilityNeeds }), _jsx(Textarea, { ...form.register("accessibilityNeeds"), placeholder: messages.travelerDialog.placeholders.accessibilityNeeds })] })] }), personId && hasDivergence ? (_jsxs("div", { className: "flex items-center justify-between gap-2 rounded-md border bg-muted/40 px-3 py-2", children: [_jsx("p", { className: "text-xs text-muted-foreground", children: savedToProfileMessage ? messages.travelerDialog.hints.savedToProfile : null }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: isSavingProfile, onClick: saveBackToProfile, children: [isSavingProfile ? (_jsx(Loader2, { className: "mr-2 h-3.5 w-3.5 animate-spin" })) : (_jsx(Upload, { className: "mr-2 h-3.5 w-3.5" })), messages.travelerDialog.actions.saveToProfile] })] })) : null] })] }), _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
71
228
  ? messages.common.saveChanges
72
229
  : messages.travelerDialog.actions.addTraveler] })] })] })] }) }));
73
230
  }
@@ -4,8 +4,8 @@ import { useBookingTravelerDocuments, useRevealTraveler, useTravelerMutation, us
4
4
  import { Button, Card, CardContent, CardHeader, CardTitle } from "@voyantjs/ui/components";
5
5
  import { Eye, EyeOff, Loader2, Pencil, Plus, Trash2, Users } from "lucide-react";
6
6
  import * as React from "react";
7
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider";
8
- import { TravelerDialog } from "./traveler-dialog";
7
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { TravelerDialog } from "./traveler-dialog.js";
9
9
  export function TravelerList({ bookingId, autoReveal = false }) {
10
10
  const [dialogOpen, setDialogOpen] = React.useState(false);
11
11
  const [editing, setEditing] = React.useState(undefined);