@voyant-travel/flights-react 0.119.2
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/LICENSE +201 -0
- package/README.md +74 -0
- package/dist/admin/index.d.ts +134 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +122 -0
- package/dist/admin/pages/flight-book-page.d.ts +12 -0
- package/dist/admin/pages/flight-book-page.d.ts.map +1 -0
- package/dist/admin/pages/flight-book-page.js +40 -0
- package/dist/admin/pages/flights-index-page.d.ts +14 -0
- package/dist/admin/pages/flights-index-page.d.ts.map +1 -0
- package/dist/admin/pages/flights-index-page.js +28 -0
- package/dist/client.d.ts +16 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +75 -0
- package/dist/components/airline-logo.d.ts +19 -0
- package/dist/components/airline-logo.d.ts.map +1 -0
- package/dist/components/airline-logo.js +18 -0
- package/dist/components/airport-combobox.d.ts +20 -0
- package/dist/components/airport-combobox.d.ts.map +1 -0
- package/dist/components/airport-combobox.js +31 -0
- package/dist/components/billing-pickers.d.ts +19 -0
- package/dist/components/billing-pickers.d.ts.map +1 -0
- package/dist/components/billing-pickers.js +148 -0
- package/dist/components/flight-baggage-step.d.ts +32 -0
- package/dist/components/flight-baggage-step.d.ts.map +1 -0
- package/dist/components/flight-baggage-step.js +119 -0
- package/dist/components/flight-billing-step.d.ts +69 -0
- package/dist/components/flight-billing-step.d.ts.map +1 -0
- package/dist/components/flight-billing-step.js +117 -0
- package/dist/components/flight-booking-journey.d.ts +31 -0
- package/dist/components/flight-booking-journey.d.ts.map +1 -0
- package/dist/components/flight-booking-journey.js +103 -0
- package/dist/components/flight-booking-ledger.d.ts +53 -0
- package/dist/components/flight-booking-ledger.d.ts.map +1 -0
- package/dist/components/flight-booking-ledger.js +104 -0
- package/dist/components/flight-booking-page.d.ts +25 -0
- package/dist/components/flight-booking-page.d.ts.map +1 -0
- package/dist/components/flight-booking-page.js +175 -0
- package/dist/components/flight-booking-shell-helpers.d.ts +29 -0
- package/dist/components/flight-booking-shell-helpers.d.ts.map +1 -0
- package/dist/components/flight-booking-shell-helpers.js +204 -0
- package/dist/components/flight-booking-shell-panels.d.ts +24 -0
- package/dist/components/flight-booking-shell-panels.d.ts.map +1 -0
- package/dist/components/flight-booking-shell-panels.js +39 -0
- package/dist/components/flight-booking-shell-types.d.ts +49 -0
- package/dist/components/flight-booking-shell-types.d.ts.map +1 -0
- package/dist/components/flight-booking-shell-types.js +18 -0
- package/dist/components/flight-booking-shell.d.ts +12 -0
- package/dist/components/flight-booking-shell.d.ts.map +1 -0
- package/dist/components/flight-booking-shell.js +210 -0
- package/dist/components/flight-contact-form.d.ts +16 -0
- package/dist/components/flight-contact-form.d.ts.map +1 -0
- package/dist/components/flight-contact-form.js +25 -0
- package/dist/components/flight-fare-upsell-step.d.ts +26 -0
- package/dist/components/flight-fare-upsell-step.d.ts.map +1 -0
- package/dist/components/flight-fare-upsell-step.js +169 -0
- package/dist/components/flight-filters-bar.d.ts +19 -0
- package/dist/components/flight-filters-bar.d.ts.map +1 -0
- package/dist/components/flight-filters-bar.js +98 -0
- package/dist/components/flight-itinerary.d.ts +28 -0
- package/dist/components/flight-itinerary.d.ts.map +1 -0
- package/dist/components/flight-itinerary.js +110 -0
- package/dist/components/flight-offer-detail.d.ts +21 -0
- package/dist/components/flight-offer-detail.d.ts.map +1 -0
- package/dist/components/flight-offer-detail.js +49 -0
- package/dist/components/flight-offer-row.d.ts +25 -0
- package/dist/components/flight-offer-row.d.ts.map +1 -0
- package/dist/components/flight-offer-row.js +78 -0
- package/dist/components/flight-order-confirmation.d.ts +13 -0
- package/dist/components/flight-order-confirmation.d.ts.map +1 -0
- package/dist/components/flight-order-confirmation.js +46 -0
- package/dist/components/flight-passenger-form.d.ts +49 -0
- package/dist/components/flight-passenger-form.d.ts.map +1 -0
- package/dist/components/flight-passenger-form.js +159 -0
- package/dist/components/flight-payment-selector.d.ts +13 -0
- package/dist/components/flight-payment-selector.d.ts.map +1 -0
- package/dist/components/flight-payment-selector.js +32 -0
- package/dist/components/flight-payment-step.d.ts +32 -0
- package/dist/components/flight-payment-step.d.ts.map +1 -0
- package/dist/components/flight-payment-step.js +81 -0
- package/dist/components/flight-search-form.d.ts +14 -0
- package/dist/components/flight-search-form.d.ts.map +1 -0
- package/dist/components/flight-search-form.js +58 -0
- package/dist/components/flight-seat-map.d.ts +32 -0
- package/dist/components/flight-seat-map.d.ts.map +1 -0
- package/dist/components/flight-seat-map.js +101 -0
- package/dist/components/flight-seats-step.d.ts +40 -0
- package/dist/components/flight-seats-step.d.ts.map +1 -0
- package/dist/components/flight-seats-step.js +214 -0
- package/dist/components/flight-services-step.d.ts +27 -0
- package/dist/components/flight-services-step.d.ts.map +1 -0
- package/dist/components/flight-services-step.js +123 -0
- package/dist/components/flights-page-panels.d.ts +27 -0
- package/dist/components/flights-page-panels.d.ts.map +1 -0
- package/dist/components/flights-page-panels.js +40 -0
- package/dist/components/flights-page-types.d.ts +39 -0
- package/dist/components/flights-page-types.d.ts.map +1 -0
- package/dist/components/flights-page-types.js +1 -0
- package/dist/components/flights-page-utils.d.ts +14 -0
- package/dist/components/flights-page-utils.d.ts.map +1 -0
- package/dist/components/flights-page-utils.js +79 -0
- package/dist/components/flights-page.d.ts +4 -0
- package/dist/components/flights-page.d.ts.map +1 -0
- package/dist/components/flights-page.js +209 -0
- package/dist/components/passenger-contact-picker.d.ts +16 -0
- package/dist/components/passenger-contact-picker.d.ts.map +1 -0
- package/dist/components/passenger-contact-picker.js +45 -0
- package/dist/components/pax-cabin-popover.d.ts +18 -0
- package/dist/components/pax-cabin-popover.d.ts.map +1 -0
- package/dist/components/pax-cabin-popover.js +35 -0
- package/dist/components/popular-routes.d.ts +42 -0
- package/dist/components/popular-routes.d.ts.map +1 -0
- package/dist/components/popular-routes.js +108 -0
- package/dist/hooks/index.d.ts +13 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +12 -0
- package/dist/hooks/use-aircraft.d.ts +17 -0
- package/dist/hooks/use-aircraft.d.ts.map +1 -0
- package/dist/hooks/use-aircraft.js +18 -0
- package/dist/hooks/use-airlines.d.ts +18 -0
- package/dist/hooks/use-airlines.d.ts.map +1 -0
- package/dist/hooks/use-airlines.js +18 -0
- package/dist/hooks/use-airport-search.d.ts +28 -0
- package/dist/hooks/use-airport-search.d.ts.map +1 -0
- package/dist/hooks/use-airport-search.js +23 -0
- package/dist/hooks/use-airports.d.ts +21 -0
- package/dist/hooks/use-airports.d.ts.map +1 -0
- package/dist/hooks/use-airports.js +17 -0
- package/dist/hooks/use-flight-ancillaries.d.ts +63 -0
- package/dist/hooks/use-flight-ancillaries.d.ts.map +1 -0
- package/dist/hooks/use-flight-ancillaries.js +24 -0
- package/dist/hooks/use-flight-book.d.ts +139 -0
- package/dist/hooks/use-flight-book.d.ts.map +1 -0
- package/dist/hooks/use-flight-book.js +24 -0
- package/dist/hooks/use-flight-offer.d.ts +106 -0
- package/dist/hooks/use-flight-offer.d.ts.map +1 -0
- package/dist/hooks/use-flight-offer.js +20 -0
- package/dist/hooks/use-flight-order.d.ts +286 -0
- package/dist/hooks/use-flight-order.d.ts.map +1 -0
- package/dist/hooks/use-flight-order.js +38 -0
- package/dist/hooks/use-flight-orders.d.ts +147 -0
- package/dist/hooks/use-flight-orders.d.ts.map +1 -0
- package/dist/hooks/use-flight-orders.js +31 -0
- package/dist/hooks/use-flight-search.d.ts +110 -0
- package/dist/hooks/use-flight-search.d.ts.map +1 -0
- package/dist/hooks/use-flight-search.js +18 -0
- package/dist/hooks/use-flight-seat-map.d.ts +49 -0
- package/dist/hooks/use-flight-seat-map.d.ts.map +1 -0
- package/dist/hooks/use-flight-seat-map.js +23 -0
- package/dist/hooks/use-saved-payment-methods.d.ts +23 -0
- package/dist/hooks/use-saved-payment-methods.d.ts.map +1 -0
- package/dist/hooks/use-saved-payment-methods.js +20 -0
- package/dist/i18n/en.d.ts +465 -0
- package/dist/i18n/en.d.ts.map +1 -0
- package/dist/i18n/en.js +520 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +3 -0
- package/dist/i18n/messages.d.ts +392 -0
- package/dist/i18n/messages.d.ts.map +1 -0
- package/dist/i18n/messages.js +1 -0
- package/dist/i18n/provider.d.ts +952 -0
- package/dist/i18n/provider.d.ts.map +1 -0
- package/dist/i18n/provider.js +44 -0
- package/dist/i18n/ro.d.ts +465 -0
- package/dist/i18n/ro.d.ts.map +1 -0
- package/dist/i18n/ro.js +520 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/provider.d.ts +2 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +1 -0
- package/dist/query-keys.d.ts +42 -0
- package/dist/query-keys.d.ts.map +1 -0
- package/dist/query-keys.js +22 -0
- package/dist/query-options.d.ts +827 -0
- package/dist/query-options.d.ts.map +1 -0
- package/dist/query-options.js +58 -0
- package/dist/schemas.d.ts +1658 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +295 -0
- package/dist/ui.d.ts +31 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +28 -0
- package/package.json +148 -0
- package/src/styles.css +11 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { usePeople } from "@voyant-travel/relationships-react";
|
|
4
|
+
import { Button } from "@voyant-travel/ui/components/button";
|
|
5
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@voyant-travel/ui/components/command";
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@voyant-travel/ui/components/popover";
|
|
7
|
+
import { ChevronDown, UserPlus, Users } from "lucide-react";
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { useFlightsUiMessagesOrDefault } from "../i18n/index.js";
|
|
10
|
+
/**
|
|
11
|
+
* Passenger card "Pick from contacts" trigger. Opens a popover with a
|
|
12
|
+
* searchable list of CRM people and maps the picked person into the
|
|
13
|
+
* `PassengerPrefill` shape expected by `FlightPassengerForm`.
|
|
14
|
+
*/
|
|
15
|
+
export function PassengerContactPicker({ onPick, onAddContact, onPersonSelected, }) {
|
|
16
|
+
const messages = useFlightsUiMessagesOrDefault().passengerContactPicker;
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
const [search, setSearch] = useState("");
|
|
19
|
+
const peopleQuery = usePeople({
|
|
20
|
+
search: search.trim() || undefined,
|
|
21
|
+
limit: 30,
|
|
22
|
+
enabled: open,
|
|
23
|
+
});
|
|
24
|
+
const people = peopleQuery.data?.data ?? [];
|
|
25
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(Button, { type: "button", variant: "outline", size: "sm", className: "h-8 gap-2" }), children: [_jsx(Users, { className: "h-3.5 w-3.5" }), messages.trigger, _jsx(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })] }), _jsx(PopoverContent, { className: "w-[320px] p-0", align: "end", children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { value: search, onValueChange: setSearch, placeholder: messages.searchPlaceholder }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: peopleQuery.isLoading ? messages.searching : messages.empty }), _jsx(CommandGroup, { children: people.map((person) => {
|
|
26
|
+
const fullName = `${person.firstName} ${person.lastName}`.trim();
|
|
27
|
+
return (_jsx(CommandItem, { value: `${fullName} ${person.email ?? ""}`, onSelect: () => {
|
|
28
|
+
onPick({
|
|
29
|
+
firstName: person.firstName,
|
|
30
|
+
...(person.middleName ? { middleName: person.middleName } : {}),
|
|
31
|
+
lastName: person.lastName,
|
|
32
|
+
email: person.email ?? undefined,
|
|
33
|
+
phone: person.phone ?? undefined,
|
|
34
|
+
...(person.gender ? { gender: person.gender } : {}),
|
|
35
|
+
...(person.dateOfBirth ? { dateOfBirth: person.dateOfBirth } : {}),
|
|
36
|
+
});
|
|
37
|
+
onPersonSelected?.(person.id);
|
|
38
|
+
setOpen(false);
|
|
39
|
+
setSearch("");
|
|
40
|
+
}, children: _jsxs("div", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [_jsx("span", { className: "truncate font-medium text-sm", children: fullName || messages.emptyName }), person.email && (_jsx("span", { className: "truncate text-muted-foreground text-xs", children: person.email }))] }) }, person.id));
|
|
41
|
+
}) }), onAddContact && (_jsxs(_Fragment, { children: [_jsx(CommandSeparator, {}), _jsx(CommandGroup, { children: _jsxs(CommandItem, { value: "__add-new", onSelect: () => {
|
|
42
|
+
onAddContact();
|
|
43
|
+
setOpen(false);
|
|
44
|
+
}, className: "text-primary", children: [_jsx(UserPlus, { className: "mr-2 h-4 w-4" }), messages.addNewContact] }) })] }))] })] }) })] }));
|
|
45
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CabinClass, PassengerCounts } from "@voyant-travel/flights/contract/types";
|
|
2
|
+
export interface PaxCabinPopoverProps {
|
|
3
|
+
passengers: PassengerCounts;
|
|
4
|
+
cabin: CabinClass;
|
|
5
|
+
onChange: (next: {
|
|
6
|
+
passengers: PassengerCounts;
|
|
7
|
+
cabin: CabinClass;
|
|
8
|
+
}) => void;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Compact pax + cabin selector — single trigger button summarizing
|
|
13
|
+
* "2 adults · Economy" that opens a popover with steppers for each pax
|
|
14
|
+
* type and a cabin select. Mirrors the Google Flights / Skyscanner
|
|
15
|
+
* pattern; keeps the search form on one row.
|
|
16
|
+
*/
|
|
17
|
+
export declare function PaxCabinPopover({ passengers, cabin, onChange, className }: PaxCabinPopoverProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=pax-cabin-popover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pax-cabin-popover.d.ts","sourceRoot":"","sources":["../../src/components/pax-cabin-popover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAA;AAcxF,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,eAAe,CAAA;IAC3B,KAAK,EAAE,UAAU,CAAA;IACjB,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,eAAe,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAA;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,oBAAoB,2CA6E/F"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { formatMessage } from "@voyant-travel/i18n";
|
|
4
|
+
import { Button } from "@voyant-travel/ui/components/button";
|
|
5
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@voyant-travel/ui/components/popover";
|
|
6
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyant-travel/ui/components/select";
|
|
7
|
+
import { Minus, Plus, Users } from "lucide-react";
|
|
8
|
+
import { useFlightsUiMessagesOrDefault } from "../i18n/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Compact pax + cabin selector — single trigger button summarizing
|
|
11
|
+
* "2 adults · Economy" that opens a popover with steppers for each pax
|
|
12
|
+
* type and a cabin select. Mirrors the Google Flights / Skyscanner
|
|
13
|
+
* pattern; keeps the search form on one row.
|
|
14
|
+
*/
|
|
15
|
+
export function PaxCabinPopover({ passengers, cabin, onChange, className }) {
|
|
16
|
+
const messages = useFlightsUiMessagesOrDefault();
|
|
17
|
+
const total = passengers.adults + (passengers.children ?? 0) + (passengers.infants ?? 0);
|
|
18
|
+
const summary = `${total} ${total === 1 ? messages.common.passengerSingular : messages.common.passengerPlural} · ${messages.common.cabinLabels[cabin]}`;
|
|
19
|
+
const setCount = (key, value) => {
|
|
20
|
+
onChange({
|
|
21
|
+
passengers: {
|
|
22
|
+
...passengers,
|
|
23
|
+
[key]: Math.max(key === "adults" ? 1 : 0, value),
|
|
24
|
+
},
|
|
25
|
+
cabin,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
return (_jsxs(Popover, { children: [_jsxs(PopoverTrigger, { render: _jsx(Button, { type: "button", variant: "outline", size: "lg", className: className }), children: [_jsx(Users, { className: "h-4 w-4 text-muted-foreground" }), _jsx("span", { className: "text-sm", children: summary })] }), _jsx(PopoverContent, { align: "end", children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsx(PaxStepper, { label: messages.paxCabinPopover.adults, sublabel: messages.paxCabinPopover.adultsSublabel, value: passengers.adults, min: 1, onChange: (v) => setCount("adults", v), messages: messages }), _jsx(PaxStepper, { label: messages.paxCabinPopover.children, sublabel: messages.paxCabinPopover.childrenSublabel, value: passengers.children ?? 0, min: 0, onChange: (v) => setCount("children", v), messages: messages }), _jsx(PaxStepper, { label: messages.paxCabinPopover.infants, sublabel: messages.paxCabinPopover.infantsSublabel, value: passengers.infants ?? 0, min: 0, onChange: (v) => setCount("infants", v), messages: messages }), _jsxs("div", { className: "mt-1 flex flex-col gap-1.5 border-t pt-3", children: [_jsx("span", { className: "text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: messages.paxCabinPopover.cabin }), _jsxs(Select, { value: cabin, onValueChange: (v) => {
|
|
29
|
+
if (v)
|
|
30
|
+
onChange({ passengers, cabin: v });
|
|
31
|
+
}, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: Object.keys(messages.common.cabinLabels).map((c) => (_jsx(SelectItem, { value: c, children: messages.common.cabinLabels[c] }, c))) })] })] })] }) })] }));
|
|
32
|
+
}
|
|
33
|
+
function PaxStepper({ label, sublabel, value, min, onChange, messages, }) {
|
|
34
|
+
return (_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex flex-col leading-tight", children: [_jsx("span", { className: "text-sm font-medium", children: label }), _jsx("span", { className: "text-[11px] text-muted-foreground", children: sublabel })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "icon", className: "h-7 w-7", onClick: () => onChange(value - 1), disabled: value <= min, "aria-label": formatMessage(messages.paxCabinPopover.decrease, { label }), children: _jsx(Minus, { className: "h-3.5 w-3.5" }) }), _jsx("span", { className: "w-6 text-center text-sm font-medium tabular-nums", children: value }), _jsx(Button, { type: "button", variant: "outline", size: "icon", className: "h-7 w-7", onClick: () => onChange(value + 1), "aria-label": formatMessage(messages.paxCabinPopover.increase, { label }), children: _jsx(Plus, { className: "h-3.5 w-3.5" }) })] })] }));
|
|
35
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { CabinClass, FlightSearchRequest } from "@voyant-travel/flights/contract/types";
|
|
2
|
+
export interface PopularRoute {
|
|
3
|
+
/** Origin IATA code. */
|
|
4
|
+
origin: string;
|
|
5
|
+
/** Display label for the origin (e.g. city). */
|
|
6
|
+
originLabel: string;
|
|
7
|
+
/** Destination IATA code. */
|
|
8
|
+
destination: string;
|
|
9
|
+
destinationLabel: string;
|
|
10
|
+
/** Optional human-readable hint shown beneath the route ("From €120"). */
|
|
11
|
+
hint?: string;
|
|
12
|
+
/** Trip flavor tag — purely cosmetic. */
|
|
13
|
+
tag?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface PopularRoutesProps {
|
|
16
|
+
routes: PopularRoute[];
|
|
17
|
+
/** Called when the user clicks a card. The page builds a search from this. */
|
|
18
|
+
onSelect: (request: FlightSearchRequest) => void;
|
|
19
|
+
/** Trip type used for the synthesized request. Default `"round_trip"`. */
|
|
20
|
+
tripType?: "one_way" | "round_trip";
|
|
21
|
+
/** Days from today to use as departure date. Default 14. */
|
|
22
|
+
daysOut?: number;
|
|
23
|
+
/** Trip duration when round-trip. Default 7. */
|
|
24
|
+
tripNights?: number;
|
|
25
|
+
/** Cabin class for the synthesized request. Default `"economy"`. */
|
|
26
|
+
cabin?: CabinClass;
|
|
27
|
+
/** Adults for the synthesized request. Default 1. */
|
|
28
|
+
adults?: number;
|
|
29
|
+
className?: string;
|
|
30
|
+
/** Section title; pass `null` to hide. */
|
|
31
|
+
title?: string | null;
|
|
32
|
+
}
|
|
33
|
+
export declare const DEFAULT_POPULAR_ROUTES: PopularRoute[];
|
|
34
|
+
/**
|
|
35
|
+
* A grid of clickable popular-route cards. Each card synthesizes a
|
|
36
|
+
* `FlightSearchRequest` (round-trip by default, 14 days out, 7 nights) and
|
|
37
|
+
* fires `onSelect` so the page can prefill its form + run the search in one
|
|
38
|
+
* step. Designed for the empty-state of a flights page: gives the user
|
|
39
|
+
* something to do without typing airport codes.
|
|
40
|
+
*/
|
|
41
|
+
export declare function PopularRoutes({ routes, onSelect, tripType, daysOut, tripNights, cabin, adults, className, title, }: PopularRoutesProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
//# sourceMappingURL=popular-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popular-routes.d.ts","sourceRoot":"","sources":["../../src/components/popular-routes.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAA;AAO5F,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAA;IACnB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAA;IAChD,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,SAAS,GAAG,YAAY,CAAA;IACnC,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAkDD,eAAO,MAAM,sBAAsB,EAAE,YAAY,EAKhD,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,QAAuB,EACvB,OAAY,EACZ,UAAc,EACd,KAAiB,EACjB,MAAU,EACV,SAAS,EACT,KAAK,GACN,EAAE,kBAAkB,2CAqEpB"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Badge } from "@voyant-travel/ui/components/badge";
|
|
4
|
+
import { cn } from "@voyant-travel/ui/lib/utils";
|
|
5
|
+
import { ArrowRight, Sparkles } from "lucide-react";
|
|
6
|
+
import { flightsUiEn } from "../i18n/en.js";
|
|
7
|
+
import { useFlightsUiMessagesOrDefault } from "../i18n/index.js";
|
|
8
|
+
/**
|
|
9
|
+
* Default route set — recognizable city pairs across regions so a fresh
|
|
10
|
+
* /flights page has something to click without having to type airports.
|
|
11
|
+
* Pages can pass their own `routes` to override.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_POPULAR_ROUTE_CODES = [
|
|
14
|
+
{
|
|
15
|
+
origin: "LHR",
|
|
16
|
+
destination: "JFK",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
origin: "CDG",
|
|
20
|
+
destination: "DXB",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
origin: "AMS",
|
|
24
|
+
destination: "SIN",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
origin: "FRA",
|
|
28
|
+
destination: "NRT",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
origin: "MAD",
|
|
32
|
+
destination: "GRU",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
origin: "BCN",
|
|
36
|
+
destination: "FCO",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
origin: "LGW",
|
|
40
|
+
destination: "MAD",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
origin: "DXB",
|
|
44
|
+
destination: "BKK",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
origin: "SFO",
|
|
48
|
+
destination: "HND",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
origin: "ZRH",
|
|
52
|
+
destination: "JNB",
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
export const DEFAULT_POPULAR_ROUTES = DEFAULT_POPULAR_ROUTE_CODES.map((route, index) => ({
|
|
56
|
+
...route,
|
|
57
|
+
...defaultRouteMessages(flightsUiEn.popularRoutes.defaults, index),
|
|
58
|
+
}));
|
|
59
|
+
/**
|
|
60
|
+
* A grid of clickable popular-route cards. Each card synthesizes a
|
|
61
|
+
* `FlightSearchRequest` (round-trip by default, 14 days out, 7 nights) and
|
|
62
|
+
* fires `onSelect` so the page can prefill its form + run the search in one
|
|
63
|
+
* step. Designed for the empty-state of a flights page: gives the user
|
|
64
|
+
* something to do without typing airport codes.
|
|
65
|
+
*/
|
|
66
|
+
export function PopularRoutes({ routes, onSelect, tripType = "round_trip", daysOut = 14, tripNights = 7, cabin = "economy", adults = 1, className, title, }) {
|
|
67
|
+
const messages = useFlightsUiMessagesOrDefault().popularRoutes;
|
|
68
|
+
const resolvedRoutes = routes.map((route, index) => route === DEFAULT_POPULAR_ROUTES[index]
|
|
69
|
+
? {
|
|
70
|
+
...route,
|
|
71
|
+
...defaultRouteMessages(messages.defaults, index),
|
|
72
|
+
}
|
|
73
|
+
: route);
|
|
74
|
+
const resolvedTitle = title === undefined ? messages.title : title;
|
|
75
|
+
const today = new Date();
|
|
76
|
+
const departure = isoDate(addDays(today, daysOut));
|
|
77
|
+
const returnDate = isoDate(addDays(today, daysOut + tripNights));
|
|
78
|
+
const buildRequest = (route) => {
|
|
79
|
+
const slices = [
|
|
80
|
+
{ origin: route.origin, destination: route.destination, departureDate: departure },
|
|
81
|
+
];
|
|
82
|
+
if (tripType === "round_trip") {
|
|
83
|
+
slices.push({
|
|
84
|
+
origin: route.destination,
|
|
85
|
+
destination: route.origin,
|
|
86
|
+
departureDate: returnDate,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return { slices, passengers: { adults, children: 0, infants: 0 }, cabin };
|
|
90
|
+
};
|
|
91
|
+
return (_jsxs("section", { className: cn("flex flex-col gap-3", className), children: [resolvedTitle && (_jsxs("div", { className: "flex items-center gap-2 text-muted-foreground text-sm", children: [_jsx(Sparkles, { className: "h-4 w-4" }), _jsx("span", { children: resolvedTitle })] })), _jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: resolvedRoutes.map((route) => (_jsxs("button", { type: "button", onClick: () => onSelect(buildRequest(route)), className: "group flex flex-col gap-2 rounded-lg border bg-card p-4 text-left shadow-sm transition-all hover:border-primary/40 hover:shadow", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsxs("span", { className: "flex flex-col leading-tight", children: [_jsx("span", { className: "font-mono text-xs text-muted-foreground", children: route.origin }), _jsx("span", { className: "font-medium", children: route.originLabel })] }), _jsx(ArrowRight, { className: "mx-auto h-4 w-4 shrink-0 text-muted-foreground transition-transform group-hover:translate-x-0.5" }), _jsxs("span", { className: "flex flex-col text-right leading-tight", children: [_jsx("span", { className: "font-mono text-xs text-muted-foreground", children: route.destination }), _jsx("span", { className: "font-medium", children: route.destinationLabel })] })] }), _jsxs("div", { className: "mt-auto flex items-center justify-between", children: [route.tag && (_jsx(Badge, { variant: "secondary", className: "text-[10px] font-normal", children: route.tag })), route.hint && _jsx("span", { className: "text-xs text-muted-foreground", children: route.hint })] })] }, `${route.origin}-${route.destination}`))) })] }));
|
|
92
|
+
}
|
|
93
|
+
function addDays(d, n) {
|
|
94
|
+
const copy = new Date(d.getTime());
|
|
95
|
+
copy.setDate(copy.getDate() + n);
|
|
96
|
+
return copy;
|
|
97
|
+
}
|
|
98
|
+
function isoDate(d) {
|
|
99
|
+
return d.toISOString().slice(0, 10);
|
|
100
|
+
}
|
|
101
|
+
function defaultRouteMessages(defaults, index) {
|
|
102
|
+
return (defaults[index] ?? {
|
|
103
|
+
originLabel: "",
|
|
104
|
+
destinationLabel: "",
|
|
105
|
+
tag: "",
|
|
106
|
+
hint: "",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { useAircraft } from "./use-aircraft.js";
|
|
2
|
+
export { useAirlines } from "./use-airlines.js";
|
|
3
|
+
export { type UseAirportSearchOptions, useAirportSearch } from "./use-airport-search.js";
|
|
4
|
+
export { type UseAirportsOptions, useAirports } from "./use-airports.js";
|
|
5
|
+
export { type UseFlightAncillariesOptions, useFlightAncillaries, } from "./use-flight-ancillaries.js";
|
|
6
|
+
export { useFlightBook } from "./use-flight-book.js";
|
|
7
|
+
export { type PriceOfferInput, useFlightOfferPrice } from "./use-flight-offer.js";
|
|
8
|
+
export { type CancelOrderInput, type UseFlightOrderOptions, useFlightOrder, useFlightOrderCancel, } from "./use-flight-order.js";
|
|
9
|
+
export { type UseFlightOrdersOptions, useFlightOrders } from "./use-flight-orders.js";
|
|
10
|
+
export { type UseFlightSearchOptions, useFlightSearch } from "./use-flight-search.js";
|
|
11
|
+
export { type UseFlightSeatMapOptions, useFlightSeatMap, } from "./use-flight-seat-map.js";
|
|
12
|
+
export { type UseSavedPaymentMethodsOptions, useSavedPaymentMethods, } from "./use-saved-payment-methods.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,KAAK,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACxF,OAAO,EAAE,KAAK,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACxE,OAAO,EACL,KAAK,2BAA2B,EAChC,oBAAoB,GACrB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,KAAK,eAAe,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,cAAc,EACd,oBAAoB,GACrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACrF,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACrF,OAAO,EACL,KAAK,uBAAuB,EAC5B,gBAAgB,GACjB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,KAAK,6BAA6B,EAClC,sBAAsB,GACvB,MAAM,gCAAgC,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { useAircraft } from "./use-aircraft.js";
|
|
2
|
+
export { useAirlines } from "./use-airlines.js";
|
|
3
|
+
export { useAirportSearch } from "./use-airport-search.js";
|
|
4
|
+
export { useAirports } from "./use-airports.js";
|
|
5
|
+
export { useFlightAncillaries, } from "./use-flight-ancillaries.js";
|
|
6
|
+
export { useFlightBook } from "./use-flight-book.js";
|
|
7
|
+
export { useFlightOfferPrice } from "./use-flight-offer.js";
|
|
8
|
+
export { useFlightOrder, useFlightOrderCancel, } from "./use-flight-order.js";
|
|
9
|
+
export { useFlightOrders } from "./use-flight-orders.js";
|
|
10
|
+
export { useFlightSearch } from "./use-flight-search.js";
|
|
11
|
+
export { useFlightSeatMap, } from "./use-flight-seat-map.js";
|
|
12
|
+
export { useSavedPaymentMethods, } from "./use-saved-payment-methods.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches the aircraft reference list. Mostly used to hydrate the IATA
|
|
3
|
+
* aircraft type code on segments (e.g. `738` → "Boeing 737-800") in the
|
|
4
|
+
* detail sheet.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useAircraft(options?: {
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
}): import("@tanstack/react-query").UseQueryResult<{
|
|
9
|
+
data: {
|
|
10
|
+
iataCode: string;
|
|
11
|
+
name: string;
|
|
12
|
+
icaoCode?: string | null | undefined;
|
|
13
|
+
manufacturer?: string | null | undefined;
|
|
14
|
+
typicalSeats?: number | null | undefined;
|
|
15
|
+
}[];
|
|
16
|
+
}, Error>;
|
|
17
|
+
//# sourceMappingURL=use-aircraft.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-aircraft.d.ts","sourceRoot":"","sources":["../../src/hooks/use-aircraft.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;UAQ9D"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { useVoyantFlightsContext } from "../provider.js";
|
|
4
|
+
import { getAircraftQueryOptions } from "../query-options.js";
|
|
5
|
+
/**
|
|
6
|
+
* Fetches the aircraft reference list. Mostly used to hydrate the IATA
|
|
7
|
+
* aircraft type code on segments (e.g. `738` → "Boeing 737-800") in the
|
|
8
|
+
* detail sheet.
|
|
9
|
+
*/
|
|
10
|
+
export function useAircraft(options = {}) {
|
|
11
|
+
const client = useVoyantFlightsContext();
|
|
12
|
+
const { enabled = true } = options;
|
|
13
|
+
return useQuery({
|
|
14
|
+
...getAircraftQueryOptions(client),
|
|
15
|
+
enabled,
|
|
16
|
+
staleTime: 24 * 60 * 60 * 1000,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches the full airline reference list. Long-stale because airlines
|
|
3
|
+
* rarely change once seeded — the operator's reference table is a
|
|
4
|
+
* deliberate snapshot, not a live feed.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useAirlines(options?: {
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
}): import("@tanstack/react-query").UseQueryResult<{
|
|
9
|
+
data: {
|
|
10
|
+
iataCode: string;
|
|
11
|
+
name: string;
|
|
12
|
+
icaoCode?: string | null | undefined;
|
|
13
|
+
country?: string | null | undefined;
|
|
14
|
+
logoUrl?: string | null | undefined;
|
|
15
|
+
alliance?: string | null | undefined;
|
|
16
|
+
}[];
|
|
17
|
+
}, Error>;
|
|
18
|
+
//# sourceMappingURL=use-airlines.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-airlines.d.ts","sourceRoot":"","sources":["../../src/hooks/use-airlines.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;UAQ9D"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { useVoyantFlightsContext } from "../provider.js";
|
|
4
|
+
import { getAirlinesQueryOptions } from "../query-options.js";
|
|
5
|
+
/**
|
|
6
|
+
* Fetches the full airline reference list. Long-stale because airlines
|
|
7
|
+
* rarely change once seeded — the operator's reference table is a
|
|
8
|
+
* deliberate snapshot, not a live feed.
|
|
9
|
+
*/
|
|
10
|
+
export function useAirlines(options = {}) {
|
|
11
|
+
const client = useVoyantFlightsContext();
|
|
12
|
+
const { enabled = true } = options;
|
|
13
|
+
return useQuery({
|
|
14
|
+
...getAirlinesQueryOptions(client),
|
|
15
|
+
enabled,
|
|
16
|
+
staleTime: 24 * 60 * 60 * 1000,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface UseAirportSearchOptions {
|
|
2
|
+
/** Debounce on keystrokes, milliseconds. Default 200. */
|
|
3
|
+
debounceMs?: number;
|
|
4
|
+
/** Maximum results returned by the server. Default 25. */
|
|
5
|
+
limit?: number;
|
|
6
|
+
/** Disable network entirely (e.g. while combobox is closed). */
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Debounced airport-search hook for combobox typeaheads. Tracks the
|
|
11
|
+
* raw input separately from the debounced server query so users can
|
|
12
|
+
* type freely without N round-trips. The query short-circuits when
|
|
13
|
+
* `enabled` is false or the debounced value is empty AND limit isn't
|
|
14
|
+
* set (callers that want a default open list should pass `limit`).
|
|
15
|
+
*/
|
|
16
|
+
export declare function useAirportSearch(input: string, options?: UseAirportSearchOptions): import("@tanstack/react-query").UseQueryResult<{
|
|
17
|
+
data: {
|
|
18
|
+
iataCode: string;
|
|
19
|
+
name: string;
|
|
20
|
+
city: string;
|
|
21
|
+
country: string;
|
|
22
|
+
icaoCode?: string | null | undefined;
|
|
23
|
+
timezone?: string | null | undefined;
|
|
24
|
+
latitude?: number | null | undefined;
|
|
25
|
+
longitude?: number | null | undefined;
|
|
26
|
+
}[];
|
|
27
|
+
}, Error>;
|
|
28
|
+
//# sourceMappingURL=use-airport-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-airport-search.d.ts","sourceRoot":"","sources":["../../src/hooks/use-airport-search.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B;;;;;;;;;;;UAcpF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { useAirports } from "./use-airports.js";
|
|
4
|
+
/**
|
|
5
|
+
* Debounced airport-search hook for combobox typeaheads. Tracks the
|
|
6
|
+
* raw input separately from the debounced server query so users can
|
|
7
|
+
* type freely without N round-trips. The query short-circuits when
|
|
8
|
+
* `enabled` is false or the debounced value is empty AND limit isn't
|
|
9
|
+
* set (callers that want a default open list should pass `limit`).
|
|
10
|
+
*/
|
|
11
|
+
export function useAirportSearch(input, options = {}) {
|
|
12
|
+
const { debounceMs = 200, limit = 25, enabled = true } = options;
|
|
13
|
+
const [debounced, setDebounced] = useState(input);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const t = setTimeout(() => setDebounced(input), debounceMs);
|
|
16
|
+
return () => clearTimeout(t);
|
|
17
|
+
}, [input, debounceMs]);
|
|
18
|
+
return useAirports({
|
|
19
|
+
q: debounced.trim() || undefined,
|
|
20
|
+
limit,
|
|
21
|
+
enabled,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AirportSearchFilters } from "../query-keys.js";
|
|
2
|
+
export interface UseAirportsOptions extends AirportSearchFilters {
|
|
3
|
+
enabled?: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Fetch the airport reference list. Use the `q` filter for substring
|
|
7
|
+
* search (city / IATA / name). Cached per-filter.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useAirports(options?: UseAirportsOptions): import("@tanstack/react-query").UseQueryResult<{
|
|
10
|
+
data: {
|
|
11
|
+
iataCode: string;
|
|
12
|
+
name: string;
|
|
13
|
+
city: string;
|
|
14
|
+
country: string;
|
|
15
|
+
icaoCode?: string | null | undefined;
|
|
16
|
+
timezone?: string | null | undefined;
|
|
17
|
+
latitude?: number | null | undefined;
|
|
18
|
+
longitude?: number | null | undefined;
|
|
19
|
+
}[];
|
|
20
|
+
}, Error>;
|
|
21
|
+
//# sourceMappingURL=use-airports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-airports.d.ts","sourceRoot":"","sources":["../../src/hooks/use-airports.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAG5D,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB;;;;;;;;;;;UAQ3D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { useVoyantFlightsContext } from "../provider.js";
|
|
4
|
+
import { getAirportsQueryOptions } from "../query-options.js";
|
|
5
|
+
/**
|
|
6
|
+
* Fetch the airport reference list. Use the `q` filter for substring
|
|
7
|
+
* search (city / IATA / name). Cached per-filter.
|
|
8
|
+
*/
|
|
9
|
+
export function useAirports(options = {}) {
|
|
10
|
+
const client = useVoyantFlightsContext();
|
|
11
|
+
const { enabled = true, ...filters } = options;
|
|
12
|
+
return useQuery({
|
|
13
|
+
...getAirportsQueryOptions(client, filters),
|
|
14
|
+
enabled,
|
|
15
|
+
staleTime: 24 * 60 * 60 * 1000,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { FlightOffer } from "@voyant-travel/flights/contract/types";
|
|
2
|
+
export interface UseFlightAncillariesOptions {
|
|
3
|
+
/** Disable the query — useful before the offer is re-priced. */
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
/** TanStack Query stale time, milliseconds. Default 5 minutes. */
|
|
6
|
+
staleTime?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* POST `/v1/admin/flights/ancillaries` — fetches the bag/assistance/extras
|
|
10
|
+
* catalog for an offer. Catalog is offer-scoped; in the per-leg booking
|
|
11
|
+
* flow callers fire one query per leg and merge the picks at book time
|
|
12
|
+
* via `FlightBookRequest.ancillaries`.
|
|
13
|
+
*
|
|
14
|
+
* Default `enabled = false` so callers gate the query on having a valid
|
|
15
|
+
* (re-priced) offer in hand. When the connector doesn't declare
|
|
16
|
+
* `flight/ancillaries`, the API returns 501 — propagated as a query error.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useFlightAncillaries(input: {
|
|
19
|
+
offerId: string;
|
|
20
|
+
offer?: FlightOffer;
|
|
21
|
+
} | null, options?: UseFlightAncillariesOptions): import("@tanstack/react-query").UseQueryResult<{
|
|
22
|
+
catalog: {
|
|
23
|
+
baggage: {
|
|
24
|
+
id: string;
|
|
25
|
+
label: string;
|
|
26
|
+
category: "cabin" | "checked" | "personal_item" | "sports" | "oversized";
|
|
27
|
+
price: {
|
|
28
|
+
amount: string;
|
|
29
|
+
currency: string;
|
|
30
|
+
};
|
|
31
|
+
weightKg?: number | undefined;
|
|
32
|
+
dimensions?: {
|
|
33
|
+
lengthCm?: number | undefined;
|
|
34
|
+
widthCm?: number | undefined;
|
|
35
|
+
heightCm?: number | undefined;
|
|
36
|
+
} | undefined;
|
|
37
|
+
recommended?: boolean | undefined;
|
|
38
|
+
providerData?: Record<string, unknown> | undefined;
|
|
39
|
+
}[];
|
|
40
|
+
assistance: {
|
|
41
|
+
id: string;
|
|
42
|
+
label: string;
|
|
43
|
+
category: "wheelchair" | "visual" | "hearing" | "cognitive" | "medical" | "other";
|
|
44
|
+
price?: {
|
|
45
|
+
amount: string;
|
|
46
|
+
currency: string;
|
|
47
|
+
} | undefined;
|
|
48
|
+
notes?: string | undefined;
|
|
49
|
+
}[];
|
|
50
|
+
extras: {
|
|
51
|
+
id: string;
|
|
52
|
+
label: string;
|
|
53
|
+
category: string;
|
|
54
|
+
price: {
|
|
55
|
+
amount: string;
|
|
56
|
+
currency: string;
|
|
57
|
+
};
|
|
58
|
+
pricingScope?: "per_passenger" | "per_booking" | undefined;
|
|
59
|
+
}[];
|
|
60
|
+
};
|
|
61
|
+
validUntil?: string | undefined;
|
|
62
|
+
}, Error>;
|
|
63
|
+
//# sourceMappingURL=use-flight-ancillaries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-flight-ancillaries.d.ts","sourceRoot":"","sources":["../../src/hooks/use-flight-ancillaries.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAKxE,MAAM,WAAW,2BAA2B;IAC1C,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG,IAAI,EACtD,OAAO,GAAE,2BAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAU1C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { useVoyantFlightsContext } from "../provider.js";
|
|
4
|
+
import { getFlightAncillariesQueryOptions } from "../query-options.js";
|
|
5
|
+
/**
|
|
6
|
+
* POST `/v1/admin/flights/ancillaries` — fetches the bag/assistance/extras
|
|
7
|
+
* catalog for an offer. Catalog is offer-scoped; in the per-leg booking
|
|
8
|
+
* flow callers fire one query per leg and merge the picks at book time
|
|
9
|
+
* via `FlightBookRequest.ancillaries`.
|
|
10
|
+
*
|
|
11
|
+
* Default `enabled = false` so callers gate the query on having a valid
|
|
12
|
+
* (re-priced) offer in hand. When the connector doesn't declare
|
|
13
|
+
* `flight/ancillaries`, the API returns 501 — propagated as a query error.
|
|
14
|
+
*/
|
|
15
|
+
export function useFlightAncillaries(input, options = {}) {
|
|
16
|
+
const client = useVoyantFlightsContext();
|
|
17
|
+
const { enabled = false, staleTime = 5 * 60_000 } = options;
|
|
18
|
+
const safeInput = input ?? { offerId: "" };
|
|
19
|
+
return useQuery({
|
|
20
|
+
...getFlightAncillariesQueryOptions(client, safeInput),
|
|
21
|
+
enabled: enabled && !!input?.offerId,
|
|
22
|
+
staleTime,
|
|
23
|
+
});
|
|
24
|
+
}
|