@voyant-travel/cruises-react 0.118.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.
Files changed (100) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +70 -0
  3. package/dist/client.d.ts +14 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +59 -0
  6. package/dist/components/cruise-catalog-card.d.ts +13 -0
  7. package/dist/components/cruise-catalog-card.d.ts.map +1 -0
  8. package/dist/components/cruise-catalog-card.js +58 -0
  9. package/dist/components/enrichment-program-list.d.ts +13 -0
  10. package/dist/components/enrichment-program-list.d.ts.map +1 -0
  11. package/dist/components/enrichment-program-list.js +45 -0
  12. package/dist/components/external-badge.d.ts +14 -0
  13. package/dist/components/external-badge.d.ts.map +1 -0
  14. package/dist/components/external-badge.js +17 -0
  15. package/dist/components/pricing-grid.d.ts +21 -0
  16. package/dist/components/pricing-grid.d.ts.map +1 -0
  17. package/dist/components/pricing-grid.js +81 -0
  18. package/dist/components/quote-display.d.ts +14 -0
  19. package/dist/components/quote-display.d.ts.map +1 -0
  20. package/dist/components/quote-display.js +61 -0
  21. package/dist/hooks/index.d.ts +15 -0
  22. package/dist/hooks/index.d.ts.map +1 -0
  23. package/dist/hooks/index.js +14 -0
  24. package/dist/hooks/use-cruise-booking.d.ts +205 -0
  25. package/dist/hooks/use-cruise-booking.d.ts.map +1 -0
  26. package/dist/hooks/use-cruise-booking.js +56 -0
  27. package/dist/hooks/use-cruise-mutation.d.ts +144 -0
  28. package/dist/hooks/use-cruise-mutation.d.ts.map +1 -0
  29. package/dist/hooks/use-cruise-mutation.js +58 -0
  30. package/dist/hooks/use-cruise.d.ts +38 -0
  31. package/dist/hooks/use-cruise.d.ts.map +1 -0
  32. package/dist/hooks/use-cruise.js +16 -0
  33. package/dist/hooks/use-cruises.d.ts +61 -0
  34. package/dist/hooks/use-cruises.d.ts.map +1 -0
  35. package/dist/hooks/use-cruises.js +16 -0
  36. package/dist/hooks/use-effective-itinerary.d.ts +27 -0
  37. package/dist/hooks/use-effective-itinerary.d.ts.map +1 -0
  38. package/dist/hooks/use-effective-itinerary.js +16 -0
  39. package/dist/hooks/use-enrichment.d.ts +72 -0
  40. package/dist/hooks/use-enrichment.d.ts.map +1 -0
  41. package/dist/hooks/use-enrichment.js +64 -0
  42. package/dist/hooks/use-external-actions.d.ts +43 -0
  43. package/dist/hooks/use-external-actions.d.ts.map +1 -0
  44. package/dist/hooks/use-external-actions.js +45 -0
  45. package/dist/hooks/use-pricing.d.ts +65 -0
  46. package/dist/hooks/use-pricing.d.ts.map +1 -0
  47. package/dist/hooks/use-pricing.js +28 -0
  48. package/dist/hooks/use-sailing-mutation.d.ts +147 -0
  49. package/dist/hooks/use-sailing-mutation.d.ts.map +1 -0
  50. package/dist/hooks/use-sailing-mutation.js +55 -0
  51. package/dist/hooks/use-sailings.d.ts +49 -0
  52. package/dist/hooks/use-sailings.d.ts.map +1 -0
  53. package/dist/hooks/use-sailings.js +20 -0
  54. package/dist/hooks/use-search-index.d.ts +43 -0
  55. package/dist/hooks/use-search-index.d.ts.map +1 -0
  56. package/dist/hooks/use-search-index.js +51 -0
  57. package/dist/hooks/use-ship-mutation.d.ts +186 -0
  58. package/dist/hooks/use-ship-mutation.d.ts.map +1 -0
  59. package/dist/hooks/use-ship-mutation.js +92 -0
  60. package/dist/hooks/use-ships.d.ts +101 -0
  61. package/dist/hooks/use-ships.d.ts.map +1 -0
  62. package/dist/hooks/use-ships.js +43 -0
  63. package/dist/hooks/use-storefront.d.ts +230 -0
  64. package/dist/hooks/use-storefront.d.ts.map +1 -0
  65. package/dist/hooks/use-storefront.js +62 -0
  66. package/dist/i18n/en.d.ts +3 -0
  67. package/dist/i18n/en.d.ts.map +1 -0
  68. package/dist/i18n/en.js +79 -0
  69. package/dist/i18n/index.d.ts +5 -0
  70. package/dist/i18n/index.d.ts.map +1 -0
  71. package/dist/i18n/index.js +3 -0
  72. package/dist/i18n/messages.d.ts +62 -0
  73. package/dist/i18n/messages.d.ts.map +1 -0
  74. package/dist/i18n/messages.js +1 -0
  75. package/dist/i18n/provider.d.ts +26 -0
  76. package/dist/i18n/provider.d.ts.map +1 -0
  77. package/dist/i18n/provider.js +44 -0
  78. package/dist/i18n/ro.d.ts +3 -0
  79. package/dist/i18n/ro.d.ts.map +1 -0
  80. package/dist/i18n/ro.js +79 -0
  81. package/dist/index.d.ts +7 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +6 -0
  84. package/dist/provider.d.ts +2 -0
  85. package/dist/provider.d.ts.map +1 -0
  86. package/dist/provider.js +1 -0
  87. package/dist/query-keys.d.ts +82 -0
  88. package/dist/query-keys.d.ts.map +1 -0
  89. package/dist/query-keys.js +39 -0
  90. package/dist/query-options.d.ts +1272 -0
  91. package/dist/query-options.d.ts.map +1 -0
  92. package/dist/query-options.js +136 -0
  93. package/dist/schemas.d.ts +1061 -0
  94. package/dist/schemas.d.ts.map +1 -0
  95. package/dist/schemas.js +339 -0
  96. package/dist/ui.d.ts +6 -0
  97. package/dist/ui.d.ts.map +1 -0
  98. package/dist/ui.js +5 -0
  99. package/package.json +121 -0
  100. package/src/styles.css +11 -0
@@ -0,0 +1,14 @@
1
+ import { Card } from "@voyant-travel/ui/components/card";
2
+ import type * as React from "react";
3
+ import type { Quote } from "../index.js";
4
+ export interface QuoteDisplayProps extends React.ComponentPropsWithoutRef<typeof Card> {
5
+ quote: Quote;
6
+ formatPrice?: (amount: string, currency: string) => string;
7
+ }
8
+ /**
9
+ * Renders an itemised cruise quote: base per person, components grouped by
10
+ * direction (additions / inclusions / credits), and totals. Mirrors what the
11
+ * server's composeQuote returns; pure presentational.
12
+ */
13
+ export declare function QuoteDisplay({ quote, formatPrice, className, ...props }: QuoteDisplayProps): import("react/jsx-runtime").JSX.Element;
14
+ //# sourceMappingURL=quote-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote-display.d.ts","sourceRoot":"","sources":["../../src/components/quote-display.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAA2B,MAAM,mCAAmC,CAAA;AAEjF,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAIxC,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,IAAI,CAAC;IACpF,KAAK,EAAE,KAAK,CAAA;IACZ,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAA;CAC3D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,2CA4G1F"}
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { formatMessage } from "@voyant-travel/i18n";
4
+ import { Card, CardContent, CardHeader } from "@voyant-travel/ui/components/card";
5
+ import { cn } from "@voyant-travel/ui/lib/utils";
6
+ import { useCruisesUiI18nOrDefault } from "../i18n/index.js";
7
+ /**
8
+ * Renders an itemised cruise quote: base per person, components grouped by
9
+ * direction (additions / inclusions / credits), and totals. Mirrors what the
10
+ * server's composeQuote returns; pure presentational.
11
+ */
12
+ export function QuoteDisplay({ quote, formatPrice, className, ...props }) {
13
+ const i18n = useCruisesUiI18nOrDefault();
14
+ const m = i18n.messages.quoteDisplay;
15
+ const formatResolvedPrice = formatPrice ??
16
+ ((amount, currency) => formatCruiseMoney(amount, currency, {
17
+ fallbackCurrencyAmount: i18n.messages.common.fallbackCurrencyAmount,
18
+ formatCurrency: i18n.formatCurrency,
19
+ }, {
20
+ minimumFractionDigits: 2,
21
+ maximumFractionDigits: 2,
22
+ }));
23
+ const additions = quote.components.filter((c) => c.direction === "addition");
24
+ const inclusions = quote.components.filter((c) => c.direction === "inclusion");
25
+ const credits = quote.components.filter((c) => c.direction === "credit");
26
+ const guestLabel = quote.guestCount === 1 ? m.guestLabelSingular : m.guestLabelPlural;
27
+ const occupancyLabel = formatMessage(m.occupancyCabin, { count: quote.occupancy });
28
+ return (_jsxs(Card, { "data-slot": "quote-display", className: cn(className), ...props, children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex items-baseline justify-between", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-base font-semibold", children: m.heading }), quote.fareCodeName ? (_jsxs("p", { className: "text-sm text-muted-foreground", children: [quote.fareCodeName, quote.fareCode ? ` (${quote.fareCode})` : ""] })) : null] }), _jsxs("div", { className: "text-right", children: [_jsx("div", { className: "text-2xl font-bold", children: formatResolvedPrice(quote.totalForCabin, quote.currency) }), _jsx("div", { className: "text-xs text-muted-foreground", children: formatMessage(m.guestSummary, {
29
+ guestCount: quote.guestCount,
30
+ guestLabel,
31
+ occupancyLabel,
32
+ }) })] })] }) }), _jsxs(CardContent, { className: "space-y-4 text-sm", children: [_jsx(Row, { label: formatMessage(m.baseLine, {
33
+ price: formatResolvedPrice(quote.basePerPerson, quote.currency),
34
+ guestCount: quote.guestCount,
35
+ }) }), additions.length > 0 ? (_jsx(Section, { title: m.sections.additions, children: additions.map((c) => (_jsx(Row, { label: componentLabel(c, m), amount: `+ ${formatResolvedPrice(c.amount, c.currency)}` }, `add-${c.kind}-${c.label ?? ""}-${c.amount}`))) })) : null, credits.length > 0 ? (_jsx(Section, { title: m.sections.credits, children: credits.map((c) => (_jsx(Row, { label: componentLabel(c, m), amount: `− ${formatResolvedPrice(c.amount, c.currency)}`, amountClassName: "text-emerald-600" }, `cred-${c.kind}-${c.label ?? ""}-${c.amount}`))) })) : null, inclusions.length > 0 ? (_jsx(Section, { title: m.sections.included, children: inclusions.map((c) => (_jsx(Row, { label: c.label ?? m.componentKindLabels[c.kind], amount: m.includedAmount }, `inc-${c.kind}-${c.label ?? ""}`))) })) : null, _jsxs("div", { className: "border-t pt-3", children: [_jsx(Row, { label: m.totals.perPerson, amount: formatResolvedPrice(quote.totalPerPerson, quote.currency), amountClassName: "font-semibold" }), _jsx(Row, { label: m.totals.totalForCabin, amount: formatResolvedPrice(quote.totalForCabin, quote.currency), amountClassName: "font-bold text-base" })] })] })] }));
36
+ }
37
+ function componentLabel(component, messages) {
38
+ const baseLabel = component.label ?? messages.componentKindLabels[component.kind];
39
+ const scope = component.perPerson
40
+ ? messages.componentScope.perPerson
41
+ : messages.componentScope.perCabin;
42
+ return `${baseLabel} (${scope})`;
43
+ }
44
+ function Section({ title, children }) {
45
+ return (_jsxs("div", { className: "space-y-1", children: [_jsx("h4", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground", children: title }), children] }));
46
+ }
47
+ function Row({ label, amount, amountClassName, }) {
48
+ return (_jsxs("div", { className: "flex items-baseline justify-between gap-4", children: [_jsx("span", { className: "text-muted-foreground", children: label }), amount ? _jsx("span", { className: cn("tabular-nums", amountClassName), children: amount }) : null] }));
49
+ }
50
+ function formatCruiseMoney(amount, currency, i18n, options) {
51
+ const n = Number(amount);
52
+ if (!Number.isFinite(n)) {
53
+ return formatMessage(i18n.fallbackCurrencyAmount, { currency, amount });
54
+ }
55
+ try {
56
+ return i18n.formatCurrency(n, currency, options);
57
+ }
58
+ catch {
59
+ return formatMessage(i18n.fallbackCurrencyAmount, { currency, amount });
60
+ }
61
+ }
@@ -0,0 +1,15 @@
1
+ export * from "./use-cruise.js";
2
+ export * from "./use-cruise-booking.js";
3
+ export * from "./use-cruise-mutation.js";
4
+ export * from "./use-cruises.js";
5
+ export * from "./use-effective-itinerary.js";
6
+ export * from "./use-enrichment.js";
7
+ export * from "./use-external-actions.js";
8
+ export * from "./use-pricing.js";
9
+ export * from "./use-sailing-mutation.js";
10
+ export * from "./use-sailings.js";
11
+ export * from "./use-search-index.js";
12
+ export * from "./use-ship-mutation.js";
13
+ export * from "./use-ships.js";
14
+ export * from "./use-storefront.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,kBAAkB,CAAA;AAChC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,kBAAkB,CAAA;AAChC,cAAc,2BAA2B,CAAA;AACzC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qBAAqB,CAAA"}
@@ -0,0 +1,14 @@
1
+ export * from "./use-cruise.js";
2
+ export * from "./use-cruise-booking.js";
3
+ export * from "./use-cruise-mutation.js";
4
+ export * from "./use-cruises.js";
5
+ export * from "./use-effective-itinerary.js";
6
+ export * from "./use-enrichment.js";
7
+ export * from "./use-external-actions.js";
8
+ export * from "./use-pricing.js";
9
+ export * from "./use-sailing-mutation.js";
10
+ export * from "./use-sailings.js";
11
+ export * from "./use-search-index.js";
12
+ export * from "./use-ship-mutation.js";
13
+ export * from "./use-ships.js";
14
+ export * from "./use-storefront.js";
@@ -0,0 +1,205 @@
1
+ import { z } from "zod";
2
+ export interface BookingPassengerInput {
3
+ firstName: string;
4
+ lastName: string;
5
+ email?: string | null;
6
+ phone?: string | null;
7
+ travelerCategory?: "adult" | "child" | "infant" | "senior" | "other" | null;
8
+ preferredLanguage?: string | null;
9
+ specialRequests?: string | null;
10
+ isPrimary?: boolean;
11
+ notes?: string | null;
12
+ }
13
+ export interface BookingContactInput {
14
+ firstName: string;
15
+ lastName: string;
16
+ email?: string | null;
17
+ phone?: string | null;
18
+ language?: string | null;
19
+ country?: string | null;
20
+ region?: string | null;
21
+ city?: string | null;
22
+ address?: string | null;
23
+ postalCode?: string | null;
24
+ }
25
+ export type BookingMode = "inquiry" | "reserve";
26
+ export interface CreateCruiseBookingInput {
27
+ sailingId: string;
28
+ cabinCategoryId: string;
29
+ cabinId?: string | null;
30
+ occupancy: number;
31
+ fareCode?: string | null;
32
+ mode?: BookingMode;
33
+ personId?: string | null;
34
+ organizationId?: string | null;
35
+ contact: BookingContactInput;
36
+ passengers: BookingPassengerInput[];
37
+ notes?: string | null;
38
+ }
39
+ declare const cruiseBookingResultSchema: z.ZodObject<{
40
+ data: z.ZodObject<{
41
+ bookingId: z.ZodString;
42
+ bookingNumber: z.ZodString;
43
+ cruiseDetails: z.ZodUnknown;
44
+ quote: z.ZodObject<{
45
+ fareCode: z.ZodNullable<z.ZodString>;
46
+ fareCodeName: z.ZodNullable<z.ZodString>;
47
+ currency: z.ZodString;
48
+ occupancy: z.ZodNumber;
49
+ guestCount: z.ZodNumber;
50
+ basePerPerson: z.ZodString;
51
+ components: z.ZodArray<z.ZodObject<{
52
+ kind: z.ZodEnum<{
53
+ gratuity: "gratuity";
54
+ onboard_credit: "onboard_credit";
55
+ port_charge: "port_charge";
56
+ tax: "tax";
57
+ ncf: "ncf";
58
+ airfare: "airfare";
59
+ transfer: "transfer";
60
+ insurance: "insurance";
61
+ }>;
62
+ label: z.ZodNullable<z.ZodString>;
63
+ amount: z.ZodString;
64
+ currency: z.ZodString;
65
+ direction: z.ZodEnum<{
66
+ addition: "addition";
67
+ inclusion: "inclusion";
68
+ credit: "credit";
69
+ }>;
70
+ perPerson: z.ZodBoolean;
71
+ }, z.core.$strip>>;
72
+ totalPerPerson: z.ZodString;
73
+ totalForCabin: z.ZodString;
74
+ }, z.core.$strip>;
75
+ }, z.core.$strip>;
76
+ }, z.core.$strip>;
77
+ declare const cruisePartyBookingResultSchema: z.ZodObject<{
78
+ data: z.ZodObject<{
79
+ groupId: z.ZodString;
80
+ primaryBookingId: z.ZodNullable<z.ZodString>;
81
+ groupDetails: z.ZodUnknown;
82
+ cabins: z.ZodArray<z.ZodObject<{
83
+ bookingId: z.ZodString;
84
+ bookingNumber: z.ZodString;
85
+ cruiseDetails: z.ZodUnknown;
86
+ quote: z.ZodObject<{
87
+ fareCode: z.ZodNullable<z.ZodString>;
88
+ fareCodeName: z.ZodNullable<z.ZodString>;
89
+ currency: z.ZodString;
90
+ occupancy: z.ZodNumber;
91
+ guestCount: z.ZodNumber;
92
+ basePerPerson: z.ZodString;
93
+ components: z.ZodArray<z.ZodObject<{
94
+ kind: z.ZodEnum<{
95
+ gratuity: "gratuity";
96
+ onboard_credit: "onboard_credit";
97
+ port_charge: "port_charge";
98
+ tax: "tax";
99
+ ncf: "ncf";
100
+ airfare: "airfare";
101
+ transfer: "transfer";
102
+ insurance: "insurance";
103
+ }>;
104
+ label: z.ZodNullable<z.ZodString>;
105
+ amount: z.ZodString;
106
+ currency: z.ZodString;
107
+ direction: z.ZodEnum<{
108
+ addition: "addition";
109
+ inclusion: "inclusion";
110
+ credit: "credit";
111
+ }>;
112
+ perPerson: z.ZodBoolean;
113
+ }, z.core.$strip>>;
114
+ totalPerPerson: z.ZodString;
115
+ totalForCabin: z.ZodString;
116
+ }, z.core.$strip>;
117
+ }, z.core.$strip>>;
118
+ }, z.core.$strip>;
119
+ }, z.core.$strip>;
120
+ export type CreateCruiseBookingResult = z.infer<typeof cruiseBookingResultSchema>["data"];
121
+ export type CreateCruisePartyBookingResult = z.infer<typeof cruisePartyBookingResultSchema>["data"];
122
+ export interface PartyCabinEntry {
123
+ cabinCategoryId: string;
124
+ cabinId?: string | null;
125
+ occupancy: number;
126
+ fareCode?: string | null;
127
+ passengers: BookingPassengerInput[];
128
+ notes?: string | null;
129
+ }
130
+ export interface CreateCruisePartyBookingInput {
131
+ sailingId: string;
132
+ cabins: PartyCabinEntry[];
133
+ leadPersonId?: string | null;
134
+ organizationId?: string | null;
135
+ contact: BookingContactInput;
136
+ mode?: BookingMode;
137
+ label?: string;
138
+ notes?: string | null;
139
+ }
140
+ /**
141
+ * Booking creation hooks. The route layer detects local vs external
142
+ * sailings from the unified key and dispatches accordingly — this hook
143
+ * doesn't need to branch.
144
+ */
145
+ export declare function useCruiseBookingMutation(): {
146
+ createSingle: import("@tanstack/react-query").UseMutationResult<{
147
+ bookingId: string;
148
+ bookingNumber: string;
149
+ cruiseDetails: unknown;
150
+ quote: {
151
+ fareCode: string | null;
152
+ fareCodeName: string | null;
153
+ currency: string;
154
+ occupancy: number;
155
+ guestCount: number;
156
+ basePerPerson: string;
157
+ components: {
158
+ kind: "gratuity" | "onboard_credit" | "port_charge" | "tax" | "ncf" | "airfare" | "transfer" | "insurance";
159
+ label: string | null;
160
+ amount: string;
161
+ currency: string;
162
+ direction: "addition" | "inclusion" | "credit";
163
+ perPerson: boolean;
164
+ }[];
165
+ totalPerPerson: string;
166
+ totalForCabin: string;
167
+ };
168
+ }, Error, {
169
+ sailingKey: string;
170
+ input: CreateCruiseBookingInput;
171
+ }, unknown>;
172
+ createParty: import("@tanstack/react-query").UseMutationResult<{
173
+ groupId: string;
174
+ primaryBookingId: string | null;
175
+ groupDetails: unknown;
176
+ cabins: {
177
+ bookingId: string;
178
+ bookingNumber: string;
179
+ cruiseDetails: unknown;
180
+ quote: {
181
+ fareCode: string | null;
182
+ fareCodeName: string | null;
183
+ currency: string;
184
+ occupancy: number;
185
+ guestCount: number;
186
+ basePerPerson: string;
187
+ components: {
188
+ kind: "gratuity" | "onboard_credit" | "port_charge" | "tax" | "ncf" | "airfare" | "transfer" | "insurance";
189
+ label: string | null;
190
+ amount: string;
191
+ currency: string;
192
+ direction: "addition" | "inclusion" | "credit";
193
+ perPerson: boolean;
194
+ }[];
195
+ totalPerPerson: string;
196
+ totalForCabin: string;
197
+ };
198
+ }[];
199
+ }, Error, {
200
+ sailingKey: string;
201
+ input: CreateCruisePartyBookingInput;
202
+ }, unknown>;
203
+ };
204
+ export {};
205
+ //# sourceMappingURL=use-cruise-booking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-cruise-booking.d.ts","sourceRoot":"","sources":["../../src/hooks/use-cruise-booking.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
2
+ import { z } from "zod";
3
+ import { fetchWithValidation } from "../client.js";
4
+ import { useVoyantCruisesContext } from "../provider.js";
5
+ import { cruisesQueryKeys } from "../query-keys.js";
6
+ import { quoteSchema, singleEnvelope } from "../schemas.js";
7
+ const cruiseBookingResultSchema = singleEnvelope(z.object({
8
+ bookingId: z.string(),
9
+ bookingNumber: z.string(),
10
+ cruiseDetails: z.unknown(),
11
+ quote: quoteSchema,
12
+ }));
13
+ const cruisePartyBookingResultSchema = singleEnvelope(z.object({
14
+ groupId: z.string(),
15
+ primaryBookingId: z.string().nullable(),
16
+ groupDetails: z.unknown(),
17
+ cabins: z.array(z.object({
18
+ bookingId: z.string(),
19
+ bookingNumber: z.string(),
20
+ cruiseDetails: z.unknown(),
21
+ quote: quoteSchema,
22
+ })),
23
+ }));
24
+ /**
25
+ * Booking creation hooks. The route layer detects local vs external
26
+ * sailings from the unified key and dispatches accordingly — this hook
27
+ * doesn't need to branch.
28
+ */
29
+ export function useCruiseBookingMutation() {
30
+ const { baseUrl, fetcher } = useVoyantCruisesContext();
31
+ const client = { baseUrl, fetcher };
32
+ const queryClient = useQueryClient();
33
+ const createSingle = useMutation({
34
+ mutationFn: async ({ sailingKey, input, }) => {
35
+ const result = await fetchWithValidation(`/v1/admin/cruises/sailings/${encodeURIComponent(sailingKey)}/bookings`, cruiseBookingResultSchema, client, { method: "POST", body: JSON.stringify(input) });
36
+ return result.data;
37
+ },
38
+ onSuccess: () => {
39
+ // Bookings live in the bookings module; we invalidate cruise aggregates
40
+ // because price availability may have changed (cabin sold).
41
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.cruises() });
42
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.sailings() });
43
+ },
44
+ });
45
+ const createParty = useMutation({
46
+ mutationFn: async ({ sailingKey, input, }) => {
47
+ const result = await fetchWithValidation(`/v1/admin/cruises/sailings/${encodeURIComponent(sailingKey)}/party-bookings`, cruisePartyBookingResultSchema, client, { method: "POST", body: JSON.stringify(input) });
48
+ return result.data;
49
+ },
50
+ onSuccess: () => {
51
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.cruises() });
52
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.sailings() });
53
+ },
54
+ });
55
+ return { createSingle, createParty };
56
+ }
@@ -0,0 +1,144 @@
1
+ export interface CreateCruiseInput {
2
+ slug: string;
3
+ name: string;
4
+ cruiseType: "ocean" | "river" | "expedition" | "coastal";
5
+ nights: number;
6
+ lineSupplierId?: string | null;
7
+ defaultShipId?: string | null;
8
+ embarkPortFacilityId?: string | null;
9
+ disembarkPortFacilityId?: string | null;
10
+ description?: string | null;
11
+ shortDescription?: string | null;
12
+ highlights?: string[];
13
+ inclusionsHtml?: string | null;
14
+ exclusionsHtml?: string | null;
15
+ regions?: string[];
16
+ themes?: string[];
17
+ heroImageUrl?: string | null;
18
+ mapImageUrl?: string | null;
19
+ status?: "draft" | "awaiting_review" | "live" | "archived";
20
+ }
21
+ export type UpdateCruiseInput = Partial<CreateCruiseInput>;
22
+ /**
23
+ * Mutation set for self-managed cruises: create / update / archive /
24
+ * recompute aggregates. Writes against external cruises return 409 from
25
+ * the server; this hook surfaces those as VoyantApiError.
26
+ */
27
+ export declare function useCruiseMutation(): {
28
+ create: import("@tanstack/react-query").UseMutationResult<{
29
+ id: string;
30
+ slug: string;
31
+ name: string;
32
+ cruiseType: "ocean" | "river" | "expedition" | "coastal";
33
+ lineSupplierId: string | null;
34
+ defaultShipId: string | null;
35
+ nights: number;
36
+ embarkPortFacilityId: string | null;
37
+ disembarkPortFacilityId: string | null;
38
+ description: string | null;
39
+ shortDescription: string | null;
40
+ highlights: string[] | null;
41
+ inclusionsHtml: string | null;
42
+ exclusionsHtml: string | null;
43
+ regions: string[] | null;
44
+ themes: string[] | null;
45
+ heroImageUrl: string | null;
46
+ mapImageUrl: string | null;
47
+ status: "draft" | "awaiting_review" | "live" | "archived";
48
+ lowestPriceCached: string | null;
49
+ lowestPriceCurrencyCached: string | null;
50
+ earliestDepartureCached: string | null;
51
+ latestDepartureCached: string | null;
52
+ externalRefs: Record<string, string> | null;
53
+ createdAt: string;
54
+ updatedAt: string;
55
+ }, Error, CreateCruiseInput, unknown>;
56
+ update: import("@tanstack/react-query").UseMutationResult<{
57
+ id: string;
58
+ slug: string;
59
+ name: string;
60
+ cruiseType: "ocean" | "river" | "expedition" | "coastal";
61
+ lineSupplierId: string | null;
62
+ defaultShipId: string | null;
63
+ nights: number;
64
+ embarkPortFacilityId: string | null;
65
+ disembarkPortFacilityId: string | null;
66
+ description: string | null;
67
+ shortDescription: string | null;
68
+ highlights: string[] | null;
69
+ inclusionsHtml: string | null;
70
+ exclusionsHtml: string | null;
71
+ regions: string[] | null;
72
+ themes: string[] | null;
73
+ heroImageUrl: string | null;
74
+ mapImageUrl: string | null;
75
+ status: "draft" | "awaiting_review" | "live" | "archived";
76
+ lowestPriceCached: string | null;
77
+ lowestPriceCurrencyCached: string | null;
78
+ earliestDepartureCached: string | null;
79
+ latestDepartureCached: string | null;
80
+ externalRefs: Record<string, string> | null;
81
+ createdAt: string;
82
+ updatedAt: string;
83
+ }, Error, {
84
+ key: string;
85
+ input: UpdateCruiseInput;
86
+ }, unknown>;
87
+ archive: import("@tanstack/react-query").UseMutationResult<{
88
+ id: string;
89
+ slug: string;
90
+ name: string;
91
+ cruiseType: "ocean" | "river" | "expedition" | "coastal";
92
+ lineSupplierId: string | null;
93
+ defaultShipId: string | null;
94
+ nights: number;
95
+ embarkPortFacilityId: string | null;
96
+ disembarkPortFacilityId: string | null;
97
+ description: string | null;
98
+ shortDescription: string | null;
99
+ highlights: string[] | null;
100
+ inclusionsHtml: string | null;
101
+ exclusionsHtml: string | null;
102
+ regions: string[] | null;
103
+ themes: string[] | null;
104
+ heroImageUrl: string | null;
105
+ mapImageUrl: string | null;
106
+ status: "draft" | "awaiting_review" | "live" | "archived";
107
+ lowestPriceCached: string | null;
108
+ lowestPriceCurrencyCached: string | null;
109
+ earliestDepartureCached: string | null;
110
+ latestDepartureCached: string | null;
111
+ externalRefs: Record<string, string> | null;
112
+ createdAt: string;
113
+ updatedAt: string;
114
+ }, Error, string, unknown>;
115
+ recomputeAggregates: import("@tanstack/react-query").UseMutationResult<{
116
+ id: string;
117
+ slug: string;
118
+ name: string;
119
+ cruiseType: "ocean" | "river" | "expedition" | "coastal";
120
+ lineSupplierId: string | null;
121
+ defaultShipId: string | null;
122
+ nights: number;
123
+ embarkPortFacilityId: string | null;
124
+ disembarkPortFacilityId: string | null;
125
+ description: string | null;
126
+ shortDescription: string | null;
127
+ highlights: string[] | null;
128
+ inclusionsHtml: string | null;
129
+ exclusionsHtml: string | null;
130
+ regions: string[] | null;
131
+ themes: string[] | null;
132
+ heroImageUrl: string | null;
133
+ mapImageUrl: string | null;
134
+ status: "draft" | "awaiting_review" | "live" | "archived";
135
+ lowestPriceCached: string | null;
136
+ lowestPriceCurrencyCached: string | null;
137
+ earliestDepartureCached: string | null;
138
+ latestDepartureCached: string | null;
139
+ externalRefs: Record<string, string> | null;
140
+ createdAt: string;
141
+ updatedAt: string;
142
+ }, Error, string, unknown>;
143
+ };
144
+ //# sourceMappingURL=use-cruise-mutation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-cruise-mutation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-cruise-mutation.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,CAAA;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,OAAO,GAAG,iBAAiB,GAAG,MAAM,GAAG,UAAU,CAAA;CAC3D;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAE1D;;;;GAIG;AACH,wBAAgB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAuBtB,MAAM;eACJ,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiD7B"}
@@ -0,0 +1,58 @@
1
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
2
+ import { fetchWithValidation } from "../client.js";
3
+ import { useVoyantCruisesContext } from "../provider.js";
4
+ import { cruisesQueryKeys } from "../query-keys.js";
5
+ import { cruiseSingleResponse } from "../schemas.js";
6
+ /**
7
+ * Mutation set for self-managed cruises: create / update / archive /
8
+ * recompute aggregates. Writes against external cruises return 409 from
9
+ * the server; this hook surfaces those as VoyantApiError.
10
+ */
11
+ export function useCruiseMutation() {
12
+ const { baseUrl, fetcher } = useVoyantCruisesContext();
13
+ const client = { baseUrl, fetcher };
14
+ const queryClient = useQueryClient();
15
+ const create = useMutation({
16
+ mutationFn: async (input) => {
17
+ const result = await fetchWithValidation("/v1/admin/cruises", cruiseSingleResponse, client, {
18
+ method: "POST",
19
+ body: JSON.stringify(input),
20
+ });
21
+ return result.data;
22
+ },
23
+ onSuccess: () => {
24
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.cruises() });
25
+ },
26
+ });
27
+ const update = useMutation({
28
+ mutationFn: async ({ key, input, }) => {
29
+ const result = await fetchWithValidation(`/v1/admin/cruises/${encodeURIComponent(key)}`, cruiseSingleResponse, client, { method: "PUT", body: JSON.stringify(input) });
30
+ return result.data;
31
+ },
32
+ onSuccess: (data) => {
33
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.cruises() });
34
+ queryClient.setQueryData(cruisesQueryKeys.cruise(data.id), data);
35
+ },
36
+ });
37
+ const archive = useMutation({
38
+ mutationFn: async (key) => {
39
+ const result = await fetchWithValidation(`/v1/admin/cruises/${encodeURIComponent(key)}`, cruiseSingleResponse, client, { method: "DELETE" });
40
+ return result.data;
41
+ },
42
+ onSuccess: (data) => {
43
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.cruises() });
44
+ queryClient.setQueryData(cruisesQueryKeys.cruise(data.id), data);
45
+ },
46
+ });
47
+ const recomputeAggregates = useMutation({
48
+ mutationFn: async (key) => {
49
+ const result = await fetchWithValidation(`/v1/admin/cruises/${encodeURIComponent(key)}/aggregates/recompute`, cruiseSingleResponse, client, { method: "POST" });
50
+ return result.data;
51
+ },
52
+ onSuccess: (data) => {
53
+ void queryClient.invalidateQueries({ queryKey: cruisesQueryKeys.cruises() });
54
+ queryClient.setQueryData(cruisesQueryKeys.cruise(data.id), data);
55
+ },
56
+ });
57
+ return { create, update, archive, recomputeAggregates };
58
+ }
@@ -0,0 +1,38 @@
1
+ export interface UseCruiseOptions {
2
+ enabled?: boolean;
3
+ include?: ReadonlyArray<"sailings" | "days">;
4
+ }
5
+ /**
6
+ * Admin cruise detail. Accepts both local TypeIDs (`cru_*`) and external
7
+ * adapter keys (`<provider>:<ref>`); the server dispatches to the local DB
8
+ * or to the registered adapter accordingly.
9
+ */
10
+ export declare function useCruise(key: string | null | undefined, options?: UseCruiseOptions): import("@tanstack/react-query").UseQueryResult<{
11
+ id: string;
12
+ slug: string;
13
+ name: string;
14
+ cruiseType: "ocean" | "river" | "expedition" | "coastal";
15
+ lineSupplierId: string | null;
16
+ defaultShipId: string | null;
17
+ nights: number;
18
+ embarkPortFacilityId: string | null;
19
+ disembarkPortFacilityId: string | null;
20
+ description: string | null;
21
+ shortDescription: string | null;
22
+ highlights: string[] | null;
23
+ inclusionsHtml: string | null;
24
+ exclusionsHtml: string | null;
25
+ regions: string[] | null;
26
+ themes: string[] | null;
27
+ heroImageUrl: string | null;
28
+ mapImageUrl: string | null;
29
+ status: "draft" | "awaiting_review" | "live" | "archived";
30
+ lowestPriceCached: string | null;
31
+ lowestPriceCurrencyCached: string | null;
32
+ earliestDepartureCached: string | null;
33
+ latestDepartureCached: string | null;
34
+ externalRefs: Record<string, string> | null;
35
+ createdAt: string;
36
+ updatedAt: string;
37
+ }, Error>;
38
+ //# sourceMappingURL=use-cruise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-cruise.d.ts","sourceRoot":"","sources":["../../src/hooks/use-cruise.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,CAAA;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,GAAE,gBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;UAOvF"}
@@ -0,0 +1,16 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { useVoyantCruisesContext } from "../provider.js";
3
+ import { getCruiseQueryOptions } from "../query-options.js";
4
+ /**
5
+ * Admin cruise detail. Accepts both local TypeIDs (`cru_*`) and external
6
+ * adapter keys (`<provider>:<ref>`); the server dispatches to the local DB
7
+ * or to the registered adapter accordingly.
8
+ */
9
+ export function useCruise(key, options = {}) {
10
+ const { baseUrl, fetcher } = useVoyantCruisesContext();
11
+ const { enabled = true, include } = options;
12
+ return useQuery({
13
+ ...getCruiseQueryOptions({ baseUrl, fetcher }, key ?? "", { include }),
14
+ enabled: enabled && !!key,
15
+ });
16
+ }