@burdenoff/microfe-billing 2026.708.1 → 2026.716.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/billing/modules/checkout/components/StoreShippingSection.js +444 -0
- package/dist/billing/modules/checkout/components/StoreShippingSection.js.map +1 -0
- package/dist/billing/modules/checkout/components/index.js +1 -0
- package/dist/billing/modules/checkout/hooks/useStoreShipping.js +113 -0
- package/dist/billing/modules/checkout/hooks/useStoreShipping.js.map +1 -0
- package/dist/billing/modules/checkout/index.js +1 -0
- package/dist/billing/modules/checkout/pages/CheckoutPage.js +542 -475
- package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
- package/dist/generated/global-operations.js +77 -1
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import { useCreateShippingAddress as e, useEstimateOrderShipping as t, useMyShippingAddresses as n, useShippingMethods as r } from "../hooks/useStoreShipping.js";
|
|
2
|
+
import { useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
|
|
3
|
+
import { Check as c, Loader2 as l, MapPin as u, Plus as d, Truck as f, X as p } from "lucide-react";
|
|
4
|
+
import { Fragment as ee, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
5
|
+
//#region src/billing/modules/checkout/components/StoreShippingSection.tsx
|
|
6
|
+
var g = [
|
|
7
|
+
{
|
|
8
|
+
value: "IN",
|
|
9
|
+
label: "India"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
value: "US",
|
|
13
|
+
label: "United States"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
value: "GB",
|
|
17
|
+
label: "United Kingdom"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
value: "AU",
|
|
21
|
+
label: "Australia"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
value: "CA",
|
|
25
|
+
label: "Canada"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: "SG",
|
|
29
|
+
label: "Singapore"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
value: "DE",
|
|
33
|
+
label: "Germany"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
value: "FR",
|
|
37
|
+
label: "France"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
value: "AE",
|
|
41
|
+
label: "UAE"
|
|
42
|
+
}
|
|
43
|
+
], _ = {
|
|
44
|
+
fullName: "",
|
|
45
|
+
phone: "",
|
|
46
|
+
addressLine1: "",
|
|
47
|
+
addressLine2: "",
|
|
48
|
+
city: "",
|
|
49
|
+
state: "",
|
|
50
|
+
postalCode: "",
|
|
51
|
+
country: "IN"
|
|
52
|
+
};
|
|
53
|
+
function v(e, t) {
|
|
54
|
+
try {
|
|
55
|
+
return e.toLocaleString("en", {
|
|
56
|
+
style: "currency",
|
|
57
|
+
currency: t || "USD"
|
|
58
|
+
});
|
|
59
|
+
} catch {
|
|
60
|
+
return `${t || "USD"} ${e.toFixed(2)}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function y(e, t) {
|
|
64
|
+
if (e == null && t == null) return null;
|
|
65
|
+
if (e != null && t != null) return e === t ? `${e} days` : `${e}–${t} days`;
|
|
66
|
+
let n = e ?? t;
|
|
67
|
+
return n == null ? null : `${n} days`;
|
|
68
|
+
}
|
|
69
|
+
var b = ({ storeOrderId: b, currency: x, onChange: S }) => {
|
|
70
|
+
let { addresses: C, loading: w, refetch: T } = n(), { createShippingAddress: E, loading: D } = e(), { methods: O, loading: k } = r(), [A, { data: j, loading: M }] = t(), [N, P] = s(null), [F, I] = s(null), [L, R] = s(!1), [z, B] = s(_), [V, H] = s({}), [U, W] = s(null), G = o(S);
|
|
71
|
+
i(() => {
|
|
72
|
+
G.current = S;
|
|
73
|
+
});
|
|
74
|
+
let K = a(() => C.find((e) => e.id === N), [C, N]), q = a(() => {
|
|
75
|
+
if (!K) return [];
|
|
76
|
+
let e = K.country;
|
|
77
|
+
return O.filter((t) => t.isActive && (t.availableCountries.length === 0 || t.availableCountries.includes(e)) && !t.excludedCountries.includes(e)).sort((e, t) => e.displayOrder - t.displayOrder);
|
|
78
|
+
}, [O, K]);
|
|
79
|
+
i(() => {
|
|
80
|
+
!N && C.length > 0 && P((C.find((e) => e.isDefault) ?? C[0]).id);
|
|
81
|
+
}, [C, N]), i(() => {
|
|
82
|
+
F && !q.some((e) => e.id === F) && I(null);
|
|
83
|
+
}, [q, F]), i(() => {
|
|
84
|
+
K && F && A({ variables: { input: {
|
|
85
|
+
orderId: b,
|
|
86
|
+
shippingMethodId: F,
|
|
87
|
+
destinationCountry: K.country,
|
|
88
|
+
destinationPostalCode: K.postalCode
|
|
89
|
+
} } });
|
|
90
|
+
}, [
|
|
91
|
+
K?.id,
|
|
92
|
+
K?.country,
|
|
93
|
+
K?.postalCode,
|
|
94
|
+
F,
|
|
95
|
+
b,
|
|
96
|
+
A,
|
|
97
|
+
K
|
|
98
|
+
]);
|
|
99
|
+
let J = j?.estimateOrderShipping, Y = !!(N && F && !M && J && J.shippingMethodId === F);
|
|
100
|
+
i(() => {
|
|
101
|
+
G.current({
|
|
102
|
+
shippingAddressId: N,
|
|
103
|
+
shippingMethodId: Y ? F : null,
|
|
104
|
+
shippingCost: Y && J ? J.cost : 0,
|
|
105
|
+
destinationCountry: K?.country ?? null
|
|
106
|
+
});
|
|
107
|
+
}, [
|
|
108
|
+
N,
|
|
109
|
+
F,
|
|
110
|
+
Y,
|
|
111
|
+
J?.cost,
|
|
112
|
+
K?.country
|
|
113
|
+
]);
|
|
114
|
+
let X = (e, t) => B((n) => ({
|
|
115
|
+
...n,
|
|
116
|
+
[e]: t
|
|
117
|
+
})), Z = () => {
|
|
118
|
+
let e = {};
|
|
119
|
+
return z.fullName.trim() || (e.fullName = "Recipient name is required"), z.addressLine1.trim() || (e.addressLine1 = "Street address is required"), z.city.trim() || (e.city = "City is required"), z.postalCode.trim() || (e.postalCode = "Postal code is required"), z.country.trim() || (e.country = "Country is required"), H(e), Object.keys(e).length === 0;
|
|
120
|
+
}, Q = async () => {
|
|
121
|
+
if (Z()) {
|
|
122
|
+
W(null);
|
|
123
|
+
try {
|
|
124
|
+
let e = await E({
|
|
125
|
+
fullName: z.fullName.trim(),
|
|
126
|
+
...z.phone.trim() ? { phone: z.phone.trim() } : {},
|
|
127
|
+
addressLine1: z.addressLine1.trim(),
|
|
128
|
+
...z.addressLine2.trim() ? { addressLine2: z.addressLine2.trim() } : {},
|
|
129
|
+
city: z.city.trim(),
|
|
130
|
+
...z.state.trim() ? { state: z.state.trim() } : {},
|
|
131
|
+
postalCode: z.postalCode.trim(),
|
|
132
|
+
country: z.country,
|
|
133
|
+
isDefault: C.length === 0
|
|
134
|
+
});
|
|
135
|
+
if (!e) {
|
|
136
|
+
W("Failed to save address. Please try again.");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
await T(), P(e.id), I(null), B(_), H({}), R(!1);
|
|
140
|
+
} catch {
|
|
141
|
+
W("Failed to save address. Please try again.");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}, $ = (e) => `w-full px-3 py-2 text-sm border rounded-input bg-bg-surface text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] ${e ? "border-status-error-border" : "border-border-subtle"}`;
|
|
145
|
+
return /* @__PURE__ */ h("div", {
|
|
146
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6 space-y-5",
|
|
147
|
+
children: [
|
|
148
|
+
/* @__PURE__ */ h("div", {
|
|
149
|
+
className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
|
|
150
|
+
children: [/* @__PURE__ */ m(f, { className: "size-4 text-text-secondary" }), "Shipping"]
|
|
151
|
+
}),
|
|
152
|
+
/* @__PURE__ */ h("section", {
|
|
153
|
+
className: "space-y-3",
|
|
154
|
+
children: [
|
|
155
|
+
/* @__PURE__ */ h("div", {
|
|
156
|
+
className: "flex items-center justify-between",
|
|
157
|
+
children: [/* @__PURE__ */ h("div", {
|
|
158
|
+
className: "flex items-center gap-2 text-sm font-medium text-text-primary",
|
|
159
|
+
children: [/* @__PURE__ */ m(u, { className: "size-4 text-text-secondary" }), "Delivery address"]
|
|
160
|
+
}), !L && /* @__PURE__ */ h("button", {
|
|
161
|
+
type: "button",
|
|
162
|
+
onClick: () => {
|
|
163
|
+
R(!0), W(null);
|
|
164
|
+
},
|
|
165
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-text-link hover:underline",
|
|
166
|
+
children: [/* @__PURE__ */ m(d, { className: "size-3.5" }), "Add address"]
|
|
167
|
+
})]
|
|
168
|
+
}),
|
|
169
|
+
w && C.length === 0 ? /* @__PURE__ */ h("div", {
|
|
170
|
+
className: "flex items-center gap-2 text-sm text-text-secondary",
|
|
171
|
+
children: [/* @__PURE__ */ m(l, { className: "size-4 animate-spin" }), "Loading addresses…"]
|
|
172
|
+
}) : /* @__PURE__ */ h(ee, { children: [C.length === 0 && !L && /* @__PURE__ */ m("p", {
|
|
173
|
+
className: "text-sm text-text-secondary",
|
|
174
|
+
children: "No saved delivery addresses yet. Add one to continue."
|
|
175
|
+
}), C.length > 0 && /* @__PURE__ */ m("div", {
|
|
176
|
+
className: "space-y-2",
|
|
177
|
+
children: C.map((e) => {
|
|
178
|
+
let t = e.id === N;
|
|
179
|
+
return /* @__PURE__ */ m("button", {
|
|
180
|
+
type: "button",
|
|
181
|
+
onClick: () => {
|
|
182
|
+
P(e.id), I(null);
|
|
183
|
+
},
|
|
184
|
+
className: `w-full text-left p-3 rounded-input border transition-colors ${t ? "border-action-primary-bg bg-bg-sunken" : "border-border-subtle hover:bg-bg-sunken"}`,
|
|
185
|
+
children: /* @__PURE__ */ h("div", {
|
|
186
|
+
className: "flex items-start justify-between gap-2",
|
|
187
|
+
children: [/* @__PURE__ */ h("div", {
|
|
188
|
+
className: "text-sm",
|
|
189
|
+
children: [
|
|
190
|
+
/* @__PURE__ */ h("p", {
|
|
191
|
+
className: "font-medium text-text-primary",
|
|
192
|
+
children: [e.fullName, e.label ? /* @__PURE__ */ h("span", {
|
|
193
|
+
className: "ml-2 text-xs text-text-muted",
|
|
194
|
+
children: [
|
|
195
|
+
"(",
|
|
196
|
+
e.label,
|
|
197
|
+
")"
|
|
198
|
+
]
|
|
199
|
+
}) : null]
|
|
200
|
+
}),
|
|
201
|
+
/* @__PURE__ */ m("p", {
|
|
202
|
+
className: "text-text-secondary text-xs mt-0.5",
|
|
203
|
+
children: [
|
|
204
|
+
e.addressLine1,
|
|
205
|
+
e.addressLine2,
|
|
206
|
+
e.city,
|
|
207
|
+
e.state,
|
|
208
|
+
e.postalCode,
|
|
209
|
+
e.country
|
|
210
|
+
].filter(Boolean).join(", ")
|
|
211
|
+
}),
|
|
212
|
+
e.phone && /* @__PURE__ */ m("p", {
|
|
213
|
+
className: "text-text-muted text-xs mt-0.5",
|
|
214
|
+
children: e.phone
|
|
215
|
+
})
|
|
216
|
+
]
|
|
217
|
+
}), t && /* @__PURE__ */ m(c, { className: "size-4 text-action-primary-bg shrink-0 mt-0.5" })]
|
|
218
|
+
})
|
|
219
|
+
}, e.id);
|
|
220
|
+
})
|
|
221
|
+
})] }),
|
|
222
|
+
L && /* @__PURE__ */ h("div", {
|
|
223
|
+
className: "rounded-input border border-border-subtle p-3 space-y-3 bg-bg-sunken",
|
|
224
|
+
children: [
|
|
225
|
+
/* @__PURE__ */ h("div", {
|
|
226
|
+
className: "flex items-center justify-between",
|
|
227
|
+
children: [/* @__PURE__ */ m("span", {
|
|
228
|
+
className: "text-sm font-medium text-text-primary",
|
|
229
|
+
children: "New delivery address"
|
|
230
|
+
}), /* @__PURE__ */ m("button", {
|
|
231
|
+
type: "button",
|
|
232
|
+
onClick: () => {
|
|
233
|
+
R(!1), H({}), W(null);
|
|
234
|
+
},
|
|
235
|
+
className: "p-1 text-text-secondary hover:text-text-primary rounded-button",
|
|
236
|
+
children: /* @__PURE__ */ m(p, { className: "size-4" })
|
|
237
|
+
})]
|
|
238
|
+
}),
|
|
239
|
+
U && /* @__PURE__ */ m("div", {
|
|
240
|
+
className: "p-2 rounded-lg bg-status-error-bg-subtle border border-status-error-border text-xs text-status-error-text",
|
|
241
|
+
children: U
|
|
242
|
+
}),
|
|
243
|
+
/* @__PURE__ */ h("div", { children: [
|
|
244
|
+
/* @__PURE__ */ m("label", {
|
|
245
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
246
|
+
children: "Recipient name"
|
|
247
|
+
}),
|
|
248
|
+
/* @__PURE__ */ m("input", {
|
|
249
|
+
type: "text",
|
|
250
|
+
value: z.fullName,
|
|
251
|
+
onChange: (e) => X("fullName", e.target.value),
|
|
252
|
+
placeholder: "Jane Doe",
|
|
253
|
+
className: $(!!V.fullName)
|
|
254
|
+
}),
|
|
255
|
+
V.fullName && /* @__PURE__ */ m("p", {
|
|
256
|
+
className: "mt-1 text-xs text-status-error-text",
|
|
257
|
+
children: V.fullName
|
|
258
|
+
})
|
|
259
|
+
] }),
|
|
260
|
+
/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("label", {
|
|
261
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
262
|
+
children: ["Phone ", /* @__PURE__ */ m("span", {
|
|
263
|
+
className: "text-text-muted",
|
|
264
|
+
children: "(optional)"
|
|
265
|
+
})]
|
|
266
|
+
}), /* @__PURE__ */ m("input", {
|
|
267
|
+
type: "tel",
|
|
268
|
+
value: z.phone,
|
|
269
|
+
onChange: (e) => X("phone", e.target.value),
|
|
270
|
+
placeholder: "+91 98765 43210",
|
|
271
|
+
className: $(!1)
|
|
272
|
+
})] }),
|
|
273
|
+
/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("label", {
|
|
274
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
275
|
+
children: "Country"
|
|
276
|
+
}), /* @__PURE__ */ m("select", {
|
|
277
|
+
value: z.country,
|
|
278
|
+
onChange: (e) => X("country", e.target.value),
|
|
279
|
+
className: $(!!V.country),
|
|
280
|
+
children: g.map((e) => /* @__PURE__ */ m("option", {
|
|
281
|
+
value: e.value,
|
|
282
|
+
children: e.label
|
|
283
|
+
}, e.value))
|
|
284
|
+
})] }),
|
|
285
|
+
/* @__PURE__ */ h("div", { children: [
|
|
286
|
+
/* @__PURE__ */ m("label", {
|
|
287
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
288
|
+
children: "Street address"
|
|
289
|
+
}),
|
|
290
|
+
/* @__PURE__ */ m("input", {
|
|
291
|
+
type: "text",
|
|
292
|
+
value: z.addressLine1,
|
|
293
|
+
onChange: (e) => X("addressLine1", e.target.value),
|
|
294
|
+
placeholder: "123 Main St",
|
|
295
|
+
className: $(!!V.addressLine1)
|
|
296
|
+
}),
|
|
297
|
+
V.addressLine1 && /* @__PURE__ */ m("p", {
|
|
298
|
+
className: "mt-1 text-xs text-status-error-text",
|
|
299
|
+
children: V.addressLine1
|
|
300
|
+
})
|
|
301
|
+
] }),
|
|
302
|
+
/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("label", {
|
|
303
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
304
|
+
children: ["Apartment, suite, etc. ", /* @__PURE__ */ m("span", {
|
|
305
|
+
className: "text-text-muted",
|
|
306
|
+
children: "(optional)"
|
|
307
|
+
})]
|
|
308
|
+
}), /* @__PURE__ */ m("input", {
|
|
309
|
+
type: "text",
|
|
310
|
+
value: z.addressLine2,
|
|
311
|
+
onChange: (e) => X("addressLine2", e.target.value),
|
|
312
|
+
placeholder: "Apt 4B",
|
|
313
|
+
className: $(!1)
|
|
314
|
+
})] }),
|
|
315
|
+
/* @__PURE__ */ h("div", {
|
|
316
|
+
className: "grid grid-cols-2 gap-3",
|
|
317
|
+
children: [/* @__PURE__ */ h("div", { children: [
|
|
318
|
+
/* @__PURE__ */ m("label", {
|
|
319
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
320
|
+
children: "City"
|
|
321
|
+
}),
|
|
322
|
+
/* @__PURE__ */ m("input", {
|
|
323
|
+
type: "text",
|
|
324
|
+
value: z.city,
|
|
325
|
+
onChange: (e) => X("city", e.target.value),
|
|
326
|
+
placeholder: "Mumbai",
|
|
327
|
+
className: $(!!V.city)
|
|
328
|
+
}),
|
|
329
|
+
V.city && /* @__PURE__ */ m("p", {
|
|
330
|
+
className: "mt-1 text-xs text-status-error-text",
|
|
331
|
+
children: V.city
|
|
332
|
+
})
|
|
333
|
+
] }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("label", {
|
|
334
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
335
|
+
children: ["State ", /* @__PURE__ */ m("span", {
|
|
336
|
+
className: "text-text-muted",
|
|
337
|
+
children: "(optional)"
|
|
338
|
+
})]
|
|
339
|
+
}), /* @__PURE__ */ m("input", {
|
|
340
|
+
type: "text",
|
|
341
|
+
value: z.state,
|
|
342
|
+
onChange: (e) => X("state", e.target.value),
|
|
343
|
+
placeholder: "Maharashtra",
|
|
344
|
+
className: $(!1)
|
|
345
|
+
})] })]
|
|
346
|
+
}),
|
|
347
|
+
/* @__PURE__ */ h("div", { children: [
|
|
348
|
+
/* @__PURE__ */ m("label", {
|
|
349
|
+
className: "block text-xs text-text-secondary mb-1",
|
|
350
|
+
children: "Postal code"
|
|
351
|
+
}),
|
|
352
|
+
/* @__PURE__ */ m("input", {
|
|
353
|
+
type: "text",
|
|
354
|
+
value: z.postalCode,
|
|
355
|
+
onChange: (e) => X("postalCode", e.target.value),
|
|
356
|
+
placeholder: "400001",
|
|
357
|
+
className: $(!!V.postalCode)
|
|
358
|
+
}),
|
|
359
|
+
V.postalCode && /* @__PURE__ */ m("p", {
|
|
360
|
+
className: "mt-1 text-xs text-status-error-text",
|
|
361
|
+
children: V.postalCode
|
|
362
|
+
})
|
|
363
|
+
] }),
|
|
364
|
+
/* @__PURE__ */ m("div", {
|
|
365
|
+
className: "flex justify-end",
|
|
366
|
+
children: /* @__PURE__ */ h("button", {
|
|
367
|
+
type: "button",
|
|
368
|
+
onClick: Q,
|
|
369
|
+
disabled: D,
|
|
370
|
+
className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg hover:bg-action-primary-bgHover rounded-lg transition-colors disabled:opacity-50",
|
|
371
|
+
children: [D && /* @__PURE__ */ m(l, { className: "size-4 animate-spin" }), "Save address"]
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
]
|
|
375
|
+
})
|
|
376
|
+
]
|
|
377
|
+
}),
|
|
378
|
+
/* @__PURE__ */ h("section", {
|
|
379
|
+
className: "space-y-3",
|
|
380
|
+
children: [
|
|
381
|
+
/* @__PURE__ */ h("div", {
|
|
382
|
+
className: "flex items-center gap-2 text-sm font-medium text-text-primary",
|
|
383
|
+
children: [/* @__PURE__ */ m(f, { className: "size-4 text-text-secondary" }), "Shipping method"]
|
|
384
|
+
}),
|
|
385
|
+
K ? k && O.length === 0 ? /* @__PURE__ */ h("div", {
|
|
386
|
+
className: "flex items-center gap-2 text-sm text-text-secondary",
|
|
387
|
+
children: [/* @__PURE__ */ m(l, { className: "size-4 animate-spin" }), "Loading options…"]
|
|
388
|
+
}) : q.length === 0 ? /* @__PURE__ */ h("p", {
|
|
389
|
+
className: "text-sm text-text-secondary",
|
|
390
|
+
children: [
|
|
391
|
+
"No shipping methods available for ",
|
|
392
|
+
K.country,
|
|
393
|
+
". Try a different address."
|
|
394
|
+
]
|
|
395
|
+
}) : /* @__PURE__ */ m("div", {
|
|
396
|
+
className: "space-y-2",
|
|
397
|
+
children: q.map((e) => {
|
|
398
|
+
let t = e.id === F, n = y(e.estimatedMinDays, e.estimatedMaxDays), r = t && Y && J;
|
|
399
|
+
return /* @__PURE__ */ m("button", {
|
|
400
|
+
type: "button",
|
|
401
|
+
onClick: () => I(e.id),
|
|
402
|
+
className: `w-full text-left p-3 rounded-input border transition-colors ${t ? "border-action-primary-bg bg-bg-sunken" : "border-border-subtle hover:bg-bg-sunken"}`,
|
|
403
|
+
children: /* @__PURE__ */ h("div", {
|
|
404
|
+
className: "flex items-start justify-between gap-3",
|
|
405
|
+
children: [/* @__PURE__ */ h("div", {
|
|
406
|
+
className: "text-sm",
|
|
407
|
+
children: [/* @__PURE__ */ m("p", {
|
|
408
|
+
className: "font-medium text-text-primary",
|
|
409
|
+
children: e.name
|
|
410
|
+
}), /* @__PURE__ */ h("p", {
|
|
411
|
+
className: "text-text-secondary text-xs mt-0.5",
|
|
412
|
+
children: [e.carrier ? `${e.carrier} · ` : "", n ?? "Delivery time varies"]
|
|
413
|
+
})]
|
|
414
|
+
}), /* @__PURE__ */ m("div", {
|
|
415
|
+
className: "text-right shrink-0",
|
|
416
|
+
children: t && M ? /* @__PURE__ */ m(l, { className: "size-4 animate-spin text-text-secondary" }) : /* @__PURE__ */ m("span", {
|
|
417
|
+
className: "text-sm font-semibold text-text-primary",
|
|
418
|
+
children: r ? v(J.cost, J.currency || x) : v(e.baseCost, e.currency || x)
|
|
419
|
+
})
|
|
420
|
+
})]
|
|
421
|
+
})
|
|
422
|
+
}, e.id);
|
|
423
|
+
})
|
|
424
|
+
}) : /* @__PURE__ */ m("p", {
|
|
425
|
+
className: "text-sm text-text-secondary",
|
|
426
|
+
children: "Select a delivery address to see options."
|
|
427
|
+
}),
|
|
428
|
+
Y && J && /* @__PURE__ */ h("p", {
|
|
429
|
+
className: "text-xs text-text-secondary",
|
|
430
|
+
children: [
|
|
431
|
+
"Estimated shipping: ",
|
|
432
|
+
v(J.cost, J.currency || x),
|
|
433
|
+
J.estimatedDeliveryDate ? ` · arrives around ${new Date(J.estimatedDeliveryDate).toLocaleDateString()}` : ""
|
|
434
|
+
]
|
|
435
|
+
})
|
|
436
|
+
]
|
|
437
|
+
})
|
|
438
|
+
]
|
|
439
|
+
});
|
|
440
|
+
};
|
|
441
|
+
//#endregion
|
|
442
|
+
export { b as StoreShippingSection };
|
|
443
|
+
|
|
444
|
+
//# sourceMappingURL=StoreShippingSection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StoreShippingSection.js","names":[],"sources":["../../../../../src/billing/modules/checkout/components/StoreShippingSection.tsx"],"sourcesContent":["/**\n * StoreShippingSection\n * ============================================================================\n * Physical-store-order-only shipping picker rendered inside the checkout\n * left column. Lets the buyer pick (or add) a delivery address and a shipping\n * method, then fetches a DISPLAY-ONLY cost estimate. The authoritative cost is\n * recomputed and persisted server-side via `setStoreOrderShipping` at\n * proceed-to-payment time (see CheckoutPage.handleProceedToPayment).\n *\n * This component is only ever mounted for store orders that contain a PHYSICAL\n * line item, so nothing here runs on the digital/plan/addon/credits checkout\n * path.\n *\n * Field set / validation / country list mirror\n * `components/CompleteBillingAccountModal.tsx` for visual + behavioural\n * consistency (shipping adds a required recipient `fullName`).\n */\n\nimport { type FC, useEffect, useMemo, useRef, useState } from 'react';\nimport { MapPin, Truck, Plus, Loader2, Check, X } from 'lucide-react';\nimport {\n useMyShippingAddresses,\n useCreateShippingAddress,\n useShippingMethods,\n useEstimateOrderShipping,\n type ShippingAddress,\n} from '../hooks/useStoreShipping';\n\n// Mirror of CompleteBillingAccountModal COUNTRY_OPTIONS.\nconst COUNTRY_OPTIONS = [\n { value: 'IN', label: 'India' },\n { value: 'US', label: 'United States' },\n { value: 'GB', label: 'United Kingdom' },\n { value: 'AU', label: 'Australia' },\n { value: 'CA', label: 'Canada' },\n { value: 'SG', label: 'Singapore' },\n { value: 'DE', label: 'Germany' },\n { value: 'FR', label: 'France' },\n { value: 'AE', label: 'UAE' },\n];\n\nexport interface StoreShippingSelection {\n shippingAddressId: string | null;\n shippingMethodId: string | null;\n /** DISPLAY-ONLY estimate in the order currency; backend recomputes on submit. */\n shippingCost: number;\n destinationCountry: string | null;\n}\n\ninterface Props {\n storeOrderId: string;\n /** Order/checkout currency, used only for formatting the estimate. */\n currency: string;\n onChange: (selection: StoreShippingSelection) => void;\n}\n\ninterface AddressFormState {\n fullName: string;\n phone: string;\n addressLine1: string;\n addressLine2: string;\n city: string;\n state: string;\n postalCode: string;\n country: string;\n}\n\ninterface AddressFormErrors {\n fullName?: string;\n addressLine1?: string;\n city?: string;\n postalCode?: string;\n country?: string;\n}\n\nconst EMPTY_FORM: AddressFormState = {\n fullName: '',\n phone: '',\n addressLine1: '',\n addressLine2: '',\n city: '',\n state: '',\n postalCode: '',\n country: 'IN',\n};\n\nfunction formatCost(amount: number, currency: string): string {\n try {\n return amount.toLocaleString('en', { style: 'currency', currency: currency || 'USD' });\n } catch {\n return `${currency || 'USD'} ${amount.toFixed(2)}`;\n }\n}\n\nfunction formatEta(minDays?: number | null, maxDays?: number | null): string | null {\n if (minDays == null && maxDays == null) return null;\n if (minDays != null && maxDays != null) {\n return minDays === maxDays ? `${minDays} days` : `${minDays}–${maxDays} days`;\n }\n const single = minDays ?? maxDays;\n return single != null ? `${single} days` : null;\n}\n\nexport const StoreShippingSection: FC<Props> = ({ storeOrderId, currency, onChange }) => {\n const {\n addresses,\n loading: addressesLoading,\n refetch: refetchAddresses,\n } = useMyShippingAddresses();\n const { createShippingAddress, loading: creatingAddress } = useCreateShippingAddress();\n const { methods, loading: methodsLoading } = useShippingMethods();\n const [runEstimate, { data: estData, loading: estimateLoading }] = useEstimateOrderShipping();\n\n const [selectedAddressId, setSelectedAddressId] = useState<string | null>(null);\n const [selectedMethodId, setSelectedMethodId] = useState<string | null>(null);\n\n const [showAddForm, setShowAddForm] = useState(false);\n const [form, setForm] = useState<AddressFormState>(EMPTY_FORM);\n const [formErrors, setFormErrors] = useState<AddressFormErrors>({});\n const [formServerError, setFormServerError] = useState<string | null>(null);\n\n // Keep onChange in a ref so the emit effect never depends on its identity.\n const onChangeRef = useRef(onChange);\n useEffect(() => {\n onChangeRef.current = onChange;\n });\n\n const selectedAddress = useMemo<ShippingAddress | undefined>(\n () => addresses.find((a) => a.id === selectedAddressId),\n [addresses, selectedAddressId]\n );\n\n // Methods available for the selected address' destination country.\n // Empty availableCountries is treated as \"available everywhere\".\n const availableMethods = useMemo(() => {\n if (!selectedAddress) return [];\n const country = selectedAddress.country;\n return methods\n .filter(\n (m) =>\n m.isActive &&\n (m.availableCountries.length === 0 || m.availableCountries.includes(country)) &&\n !m.excludedCountries.includes(country)\n )\n .sort((a, b) => a.displayOrder - b.displayOrder);\n }, [methods, selectedAddress]);\n\n // Default the address selection to the user's default (or first) address.\n useEffect(() => {\n if (!selectedAddressId && addresses.length > 0) {\n const preferred = addresses.find((a) => a.isDefault) ?? addresses[0];\n setSelectedAddressId(preferred.id);\n }\n }, [addresses, selectedAddressId]);\n\n // Drop a selected method that is no longer valid for the chosen destination.\n useEffect(() => {\n if (selectedMethodId && !availableMethods.some((m) => m.id === selectedMethodId)) {\n setSelectedMethodId(null);\n }\n }, [availableMethods, selectedMethodId]);\n\n // Fetch a fresh estimate whenever address + method are both chosen.\n useEffect(() => {\n if (selectedAddress && selectedMethodId) {\n void runEstimate({\n variables: {\n input: {\n orderId: storeOrderId,\n shippingMethodId: selectedMethodId,\n destinationCountry: selectedAddress.country,\n destinationPostalCode: selectedAddress.postalCode,\n },\n },\n });\n }\n }, [\n selectedAddress?.id,\n selectedAddress?.country,\n selectedAddress?.postalCode,\n selectedMethodId,\n storeOrderId,\n runEstimate,\n selectedAddress,\n ]);\n\n const estimate = estData?.estimateOrderShipping;\n const estimateReady = Boolean(\n selectedAddressId &&\n selectedMethodId &&\n !estimateLoading &&\n estimate &&\n estimate.shippingMethodId === selectedMethodId\n );\n\n // Emit the current selection upward. Method id + cost are only surfaced once a\n // matching estimate has resolved, so the parent's proceed gate stays disabled\n // while an estimate is in flight (free shipping resolves with cost 0, which is\n // still \"ready\").\n useEffect(() => {\n onChangeRef.current({\n shippingAddressId: selectedAddressId,\n shippingMethodId: estimateReady ? selectedMethodId : null,\n shippingCost: estimateReady && estimate ? estimate.cost : 0,\n destinationCountry: selectedAddress?.country ?? null,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps -- emit derived selection; estimate object identity excluded intentionally\n }, [\n selectedAddressId,\n selectedMethodId,\n estimateReady,\n estimate?.cost,\n selectedAddress?.country,\n ]);\n\n const setField = (field: keyof AddressFormState, value: string) =>\n setForm((prev) => ({ ...prev, [field]: value }));\n\n const validateForm = (): boolean => {\n const e: AddressFormErrors = {};\n if (!form.fullName.trim()) e.fullName = 'Recipient name is required';\n if (!form.addressLine1.trim()) e.addressLine1 = 'Street address is required';\n if (!form.city.trim()) e.city = 'City is required';\n if (!form.postalCode.trim()) e.postalCode = 'Postal code is required';\n if (!form.country.trim()) e.country = 'Country is required';\n setFormErrors(e);\n return Object.keys(e).length === 0;\n };\n\n const handleCreateAddress = async () => {\n if (!validateForm()) return;\n setFormServerError(null);\n try {\n const created = await createShippingAddress({\n fullName: form.fullName.trim(),\n ...(form.phone.trim() ? { phone: form.phone.trim() } : {}),\n addressLine1: form.addressLine1.trim(),\n ...(form.addressLine2.trim() ? { addressLine2: form.addressLine2.trim() } : {}),\n city: form.city.trim(),\n ...(form.state.trim() ? { state: form.state.trim() } : {}),\n postalCode: form.postalCode.trim(),\n country: form.country,\n isDefault: addresses.length === 0,\n });\n if (!created) {\n setFormServerError('Failed to save address. Please try again.');\n return;\n }\n await refetchAddresses();\n setSelectedAddressId(created.id);\n setSelectedMethodId(null);\n setForm(EMPTY_FORM);\n setFormErrors({});\n setShowAddForm(false);\n } catch {\n setFormServerError('Failed to save address. Please try again.');\n }\n };\n\n const inputClass = (hasError: boolean) =>\n `w-full px-3 py-2 text-sm border rounded-input bg-bg-surface text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] ${\n hasError ? 'border-status-error-border' : 'border-border-subtle'\n }`;\n\n return (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6 space-y-5\">\n <div className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Truck className=\"size-4 text-text-secondary\" />\n Shipping\n </div>\n\n {/* Delivery address */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2 text-sm font-medium text-text-primary\">\n <MapPin className=\"size-4 text-text-secondary\" />\n Delivery address\n </div>\n {!showAddForm && (\n <button\n type=\"button\"\n onClick={() => {\n setShowAddForm(true);\n setFormServerError(null);\n }}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-text-link hover:underline\"\n >\n <Plus className=\"size-3.5\" />\n Add address\n </button>\n )}\n </div>\n\n {addressesLoading && addresses.length === 0 ? (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"size-4 animate-spin\" />\n Loading addresses…\n </div>\n ) : (\n <>\n {addresses.length === 0 && !showAddForm && (\n <p className=\"text-sm text-text-secondary\">\n No saved delivery addresses yet. Add one to continue.\n </p>\n )}\n {addresses.length > 0 && (\n <div className=\"space-y-2\">\n {addresses.map((addr) => {\n const selected = addr.id === selectedAddressId;\n return (\n <button\n key={addr.id}\n type=\"button\"\n onClick={() => {\n setSelectedAddressId(addr.id);\n setSelectedMethodId(null);\n }}\n className={`w-full text-left p-3 rounded-input border transition-colors ${\n selected\n ? 'border-action-primary-bg bg-bg-sunken'\n : 'border-border-subtle hover:bg-bg-sunken'\n }`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"text-sm\">\n <p className=\"font-medium text-text-primary\">\n {addr.fullName}\n {addr.label ? (\n <span className=\"ml-2 text-xs text-text-muted\">({addr.label})</span>\n ) : null}\n </p>\n <p className=\"text-text-secondary text-xs mt-0.5\">\n {[\n addr.addressLine1,\n addr.addressLine2,\n addr.city,\n addr.state,\n addr.postalCode,\n addr.country,\n ]\n .filter(Boolean)\n .join(', ')}\n </p>\n {addr.phone && (\n <p className=\"text-text-muted text-xs mt-0.5\">{addr.phone}</p>\n )}\n </div>\n {selected && (\n <Check className=\"size-4 text-action-primary-bg shrink-0 mt-0.5\" />\n )}\n </div>\n </button>\n );\n })}\n </div>\n )}\n </>\n )}\n\n {/* Inline add-address form */}\n {showAddForm && (\n <div className=\"rounded-input border border-border-subtle p-3 space-y-3 bg-bg-sunken\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-text-primary\">New delivery address</span>\n <button\n type=\"button\"\n onClick={() => {\n setShowAddForm(false);\n setFormErrors({});\n setFormServerError(null);\n }}\n className=\"p-1 text-text-secondary hover:text-text-primary rounded-button\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n\n {formServerError && (\n <div className=\"p-2 rounded-lg bg-status-error-bg-subtle border border-status-error-border text-xs text-status-error-text\">\n {formServerError}\n </div>\n )}\n\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">Recipient name</label>\n <input\n type=\"text\"\n value={form.fullName}\n onChange={(e) => setField('fullName', e.target.value)}\n placeholder=\"Jane Doe\"\n className={inputClass(Boolean(formErrors.fullName))}\n />\n {formErrors.fullName && (\n <p className=\"mt-1 text-xs text-status-error-text\">{formErrors.fullName}</p>\n )}\n </div>\n\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">\n Phone <span className=\"text-text-muted\">(optional)</span>\n </label>\n <input\n type=\"tel\"\n value={form.phone}\n onChange={(e) => setField('phone', e.target.value)}\n placeholder=\"+91 98765 43210\"\n className={inputClass(false)}\n />\n </div>\n\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">Country</label>\n <select\n value={form.country}\n onChange={(e) => setField('country', e.target.value)}\n className={inputClass(Boolean(formErrors.country))}\n >\n {COUNTRY_OPTIONS.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </select>\n </div>\n\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">Street address</label>\n <input\n type=\"text\"\n value={form.addressLine1}\n onChange={(e) => setField('addressLine1', e.target.value)}\n placeholder=\"123 Main St\"\n className={inputClass(Boolean(formErrors.addressLine1))}\n />\n {formErrors.addressLine1 && (\n <p className=\"mt-1 text-xs text-status-error-text\">{formErrors.addressLine1}</p>\n )}\n </div>\n\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">\n Apartment, suite, etc. <span className=\"text-text-muted\">(optional)</span>\n </label>\n <input\n type=\"text\"\n value={form.addressLine2}\n onChange={(e) => setField('addressLine2', e.target.value)}\n placeholder=\"Apt 4B\"\n className={inputClass(false)}\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">City</label>\n <input\n type=\"text\"\n value={form.city}\n onChange={(e) => setField('city', e.target.value)}\n placeholder=\"Mumbai\"\n className={inputClass(Boolean(formErrors.city))}\n />\n {formErrors.city && (\n <p className=\"mt-1 text-xs text-status-error-text\">{formErrors.city}</p>\n )}\n </div>\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">\n State <span className=\"text-text-muted\">(optional)</span>\n </label>\n <input\n type=\"text\"\n value={form.state}\n onChange={(e) => setField('state', e.target.value)}\n placeholder=\"Maharashtra\"\n className={inputClass(false)}\n />\n </div>\n </div>\n\n <div>\n <label className=\"block text-xs text-text-secondary mb-1\">Postal code</label>\n <input\n type=\"text\"\n value={form.postalCode}\n onChange={(e) => setField('postalCode', e.target.value)}\n placeholder=\"400001\"\n className={inputClass(Boolean(formErrors.postalCode))}\n />\n {formErrors.postalCode && (\n <p className=\"mt-1 text-xs text-status-error-text\">{formErrors.postalCode}</p>\n )}\n </div>\n\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n onClick={handleCreateAddress}\n disabled={creatingAddress}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg hover:bg-action-primary-bgHover rounded-lg transition-colors disabled:opacity-50\"\n >\n {creatingAddress && <Loader2 className=\"size-4 animate-spin\" />}\n Save address\n </button>\n </div>\n </div>\n )}\n </section>\n\n {/* Shipping method */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium text-text-primary\">\n <Truck className=\"size-4 text-text-secondary\" />\n Shipping method\n </div>\n\n {!selectedAddress ? (\n <p className=\"text-sm text-text-secondary\">Select a delivery address to see options.</p>\n ) : methodsLoading && methods.length === 0 ? (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"size-4 animate-spin\" />\n Loading options…\n </div>\n ) : availableMethods.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n No shipping methods available for {selectedAddress.country}. Try a different address.\n </p>\n ) : (\n <div className=\"space-y-2\">\n {availableMethods.map((method) => {\n const selected = method.id === selectedMethodId;\n const eta = formatEta(method.estimatedMinDays, method.estimatedMaxDays);\n const showEstimate = selected && estimateReady && estimate;\n return (\n <button\n key={method.id}\n type=\"button\"\n onClick={() => setSelectedMethodId(method.id)}\n className={`w-full text-left p-3 rounded-input border transition-colors ${\n selected\n ? 'border-action-primary-bg bg-bg-sunken'\n : 'border-border-subtle hover:bg-bg-sunken'\n }`}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"text-sm\">\n <p className=\"font-medium text-text-primary\">{method.name}</p>\n <p className=\"text-text-secondary text-xs mt-0.5\">\n {method.carrier ? `${method.carrier} · ` : ''}\n {eta ?? 'Delivery time varies'}\n </p>\n </div>\n <div className=\"text-right shrink-0\">\n {selected && estimateLoading ? (\n <Loader2 className=\"size-4 animate-spin text-text-secondary\" />\n ) : (\n <span className=\"text-sm font-semibold text-text-primary\">\n {showEstimate\n ? formatCost(estimate.cost, estimate.currency || currency)\n : formatCost(method.baseCost, method.currency || currency)}\n </span>\n )}\n </div>\n </div>\n </button>\n );\n })}\n </div>\n )}\n\n {estimateReady && estimate && (\n <p className=\"text-xs text-text-secondary\">\n Estimated shipping: {formatCost(estimate.cost, estimate.currency || currency)}\n {estimate.estimatedDeliveryDate\n ? ` · arrives around ${new Date(estimate.estimatedDeliveryDate).toLocaleDateString()}`\n : ''}\n </p>\n )}\n </section>\n </div>\n );\n};\n"],"mappings":";;;;;AA6BA,IAAM,IAAkB;CACtB;EAAE,OAAO;EAAM,OAAO;EAAS;CAC/B;EAAE,OAAO;EAAM,OAAO;EAAiB;CACvC;EAAE,OAAO;EAAM,OAAO;EAAkB;CACxC;EAAE,OAAO;EAAM,OAAO;EAAa;CACnC;EAAE,OAAO;EAAM,OAAO;EAAU;CAChC;EAAE,OAAO;EAAM,OAAO;EAAa;CACnC;EAAE,OAAO;EAAM,OAAO;EAAW;CACjC;EAAE,OAAO;EAAM,OAAO;EAAU;CAChC;EAAE,OAAO;EAAM,OAAO;EAAO;CAC9B,EAoCK,IAA+B;CACnC,UAAU;CACV,OAAO;CACP,cAAc;CACd,cAAc;CACd,MAAM;CACN,OAAO;CACP,YAAY;CACZ,SAAS;CACV;AAED,SAAS,EAAW,GAAgB,GAA0B;AAC5D,KAAI;AACF,SAAO,EAAO,eAAe,MAAM;GAAE,OAAO;GAAY,UAAU,KAAY;GAAO,CAAC;SAChF;AACN,SAAO,GAAG,KAAY,MAAM,GAAG,EAAO,QAAQ,EAAE;;;AAIpD,SAAS,EAAU,GAAyB,GAAwC;AAClF,KAAI,KAAW,QAAQ,KAAW,KAAM,QAAO;AAC/C,KAAI,KAAW,QAAQ,KAAW,KAChC,QAAO,MAAY,IAAU,GAAG,EAAQ,SAAS,GAAG,EAAQ,GAAG,EAAQ;CAEzE,IAAM,IAAS,KAAW;AAC1B,QAAO,KAAU,OAA0B,OAAnB,GAAG,EAAO;;AAGpC,IAAa,KAAmC,EAAE,iBAAc,aAAU,kBAAe;CACvF,IAAM,EACJ,cACA,SAAS,GACT,SAAS,MACP,GAAwB,EACtB,EAAE,0BAAuB,SAAS,MAAoB,GAA0B,EAChF,EAAE,YAAS,SAAS,MAAmB,GAAoB,EAC3D,CAAC,GAAa,EAAE,MAAM,GAAS,SAAS,OAAqB,GAA0B,EAEvF,CAAC,GAAmB,KAAwB,EAAwB,KAAK,EACzE,CAAC,GAAkB,KAAuB,EAAwB,KAAK,EAEvE,CAAC,GAAa,KAAkB,EAAS,GAAM,EAC/C,CAAC,GAAM,KAAW,EAA2B,EAAW,EACxD,CAAC,GAAY,KAAiB,EAA4B,EAAE,CAAC,EAC7D,CAAC,GAAiB,KAAsB,EAAwB,KAAK,EAGrE,IAAc,EAAO,EAAS;AACpC,SAAgB;AACd,IAAY,UAAU;GACtB;CAEF,IAAM,IAAkB,QAChB,EAAU,MAAM,MAAM,EAAE,OAAO,EAAkB,EACvD,CAAC,GAAW,EAAkB,CAC/B,EAIK,IAAmB,QAAc;AACrC,MAAI,CAAC,EAAiB,QAAO,EAAE;EAC/B,IAAM,IAAU,EAAgB;AAChC,SAAO,EACJ,QACE,MACC,EAAE,aACD,EAAE,mBAAmB,WAAW,KAAK,EAAE,mBAAmB,SAAS,EAAQ,KAC5E,CAAC,EAAE,kBAAkB,SAAS,EAAQ,CACzC,CACA,MAAM,GAAG,MAAM,EAAE,eAAe,EAAE,aAAa;IACjD,CAAC,GAAS,EAAgB,CAAC;AAkB9B,CAfA,QAAgB;AACd,EAAI,CAAC,KAAqB,EAAU,SAAS,KAE3C,GADkB,EAAU,MAAM,MAAM,EAAE,UAAU,IAAI,EAAU,IACnC,GAAG;IAEnC,CAAC,GAAW,EAAkB,CAAC,EAGlC,QAAgB;AACd,EAAI,KAAoB,CAAC,EAAiB,MAAM,MAAM,EAAE,OAAO,EAAiB,IAC9E,EAAoB,KAAK;IAE1B,CAAC,GAAkB,EAAiB,CAAC,EAGxC,QAAgB;AACd,EAAI,KAAmB,KAChB,EAAY,EACf,WAAW,EACT,OAAO;GACL,SAAS;GACT,kBAAkB;GAClB,oBAAoB,EAAgB;GACpC,uBAAuB,EAAgB;GACxC,EACF,EACF,CAAC;IAEH;EACD,GAAiB;EACjB,GAAiB;EACjB,GAAiB;EACjB;EACA;EACA;EACA;EACD,CAAC;CAEF,IAAM,IAAW,GAAS,uBACpB,IAAgB,GACpB,KACA,KACA,CAAC,KACD,KACA,EAAS,qBAAqB;AAOhC,SAAgB;AACd,IAAY,QAAQ;GAClB,mBAAmB;GACnB,kBAAkB,IAAgB,IAAmB;GACrD,cAAc,KAAiB,IAAW,EAAS,OAAO;GAC1D,oBAAoB,GAAiB,WAAW;GACjD,CAAC;IAED;EACD;EACA;EACA;EACA,GAAU;EACV,GAAiB;EAClB,CAAC;CAEF,IAAM,KAAY,GAA+B,MAC/C,GAAS,OAAU;EAAE,GAAG;GAAO,IAAQ;EAAO,EAAE,EAE5C,UAA8B;EAClC,IAAM,IAAuB,EAAE;AAO/B,SANK,EAAK,SAAS,MAAM,KAAE,EAAE,WAAW,+BACnC,EAAK,aAAa,MAAM,KAAE,EAAE,eAAe,+BAC3C,EAAK,KAAK,MAAM,KAAE,EAAE,OAAO,qBAC3B,EAAK,WAAW,MAAM,KAAE,EAAE,aAAa,4BACvC,EAAK,QAAQ,MAAM,KAAE,EAAE,UAAU,wBACtC,EAAc,EAAE,EACT,OAAO,KAAK,EAAE,CAAC,WAAW;IAG7B,IAAsB,YAAY;AACjC,SAAc,EACnB;KAAmB,KAAK;AACxB,OAAI;IACF,IAAM,IAAU,MAAM,EAAsB;KAC1C,UAAU,EAAK,SAAS,MAAM;KAC9B,GAAI,EAAK,MAAM,MAAM,GAAG,EAAE,OAAO,EAAK,MAAM,MAAM,EAAE,GAAG,EAAE;KACzD,cAAc,EAAK,aAAa,MAAM;KACtC,GAAI,EAAK,aAAa,MAAM,GAAG,EAAE,cAAc,EAAK,aAAa,MAAM,EAAE,GAAG,EAAE;KAC9E,MAAM,EAAK,KAAK,MAAM;KACtB,GAAI,EAAK,MAAM,MAAM,GAAG,EAAE,OAAO,EAAK,MAAM,MAAM,EAAE,GAAG,EAAE;KACzD,YAAY,EAAK,WAAW,MAAM;KAClC,SAAS,EAAK;KACd,WAAW,EAAU,WAAW;KACjC,CAAC;AACF,QAAI,CAAC,GAAS;AACZ,OAAmB,4CAA4C;AAC/D;;AAOF,IALA,MAAM,GAAkB,EACxB,EAAqB,EAAQ,GAAG,EAChC,EAAoB,KAAK,EACzB,EAAQ,EAAW,EACnB,EAAc,EAAE,CAAC,EACjB,EAAe,GAAM;WACf;AACN,MAAmB,4CAA4C;;;IAI7D,KAAc,MAClB,wLACE,IAAW,+BAA+B;AAG9C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAO,WAAU,8BAA+B,CAAA,EAAA,WAE5C;;GAGN,kBAAC,WAAD;IAAS,WAAU;cAAnB;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,8BAA+B,CAAA,EAAA,mBAE7C;UACL,CAAC,KACA,kBAAC,UAAD;OACE,MAAK;OACL,eAAe;AAEb,QADA,EAAe,GAAK,EACpB,EAAmB,KAAK;;OAE1B,WAAU;iBANZ,CAQE,kBAAC,GAAD,EAAM,WAAU,YAAa,CAAA,EAAA,cAEtB;SAEP;;KAEL,KAAoB,EAAU,WAAW,IACxC,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,EAAA,qBAEvC;UAEN,kBAAA,IAAA,EAAA,UAAA,CACG,EAAU,WAAW,KAAK,CAAC,KAC1B,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAEvC,CAAA,EAEL,EAAU,SAAS,KAClB,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAU,KAAK,MAAS;OACvB,IAAM,IAAW,EAAK,OAAO;AAC7B,cACE,kBAAC,UAAD;QAEE,MAAK;QACL,eAAe;AAEb,SADA,EAAqB,EAAK,GAAG,EAC7B,EAAoB,KAAK;;QAE3B,WAAW,+DACT,IACI,0CACA;kBAGN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,KAAD;YAAG,WAAU;sBAAb,CACG,EAAK,UACL,EAAK,QACJ,kBAAC,QAAD;aAAM,WAAU;uBAAhB;cAA+C;cAAE,EAAK;cAAM;cAAQ;iBAClE,KACF;;WACJ,kBAAC,KAAD;YAAG,WAAU;sBACV;aACC,EAAK;aACL,EAAK;aACL,EAAK;aACL,EAAK;aACL,EAAK;aACL,EAAK;aACN,CACE,OAAO,QAAQ,CACf,KAAK,KAAK;YACX,CAAA;WACH,EAAK,SACJ,kBAAC,KAAD;YAAG,WAAU;sBAAkC,EAAK;YAAU,CAAA;WAE5D;aACL,KACC,kBAAC,GAAD,EAAO,WAAU,iDAAkD,CAAA,CAEjE;;QACC,EAxCF,EAAK,GAwCH;QAEX;MACE,CAAA,CAEP,EAAA,CAAA;KAIJ,KACC,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwC;SAA2B,CAAA,EACnF,kBAAC,UAAD;SACE,MAAK;SACL,eAAe;AAGb,UAFA,EAAe,GAAM,EACrB,EAAc,EAAE,CAAC,EACjB,EAAmB,KAAK;;SAE1B,WAAU;mBAEV,kBAAC,GAAD,EAAG,WAAU,UAAW,CAAA;SACjB,CAAA,CACL;;OAEL,KACC,kBAAC,OAAD;QAAK,WAAU;kBACZ;QACG,CAAA;OAGR,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SAAO,WAAU;mBAAyC;SAAsB,CAAA;QAChF,kBAAC,SAAD;SACE,MAAK;SACL,OAAO,EAAK;SACZ,WAAW,MAAM,EAAS,YAAY,EAAE,OAAO,MAAM;SACrD,aAAY;SACZ,WAAW,EAAW,EAAQ,EAAW,SAAU;SACnD,CAAA;QACD,EAAW,YACV,kBAAC,KAAD;SAAG,WAAU;mBAAuC,EAAW;SAAa,CAAA;QAE1E,EAAA,CAAA;OAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CAA0D,UAClD,kBAAC,QAAD;SAAM,WAAU;mBAAkB;SAAiB,CAAA,CACnD;WACR,kBAAC,SAAD;QACE,MAAK;QACL,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,SAAS,EAAE,OAAO,MAAM;QAClD,aAAY;QACZ,WAAW,EAAW,GAAM;QAC5B,CAAA,CACE,EAAA,CAAA;OAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAyC;QAAe,CAAA,EACzE,kBAAC,UAAD;QACE,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,WAAW,EAAE,OAAO,MAAM;QACpD,WAAW,EAAW,EAAQ,EAAW,QAAS;kBAEjD,EAAgB,KAAK,MACpB,kBAAC,UAAD;SAAsB,OAAO,EAAE;mBAC5B,EAAE;SACI,EAFI,EAAE,MAEN,CACT;QACK,CAAA,CACL,EAAA,CAAA;OAEN,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SAAO,WAAU;mBAAyC;SAAsB,CAAA;QAChF,kBAAC,SAAD;SACE,MAAK;SACL,OAAO,EAAK;SACZ,WAAW,MAAM,EAAS,gBAAgB,EAAE,OAAO,MAAM;SACzD,aAAY;SACZ,WAAW,EAAW,EAAQ,EAAW,aAAc;SACvD,CAAA;QACD,EAAW,gBACV,kBAAC,KAAD;SAAG,WAAU;mBAAuC,EAAW;SAAiB,CAAA;QAE9E,EAAA,CAAA;OAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CAA0D,2BACjC,kBAAC,QAAD;SAAM,WAAU;mBAAkB;SAAiB,CAAA,CACpE;WACR,kBAAC,SAAD;QACE,MAAK;QACL,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,gBAAgB,EAAE,OAAO,MAAM;QACzD,aAAY;QACZ,WAAW,EAAW,GAAM;QAC5B,CAAA,CACE,EAAA,CAAA;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD,EAAA,UAAA;SACE,kBAAC,SAAD;UAAO,WAAU;oBAAyC;UAAY,CAAA;SACtE,kBAAC,SAAD;UACE,MAAK;UACL,OAAO,EAAK;UACZ,WAAW,MAAM,EAAS,QAAQ,EAAE,OAAO,MAAM;UACjD,aAAY;UACZ,WAAW,EAAW,EAAQ,EAAW,KAAM;UAC/C,CAAA;SACD,EAAW,QACV,kBAAC,KAAD;UAAG,WAAU;oBAAuC,EAAW;UAAS,CAAA;SAEtE,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;SAAO,WAAU;mBAAjB,CAA0D,UAClD,kBAAC,QAAD;UAAM,WAAU;oBAAkB;UAAiB,CAAA,CACnD;YACR,kBAAC,SAAD;SACE,MAAK;SACL,OAAO,EAAK;SACZ,WAAW,MAAM,EAAS,SAAS,EAAE,OAAO,MAAM;SAClD,aAAY;SACZ,WAAW,EAAW,GAAM;SAC5B,CAAA,CACE,EAAA,CAAA,CACF;;OAEN,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SAAO,WAAU;mBAAyC;SAAmB,CAAA;QAC7E,kBAAC,SAAD;SACE,MAAK;SACL,OAAO,EAAK;SACZ,WAAW,MAAM,EAAS,cAAc,EAAE,OAAO,MAAM;SACvD,aAAY;SACZ,WAAW,EAAW,EAAQ,EAAW,WAAY;SACrD,CAAA;QACD,EAAW,cACV,kBAAC,KAAD;SAAG,WAAU;mBAAuC,EAAW;SAAe,CAAA;QAE5E,EAAA,CAAA;OAEN,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,UAAD;SACE,MAAK;SACL,SAAS;SACT,UAAU;SACV,WAAU;mBAJZ,CAMG,KAAmB,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,EAAC,eAEzD;;QACL,CAAA;OACF;;KAEA;;GAGV,kBAAC,WAAD;IAAS,WAAU;cAAnB;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,8BAA+B,CAAA,EAAA,kBAE5C;;KAEJ,IAEE,KAAkB,EAAQ,WAAW,IACvC,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,EAAA,mBAEvC;UACJ,EAAiB,WAAW,IAC9B,kBAAC,KAAD;MAAG,WAAU;gBAAb;OAA2C;OACN,EAAgB;OAAQ;OACzD;UAEJ,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAiB,KAAK,MAAW;OAChC,IAAM,IAAW,EAAO,OAAO,GACzB,IAAM,EAAU,EAAO,kBAAkB,EAAO,iBAAiB,EACjE,IAAe,KAAY,KAAiB;AAClD,cACE,kBAAC,UAAD;QAEE,MAAK;QACL,eAAe,EAAoB,EAAO,GAAG;QAC7C,WAAW,+DACT,IACI,0CACA;kBAGN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAiC,EAAO;WAAS,CAAA,EAC9D,kBAAC,KAAD;WAAG,WAAU;qBAAb,CACG,EAAO,UAAU,GAAG,EAAO,QAAQ,OAAO,IAC1C,KAAO,uBACN;aACA;aACN,kBAAC,OAAD;UAAK,WAAU;oBACZ,KAAY,IACX,kBAAC,GAAD,EAAS,WAAU,2CAA4C,CAAA,GAE/D,kBAAC,QAAD;WAAM,WAAU;qBACb,IACG,EAAW,EAAS,MAAM,EAAS,YAAY,EAAS,GACxD,EAAW,EAAO,UAAU,EAAO,YAAY,EAAS;WACvD,CAAA;UAEL,CAAA,CACF;;QACC,EA7BF,EAAO,GA6BL;QAEX;MACE,CAAA,GAlDN,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAA6C,CAAA;KAqDzF,KAAiB,KAChB,kBAAC,KAAD;MAAG,WAAU;gBAAb;OAA2C;OACpB,EAAW,EAAS,MAAM,EAAS,YAAY,EAAS;OAC5E,EAAS,wBACN,qBAAqB,IAAI,KAAK,EAAS,sBAAsB,CAAC,oBAAoB,KAClF;OACF;;KAEE;;GACN"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { gql as e, useLazyQuery as t, useMutation as n, useQuery as r } from "@burdenoff/fe-libs/shared/graphql";
|
|
2
|
+
//#region src/billing/modules/checkout/hooks/useStoreShipping.ts
|
|
3
|
+
var i = "store-shipping", a = e`
|
|
4
|
+
query ShippingMethods {
|
|
5
|
+
shippingMethods {
|
|
6
|
+
id
|
|
7
|
+
name
|
|
8
|
+
code
|
|
9
|
+
carrier
|
|
10
|
+
baseCost
|
|
11
|
+
currency
|
|
12
|
+
estimatedMinDays
|
|
13
|
+
estimatedMaxDays
|
|
14
|
+
availableCountries
|
|
15
|
+
excludedCountries
|
|
16
|
+
isActive
|
|
17
|
+
displayOrder
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
`, o = e`
|
|
21
|
+
query MyShippingAddresses {
|
|
22
|
+
myShippingAddresses {
|
|
23
|
+
id
|
|
24
|
+
fullName
|
|
25
|
+
phone
|
|
26
|
+
email
|
|
27
|
+
addressLine1
|
|
28
|
+
addressLine2
|
|
29
|
+
city
|
|
30
|
+
state
|
|
31
|
+
postalCode
|
|
32
|
+
country
|
|
33
|
+
isDefault
|
|
34
|
+
label
|
|
35
|
+
instructions
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
`, s = e`
|
|
39
|
+
mutation CreateShippingAddress($input: CreateShippingAddressInput!) {
|
|
40
|
+
createShippingAddress(input: $input) {
|
|
41
|
+
id
|
|
42
|
+
fullName
|
|
43
|
+
phone
|
|
44
|
+
email
|
|
45
|
+
addressLine1
|
|
46
|
+
addressLine2
|
|
47
|
+
city
|
|
48
|
+
state
|
|
49
|
+
postalCode
|
|
50
|
+
country
|
|
51
|
+
isDefault
|
|
52
|
+
label
|
|
53
|
+
instructions
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`, c = e`
|
|
57
|
+
query EstimateOrderShipping($input: OrderShippingEstimateInput!) {
|
|
58
|
+
estimateOrderShipping(input: $input) {
|
|
59
|
+
orderId
|
|
60
|
+
shippingMethodId
|
|
61
|
+
cost
|
|
62
|
+
currency
|
|
63
|
+
methodName
|
|
64
|
+
carrier
|
|
65
|
+
estimatedMinDays
|
|
66
|
+
estimatedMaxDays
|
|
67
|
+
estimatedDeliveryDate
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
`, l = e`
|
|
71
|
+
mutation SetStoreOrderShipping($input: SetStoreOrderShippingInput!) {
|
|
72
|
+
setStoreOrderShipping(input: $input) {
|
|
73
|
+
id
|
|
74
|
+
total
|
|
75
|
+
shippingCost
|
|
76
|
+
shippingCurrency
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
80
|
+
function u() {
|
|
81
|
+
let { data: e, loading: t, error: n } = r(a, { fetchPolicy: "cache-and-network" });
|
|
82
|
+
return {
|
|
83
|
+
methods: e?.shippingMethods ?? [],
|
|
84
|
+
loading: t,
|
|
85
|
+
error: n ?? null
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function d() {
|
|
89
|
+
let { data: e, loading: t, error: n, refetch: i } = r(o, { fetchPolicy: "cache-and-network" });
|
|
90
|
+
return {
|
|
91
|
+
addresses: e?.myShippingAddresses ?? [],
|
|
92
|
+
loading: t,
|
|
93
|
+
error: n ?? null,
|
|
94
|
+
refetch: i
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function f() {
|
|
98
|
+
let [e, { loading: t }] = n(s);
|
|
99
|
+
return {
|
|
100
|
+
createShippingAddress: async (t) => (await e({ variables: { input: t } })).data?.createShippingAddress ?? null,
|
|
101
|
+
loading: t
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function p() {
|
|
105
|
+
return t(c, { fetchPolicy: "network-only" });
|
|
106
|
+
}
|
|
107
|
+
function m() {
|
|
108
|
+
return n(l);
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { i as STORE_SHIPPING_ITEM_ID, f as useCreateShippingAddress, p as useEstimateOrderShipping, d as useMyShippingAddresses, m as useSetStoreOrderShipping, u as useShippingMethods };
|
|
112
|
+
|
|
113
|
+
//# sourceMappingURL=useStoreShipping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStoreShipping.js","names":[],"sources":["../../../../../src/billing/modules/checkout/hooks/useStoreShipping.ts"],"sourcesContent":["/**\n * Store checkout — shipping operations (physical products only)\n * ============================================================================\n *\n * TRANSITIONAL SHIM. These hooks are hand-written against the STORE subgraph\n * (federated behind the global gateway) using inline `gql` documents, mirroring\n * the existing precedent in `modules/usage/hooks/useUsage.ts`.\n *\n * Why hand-written and not codegen'd?\n * - The canonical GraphQL operations live in\n * `src/operations/global/store/{queries,mutations}/*.graphql` (added in this\n * PR as the backend contract), but the committed schema snapshot\n * (`graphql/global.graphql`) is stale and does NOT yet expose\n * `shippingMethods` / `myShippingAddresses` / `createShippingAddress` /\n * `setStoreOrderShipping`. Running `bun run codegen` offline against the\n * stale schema therefore fails, so the generated hooks\n * (`useShippingMethodsQuery`, `useSetStoreOrderShippingMutation`, ...) do\n * not exist yet.\n * - `setStoreOrderShipping` is a NEW mutation that the global-store-svc order\n * module must add (see the coordinating backend PR). Until it ships, the\n * write is inert at runtime.\n *\n * FOLLOW-UP once the backend + a fresh `bun run schema:pull` land: delete this\n * module and switch the imports in `StoreShippingSection.tsx` / `CheckoutPage.tsx`\n * to the generated hooks in `src/generated/global-operations.ts`.\n *\n * Everything here is scoped to physical STORE-order checkout and is never\n * imported on the digital/plan/addon/credits checkout path.\n */\n\nimport { gql, useQuery, useLazyQuery, useMutation } from '@burdenoff/fe-libs/shared/graphql';\n\n/** Synthetic checkout line-item id used to fold shipping cost into the billing total. */\nexport const STORE_SHIPPING_ITEM_ID = 'store-shipping';\n\n// ============================================================================\n// Types (mirror the STORE subgraph shapes in graphql/global.graphql)\n// ============================================================================\n\nexport interface ShippingMethod {\n id: string;\n name: string;\n code: string;\n carrier?: string | null;\n baseCost: number;\n currency: string;\n estimatedMinDays?: number | null;\n estimatedMaxDays?: number | null;\n availableCountries: string[];\n excludedCountries: string[];\n isActive: boolean;\n displayOrder: number;\n}\n\nexport interface ShippingAddress {\n id: string;\n fullName: string;\n phone?: string | null;\n email?: string | null;\n addressLine1: string;\n addressLine2?: string | null;\n city: string;\n state?: string | null;\n postalCode: string;\n country: string;\n isDefault: boolean;\n label?: string | null;\n instructions?: string | null;\n}\n\nexport interface OrderShippingEstimate {\n orderId: string;\n shippingMethodId: string;\n cost: number;\n currency: string;\n methodName: string;\n carrier?: string | null;\n estimatedMinDays?: number | null;\n estimatedMaxDays?: number | null;\n estimatedDeliveryDate?: string | null;\n}\n\nexport interface CreateShippingAddressInput {\n fullName: string;\n phone?: string;\n email?: string;\n addressLine1: string;\n addressLine2?: string;\n city: string;\n state?: string;\n postalCode: string;\n country: string;\n instructions?: string;\n label?: string;\n isDefault?: boolean;\n}\n\nexport interface OrderShippingEstimateInput {\n orderId: string;\n shippingMethodId: string;\n destinationCountry: string;\n destinationPostalCode?: string;\n}\n\nexport interface SetStoreOrderShippingInput {\n orderId: string;\n shippingMethodId: string;\n shippingAddressId?: string;\n}\n\n// setStoreOrderShipping returns the updated StoreOrder directly (product-only `total`,\n// with the server-computed shipping cost persisted on `shippingCost`/`shippingCurrency`).\nexport interface SetStoreOrderShippingResult {\n id: string;\n total: number;\n shippingCost: number | null;\n shippingCurrency: string | null;\n}\n\n// ============================================================================\n// GraphQL documents\n// ============================================================================\n\nconst SHIPPING_METHODS_QUERY = gql`\n query ShippingMethods {\n shippingMethods {\n id\n name\n code\n carrier\n baseCost\n currency\n estimatedMinDays\n estimatedMaxDays\n availableCountries\n excludedCountries\n isActive\n displayOrder\n }\n }\n`;\n\nconst MY_SHIPPING_ADDRESSES_QUERY = gql`\n query MyShippingAddresses {\n myShippingAddresses {\n id\n fullName\n phone\n email\n addressLine1\n addressLine2\n city\n state\n postalCode\n country\n isDefault\n label\n instructions\n }\n }\n`;\n\nconst CREATE_SHIPPING_ADDRESS_MUTATION = gql`\n mutation CreateShippingAddress($input: CreateShippingAddressInput!) {\n createShippingAddress(input: $input) {\n id\n fullName\n phone\n email\n addressLine1\n addressLine2\n city\n state\n postalCode\n country\n isDefault\n label\n instructions\n }\n }\n`;\n\nconst ESTIMATE_ORDER_SHIPPING_QUERY = gql`\n query EstimateOrderShipping($input: OrderShippingEstimateInput!) {\n estimateOrderShipping(input: $input) {\n orderId\n shippingMethodId\n cost\n currency\n methodName\n carrier\n estimatedMinDays\n estimatedMaxDays\n estimatedDeliveryDate\n }\n }\n`;\n\n// NOTE: blocked on global-store-svc adding this mutation. Inert until then.\nconst SET_STORE_ORDER_SHIPPING_MUTATION = gql`\n mutation SetStoreOrderShipping($input: SetStoreOrderShippingInput!) {\n setStoreOrderShipping(input: $input) {\n id\n total\n shippingCost\n shippingCurrency\n }\n }\n`;\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport function useShippingMethods() {\n const { data, loading, error } = useQuery<{ shippingMethods: ShippingMethod[] }>(\n SHIPPING_METHODS_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n return { methods: data?.shippingMethods ?? [], loading, error: error ?? null };\n}\n\nexport function useMyShippingAddresses() {\n const { data, loading, error, refetch } = useQuery<{ myShippingAddresses: ShippingAddress[] }>(\n MY_SHIPPING_ADDRESSES_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n return {\n addresses: data?.myShippingAddresses ?? [],\n loading,\n error: error ?? null,\n refetch,\n };\n}\n\nexport function useCreateShippingAddress() {\n const [mutate, { loading }] = useMutation<\n { createShippingAddress: ShippingAddress },\n { input: CreateShippingAddressInput }\n >(CREATE_SHIPPING_ADDRESS_MUTATION);\n\n const createShippingAddress = async (\n input: CreateShippingAddressInput\n ): Promise<ShippingAddress | null> => {\n const result = await mutate({ variables: { input } });\n return result.data?.createShippingAddress ?? null;\n };\n\n return { createShippingAddress, loading };\n}\n\nexport function useEstimateOrderShipping() {\n return useLazyQuery<\n { estimateOrderShipping: OrderShippingEstimate },\n { input: OrderShippingEstimateInput }\n >(ESTIMATE_ORDER_SHIPPING_QUERY, { fetchPolicy: 'network-only' });\n}\n\nexport function useSetStoreOrderShipping() {\n return useMutation<\n { setStoreOrderShipping: SetStoreOrderShippingResult },\n { input: SetStoreOrderShippingInput }\n >(SET_STORE_ORDER_SHIPPING_MUTATION);\n}\n"],"mappings":";;AAiCA,IAAa,IAAyB,kBA0FhC,IAAyB,CAAG;;;;;;;;;;;;;;;;;GAmB5B,IAA8B,CAAG;;;;;;;;;;;;;;;;;;GAoBjC,IAAmC,CAAG;;;;;;;;;;;;;;;;;;GAoBtC,IAAgC,CAAG;;;;;;;;;;;;;;GAiBnC,IAAoC,CAAG;;;;;;;;;;AAe7C,SAAgB,IAAqB;CACnC,IAAM,EAAE,SAAM,YAAS,aAAU,EAC/B,GACA,EAAE,aAAa,qBAAqB,CACrC;AACD,QAAO;EAAE,SAAS,GAAM,mBAAmB,EAAE;EAAE;EAAS,OAAO,KAAS;EAAM;;AAGhF,SAAgB,IAAyB;CACvC,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EACxC,GACA,EAAE,aAAa,qBAAqB,CACrC;AACD,QAAO;EACL,WAAW,GAAM,uBAAuB,EAAE;EAC1C;EACA,OAAO,KAAS;EAChB;EACD;;AAGH,SAAgB,IAA2B;CACzC,IAAM,CAAC,GAAQ,EAAE,gBAAa,EAG5B,EAAiC;AASnC,QAAO;EAAE,uBAPqB,OAC5B,OAEe,MAAM,EAAO,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC,EACvC,MAAM,yBAAyB;EAGf;EAAS;;AAG3C,SAAgB,IAA2B;AACzC,QAAO,EAGL,GAA+B,EAAE,aAAa,gBAAgB,CAAC;;AAGnE,SAAgB,IAA2B;AACzC,QAAO,EAGL,EAAkC"}
|
|
@@ -14,6 +14,7 @@ import "./components/SubscriptionSelector.js";
|
|
|
14
14
|
import "./components/SimpleAutoPayToggle.js";
|
|
15
15
|
import "./components/UnifiedPaymentMethodSelector.js";
|
|
16
16
|
import "./components/CompleteBillingAccountModal.js";
|
|
17
|
+
import "./components/StoreShippingSection.js";
|
|
17
18
|
import "./components/WorkspaceQuotaAssignmentModal.js";
|
|
18
19
|
import "./components/index.js";
|
|
19
20
|
import { CheckoutPage as e } from "./pages/CheckoutPage.js";
|