@fluid-app/portal-sdk 0.1.28 → 0.1.30

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 (87) hide show
  1. package/dist/{AppNavigationContext-DrayF_RG.cjs → AppNavigationContext-DAcrNgXZ.cjs} +1 -1
  2. package/dist/{AppNavigationContext-DrayF_RG.cjs.map → AppNavigationContext-DAcrNgXZ.cjs.map} +1 -1
  3. package/dist/{AppNavigationContext-2nkMoO8F.mjs → AppNavigationContext-v_y8OYHo.mjs} +1 -1
  4. package/dist/{AppNavigationContext-2nkMoO8F.mjs.map → AppNavigationContext-v_y8OYHo.mjs.map} +1 -1
  5. package/dist/{ContactsScreen-GPOgZ-Wi.cjs → ContactsScreen-BL5Jlaz5.cjs} +2 -2
  6. package/dist/{ContactsScreen-GPOgZ-Wi.cjs.map → ContactsScreen-BL5Jlaz5.cjs.map} +1 -1
  7. package/dist/{ContactsScreen-BicHZ37M.mjs → ContactsScreen-CcNUC8xu.mjs} +2 -2
  8. package/dist/{ContactsScreen-BicHZ37M.mjs.map → ContactsScreen-CcNUC8xu.mjs.map} +1 -1
  9. package/dist/{CoreScreenPlaceholder-Cl_zuOBC.cjs → CoreScreenPlaceholder-B64M78iR.cjs} +1 -1
  10. package/dist/{CoreScreenPlaceholder-Cl_zuOBC.cjs.map → CoreScreenPlaceholder-B64M78iR.cjs.map} +1 -1
  11. package/dist/{CoreScreenPlaceholder-Cdyl97Wo.mjs → CoreScreenPlaceholder-DVVLc-OM.mjs} +1 -1
  12. package/dist/{CoreScreenPlaceholder-Cdyl97Wo.mjs.map → CoreScreenPlaceholder-DVVLc-OM.mjs.map} +1 -1
  13. package/dist/{CustomersScreen-Brz5zLkq.mjs → CustomersScreen-SuHGSUdb.mjs} +2 -2
  14. package/dist/{CustomersScreen-Brz5zLkq.mjs.map → CustomersScreen-SuHGSUdb.mjs.map} +1 -1
  15. package/dist/{CustomersScreen-CK1jJhvM.cjs → CustomersScreen-zl_vRzcJ.cjs} +2 -2
  16. package/dist/{CustomersScreen-CK1jJhvM.cjs.map → CustomersScreen-zl_vRzcJ.cjs.map} +1 -1
  17. package/dist/{MessagingScreen-DVU3c8fX.mjs → MessagingScreen-BGzfLD8k.mjs} +2 -2
  18. package/dist/{MessagingScreen-sAWF7pjl.cjs → MessagingScreen-CRLd91tP.cjs} +2 -2
  19. package/dist/{MessagingScreen-sAWF7pjl.cjs.map → MessagingScreen-CRLd91tP.cjs.map} +1 -1
  20. package/dist/{MessagingScreen-C33eDdna.cjs → MessagingScreen-DIZ72Tg0.cjs} +2 -2
  21. package/dist/{MessagingScreen-II_iNqLk.mjs → MessagingScreen-We1B2pka.mjs} +2 -2
  22. package/dist/{MessagingScreen-II_iNqLk.mjs.map → MessagingScreen-We1B2pka.mjs.map} +1 -1
  23. package/dist/OrdersScreen-Bu-ENmH6.cjs +133 -0
  24. package/dist/OrdersScreen-Bu-ENmH6.cjs.map +1 -0
  25. package/dist/OrdersScreen-TSXDDHZe.cjs +33 -0
  26. package/dist/OrdersScreen-afRAHf07.mjs +126 -0
  27. package/dist/OrdersScreen-afRAHf07.mjs.map +1 -0
  28. package/dist/{ProductsScreen-DrrBYFl0.mjs → ProductsScreen-B-oWUzvD.mjs} +3 -3
  29. package/dist/{ProductsScreen-BOngRxSO.mjs → ProductsScreen-ChvK61hX.mjs} +3 -3
  30. package/dist/{ProductsScreen-BOngRxSO.mjs.map → ProductsScreen-ChvK61hX.mjs.map} +1 -1
  31. package/dist/{ProductsScreen-DzD-TPh5.cjs → ProductsScreen-CkE2nyuw.cjs} +3 -3
  32. package/dist/{ProductsScreen-DzD-TPh5.cjs.map → ProductsScreen-CkE2nyuw.cjs.map} +1 -1
  33. package/dist/{ProductsScreen-CdP_m_Ok.cjs → ProductsScreen-PCg91SbX.cjs} +3 -3
  34. package/dist/ProfileScreen-B6Dp7RLa.cjs +2856 -0
  35. package/dist/ProfileScreen-B6Dp7RLa.cjs.map +1 -0
  36. package/dist/ProfileScreen-B83tzedh.mjs +2849 -0
  37. package/dist/ProfileScreen-B83tzedh.mjs.map +1 -0
  38. package/dist/{AccountScreen-Vzz8W4Iq.cjs → ProfileScreen-CH3B-IQz.cjs} +3 -3
  39. package/dist/{ShareablesScreen-DYPJgZ3z.cjs → ShareablesScreen-Bqj6dtOM.cjs} +3 -3
  40. package/dist/{ShareablesScreen-DYPJgZ3z.cjs.map → ShareablesScreen-Bqj6dtOM.cjs.map} +1 -1
  41. package/dist/{ShareablesScreen-jHqLmOC6.cjs → ShareablesScreen-BvJIBZvI.cjs} +3 -3
  42. package/dist/{ShareablesScreen-CQy39TAK.mjs → ShareablesScreen-ChS517hq.mjs} +3 -3
  43. package/dist/{ShareablesScreen-CQy39TAK.mjs.map → ShareablesScreen-ChS517hq.mjs.map} +1 -1
  44. package/dist/{ShareablesScreen-BsqZvRSK.mjs → ShareablesScreen-CqVj81Ol.mjs} +3 -3
  45. package/dist/{ShopScreen-BPCwix1m.cjs → ShopScreen-CjoTGnCJ.cjs} +2 -2
  46. package/dist/{ShopScreen-BPCwix1m.cjs.map → ShopScreen-CjoTGnCJ.cjs.map} +1 -1
  47. package/dist/{ShopScreen--pUsiUNt.cjs → ShopScreen-DS4p47Ry.cjs} +1 -1
  48. package/dist/{ShopScreen-BKBzgkr7.mjs → ShopScreen-KeU6x3PT.mjs} +2 -2
  49. package/dist/{ShopScreen-BKBzgkr7.mjs.map → ShopScreen-KeU6x3PT.mjs.map} +1 -1
  50. package/dist/SubscriptionsScreen-CHn_Q0zf.cjs +1288 -0
  51. package/dist/SubscriptionsScreen-CHn_Q0zf.cjs.map +1 -0
  52. package/dist/SubscriptionsScreen-D5_eJwBP.mjs +1281 -0
  53. package/dist/SubscriptionsScreen-D5_eJwBP.mjs.map +1 -0
  54. package/dist/SubscriptionsScreen-DGJ_YeX3.cjs +33 -0
  55. package/dist/{es-kNOrmozy.cjs → es-BtechuHV.cjs} +1 -1
  56. package/dist/{es-kNOrmozy.cjs.map → es-BtechuHV.cjs.map} +1 -1
  57. package/dist/{es-BL8VBBDa.mjs → es-DxWiENwN.mjs} +1 -1
  58. package/dist/{es-BL8VBBDa.mjs.map → es-DxWiENwN.mjs.map} +1 -1
  59. package/dist/index.cjs +166 -94
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.d.cts +38 -8
  62. package/dist/index.d.cts.map +1 -1
  63. package/dist/index.d.mts +38 -8
  64. package/dist/index.d.mts.map +1 -1
  65. package/dist/index.mjs +162 -92
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/src-BZEkCfd4.mjs +973 -0
  68. package/dist/src-BZEkCfd4.mjs.map +1 -0
  69. package/dist/src-DXC-Jw6i.cjs +1009 -0
  70. package/dist/src-DXC-Jw6i.cjs.map +1 -0
  71. package/dist/{src-DMjlIMO9.cjs → src-vxm9rMYT.cjs} +2 -2
  72. package/dist/{src-DMjlIMO9.cjs.map → src-vxm9rMYT.cjs.map} +1 -1
  73. package/dist/{src-9pW9wS5O.mjs → src-wpQFW94i.mjs} +2 -2
  74. package/dist/{src-9pW9wS5O.mjs.map → src-wpQFW94i.mjs.map} +1 -1
  75. package/dist/use-account-clients-DYTyFvdN.mjs +134 -0
  76. package/dist/use-account-clients-DYTyFvdN.mjs.map +1 -0
  77. package/dist/use-account-clients-n2a8bdSP.cjs +182 -0
  78. package/dist/use-account-clients-n2a8bdSP.cjs.map +1 -0
  79. package/package.json +10 -10
  80. package/dist/AccountScreen-Dp6QFyEr.cjs +0 -5322
  81. package/dist/AccountScreen-Dp6QFyEr.cjs.map +0 -1
  82. package/dist/AccountScreen-E4ZBgOUS.mjs +0 -5309
  83. package/dist/AccountScreen-E4ZBgOUS.mjs.map +0 -1
  84. package/dist/OrdersScreen-DGt-CTBS.mjs +0 -24
  85. package/dist/OrdersScreen-DGt-CTBS.mjs.map +0 -1
  86. package/dist/OrdersScreen-Dy-JChVQ.cjs +0 -41
  87. package/dist/OrdersScreen-Dy-JChVQ.cjs.map +0 -1
@@ -0,0 +1,2856 @@
1
+ require("./chunk-9hOWP6kD.cjs");
2
+ const require_FluidProvider = require("./FluidProvider-BmkSwcgV.cjs");
3
+ const require_src = require("./src-CaogiXSc.cjs");
4
+ const require_use_account_clients = require("./use-account-clients-n2a8bdSP.cjs");
5
+ let react = require("react");
6
+ let _tanstack_react_query = require("@tanstack/react-query");
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ let lucide_react = require("lucide-react");
9
+ let _hookform_resolvers_zod = require("@hookform/resolvers/zod");
10
+ let react_hook_form = require("react-hook-form");
11
+ let zod = require("zod");
12
+ //#region ../../platform/api-client-core/src/parse-api-errors.ts
13
+ /**
14
+ * Framework-agnostic API error parsing utilities.
15
+ *
16
+ * Extracts structured field-level errors from API responses and formats
17
+ * them into human-readable messages. Works with ApiError from this package
18
+ * as well as any error object that has `status`, `data`, and optional `message`.
19
+ */
20
+ /**
21
+ * Converts snake_case or camelCase field names to Title Case
22
+ */
23
+ function formatFieldName(field) {
24
+ return field.replace(/_/g, " ").replace(/([A-Z])/g, " $1").split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ").trim();
25
+ }
26
+ /**
27
+ * Type guard to check if an error looks like an API error
28
+ */
29
+ function isApiLikeError(error) {
30
+ if (!error || typeof error !== "object") return false;
31
+ const err = error;
32
+ return typeof err.status === "number" && "data" in err && (typeof err.message === "string" || err.message === void 0);
33
+ }
34
+ /**
35
+ * Extracts field-level errors from API error data
36
+ */
37
+ function extractFieldErrors(data) {
38
+ const errors = [];
39
+ if (!data || typeof data !== "object") return errors;
40
+ const errorObj = data;
41
+ for (const [key, value] of Object.entries(errorObj)) if (Array.isArray(value) && value.length > 0) errors.push({
42
+ field: formatFieldName(key),
43
+ messages: value.map((item) => typeof item === "string" ? item : JSON.stringify(item))
44
+ });
45
+ else if (typeof value === "string" && value.length > 0) errors.push({
46
+ field: formatFieldName(key),
47
+ messages: [value]
48
+ });
49
+ else if (value && typeof value === "object" && !Array.isArray(value)) extractFieldErrors(value).forEach((nestedError) => {
50
+ errors.push({
51
+ field: `${formatFieldName(key)} → ${nestedError.field}`,
52
+ messages: nestedError.messages
53
+ });
54
+ });
55
+ return errors;
56
+ }
57
+ /**
58
+ * Formats field errors into a readable description string
59
+ */
60
+ function formatErrorDescription(errors) {
61
+ if (errors.length === 0) return "";
62
+ if (errors.length === 1) {
63
+ const err = errors[0];
64
+ if (!err) return "";
65
+ const message = err.messages[0] || "is invalid";
66
+ return `${err.field} ${message}`;
67
+ }
68
+ if (errors.length <= 3) return errors.map((e) => `${e.field} ${e.messages[0] || "is invalid"}`).join("\n");
69
+ const shown = errors.slice(0, 3).map((e) => `${e.field} ${e.messages[0] || "is invalid"}`).join("\n");
70
+ const remaining = errors.length - 3;
71
+ return `${shown}\n...and ${remaining} more ${remaining === 1 ? "error" : "errors"}`;
72
+ }
73
+ /**
74
+ * Parses an error and returns a human-readable description string.
75
+ *
76
+ * Handles:
77
+ * - API-like errors with structured field-level data
78
+ * - API-like errors with a top-level message
79
+ * - Standard Error instances
80
+ * - Falls back to the provided fallback string
81
+ *
82
+ * @param error - The error to parse (ApiError, Error, or unknown)
83
+ * @param fallback - Optional fallback description if error cannot be parsed
84
+ * @returns A human-readable error description, or undefined if nothing could be extracted
85
+ */
86
+ function parseApiErrors(error, fallback) {
87
+ if (isApiLikeError(error)) {
88
+ if (error.data) {
89
+ const fieldErrors = extractFieldErrors(error.data);
90
+ if (fieldErrors.length > 0) return formatErrorDescription(fieldErrors);
91
+ }
92
+ if (error.message) return error.message;
93
+ } else if (error instanceof Error) return error.message;
94
+ return fallback;
95
+ }
96
+ //#endregion
97
+ //#region ../../profile/core/src/context.ts
98
+ const ProfileUIContext = (0, react.createContext)(null);
99
+ function useProfileUI() {
100
+ const context = (0, react.useContext)(ProfileUIContext);
101
+ if (!context) throw new Error("useProfileUI must be used within a ProfileUIProvider");
102
+ return context;
103
+ }
104
+ //#endregion
105
+ //#region ../../profile/core/src/provider.tsx
106
+ function ProfileUIProvider({ t, children }) {
107
+ const value = (0, react.useMemo)(() => ({ t }), [t]);
108
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProfileUIContext.Provider, {
109
+ value,
110
+ children
111
+ });
112
+ }
113
+ //#endregion
114
+ //#region ../../fluid-pay/api-client/src/namespaces/addresses.ts
115
+ /**
116
+ * Fetch all customer addresses.
117
+ * Endpoint: GET /fluid_pay/addresses?jwt={jwt}
118
+ */
119
+ async function fetchCustomerAddresses(client, jwt) {
120
+ return client.get("/fluid_pay/addresses", {
121
+ jwt,
122
+ page: "1",
123
+ per_page: "100"
124
+ });
125
+ }
126
+ /**
127
+ * Create a new customer address.
128
+ * Endpoint: POST /fluid_pay/create_address?jwt={jwt}
129
+ */
130
+ async function createCustomerAddress(client, jwt, body) {
131
+ return client.post(`/fluid_pay/create_address?jwt=${jwt}`, body);
132
+ }
133
+ /**
134
+ * Update an existing customer address.
135
+ * Endpoint: PATCH /fluid_pay/update_address/{addressId}?jwt={jwt}
136
+ */
137
+ async function updateCustomerAddress(client, jwt, addressId, body) {
138
+ return client.patch(`/fluid_pay/update_address/${addressId}?jwt=${jwt}`, body);
139
+ }
140
+ /**
141
+ * Delete a customer address.
142
+ * Endpoint: DELETE /fluid_pay/delete_address/{addressId}?jwt={jwt}
143
+ */
144
+ async function deleteCustomerAddress(client, jwt, addressId) {
145
+ return client.delete(`/fluid_pay/delete_address/${addressId}?jwt=${jwt}`);
146
+ }
147
+ //#endregion
148
+ //#region ../../fluid-pay/api-client/src/namespaces/payment-methods.ts
149
+ /**
150
+ * Fetch all customer payment methods.
151
+ * Endpoint: GET /fluid_pay/payment_methods?jwt={jwt}
152
+ */
153
+ async function fetchCustomerPaymentMethods(client, jwt, countryCode) {
154
+ const params = {
155
+ jwt,
156
+ page: "1",
157
+ per_page: "100"
158
+ };
159
+ if (countryCode) params.country_code = countryCode;
160
+ return client.get("/fluid_pay/payment_methods", params);
161
+ }
162
+ /**
163
+ * Add a credit card to the customer's account.
164
+ * Endpoint: POST /fluid_pay/create_payment_method?jwt={jwt}
165
+ */
166
+ async function addCreditCardToCustomer(client, jwt, data) {
167
+ return client.post(`/fluid_pay/create_payment_method?jwt=${jwt}`, data);
168
+ }
169
+ /**
170
+ * Delete a customer payment method.
171
+ * Endpoint: DELETE /fluid_pay/delete_payment_method/{id}?jwt={jwt}
172
+ */
173
+ async function deleteCustomerPaymentMethod(client, jwt, paymentMethodId) {
174
+ return client.delete(`/fluid_pay/delete_payment_method/${paymentMethodId}?jwt=${jwt}`);
175
+ }
176
+ /**
177
+ * Update a payment method (default status, billing address).
178
+ * Endpoint: PATCH /fluid_pay/update_payment_method/{id}?jwt={jwt}
179
+ */
180
+ async function updatePaymentMethod(client, jwt, paymentMethodId, body) {
181
+ return client.patch(`/fluid_pay/update_payment_method/${paymentMethodId}?jwt=${jwt}`, body);
182
+ }
183
+ //#endregion
184
+ //#region ../../fluid-pay/api-client/src/namespaces/vault.ts
185
+ /**
186
+ * Fetch VGS vault credentials for the customer's payment account.
187
+ * Endpoint: GET /fluid_pay/vault?jwt={jwt}
188
+ */
189
+ async function fetchVaultCredentialsForPaymentAccount(client, jwt) {
190
+ return client.get("/fluid_pay/vault", { jwt });
191
+ }
192
+ //#endregion
193
+ //#region ../../fluid-pay/core/src/utils/country-config.ts
194
+ const US_STATES = [
195
+ {
196
+ name: "Alabama",
197
+ isoCode: "AL"
198
+ },
199
+ {
200
+ name: "Alaska",
201
+ isoCode: "AK"
202
+ },
203
+ {
204
+ name: "Arizona",
205
+ isoCode: "AZ"
206
+ },
207
+ {
208
+ name: "Arkansas",
209
+ isoCode: "AR"
210
+ },
211
+ {
212
+ name: "California",
213
+ isoCode: "CA"
214
+ },
215
+ {
216
+ name: "Colorado",
217
+ isoCode: "CO"
218
+ },
219
+ {
220
+ name: "Connecticut",
221
+ isoCode: "CT"
222
+ },
223
+ {
224
+ name: "Delaware",
225
+ isoCode: "DE"
226
+ },
227
+ {
228
+ name: "Florida",
229
+ isoCode: "FL"
230
+ },
231
+ {
232
+ name: "Georgia",
233
+ isoCode: "GA"
234
+ },
235
+ {
236
+ name: "Hawaii",
237
+ isoCode: "HI"
238
+ },
239
+ {
240
+ name: "Idaho",
241
+ isoCode: "ID"
242
+ },
243
+ {
244
+ name: "Illinois",
245
+ isoCode: "IL"
246
+ },
247
+ {
248
+ name: "Indiana",
249
+ isoCode: "IN"
250
+ },
251
+ {
252
+ name: "Iowa",
253
+ isoCode: "IA"
254
+ },
255
+ {
256
+ name: "Kansas",
257
+ isoCode: "KS"
258
+ },
259
+ {
260
+ name: "Kentucky",
261
+ isoCode: "KY"
262
+ },
263
+ {
264
+ name: "Louisiana",
265
+ isoCode: "LA"
266
+ },
267
+ {
268
+ name: "Maine",
269
+ isoCode: "ME"
270
+ },
271
+ {
272
+ name: "Maryland",
273
+ isoCode: "MD"
274
+ },
275
+ {
276
+ name: "Massachusetts",
277
+ isoCode: "MA"
278
+ },
279
+ {
280
+ name: "Michigan",
281
+ isoCode: "MI"
282
+ },
283
+ {
284
+ name: "Minnesota",
285
+ isoCode: "MN"
286
+ },
287
+ {
288
+ name: "Mississippi",
289
+ isoCode: "MS"
290
+ },
291
+ {
292
+ name: "Missouri",
293
+ isoCode: "MO"
294
+ },
295
+ {
296
+ name: "Montana",
297
+ isoCode: "MT"
298
+ },
299
+ {
300
+ name: "Nebraska",
301
+ isoCode: "NE"
302
+ },
303
+ {
304
+ name: "Nevada",
305
+ isoCode: "NV"
306
+ },
307
+ {
308
+ name: "New Hampshire",
309
+ isoCode: "NH"
310
+ },
311
+ {
312
+ name: "New Jersey",
313
+ isoCode: "NJ"
314
+ },
315
+ {
316
+ name: "New Mexico",
317
+ isoCode: "NM"
318
+ },
319
+ {
320
+ name: "New York",
321
+ isoCode: "NY"
322
+ },
323
+ {
324
+ name: "North Carolina",
325
+ isoCode: "NC"
326
+ },
327
+ {
328
+ name: "North Dakota",
329
+ isoCode: "ND"
330
+ },
331
+ {
332
+ name: "Ohio",
333
+ isoCode: "OH"
334
+ },
335
+ {
336
+ name: "Oklahoma",
337
+ isoCode: "OK"
338
+ },
339
+ {
340
+ name: "Oregon",
341
+ isoCode: "OR"
342
+ },
343
+ {
344
+ name: "Pennsylvania",
345
+ isoCode: "PA"
346
+ },
347
+ {
348
+ name: "Rhode Island",
349
+ isoCode: "RI"
350
+ },
351
+ {
352
+ name: "South Carolina",
353
+ isoCode: "SC"
354
+ },
355
+ {
356
+ name: "South Dakota",
357
+ isoCode: "SD"
358
+ },
359
+ {
360
+ name: "Tennessee",
361
+ isoCode: "TN"
362
+ },
363
+ {
364
+ name: "Texas",
365
+ isoCode: "TX"
366
+ },
367
+ {
368
+ name: "Utah",
369
+ isoCode: "UT"
370
+ },
371
+ {
372
+ name: "Vermont",
373
+ isoCode: "VT"
374
+ },
375
+ {
376
+ name: "Virginia",
377
+ isoCode: "VA"
378
+ },
379
+ {
380
+ name: "Washington",
381
+ isoCode: "WA"
382
+ },
383
+ {
384
+ name: "West Virginia",
385
+ isoCode: "WV"
386
+ },
387
+ {
388
+ name: "Wisconsin",
389
+ isoCode: "WI"
390
+ },
391
+ {
392
+ name: "Wyoming",
393
+ isoCode: "WY"
394
+ },
395
+ {
396
+ name: "District of Columbia",
397
+ isoCode: "DC"
398
+ }
399
+ ];
400
+ const COUNTRY_CONFIGS = {
401
+ US: {
402
+ regionLabel: "State",
403
+ postalLabel: "ZIP Code"
404
+ },
405
+ JP: {
406
+ regionLabel: "Prefecture",
407
+ postalLabel: "Postal Code"
408
+ }
409
+ };
410
+ const DEFAULT_REGION_CONFIG = {
411
+ regionLabel: "Province",
412
+ postalLabel: "Postal Code"
413
+ };
414
+ function getRegionConfig(countryCode) {
415
+ return COUNTRY_CONFIGS[countryCode] ?? DEFAULT_REGION_CONFIG;
416
+ }
417
+ //#endregion
418
+ //#region ../../fluid-pay/core/src/hooks/use-country-states.ts
419
+ function useCountryStates() {
420
+ const [selectedCountry, setSelectedCountry] = (0, react.useState)("US");
421
+ const [stateOptions, setStateOptions] = (0, react.useState)(US_STATES);
422
+ return {
423
+ handleCountryChange: (0, react.useCallback)((selectedCountryCode, fetchStates) => {
424
+ setSelectedCountry(selectedCountryCode);
425
+ if (selectedCountryCode === "US") setStateOptions(US_STATES);
426
+ else if (fetchStates) fetchStates(selectedCountryCode).then((states) => setStateOptions(states)).catch((error) => {
427
+ console.error("Failed to fetch states:", error);
428
+ setStateOptions([]);
429
+ });
430
+ else setStateOptions([]);
431
+ }, []),
432
+ stateOptions,
433
+ config: getRegionConfig(selectedCountry),
434
+ selectedCountry
435
+ };
436
+ }
437
+ //#endregion
438
+ //#region ../../profile/ui/src/components/ellipses-dropdown.tsx
439
+ function EllipsesDropdown({ onDelete, onEdit, editLabel = "Edit", deleteLabel = "Delete", disabled = false }) {
440
+ if (disabled) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
441
+ variant: "ghost",
442
+ disabled: true,
443
+ className: "cursor-not-allowed opacity-50",
444
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
445
+ xmlns: "http://www.w3.org/2000/svg",
446
+ viewBox: "0 0 128 512",
447
+ className: "h-4 w-1 fill-gray-400",
448
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z" })
449
+ })
450
+ });
451
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuTrigger, {
452
+ asChild: true,
453
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
454
+ variant: "ghost",
455
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
456
+ xmlns: "http://www.w3.org/2000/svg",
457
+ viewBox: "0 0 128 512",
458
+ className: "h-4 w-1 fill-gray-400",
459
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z" })
460
+ })
461
+ })
462
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenuContent, {
463
+ className: "min-w-20 space-y-1 text-sm text-gray-900",
464
+ children: [onEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenuItem, {
465
+ className: "flex cursor-pointer flex-row items-center justify-between space-x-2 rounded px-2 hover:bg-gray-50",
466
+ onClick: (e) => {
467
+ e.stopPropagation();
468
+ onEdit();
469
+ },
470
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: editLabel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
471
+ xmlns: "http://www.w3.org/2000/svg",
472
+ viewBox: "0 0 512 512",
473
+ className: "h-2.5 w-2.5 fill-current",
474
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M362.7 19.3L314.3 67.7 444.3 197.7l48.4-48.4c25-25 25-65.5 0-90.5L453.3 19.3c-25-25-65.5-25-90.5 0zm-71 71L58.6 323.5c-10.4 10.4-18 23.3-22.2 37.4L1 481.2C-1.5 489.7 .8 498.8 7 505s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L421.7 220.3 291.7 90.3z" })
475
+ })]
476
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuSeparator, {})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenuItem, {
477
+ className: "flex cursor-pointer flex-row items-center justify-between space-x-2 rounded px-2 text-red-500 hover:bg-red-50",
478
+ onClick: (e) => {
479
+ e.stopPropagation();
480
+ onDelete?.();
481
+ },
482
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: deleteLabel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
483
+ xmlns: "http://www.w3.org/2000/svg",
484
+ viewBox: "0 0 448 512",
485
+ className: "h-2.5 w-2.5 fill-red-500",
486
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M135.2 17.7C140.6 6.8 151.7 0 163.8 0L284.2 0c12.1 0 23.2 6.8 28.6 17.7L320 32l80 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L48 96C30.3 96 16 81.7 16 64S30.3 32 48 32l80 0 7.2-14.3zM32 128l384 0 0 320c0 35.3-28.7 64-64 64L96 512c-35.3 0-64-28.7-64-64l0-320z" })
487
+ })]
488
+ })]
489
+ })] });
490
+ }
491
+ //#endregion
492
+ //#region ../../profile/ui/src/components/confirm-action-dialog.tsx
493
+ function ConfirmActionDialog({ title, description, onAction, openDialog, setOpenDialog, errorMsg, isLoading, actionText = "Delete" }) {
494
+ const { t } = useProfileUI();
495
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Dialog, {
496
+ open: openDialog,
497
+ onOpenChange: setOpenDialog,
498
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DialogContent, {
499
+ className: "max-w-sm rounded md:w-90",
500
+ children: [
501
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogHeader, {
502
+ className: "flex flex-row justify-between",
503
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogTitle, {
504
+ className: "text-md w-full text-left font-medium",
505
+ children: title
506
+ })
507
+ }),
508
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
509
+ className: "space-y-4",
510
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
511
+ className: "text-left text-sm text-gray-500",
512
+ children: description
513
+ })
514
+ }),
515
+ errorMsg && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
516
+ className: "text-sm text-red-500",
517
+ children: errorMsg
518
+ }),
519
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogFooter, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
520
+ className: "flex w-full flex-row justify-between space-x-2",
521
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogClose, {
522
+ asChild: true,
523
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
524
+ className: "min-w-[70px] rounded bg-gray-50 p-3 text-gray-900 ring-1 ring-gray-300 hover:bg-gray-100",
525
+ onClick: () => setOpenDialog(false),
526
+ children: t("cancel")
527
+ })
528
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
529
+ type: "button",
530
+ className: "min-w-[70px] rounded bg-red-600 p-3 text-white hover:bg-red-700",
531
+ onClick: onAction,
532
+ disabled: isLoading,
533
+ children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-5 w-5 animate-spin rounded-full border-4 border-t-4 border-white border-t-transparent" }) : actionText
534
+ })]
535
+ }) })
536
+ ]
537
+ })
538
+ });
539
+ }
540
+ //#endregion
541
+ //#region ../../profile/ui/src/components/customer-points-ledger.tsx
542
+ function formatTransactionType(ledger, t) {
543
+ const transactionType = ledger.metadata.transaction_type;
544
+ if (!transactionType) {
545
+ if (ledger.metadata.source) return ledger.amount > 0 ? t("points_awarded") : t("points_redeemed");
546
+ return t("transaction");
547
+ }
548
+ const translationKey = transactionType.toLowerCase().replace(/ /g, "_");
549
+ const translated = t(translationKey);
550
+ if (translated !== translationKey) return translated;
551
+ return transactionType.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
552
+ }
553
+ function formatPoints(amount) {
554
+ return `${amount >= 0 ? "+" : ""}${amount}`;
555
+ }
556
+ function formatDateTime(dateString) {
557
+ return new Date(dateString).toLocaleDateString(void 0, {
558
+ year: "numeric",
559
+ month: "short",
560
+ day: "numeric",
561
+ hour: "2-digit",
562
+ minute: "2-digit"
563
+ });
564
+ }
565
+ function CustomerPointsLedger({ pointsLedger, isLoading = false }) {
566
+ const [accordionValue, setAccordionValue] = (0, react.useState)("");
567
+ const { t } = useProfileUI();
568
+ const availablePoints = pointsLedger[0]?.total_balance ?? 0;
569
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
570
+ className: "mb-6 border-b border-gray-300 pb-4",
571
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Accordion, {
572
+ type: "single",
573
+ collapsible: true,
574
+ value: accordionValue,
575
+ onValueChange: setAccordionValue,
576
+ className: "w-full",
577
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.AccordionItem, {
578
+ value: "points-history",
579
+ className: "border-b-0",
580
+ children: [
581
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
582
+ className: "flex flex-row items-center justify-between",
583
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
584
+ className: "mt-4 mb-1 text-sm text-gray-400",
585
+ children: t("points_history")
586
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.AccordionTrigger, { className: "m-0 ml-2 flex h-auto min-h-0 w-auto py-0 hover:no-underline" })]
587
+ }),
588
+ isLoading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-6 w-full" }),
589
+ !isLoading && !accordionValue && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
590
+ className: "mb-2 flex w-full cursor-pointer flex-col",
591
+ onClick: () => setAccordionValue("points-history"),
592
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
593
+ className: "text-sm font-semibold text-gray-900",
594
+ children: [
595
+ availablePoints.toLocaleString(),
596
+ " ",
597
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
598
+ className: "font-normal text-gray-500",
599
+ children: t("points_available").toLowerCase()
600
+ })
601
+ ]
602
+ })
603
+ }),
604
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.AccordionContent, {
605
+ className: "max-h-[400px] overflow-y-auto pt-2",
606
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
607
+ className: "mb-3 flex w-full flex-col",
608
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
609
+ className: "text-sm font-semibold text-gray-900",
610
+ children: [
611
+ availablePoints.toLocaleString(),
612
+ " ",
613
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
614
+ className: "font-normal text-gray-500",
615
+ children: t("points_available").toLowerCase()
616
+ })
617
+ ]
618
+ })
619
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
620
+ className: "flex flex-col space-y-0",
621
+ children: pointsLedger.length > 0 ? pointsLedger.map((ledger) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
622
+ className: "relative flex flex-row items-start justify-between py-3",
623
+ children: [
624
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
625
+ className: "absolute top-3 left-0",
626
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mt-1.5 h-2 w-2 flex-shrink-0 rounded-full border border-gray-300" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mr-1 h-10 border-r border-gray-200" })]
627
+ }),
628
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
629
+ className: "ml-6 flex flex-row items-start space-x-3",
630
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
631
+ className: "flex flex-col",
632
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
633
+ className: "text-sm font-medium text-gray-900",
634
+ children: formatTransactionType(ledger, t)
635
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
636
+ className: "text-sm text-gray-500",
637
+ children: formatDateTime(ledger.created_at)
638
+ })]
639
+ })
640
+ }),
641
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
642
+ className: require_src.cn("text-sm font-medium", ledger.amount >= 0 ? "text-green-500" : "text-red-500"),
643
+ children: formatPoints(ledger.amount)
644
+ })
645
+ ]
646
+ }, ledger.id)) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
647
+ className: "text-sm text-gray-500",
648
+ children: t("no_points_history_found")
649
+ })
650
+ })]
651
+ })
652
+ ]
653
+ })
654
+ })
655
+ });
656
+ }
657
+ //#endregion
658
+ //#region ../../profile/ui/src/components/form-fields.tsx
659
+ function FormTextField$1({ control, name, label, containerClassName, ...props }) {
660
+ const { field, fieldState: { error } } = (0, react_hook_form.useController)({
661
+ name,
662
+ control
663
+ });
664
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
665
+ className: require_src.cn("space-y-1", containerClassName),
666
+ children: [
667
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Label, {
668
+ htmlFor: name,
669
+ className: "mb-1.5 block text-sm font-medium text-gray-700",
670
+ children: label
671
+ }),
672
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Input, {
673
+ ...field,
674
+ ...props,
675
+ id: name,
676
+ value: field.value ?? "",
677
+ className: require_src.cn(error && "ring-1 ring-red-500", props.className)
678
+ }),
679
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
680
+ className: "text-sm text-red-500",
681
+ children: error.message
682
+ })
683
+ ]
684
+ });
685
+ }
686
+ function FormSelectField$1({ control, name, label, options, placeholder, containerClassName, onChange }) {
687
+ const { field, fieldState: { error } } = (0, react_hook_form.useController)({
688
+ name,
689
+ control
690
+ });
691
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
692
+ className: require_src.cn("space-y-1", containerClassName),
693
+ children: [
694
+ label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Label, {
695
+ htmlFor: name,
696
+ className: "block text-sm font-medium text-gray-700",
697
+ children: label
698
+ }),
699
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Select, {
700
+ value: field.value?.toString() ?? "",
701
+ onValueChange: (val) => {
702
+ field.onChange(val);
703
+ onChange?.(val);
704
+ },
705
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectTrigger, {
706
+ className: require_src.cn(error && "ring-1 ring-red-500"),
707
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectValue, { placeholder })
708
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectContent, { children: options?.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectItem, {
709
+ value: opt.value.toString(),
710
+ children: opt.name
711
+ }, `${opt.name}-${opt.value}`)) })]
712
+ }),
713
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
714
+ className: "text-sm text-red-500",
715
+ children: error.message
716
+ })
717
+ ]
718
+ });
719
+ }
720
+ //#endregion
721
+ //#region ../../profile/ui/src/components/user-info-dialog.tsx
722
+ function UserInfoDialog({ control, isOpen, onSubmit, handleClose, languageOptions, errorMsg, isSubmitting }) {
723
+ const { t } = useProfileUI();
724
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Dialog, {
725
+ open: isOpen,
726
+ onOpenChange: (open) => !open && handleClose(),
727
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DialogContent, {
728
+ className: "max-w-sm rounded md:max-w-lg",
729
+ children: [
730
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogTitle, {
731
+ className: "text-md font-medium text-gray-900",
732
+ children: t("edit_profile")
733
+ }) }),
734
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
735
+ className: "space-y-0",
736
+ children: [
737
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
738
+ control,
739
+ name: "first_name",
740
+ label: t("first_name")
741
+ }),
742
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
743
+ control,
744
+ name: "last_name",
745
+ label: t("last_name")
746
+ }),
747
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
748
+ control,
749
+ name: "phone_number",
750
+ label: t("phone_number"),
751
+ type: "tel"
752
+ }),
753
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField$1, {
754
+ control,
755
+ name: "language",
756
+ label: t("language"),
757
+ options: languageOptions,
758
+ placeholder: t("select_an_option")
759
+ })
760
+ ]
761
+ }),
762
+ errorMsg && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
763
+ className: "text-sm text-red-500",
764
+ children: errorMsg
765
+ }),
766
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogFooter, {
767
+ className: "flex flex-row items-center justify-end",
768
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
769
+ className: "flex-1 text-right",
770
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogClose, {
771
+ asChild: true,
772
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Button, {
773
+ type: "button",
774
+ onClick: onSubmit,
775
+ children: [isSubmitting && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mr-3 h-5 w-5 animate-spin rounded-full border-4 border-t-4 border-white border-t-transparent" }), isSubmitting ? t("saving") : t("save_changes")]
776
+ })
777
+ })
778
+ })
779
+ })
780
+ ]
781
+ })
782
+ });
783
+ }
784
+ //#endregion
785
+ //#region ../../profile/ui/src/components/customer-info.tsx
786
+ function createUserInfoSchema(messages) {
787
+ return zod.z.object({
788
+ first_name: zod.z.string().min(1, { message: messages.firstNameRequired }),
789
+ last_name: zod.z.string().min(1, { message: messages.lastNameRequired }),
790
+ phone_number: zod.z.string().optional(),
791
+ language: zod.z.string().min(1, { message: messages.languageRequired })
792
+ });
793
+ }
794
+ function CustomerInfo({ customerAccount, languages, onUpdateCustomer, isUpdating = false }) {
795
+ const [isEditDialogOpen, setIsEditDialogOpen] = (0, react.useState)(false);
796
+ const [updateError, setUpdateError] = (0, react.useState)(void 0);
797
+ const { t } = useProfileUI();
798
+ const { first_name, full_name } = customerAccount.customer;
799
+ const derivedLastName = full_name.startsWith(first_name) ? full_name.slice(first_name.length).trim() : "";
800
+ const userInitial = first_name ? first_name.charAt(0).toUpperCase() : "";
801
+ const customerLanguage = languages?.find((language) => language.iso === customerAccount.fluid_pay_account.language_iso)?.name;
802
+ const languageOptions = languages?.map((language) => ({
803
+ name: language.name,
804
+ value: language.name
805
+ }));
806
+ const { control, handleSubmit, reset } = (0, react_hook_form.useForm)({
807
+ resolver: (0, _hookform_resolvers_zod.zodResolver)((0, react.useMemo)(() => createUserInfoSchema({
808
+ firstNameRequired: t("first_name_is_required"),
809
+ lastNameRequired: t("last_name_is_required"),
810
+ languageRequired: t("language_is_required")
811
+ }), [t])),
812
+ defaultValues: {
813
+ first_name: customerAccount.customer.first_name || "",
814
+ last_name: derivedLastName,
815
+ phone_number: customerAccount.customer.phone || "",
816
+ language: customerLanguage || "English"
817
+ }
818
+ });
819
+ const handleOpenEditDialog = () => {
820
+ reset({
821
+ first_name: customerAccount.customer.first_name || "",
822
+ last_name: derivedLastName,
823
+ phone_number: customerAccount.customer.phone || "",
824
+ language: customerLanguage || "English"
825
+ });
826
+ setIsEditDialogOpen(true);
827
+ };
828
+ const handleCloseEditDialog = () => {
829
+ setIsEditDialogOpen(false);
830
+ setUpdateError(void 0);
831
+ };
832
+ const onSubmitUserInfo = handleSubmit(async (data) => {
833
+ try {
834
+ await onUpdateCustomer(data);
835
+ setIsEditDialogOpen(false);
836
+ } catch (error) {
837
+ console.error("Error updating profile:", error);
838
+ setUpdateError("Error updating profile. Please verify your information and try again.");
839
+ }
840
+ });
841
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
842
+ className: "mb-6 flex flex-row items-center justify-between space-x-2 border-b border-gray-300 pb-4",
843
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
844
+ className: "flex flex-row items-center space-x-2",
845
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Avatar, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.AvatarFallback, { children: userInitial }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
846
+ className: "flex flex-col",
847
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
848
+ className: "text-sm font-medium",
849
+ children: customerAccount.customer.full_name
850
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
851
+ className: "text-sm text-gray-500",
852
+ children: customerAccount.customer.email
853
+ })]
854
+ })]
855
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
856
+ className: "cursor-pointer rounded-md border border-gray-300 p-1 hover:bg-gray-50 disabled:opacity-50",
857
+ onClick: handleOpenEditDialog,
858
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Pencil, { className: "h-2.5 w-2.5 text-gray-400" })
859
+ })]
860
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UserInfoDialog, {
861
+ control,
862
+ isOpen: isEditDialogOpen,
863
+ onSubmit: onSubmitUserInfo,
864
+ handleClose: handleCloseEditDialog,
865
+ languageOptions,
866
+ errorMsg: updateError,
867
+ isSubmitting: isUpdating
868
+ })] });
869
+ }
870
+ //#endregion
871
+ //#region ../../profile/ui/src/components/address-dropdown.tsx
872
+ function formatAddressName(address) {
873
+ return address.name ?? "";
874
+ }
875
+ function AddressDropdown({ title, displayAddress, addressList, onAddAddressClick, onEditAddress, onDeleteAddress, accordionItemValue, addAddressLabel, showAddButton = true, borderStyle = "border-b border-gray-300 pb-4 mb-6", className = "", showActions = true, isLoading = false }) {
876
+ const [addressesValue, setAddressesValue] = (0, react.useState)("");
877
+ const { t } = useProfileUI();
878
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
879
+ className: `${borderStyle} ${className}`,
880
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Accordion, {
881
+ type: "single",
882
+ collapsible: true,
883
+ value: addressesValue,
884
+ onValueChange: setAddressesValue,
885
+ className: "w-full",
886
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.AccordionItem, {
887
+ value: accordionItemValue,
888
+ className: "border-b-0",
889
+ children: [
890
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
891
+ className: "flex flex-row items-center justify-between",
892
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
893
+ className: "mt-4 mb-1 text-sm text-gray-400",
894
+ children: title
895
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.AccordionTrigger, { className: "m-0 ml-2 flex h-auto min-h-0 w-auto py-0 hover:no-underline" })]
896
+ }),
897
+ isLoading && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
898
+ className: "space-y-2",
899
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-2/3" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-1/2" })]
900
+ }),
901
+ !isLoading && !addressesValue && displayAddress && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
902
+ className: "mb-2 flex w-full cursor-pointer flex-col",
903
+ onClick: () => setAddressesValue(accordionItemValue),
904
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
905
+ className: "flex items-center text-sm font-medium text-gray-900",
906
+ children: [
907
+ formatAddressName(displayAddress),
908
+ ", ",
909
+ displayAddress.address1
910
+ ]
911
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
912
+ className: "text-sm text-gray-500",
913
+ children: [
914
+ displayAddress.city,
915
+ ", ",
916
+ displayAddress.state,
917
+ " ",
918
+ displayAddress.postal_code
919
+ ]
920
+ })]
921
+ }),
922
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.AccordionContent, {
923
+ className: "max-h-[400px] overflow-y-auto pt-2",
924
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
925
+ className: "mt-2 flex flex-col justify-between space-y-4 px-0.5",
926
+ children: addressList.length > 0 ? addressList.map((address, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
927
+ className: require_src.cn("flex min-h-[48px] w-full flex-row items-center justify-between space-x-2 px-2", { "items-center border-b border-gray-300 p-3": addressList.length - 1 !== index }),
928
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
929
+ className: "flex flex-col",
930
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
931
+ className: "text-sm text-gray-900",
932
+ children: [
933
+ formatAddressName(address),
934
+ " ",
935
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
936
+ address.address1,
937
+ " ",
938
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
939
+ address.city,
940
+ ", ",
941
+ address.state,
942
+ " ",
943
+ address.postal_code
944
+ ]
945
+ })
946
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
947
+ className: "flex flex-row items-center space-x-2",
948
+ children: [address.default && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
949
+ className: "mt-1 w-fit rounded bg-gray-500 px-2 py-0.5 text-xs font-medium text-white",
950
+ children: t("default")
951
+ }), showActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EllipsesDropdown, {
952
+ onDelete: () => onDeleteAddress?.(address),
953
+ onEdit: () => onEditAddress?.(address),
954
+ editLabel: t("edit"),
955
+ deleteLabel: t("delete")
956
+ })]
957
+ })]
958
+ }, address.id)) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
959
+ className: "text-sm text-gray-500",
960
+ children: t("no_saved_addresses_found")
961
+ })
962
+ })
963
+ })
964
+ ]
965
+ })
966
+ }), showAddButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
967
+ className: "mt-3 text-left text-sm text-gray-900",
968
+ onClick: onAddAddressClick,
969
+ children: addAddressLabel
970
+ })]
971
+ });
972
+ }
973
+ //#endregion
974
+ //#region ../../profile/ui/src/components/addresses.tsx
975
+ function Addresses({ addresses, isLoading = false, onCreateAddress, onDeleteAddress, isDeletingAddress = false, renderAddressDialog }) {
976
+ const [openAddressDialog, setOpenAddressDialog] = (0, react.useState)(false);
977
+ const [openDeleteDialog, setOpenDeleteDialog] = (0, react.useState)(false);
978
+ const [selectedAddress, setSelectedAddress] = (0, react.useState)(null);
979
+ const [deleteAddressError, setDeleteAddressError] = (0, react.useState)(void 0);
980
+ const { t } = useProfileUI();
981
+ const defaultAddress = addresses.find((addr) => addr.default) ?? null;
982
+ const handleDeleteClick = (address) => {
983
+ setSelectedAddress(address);
984
+ setDeleteAddressError(void 0);
985
+ requestAnimationFrame(() => {
986
+ setOpenDeleteDialog(true);
987
+ });
988
+ };
989
+ const handleEditClick = (address) => {
990
+ setSelectedAddress(address);
991
+ requestAnimationFrame(() => {
992
+ setOpenAddressDialog(true);
993
+ });
994
+ };
995
+ const handleDeleteAddress = async () => {
996
+ if (!selectedAddress) return;
997
+ try {
998
+ await onDeleteAddress(selectedAddress.id);
999
+ setDeleteAddressError(void 0);
1000
+ setOpenDeleteDialog(false);
1001
+ setSelectedAddress(null);
1002
+ } catch {
1003
+ setDeleteAddressError("We were unable to delete this address. Please try again.");
1004
+ }
1005
+ };
1006
+ const handleAddClick = () => {
1007
+ setSelectedAddress(null);
1008
+ if (onCreateAddress) onCreateAddress();
1009
+ setOpenAddressDialog(true);
1010
+ };
1011
+ const handleCloseAddressDialog = () => {
1012
+ setOpenAddressDialog(false);
1013
+ setSelectedAddress(null);
1014
+ };
1015
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1016
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddressDropdown, {
1017
+ title: t("shipping_addresses"),
1018
+ displayAddress: defaultAddress,
1019
+ addressList: addresses,
1020
+ onAddAddressClick: handleAddClick,
1021
+ onEditAddress: handleEditClick,
1022
+ onDeleteAddress: handleDeleteClick,
1023
+ accordionItemValue: "addresses",
1024
+ addAddressLabel: `+ ${t("add_an_address")}`,
1025
+ showAddButton: true,
1026
+ borderStyle: "border-b border-gray-300 pb-4 mb-6",
1027
+ showActions: true,
1028
+ isLoading
1029
+ }),
1030
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmActionDialog, {
1031
+ title: t("delete_address"),
1032
+ description: t("delete_address_message"),
1033
+ onAction: handleDeleteAddress,
1034
+ actionText: t("delete"),
1035
+ openDialog: openDeleteDialog,
1036
+ setOpenDialog: setOpenDeleteDialog,
1037
+ errorMsg: deleteAddressError,
1038
+ isLoading: isDeletingAddress
1039
+ }),
1040
+ renderAddressDialog?.({
1041
+ isOpen: openAddressDialog,
1042
+ onClose: handleCloseAddressDialog,
1043
+ selectedAddress
1044
+ })
1045
+ ] });
1046
+ }
1047
+ //#endregion
1048
+ //#region ../../profile/ui/src/components/payment-method-dropdown.tsx
1049
+ function getCardDisplayName(paymentMethod) {
1050
+ if (paymentMethod.payment_type === "Credit Card") {
1051
+ const brand = paymentMethod.details.card_type;
1052
+ const lastFour = paymentMethod.details.last_four;
1053
+ return `${brand ?? "Card"} •••• ${lastFour ?? "****"}`;
1054
+ }
1055
+ return paymentMethod.payment_type;
1056
+ }
1057
+ function getCardExpiry(paymentMethod) {
1058
+ const { exp_month, exp_year } = paymentMethod.details;
1059
+ if (exp_month != null && exp_year != null) return `Expires ${exp_month}/${exp_year}`;
1060
+ return "";
1061
+ }
1062
+ function PaymentMethodDropdown({ title, displayPaymentMethod, paymentMethodList, onAddPaymentMethodClick, onEditPaymentMethod, onDeletePaymentMethod, accordionItemValue = "paymentMethods", addPaymentMethodLabel = "+ Add a payment method", showAddButton = true, borderStyle = "border-b border-gray-300 pb-4 mb-6", className = "", showActions = true, isLoading = false }) {
1063
+ const [paymentsValue, setPaymentsValue] = (0, react.useState)("");
1064
+ const { t } = useProfileUI();
1065
+ const renderPaymentMethod = (paymentMethod) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1066
+ className: "flex flex-row items-center space-x-2",
1067
+ children: [paymentMethod.details.logo_url && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1068
+ className: "h-6 w-10 flex-shrink-0",
1069
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1070
+ src: paymentMethod.details.logo_url,
1071
+ alt: paymentMethod.details.card_type ?? t("payment_method"),
1072
+ width: 40,
1073
+ height: 24,
1074
+ className: "object-contain"
1075
+ })
1076
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1077
+ className: "flex flex-col",
1078
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1079
+ className: "flex items-center text-sm font-medium text-gray-900",
1080
+ children: getCardDisplayName(paymentMethod)
1081
+ }), getCardExpiry(paymentMethod) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1082
+ className: "text-sm text-gray-500",
1083
+ children: getCardExpiry(paymentMethod)
1084
+ })]
1085
+ })]
1086
+ });
1087
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1088
+ className: `${borderStyle} ${className}`,
1089
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Accordion, {
1090
+ type: "single",
1091
+ collapsible: true,
1092
+ value: paymentsValue,
1093
+ onValueChange: setPaymentsValue,
1094
+ className: "w-full",
1095
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.AccordionItem, {
1096
+ value: accordionItemValue,
1097
+ className: "border-b-0",
1098
+ children: [
1099
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1100
+ className: "flex flex-row items-center justify-between",
1101
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1102
+ className: "mt-4 mb-1 text-sm text-gray-400",
1103
+ children: title
1104
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.AccordionTrigger, { className: "m-0 ml-2 flex h-auto min-h-0 w-auto py-0 hover:no-underline" })]
1105
+ }),
1106
+ !paymentsValue && isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1107
+ className: "mb-2 flex w-full flex-row items-center space-x-2",
1108
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-6 w-10" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1109
+ className: "flex flex-col space-y-1",
1110
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-32" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-24" })]
1111
+ })]
1112
+ }) : !paymentsValue && displayPaymentMethod && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1113
+ className: "mb-2 flex w-full cursor-pointer flex-col",
1114
+ onClick: () => setPaymentsValue(accordionItemValue),
1115
+ children: renderPaymentMethod(displayPaymentMethod)
1116
+ }),
1117
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.AccordionContent, {
1118
+ className: "max-h-[400px] overflow-y-auto pt-2",
1119
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1120
+ className: "mt-2 flex flex-col justify-between space-y-4 px-0.5",
1121
+ children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: [1, 2].map((i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1122
+ className: "items-center rounded bg-gray-100 p-3",
1123
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1124
+ className: "flex flex-row items-center justify-between",
1125
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1126
+ className: "flex flex-row items-center space-x-2",
1127
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-6 w-10" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1128
+ className: "flex flex-col space-y-1",
1129
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-32" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-24" })]
1130
+ })]
1131
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-6 w-6" })]
1132
+ })
1133
+ }, `skeleton-${i}`)) }) : paymentMethodList.map((paymentMethod, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1134
+ className: require_src.cn("flex min-h-[48px] w-full flex-row items-center justify-between space-x-2 px-2", { "items-center border-b border-gray-300 p-3": paymentMethodList.length - 1 !== index }),
1135
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1136
+ className: "flex flex-row items-center space-x-2",
1137
+ children: [paymentMethod.details.logo_url && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1138
+ className: "h-6 w-10 flex-shrink-0",
1139
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1140
+ src: paymentMethod.details.logo_url,
1141
+ alt: paymentMethod.details.card_type ?? t("payment_method"),
1142
+ width: 40,
1143
+ height: 24,
1144
+ className: "object-contain"
1145
+ })
1146
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1147
+ className: "flex flex-col",
1148
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1149
+ className: "flex items-center text-sm font-medium text-gray-900",
1150
+ children: `${paymentMethod.details.card_type ?? "Card"} •••• ${paymentMethod.details.last_four ?? "****"}`
1151
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1152
+ className: "text-sm text-gray-500",
1153
+ children: `${t("card_expires")} ${paymentMethod.details.exp_month}/${paymentMethod.details.exp_year}`
1154
+ })]
1155
+ })]
1156
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1157
+ className: "flex flex-row items-center space-x-2",
1158
+ children: [paymentMethod.default && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1159
+ className: "mt-1 w-fit rounded bg-gray-500 px-2 py-0.5 text-xs font-medium text-white",
1160
+ children: t("default")
1161
+ }), showActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EllipsesDropdown, {
1162
+ onDelete: () => onDeletePaymentMethod?.(paymentMethod),
1163
+ deleteLabel: t("delete"),
1164
+ onEdit: () => onEditPaymentMethod?.(paymentMethod),
1165
+ editLabel: t("edit")
1166
+ })]
1167
+ })]
1168
+ }, paymentMethod.id))
1169
+ })
1170
+ })
1171
+ ]
1172
+ })
1173
+ }), showAddButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1174
+ className: "mt-3 text-left text-sm text-gray-900",
1175
+ onClick: onAddPaymentMethodClick,
1176
+ children: addPaymentMethodLabel
1177
+ })]
1178
+ });
1179
+ }
1180
+ //#endregion
1181
+ //#region ../../profile/ui/src/components/view-payment-method-dialog.tsx
1182
+ function ViewPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClose, onEdit }) {
1183
+ const { t } = useProfileUI();
1184
+ if (!paymentMethod) return null;
1185
+ const { details } = paymentMethod;
1186
+ const cardBrand = details.card_type ?? "Card";
1187
+ const lastFour = details.last_four ?? "****";
1188
+ const expMonth = details.exp_month;
1189
+ const expYear = details.exp_year;
1190
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Dialog, {
1191
+ open: isOpen,
1192
+ onOpenChange: (open) => !open && onClose(),
1193
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DialogContent, {
1194
+ className: "max-w-sm rounded md:max-w-lg",
1195
+ children: [
1196
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogTitle, {
1197
+ className: "text-md font-medium",
1198
+ children: t("edit_card")
1199
+ }) }),
1200
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1201
+ className: "space-y-4",
1202
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1203
+ className: "rounded-lg bg-gray-50 p-4",
1204
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1205
+ className: "flex items-center space-x-3",
1206
+ children: [details.logo_url && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1207
+ className: "h-6 w-10 flex-shrink-0",
1208
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1209
+ src: details.logo_url,
1210
+ alt: cardBrand,
1211
+ width: 40,
1212
+ height: 24,
1213
+ className: "object-contain"
1214
+ })
1215
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1216
+ className: "flex flex-col",
1217
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1218
+ className: "text-sm font-medium text-gray-900",
1219
+ children: [
1220
+ cardBrand,
1221
+ " •••• ",
1222
+ lastFour
1223
+ ]
1224
+ }), expMonth != null && expYear != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1225
+ className: "text-sm text-gray-500",
1226
+ children: [
1227
+ t("card_expires"),
1228
+ " ",
1229
+ expMonth,
1230
+ "/",
1231
+ expYear
1232
+ ]
1233
+ })]
1234
+ })]
1235
+ }), paymentMethod.default && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1236
+ className: "mt-2 inline-block rounded bg-gray-500 px-2 py-0.5 text-xs font-medium text-white",
1237
+ children: t("default")
1238
+ })]
1239
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1240
+ className: "mb-2 flex items-center justify-between",
1241
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
1242
+ className: "text-sm font-medium text-gray-900",
1243
+ children: t("billing_address")
1244
+ }), onEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
1245
+ variant: "ghost",
1246
+ size: "sm",
1247
+ className: "h-auto p-0 text-sm text-gray-600 underline hover:bg-transparent",
1248
+ onClick: onEdit,
1249
+ children: t("edit")
1250
+ })]
1251
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1252
+ className: "rounded-lg bg-gray-50 p-4",
1253
+ children: billingAddress ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1254
+ className: "space-y-1 text-sm text-gray-900",
1255
+ children: [
1256
+ billingAddress.name && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: billingAddress.name }),
1257
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: billingAddress.address1 }),
1258
+ billingAddress.address2 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: billingAddress.address2 }),
1259
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
1260
+ billingAddress.city,
1261
+ ", ",
1262
+ billingAddress.state,
1263
+ " ",
1264
+ billingAddress.zip
1265
+ ] }),
1266
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: billingAddress.country_code })
1267
+ ]
1268
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1269
+ className: "text-sm text-gray-500 italic",
1270
+ children: t("no_billing_address")
1271
+ })
1272
+ })] })]
1273
+ }),
1274
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogFooter, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogClose, {
1275
+ asChild: true,
1276
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
1277
+ className: "rounded bg-gray-50 p-3 text-gray-900 ring-1 ring-gray-300 hover:bg-gray-100",
1278
+ onClick: onClose,
1279
+ children: t("close")
1280
+ })
1281
+ }) })
1282
+ ]
1283
+ })
1284
+ });
1285
+ }
1286
+ //#endregion
1287
+ //#region ../../profile/ui/src/components/edit-payment-method-dialog.tsx
1288
+ const editPaymentMethodFormSchema = zod.z.object({
1289
+ billing_address: zod.z.object({
1290
+ name: zod.z.string().min(1, "Name is required"),
1291
+ address1: zod.z.string().min(1, "Address line 1 is required"),
1292
+ address2: zod.z.string().optional().nullable(),
1293
+ city: zod.z.string().min(1, "City is required"),
1294
+ state: zod.z.string().min(1, "State is required"),
1295
+ zip: zod.z.string().min(1, "Zip code is required"),
1296
+ country_code: zod.z.string().min(1, "Country is required")
1297
+ }),
1298
+ set_as_default: zod.z.boolean()
1299
+ });
1300
+ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClose, onSubmit, isSubmitting, error, countries = [] }) {
1301
+ const { t } = useProfileUI();
1302
+ const { control, handleSubmit, reset, setValue } = (0, react_hook_form.useForm)({
1303
+ resolver: (0, _hookform_resolvers_zod.zodResolver)(editPaymentMethodFormSchema),
1304
+ defaultValues: {
1305
+ billing_address: {
1306
+ name: "",
1307
+ address1: "",
1308
+ address2: "",
1309
+ city: "",
1310
+ state: "",
1311
+ zip: "",
1312
+ country_code: "US"
1313
+ },
1314
+ set_as_default: false
1315
+ }
1316
+ });
1317
+ const billingCountry = (0, react_hook_form.useWatch)({
1318
+ control,
1319
+ name: "billing_address.country_code"
1320
+ });
1321
+ const setAsDefault = (0, react_hook_form.useWatch)({
1322
+ control,
1323
+ name: "set_as_default"
1324
+ });
1325
+ const { stateOptions, config, handleCountryChange } = useCountryStates();
1326
+ const countryOptions = [...countries].map((country) => ({
1327
+ name: country.name,
1328
+ value: country.iso
1329
+ })).sort((a, b) => {
1330
+ if (a.value === billingCountry) return -1;
1331
+ if (b.value === billingCountry) return 1;
1332
+ return a.name.localeCompare(b.name);
1333
+ });
1334
+ const stateSelectOptions = stateOptions.map((state) => ({
1335
+ name: state.name,
1336
+ value: state.isoCode
1337
+ }));
1338
+ (0, react.useEffect)(() => {
1339
+ if (paymentMethod && isOpen) reset({
1340
+ billing_address: {
1341
+ name: billingAddress?.name ?? "",
1342
+ address1: billingAddress?.address1 ?? "",
1343
+ address2: billingAddress?.address2 ?? "",
1344
+ city: billingAddress?.city ?? "",
1345
+ state: billingAddress?.state ?? "",
1346
+ zip: billingAddress?.zip ?? "",
1347
+ country_code: billingAddress?.country_code ?? "US"
1348
+ },
1349
+ set_as_default: paymentMethod.default
1350
+ });
1351
+ }, [
1352
+ paymentMethod,
1353
+ billingAddress,
1354
+ isOpen,
1355
+ reset
1356
+ ]);
1357
+ const handleCountrySelect = (countryCode) => {
1358
+ handleCountryChange(countryCode);
1359
+ setValue("billing_address.country_code", countryCode, { shouldValidate: true });
1360
+ };
1361
+ const handleFormSubmit = handleSubmit((data) => {
1362
+ onSubmit(data);
1363
+ });
1364
+ if (!paymentMethod) return null;
1365
+ const { details } = paymentMethod;
1366
+ const cardBrand = details.card_type ?? "Card";
1367
+ const lastFour = details.last_four ?? "****";
1368
+ const expMonth = details.exp_month;
1369
+ const expYear = details.exp_year;
1370
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Dialog, {
1371
+ open: isOpen,
1372
+ onOpenChange: (open) => !open && onClose(),
1373
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DialogContent, {
1374
+ className: "max-h-[90vh] max-w-sm overflow-y-auto rounded md:max-w-lg",
1375
+ children: [
1376
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogTitle, {
1377
+ className: "text-md font-medium",
1378
+ children: t("edit_card")
1379
+ }) }),
1380
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1381
+ className: "space-y-4",
1382
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1383
+ className: "rounded-lg bg-gray-50 p-4",
1384
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1385
+ className: "flex items-center space-x-3",
1386
+ children: [details.logo_url && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1387
+ className: "h-6 w-10 flex-shrink-0",
1388
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1389
+ src: details.logo_url,
1390
+ alt: cardBrand,
1391
+ width: 40,
1392
+ height: 24,
1393
+ className: "object-contain"
1394
+ })
1395
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1396
+ className: "flex flex-col",
1397
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1398
+ className: "text-sm font-medium text-gray-900",
1399
+ children: [
1400
+ cardBrand,
1401
+ " •••• ",
1402
+ lastFour
1403
+ ]
1404
+ }), expMonth != null && expYear != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1405
+ className: "text-sm text-gray-500",
1406
+ children: [
1407
+ t("card_expires"),
1408
+ " ",
1409
+ expMonth,
1410
+ "/",
1411
+ expYear
1412
+ ]
1413
+ })]
1414
+ })]
1415
+ })
1416
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
1417
+ className: "mb-1 text-sm font-medium text-gray-900",
1418
+ children: t("billing_address")
1419
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1420
+ className: "space-y-0",
1421
+ children: [
1422
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField$1, {
1423
+ control,
1424
+ name: "billing_address.country_code",
1425
+ label: t("country"),
1426
+ options: countryOptions,
1427
+ placeholder: t("select_an_option"),
1428
+ onChange: (val) => {
1429
+ handleCountrySelect(val);
1430
+ }
1431
+ }),
1432
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1433
+ control,
1434
+ name: "billing_address.name",
1435
+ label: t("name")
1436
+ }),
1437
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1438
+ control,
1439
+ name: "billing_address.address1",
1440
+ label: t("address_line_1")
1441
+ }),
1442
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1443
+ control,
1444
+ name: "billing_address.address2",
1445
+ label: t("address_line_2")
1446
+ }),
1447
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1448
+ className: "sm:flex sm:gap-2",
1449
+ children: [
1450
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1451
+ control,
1452
+ name: "billing_address.city",
1453
+ label: t("city"),
1454
+ containerClassName: "flex-1"
1455
+ }),
1456
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField$1, {
1457
+ control,
1458
+ name: "billing_address.state",
1459
+ label: config?.regionLabel ? t(config.regionLabel) : t("state"),
1460
+ options: stateSelectOptions,
1461
+ placeholder: t("select_state"),
1462
+ containerClassName: "flex-1"
1463
+ }),
1464
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1465
+ control,
1466
+ name: "billing_address.zip",
1467
+ label: config?.postalLabel ? t(config.postalLabel) : t("zip_code"),
1468
+ containerClassName: "flex-1"
1469
+ })
1470
+ ]
1471
+ })
1472
+ ]
1473
+ })] })]
1474
+ }),
1475
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1476
+ className: "mt-2 flex items-center space-x-2",
1477
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1478
+ type: "checkbox",
1479
+ id: "set_as_default",
1480
+ checked: setAsDefault,
1481
+ onChange: () => setValue("set_as_default", !setAsDefault),
1482
+ className: "h-4 w-4"
1483
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1484
+ htmlFor: "set_as_default",
1485
+ className: "text-sm",
1486
+ children: t("set_as_default_payment_method")
1487
+ })]
1488
+ }),
1489
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1490
+ className: "text-sm text-red-500",
1491
+ children: error
1492
+ }),
1493
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DialogFooter, {
1494
+ className: "flex flex-row items-center justify-between",
1495
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1496
+ className: "flex-2",
1497
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
1498
+ type: "button",
1499
+ className: "rounded bg-gray-50 p-3 text-gray-900 ring-1 ring-gray-300 hover:bg-gray-100",
1500
+ onClick: onClose,
1501
+ disabled: isSubmitting,
1502
+ children: t("cancel")
1503
+ })
1504
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1505
+ className: "flex-1 text-right",
1506
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
1507
+ type: "submit",
1508
+ onClick: handleFormSubmit,
1509
+ disabled: isSubmitting,
1510
+ className: "rounded bg-gray-900 p-3 text-white hover:bg-gray-800",
1511
+ children: isSubmitting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-5 w-5 animate-spin rounded-full border-4 border-t-4 border-white border-t-transparent" }) : t("save")
1512
+ })
1513
+ })]
1514
+ })
1515
+ ]
1516
+ })
1517
+ });
1518
+ }
1519
+ //#endregion
1520
+ //#region ../../profile/ui/src/components/payment-methods.tsx
1521
+ function PaymentMethods({ paymentMethods, isLoading = false, onDeletePaymentMethod, isDeletingPaymentMethod = false, onUpdatePaymentMethod, isUpdatingPaymentMethod = false, getBillingAddress, countries, renderCreditCardDialog }) {
1522
+ const [isOpen, setIsOpen] = (0, react.useState)(false);
1523
+ const [openDeleteDialog, setOpenDeleteDialog] = (0, react.useState)(false);
1524
+ const [deleteCardError, setDeleteCardError] = (0, react.useState)(void 0);
1525
+ const [selectedCreditCard, setSelectedCreditCard] = (0, react.useState)(void 0);
1526
+ const [isViewOpen, setIsViewOpen] = (0, react.useState)(false);
1527
+ const [isEditOpen, setIsEditOpen] = (0, react.useState)(false);
1528
+ const [selectedPaymentMethod, setSelectedPaymentMethod] = (0, react.useState)(null);
1529
+ const [editError, setEditError] = (0, react.useState)(void 0);
1530
+ const { t } = useProfileUI();
1531
+ const defaultPaymentMethod = paymentMethods.find((method) => method.default) ?? null;
1532
+ const handleDeleteCard = async (cardId) => {
1533
+ if (!cardId) return;
1534
+ try {
1535
+ await onDeletePaymentMethod(cardId);
1536
+ setSelectedCreditCard(void 0);
1537
+ setDeleteCardError(void 0);
1538
+ setOpenDeleteDialog(false);
1539
+ } catch {
1540
+ setDeleteCardError("Unable to delete payment method. Please try again.");
1541
+ }
1542
+ };
1543
+ const handleDeletePaymentMethod = (paymentMethod) => {
1544
+ setSelectedCreditCard(paymentMethod);
1545
+ requestAnimationFrame(() => {
1546
+ setOpenDeleteDialog(true);
1547
+ });
1548
+ };
1549
+ const handleViewPaymentMethod = (paymentMethod) => {
1550
+ setSelectedPaymentMethod(paymentMethod);
1551
+ requestAnimationFrame(() => {
1552
+ setIsViewOpen(true);
1553
+ });
1554
+ };
1555
+ const handleCloseViewDialog = () => {
1556
+ setIsViewOpen(false);
1557
+ setSelectedPaymentMethod(null);
1558
+ };
1559
+ const handleOpenEditFromView = () => {
1560
+ setIsViewOpen(false);
1561
+ setEditError(void 0);
1562
+ requestAnimationFrame(() => {
1563
+ setIsEditOpen(true);
1564
+ });
1565
+ };
1566
+ const handleCloseEditDialog = () => {
1567
+ setIsEditOpen(false);
1568
+ setSelectedPaymentMethod(null);
1569
+ setEditError(void 0);
1570
+ };
1571
+ const handleEditSubmit = async (data) => {
1572
+ if (!selectedPaymentMethod) return;
1573
+ try {
1574
+ await onUpdatePaymentMethod(selectedPaymentMethod.id, data);
1575
+ handleCloseEditDialog();
1576
+ require_src.fluidToast({
1577
+ title: t("default_payment_method_updated"),
1578
+ type: "success"
1579
+ });
1580
+ } catch (error) {
1581
+ console.error("Error updating payment method:", error);
1582
+ require_src.fluidToast({
1583
+ title: t("failed_to_set_default_payment_method"),
1584
+ type: "error",
1585
+ description: parseApiErrors(error)
1586
+ });
1587
+ if (error instanceof Error) setEditError(error.message);
1588
+ else setEditError("An unexpected error occurred. Please try again.");
1589
+ }
1590
+ };
1591
+ const handleOpenDialog = () => {
1592
+ setIsOpen(true);
1593
+ };
1594
+ const handleCloseDialog = () => {
1595
+ setIsOpen(false);
1596
+ };
1597
+ const selectedBillingAddress = selectedPaymentMethod ? getBillingAddress?.(selectedPaymentMethod) ?? null : null;
1598
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1599
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PaymentMethodDropdown, {
1600
+ title: t("payment_methods"),
1601
+ displayPaymentMethod: defaultPaymentMethod,
1602
+ paymentMethodList: paymentMethods,
1603
+ onAddPaymentMethodClick: handleOpenDialog,
1604
+ onEditPaymentMethod: handleViewPaymentMethod,
1605
+ onDeletePaymentMethod: handleDeletePaymentMethod,
1606
+ addPaymentMethodLabel: `+ ${t("add_payment_method")}`,
1607
+ isLoading
1608
+ }),
1609
+ renderCreditCardDialog?.({
1610
+ isOpen,
1611
+ onClose: handleCloseDialog
1612
+ }),
1613
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmActionDialog, {
1614
+ title: t("delete_credit_card"),
1615
+ description: t("delete_credit_card_message"),
1616
+ actionText: t("delete"),
1617
+ onAction: () => handleDeleteCard(selectedCreditCard?.id ?? null),
1618
+ openDialog: openDeleteDialog,
1619
+ setOpenDialog: setOpenDeleteDialog,
1620
+ errorMsg: deleteCardError,
1621
+ isLoading: isDeletingPaymentMethod
1622
+ }),
1623
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewPaymentMethodDialog, {
1624
+ isOpen: isViewOpen,
1625
+ paymentMethod: selectedPaymentMethod,
1626
+ billingAddress: selectedBillingAddress,
1627
+ onClose: handleCloseViewDialog,
1628
+ onEdit: handleOpenEditFromView
1629
+ }),
1630
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EditPaymentMethodDialog, {
1631
+ isOpen: isEditOpen,
1632
+ paymentMethod: selectedPaymentMethod,
1633
+ billingAddress: selectedBillingAddress,
1634
+ onClose: handleCloseEditDialog,
1635
+ onSubmit: handleEditSubmit,
1636
+ isSubmitting: isUpdatingPaymentMethod,
1637
+ error: editError,
1638
+ countries
1639
+ })
1640
+ ] });
1641
+ }
1642
+ //#endregion
1643
+ //#region ../../profile/ui/src/components/profile.tsx
1644
+ function Profile({ customerAccount, languages, onUpdateCustomer, isUpdatingCustomer, rewardsPointsEnabled = false, pointsLedger, isLoadingPointsLedger, addresses, isLoadingAddresses, onDeleteAddress, isDeletingAddress, renderAddressDialog, paymentMethods, isLoadingPaymentMethods, onDeletePaymentMethod, isDeletingPaymentMethod, onUpdatePaymentMethod, isUpdatingPaymentMethod, getBillingAddress, countries, renderCreditCardDialog }) {
1645
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1646
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomerInfo, {
1647
+ customerAccount,
1648
+ languages,
1649
+ onUpdateCustomer,
1650
+ isUpdating: isUpdatingCustomer
1651
+ }),
1652
+ rewardsPointsEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomerPointsLedger, {
1653
+ pointsLedger: pointsLedger ?? [],
1654
+ isLoading: isLoadingPointsLedger
1655
+ }),
1656
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Addresses, {
1657
+ addresses,
1658
+ isLoading: isLoadingAddresses,
1659
+ onDeleteAddress,
1660
+ isDeletingAddress,
1661
+ renderAddressDialog
1662
+ }),
1663
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PaymentMethods, {
1664
+ paymentMethods,
1665
+ isLoading: isLoadingPaymentMethods,
1666
+ onDeletePaymentMethod,
1667
+ isDeletingPaymentMethod,
1668
+ onUpdatePaymentMethod,
1669
+ isUpdatingPaymentMethod,
1670
+ getBillingAddress,
1671
+ countries,
1672
+ renderCreditCardDialog
1673
+ })
1674
+ ] });
1675
+ }
1676
+ //#endregion
1677
+ //#region ../../fluid-pay/ui/src/components/form-fields/FormTextField.tsx
1678
+ function FormTextField({ control, name, placeholder, containerClassName, type, disabled, inputMode }) {
1679
+ const { field, fieldState: { error } } = (0, react_hook_form.useController)({
1680
+ name,
1681
+ control
1682
+ });
1683
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1684
+ className: require_src.cn("space-y-1", containerClassName),
1685
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Input, {
1686
+ ...field,
1687
+ value: field.value ?? "",
1688
+ id: name,
1689
+ type,
1690
+ disabled,
1691
+ inputMode,
1692
+ placeholder,
1693
+ "aria-invalid": !!error
1694
+ }), error?.message && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1695
+ className: "text-sm text-red-500",
1696
+ children: error.message
1697
+ })]
1698
+ });
1699
+ }
1700
+ //#endregion
1701
+ //#region ../../fluid-pay/ui/src/components/form-fields/FormSelectField.tsx
1702
+ function FormSelectField({ control, name, placeholder = "Select", options, containerClassName, disabled }) {
1703
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1704
+ className: require_src.cn("space-y-1", containerClassName),
1705
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_hook_form.Controller, {
1706
+ control,
1707
+ name,
1708
+ render: ({ field: { onChange, value }, fieldState: { error } }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Select, {
1709
+ value: value?.toString() ?? "",
1710
+ onValueChange: onChange,
1711
+ disabled,
1712
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectTrigger, {
1713
+ "aria-invalid": !!error,
1714
+ className: require_src.cn("w-full", error && "border-red-500 ring-1 ring-red-500"),
1715
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectValue, { placeholder })
1716
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectContent, { children: options && options.length > 0 ? options.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectItem, {
1717
+ value: opt.value.toString(),
1718
+ children: opt.name
1719
+ }, opt.value.toString())) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.SelectItem, {
1720
+ value: "__empty",
1721
+ disabled: true,
1722
+ children: "No available options"
1723
+ }) })]
1724
+ }), error?.message && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1725
+ className: "text-sm text-red-500",
1726
+ children: error.message
1727
+ })] })
1728
+ })
1729
+ });
1730
+ }
1731
+ //#endregion
1732
+ //#region ../../fluid-pay/ui/src/components/AddressFormDialog.tsx
1733
+ const addressFormSchema = zod.z.object({
1734
+ first_name: zod.z.string().min(1, "First name is required"),
1735
+ last_name: zod.z.string().min(1, "Last name is required"),
1736
+ address1: zod.z.string().min(1, "Address line 1 is required"),
1737
+ address2: zod.z.string().optional().nullable(),
1738
+ city: zod.z.string().min(1, "City is required"),
1739
+ state: zod.z.string().min(1, "State is required"),
1740
+ postal_code: zod.z.string().min(1, "Postal code is required"),
1741
+ country_code: zod.z.string().min(1, "Country is required"),
1742
+ default: zod.z.boolean()
1743
+ });
1744
+ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmitting, countries = [], error, renderAddressAutocomplete, t }) {
1745
+ const { control, handleSubmit, reset, setValue } = (0, react_hook_form.useForm)({
1746
+ resolver: (0, _hookform_resolvers_zod.zodResolver)(addressFormSchema),
1747
+ defaultValues: {
1748
+ first_name: "",
1749
+ last_name: "",
1750
+ address1: "",
1751
+ address2: "",
1752
+ city: "",
1753
+ state: "",
1754
+ postal_code: "",
1755
+ country_code: "US",
1756
+ default: false
1757
+ }
1758
+ });
1759
+ const selectedCountryCode = (0, react_hook_form.useWatch)({
1760
+ control,
1761
+ name: "country_code"
1762
+ });
1763
+ const isDefault = (0, react_hook_form.useWatch)({
1764
+ control,
1765
+ name: "default"
1766
+ });
1767
+ const { stateOptions, config, handleCountryChange } = useCountryStates();
1768
+ const countrySelectOptions = [...countries].map((country) => ({
1769
+ name: country.name,
1770
+ value: country.iso
1771
+ })).sort((a, b) => {
1772
+ if (a.value === selectedCountryCode) return -1;
1773
+ if (b.value === selectedCountryCode) return 1;
1774
+ return a.name.localeCompare(b.name);
1775
+ });
1776
+ const stateSelectOptions = stateOptions.map((state) => ({
1777
+ name: state.name,
1778
+ value: state.isoCode
1779
+ }));
1780
+ (0, react.useEffect)(() => {
1781
+ if (isOpen) if (selectedAddress) {
1782
+ const nameParts = (selectedAddress.name ?? "").split(" ");
1783
+ reset({
1784
+ first_name: nameParts[0] ?? "",
1785
+ last_name: nameParts.slice(1).join(" "),
1786
+ address1: selectedAddress.address1,
1787
+ address2: selectedAddress.address2 ?? "",
1788
+ city: selectedAddress.city,
1789
+ state: selectedAddress.state,
1790
+ postal_code: selectedAddress.postal_code,
1791
+ country_code: selectedAddress.country_code ?? "US",
1792
+ default: selectedAddress.default
1793
+ });
1794
+ handleCountryChange(selectedAddress.country_code ?? "US");
1795
+ } else {
1796
+ reset({
1797
+ first_name: "",
1798
+ last_name: "",
1799
+ address1: "",
1800
+ address2: "",
1801
+ city: "",
1802
+ state: "",
1803
+ postal_code: "",
1804
+ country_code: "US",
1805
+ default: false
1806
+ });
1807
+ handleCountryChange("US");
1808
+ }
1809
+ }, [
1810
+ selectedAddress,
1811
+ isOpen,
1812
+ reset,
1813
+ handleCountryChange
1814
+ ]);
1815
+ (0, react.useEffect)(() => {
1816
+ handleCountryChange(selectedCountryCode);
1817
+ }, [selectedCountryCode, handleCountryChange]);
1818
+ const handleFormSubmit = handleSubmit((data) => {
1819
+ onSubmit({ address: {
1820
+ first_name: data.first_name,
1821
+ last_name: data.last_name,
1822
+ address1: data.address1,
1823
+ address2: data.address2 ?? null,
1824
+ city: data.city,
1825
+ state: data.state,
1826
+ postal_code: data.postal_code,
1827
+ country_code: data.country_code,
1828
+ default: data.default
1829
+ } });
1830
+ });
1831
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Dialog, {
1832
+ open: isOpen,
1833
+ onOpenChange: (open) => !open && onClose(),
1834
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DialogContent, {
1835
+ className: "max-h-[90vh] max-w-md overflow-y-auto rounded md:max-w-xl",
1836
+ children: [
1837
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogTitle, {
1838
+ className: "text-lg font-medium",
1839
+ children: selectedAddress !== null ? t("edit_address") : t("add_an_address")
1840
+ }) }),
1841
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1842
+ className: "space-y-3 pt-2",
1843
+ children: [
1844
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
1845
+ control,
1846
+ name: "country_code",
1847
+ placeholder: t("country"),
1848
+ options: countrySelectOptions,
1849
+ disabled: isSubmitting
1850
+ }),
1851
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1852
+ className: "flex gap-3",
1853
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
1854
+ control,
1855
+ name: "first_name",
1856
+ placeholder: t("first_name"),
1857
+ containerClassName: "flex-1",
1858
+ disabled: isSubmitting
1859
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
1860
+ control,
1861
+ name: "last_name",
1862
+ placeholder: t("last_name"),
1863
+ containerClassName: "flex-1",
1864
+ disabled: isSubmitting
1865
+ })]
1866
+ }),
1867
+ renderAddressAutocomplete ? renderAddressAutocomplete({
1868
+ control,
1869
+ setValue,
1870
+ countryCode: selectedCountryCode
1871
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
1872
+ control,
1873
+ name: "address1",
1874
+ placeholder: t("address_line_1"),
1875
+ disabled: isSubmitting
1876
+ }),
1877
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
1878
+ control,
1879
+ name: "address2",
1880
+ placeholder: t("address_line_2"),
1881
+ disabled: isSubmitting
1882
+ }),
1883
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1884
+ className: "flex gap-3",
1885
+ children: [
1886
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
1887
+ control,
1888
+ name: "city",
1889
+ placeholder: t("city"),
1890
+ containerClassName: "flex-1",
1891
+ disabled: isSubmitting
1892
+ }),
1893
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
1894
+ control,
1895
+ name: "state",
1896
+ placeholder: config?.regionLabel ? t(config.regionLabel) : t("select_state"),
1897
+ options: stateSelectOptions,
1898
+ containerClassName: "flex-1",
1899
+ disabled: isSubmitting
1900
+ }),
1901
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
1902
+ control,
1903
+ name: "postal_code",
1904
+ placeholder: config?.postalLabel ? t(config.postalLabel) : t("zip_code"),
1905
+ containerClassName: "flex-1",
1906
+ disabled: isSubmitting
1907
+ })
1908
+ ]
1909
+ })
1910
+ ]
1911
+ }),
1912
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1913
+ className: "mt-4 flex items-center justify-between",
1914
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1915
+ className: "flex items-center space-x-2",
1916
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1917
+ type: "checkbox",
1918
+ id: "set_as_default_address",
1919
+ checked: isDefault,
1920
+ onChange: () => setValue("default", !isDefault),
1921
+ disabled: isSubmitting,
1922
+ className: "h-4 w-4"
1923
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1924
+ htmlFor: "set_as_default_address",
1925
+ className: "text-sm",
1926
+ children: t("set_as_default_address")
1927
+ })]
1928
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
1929
+ type: "submit",
1930
+ onClick: handleFormSubmit,
1931
+ disabled: isSubmitting,
1932
+ className: "rounded bg-gray-900 px-5 py-2.5 text-white hover:bg-gray-800",
1933
+ children: isSubmitting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-5 w-5 animate-spin rounded-full border-4 border-t-4 border-white border-t-transparent" }) : t("save_address")
1934
+ })]
1935
+ }),
1936
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1937
+ className: "mt-2 text-sm text-red-500",
1938
+ children: error
1939
+ })
1940
+ ]
1941
+ })
1942
+ });
1943
+ }
1944
+ //#endregion
1945
+ //#region ../../fluid-pay/ui/src/hooks/use-vgs-collect.ts
1946
+ const getVGSCollect = () => {
1947
+ if (typeof window !== "undefined") return window.VGSCollect || null;
1948
+ return null;
1949
+ };
1950
+ const DEFAULT_FIELD_STATE = {
1951
+ card_number: {
1952
+ isFocused: false,
1953
+ isValid: false,
1954
+ isEmpty: true
1955
+ },
1956
+ card_exp: {
1957
+ isFocused: false,
1958
+ isValid: false,
1959
+ isEmpty: true
1960
+ },
1961
+ card_cvc: {
1962
+ isFocused: false,
1963
+ isValid: false,
1964
+ isEmpty: true
1965
+ },
1966
+ card_holder: {
1967
+ isFocused: false,
1968
+ isValid: false,
1969
+ isEmpty: true
1970
+ }
1971
+ };
1972
+ function useVgsCollect() {
1973
+ const [isFormReady, setIsFormReady] = (0, react.useState)(false);
1974
+ const [isLoading, setIsLoading] = (0, react.useState)(false);
1975
+ const [isScriptLoaded, setIsScriptLoaded] = (0, react.useState)(false);
1976
+ const [vgsFieldState, setVgsFieldState] = (0, react.useState)(DEFAULT_FIELD_STATE);
1977
+ const formRef = (0, react.useRef)(null);
1978
+ const onSuccessRef = (0, react.useRef)(null);
1979
+ const onErrorRef = (0, react.useRef)(null);
1980
+ (0, react.useEffect)(() => {
1981
+ if (typeof window === "undefined") return;
1982
+ if (getVGSCollect()) {
1983
+ const timeoutId = window.setTimeout(() => {
1984
+ setIsScriptLoaded(true);
1985
+ }, 0);
1986
+ return () => window.clearTimeout(timeoutId);
1987
+ }
1988
+ if (isScriptLoaded) return;
1989
+ const script = document.createElement("script");
1990
+ script.src = "https://js.verygoodvault.com/vgs-collect/3.3.0/vgs-collect.js";
1991
+ script.async = true;
1992
+ script.onload = () => setIsScriptLoaded(true);
1993
+ script.onerror = () => onErrorRef.current?.("Failed to load payment form");
1994
+ document.head.appendChild(script);
1995
+ }, [isScriptLoaded]);
1996
+ const updateFieldState = (0, react.useCallback)((state) => {
1997
+ if (!state) return;
1998
+ setVgsFieldState((prev) => {
1999
+ const newState = { ...prev };
2000
+ let hasChanges = false;
2001
+ Object.keys(state).forEach((key) => {
2002
+ const field = state[key];
2003
+ if (!field) return;
2004
+ const next = {
2005
+ isFocused: !!field.isFocused,
2006
+ isValid: !!field.isValid,
2007
+ isEmpty: !!field.isEmpty
2008
+ };
2009
+ if (!newState[key] || JSON.stringify(newState[key]) !== JSON.stringify(next)) {
2010
+ newState[key] = next;
2011
+ hasChanges = true;
2012
+ }
2013
+ });
2014
+ return hasChanges ? newState : prev;
2015
+ });
2016
+ }, []);
2017
+ const resetVgs = (0, react.useCallback)(() => {
2018
+ if (formRef.current) {
2019
+ try {
2020
+ formRef.current.unmount();
2021
+ } catch (e) {
2022
+ console.warn("VGS unmount error", e);
2023
+ }
2024
+ formRef.current = null;
2025
+ }
2026
+ setIsFormReady(false);
2027
+ setVgsFieldState({ ...DEFAULT_FIELD_STATE });
2028
+ }, []);
2029
+ const initializeForm = (0, react.useCallback)(async (credentials) => {
2030
+ if (!isScriptLoaded) return;
2031
+ const VGSCollect = getVGSCollect();
2032
+ if (!VGSCollect) {
2033
+ onErrorRef.current?.("Payment script not loaded");
2034
+ return;
2035
+ }
2036
+ try {
2037
+ setIsLoading(true);
2038
+ const vgsEnvironment = credentials.vault.environment === "sandbox" ? "sandbox" : "live-eu-1";
2039
+ const form = VGSCollect.create(credentials.vault.vault_id, vgsEnvironment, (state) => updateFieldState(state));
2040
+ if (credentials.vault.route_id) form.setRouteId(credentials.vault.route_id);
2041
+ formRef.current = form;
2042
+ let retries = 0;
2043
+ const maxRetries = 20;
2044
+ const retryDelay = 200;
2045
+ const waitForDom = async () => {
2046
+ if ([
2047
+ "vgs-card-number",
2048
+ "vgs-expiration-date",
2049
+ "vgs-cvc",
2050
+ "vgs-card-holder"
2051
+ ].every((id) => {
2052
+ const el = document.getElementById(id);
2053
+ return el && el.isConnected;
2054
+ })) return true;
2055
+ if (retries >= maxRetries) return false;
2056
+ retries++;
2057
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
2058
+ return waitForDom();
2059
+ };
2060
+ if (!await waitForDom()) throw new Error("Payment form elements not ready");
2061
+ const css = {
2062
+ fontSize: "14px",
2063
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
2064
+ color: "#1f2937",
2065
+ paddingTop: "0px",
2066
+ paddingBottom: "0px",
2067
+ paddingLeft: "0px",
2068
+ paddingRight: "0px",
2069
+ boxSizing: "border-box",
2070
+ lineHeight: "38px",
2071
+ height: "100%",
2072
+ width: "100%",
2073
+ "&::placeholder": {
2074
+ color: "#9ca3af",
2075
+ opacity: 1
2076
+ },
2077
+ "&:focus": { outline: "none" }
2078
+ };
2079
+ form.field("#vgs-card-number", {
2080
+ type: "card-number",
2081
+ name: "card_number",
2082
+ placeholder: "0000 0000 0000 0000",
2083
+ showCardIcon: true,
2084
+ css: {
2085
+ ...css,
2086
+ paddingRight: "40px"
2087
+ },
2088
+ autoComplete: "cc-number",
2089
+ validations: ["required", "validCardNumber"]
2090
+ });
2091
+ form.field("#vgs-expiration-date", {
2092
+ type: "card-expiration-date",
2093
+ name: "card_exp",
2094
+ yearLength: 2,
2095
+ placeholder: "MM / YY",
2096
+ css,
2097
+ autoComplete: "cc-exp",
2098
+ validations: ["required", "validCardExpirationDate"]
2099
+ });
2100
+ form.field("#vgs-cvc", {
2101
+ type: "card-security-code",
2102
+ name: "card_cvc",
2103
+ placeholder: "123",
2104
+ css,
2105
+ autoComplete: "cc-csc",
2106
+ validations: ["required", "validCardSecurityCode"]
2107
+ });
2108
+ form.field("#vgs-card-holder", {
2109
+ type: "text",
2110
+ name: "card_holder",
2111
+ placeholder: "Full Name",
2112
+ css,
2113
+ autoComplete: "cc-name",
2114
+ validations: ["required"]
2115
+ });
2116
+ setIsFormReady(true);
2117
+ } catch (error) {
2118
+ console.error("Failed to initialize VGS:", error);
2119
+ onErrorRef.current?.("Failed to initialize payment form");
2120
+ } finally {
2121
+ setIsLoading(false);
2122
+ }
2123
+ }, [isScriptLoaded, updateFieldState]);
2124
+ const submitCard = (0, react.useCallback)(() => {
2125
+ if (!formRef.current) {
2126
+ onErrorRef.current?.("Form not initialized");
2127
+ return;
2128
+ }
2129
+ formRef.current.submit(`/post`, {}, (status, response) => {
2130
+ if (status >= 200 && status < 400) onSuccessRef.current?.(response);
2131
+ else onErrorRef.current?.("Payment failed");
2132
+ }, (errors) => {
2133
+ const allErrors = Object.values(errors).flat().filter((msg) => typeof msg === "string" && msg.trim().length > 0 && msg !== "Required");
2134
+ const uniqueErrors = Array.from(new Set(allErrors));
2135
+ let errorMsg = "Please verify your payment details.";
2136
+ if (uniqueErrors.length > 0) errorMsg = uniqueErrors.join(", ");
2137
+ else if (Object.values(errors).flat().length > 0) errorMsg = "Please fill in all required fields.";
2138
+ onErrorRef.current?.(errorMsg);
2139
+ });
2140
+ }, []);
2141
+ (0, react.useEffect)(() => {
2142
+ return () => {
2143
+ if (formRef.current) {
2144
+ try {
2145
+ formRef.current.unmount();
2146
+ } catch (e) {
2147
+ console.warn("VGS unmount error", e);
2148
+ }
2149
+ formRef.current = null;
2150
+ }
2151
+ };
2152
+ }, []);
2153
+ return {
2154
+ isFormReady,
2155
+ isLoading,
2156
+ isScriptLoaded,
2157
+ initializeForm,
2158
+ submitCard,
2159
+ vgsFieldState,
2160
+ resetVgs,
2161
+ onSuccessRef,
2162
+ onErrorRef
2163
+ };
2164
+ }
2165
+ //#endregion
2166
+ //#region ../../fluid-pay/ui/src/components/CreditCardFormDialog.tsx
2167
+ const billingAddressSchema = zod.z.object({
2168
+ name: zod.z.string().min(1, "Name is required"),
2169
+ address1: zod.z.string().min(1, "Address line 1 is required"),
2170
+ address2: zod.z.string().optional().nullable(),
2171
+ city: zod.z.string().min(1, "City is required"),
2172
+ state: zod.z.string().min(1, "State is required"),
2173
+ zip: zod.z.string().min(1, "Zip code is required"),
2174
+ country_code: zod.z.string().min(1, "Country is required"),
2175
+ set_as_default: zod.z.boolean()
2176
+ });
2177
+ function VgsInputWrapper({ id, fieldState, className }) {
2178
+ const isInvalid = fieldState?.isValid === false && !fieldState?.isFocused && !fieldState?.isEmpty;
2179
+ const isFocused = fieldState?.isFocused;
2180
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2181
+ className: "w-full",
2182
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2183
+ id,
2184
+ className: require_src.cn("relative flex h-10 w-full items-center rounded-md border border-gray-300 bg-white px-3 shadow-sm transition-all duration-200 ease-in-out", "[&_iframe]:block! [&_iframe]:h-full! [&_iframe]:w-full!", isFocused && "border-blue-600 ring-1 ring-blue-600", isInvalid && "border-red-500 ring-1 ring-red-500", className)
2185
+ })
2186
+ });
2187
+ }
2188
+ function VgsCardForm({ isLoading, isFormReady, vgsFieldState, networkError, t }) {
2189
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2190
+ className: "space-y-4",
2191
+ "aria-label": "Credit card form",
2192
+ children: [
2193
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VgsInputWrapper, {
2194
+ id: "vgs-card-number",
2195
+ fieldState: vgsFieldState["card_number"]
2196
+ }),
2197
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2198
+ className: "flex gap-3",
2199
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2200
+ className: "flex-1",
2201
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VgsInputWrapper, {
2202
+ id: "vgs-expiration-date",
2203
+ fieldState: vgsFieldState["card_exp"]
2204
+ })
2205
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2206
+ className: "flex-1",
2207
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VgsInputWrapper, {
2208
+ id: "vgs-cvc",
2209
+ fieldState: vgsFieldState["card_cvc"]
2210
+ })
2211
+ })]
2212
+ }),
2213
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VgsInputWrapper, {
2214
+ id: "vgs-card-holder",
2215
+ fieldState: vgsFieldState["card_holder"]
2216
+ }),
2217
+ networkError && networkError.trim().length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2218
+ className: "rounded-md bg-red-50 p-3 text-sm text-red-600",
2219
+ children: networkError
2220
+ })
2221
+ ]
2222
+ });
2223
+ }
2224
+ function CreditCardFormDialog({ isOpen, onClose, onSubmit, isSubmitting, countries = [], error, jwt, client, renderAddressAutocomplete, t }) {
2225
+ const [cardError, setCardError] = (0, react.useState)(void 0);
2226
+ const [isVgsSubmitting, setIsVgsSubmitting] = (0, react.useState)(false);
2227
+ const { isFormReady, isLoading: isVgsLoading, isScriptLoaded, initializeForm, submitCard, vgsFieldState, resetVgs, onSuccessRef, onErrorRef } = useVgsCollect();
2228
+ const { control, handleSubmit, reset, setValue } = (0, react_hook_form.useForm)({
2229
+ resolver: (0, _hookform_resolvers_zod.zodResolver)(billingAddressSchema),
2230
+ defaultValues: {
2231
+ name: "",
2232
+ address1: "",
2233
+ address2: "",
2234
+ city: "",
2235
+ state: "",
2236
+ zip: "",
2237
+ country_code: "US",
2238
+ set_as_default: false
2239
+ }
2240
+ });
2241
+ const billingCountry = (0, react_hook_form.useWatch)({
2242
+ control,
2243
+ name: "country_code"
2244
+ });
2245
+ const setAsDefault = (0, react_hook_form.useWatch)({
2246
+ control,
2247
+ name: "set_as_default"
2248
+ });
2249
+ const { stateOptions, config, handleCountryChange } = useCountryStates();
2250
+ const countrySelectOptions = [...countries].map((country) => ({
2251
+ name: country.name,
2252
+ value: country.iso
2253
+ })).sort((a, b) => {
2254
+ if (a.value === billingCountry) return -1;
2255
+ if (b.value === billingCountry) return 1;
2256
+ return a.name.localeCompare(b.name);
2257
+ });
2258
+ const stateSelectOptions = stateOptions.map((state) => ({
2259
+ name: state.name,
2260
+ value: state.isoCode
2261
+ }));
2262
+ (0, react.useEffect)(() => {
2263
+ handleCountryChange(billingCountry);
2264
+ }, [billingCountry, handleCountryChange]);
2265
+ (0, react.useEffect)(() => {
2266
+ if (!isOpen || !isScriptLoaded || !jwt) return;
2267
+ let cancelled = false;
2268
+ const init = async () => {
2269
+ try {
2270
+ const credentials = await fetchVaultCredentialsForPaymentAccount(client, jwt);
2271
+ if (!cancelled) await initializeForm(credentials);
2272
+ } catch (err) {
2273
+ console.error("Failed to fetch vault credentials:", err);
2274
+ if (!cancelled) setCardError("Failed to initialize payment form");
2275
+ }
2276
+ };
2277
+ init();
2278
+ return () => {
2279
+ cancelled = true;
2280
+ };
2281
+ }, [
2282
+ isOpen,
2283
+ isScriptLoaded,
2284
+ jwt,
2285
+ client,
2286
+ initializeForm
2287
+ ]);
2288
+ const handleVgsSuccess = (0, react.useCallback)((response) => {
2289
+ const expValue = response?.card_exp;
2290
+ if (!expValue) {
2291
+ setCardError("Missing expiration date from payment form");
2292
+ setIsVgsSubmitting(false);
2293
+ return;
2294
+ }
2295
+ const [expMonth, expYearShort] = expValue.replace(/\s+/g, "").split("/");
2296
+ if (!expMonth || !expYearShort) {
2297
+ setCardError("Invalid expiration date format");
2298
+ setIsVgsSubmitting(false);
2299
+ return;
2300
+ }
2301
+ const expYear = expYearShort.length === 2 ? `20${expYearShort}` : expYearShort;
2302
+ const cardholderName = response?.card_holder?.trim();
2303
+ if (!cardholderName) {
2304
+ setCardError("Cardholder name is required");
2305
+ setIsVgsSubmitting(false);
2306
+ return;
2307
+ }
2308
+ handleSubmit((formData) => {
2309
+ onSubmit({
2310
+ type: "credit_card",
2311
+ country_code: formData.country_code,
2312
+ default_payment_method: formData.set_as_default,
2313
+ payment_method: {
2314
+ token: response.card_number,
2315
+ cvv_token: response.card_cvc,
2316
+ exp_month: expMonth,
2317
+ exp_year: expYear,
2318
+ card_holder: cardholderName,
2319
+ billing_zip: formData.zip
2320
+ },
2321
+ billing_address: {
2322
+ name: formData.name,
2323
+ address1: formData.address1,
2324
+ address2: formData.address2 ?? void 0,
2325
+ city: formData.city,
2326
+ state: formData.state,
2327
+ zip: formData.zip,
2328
+ country_code: formData.country_code
2329
+ }
2330
+ });
2331
+ setIsVgsSubmitting(false);
2332
+ })();
2333
+ }, [handleSubmit, onSubmit]);
2334
+ const handleVgsError = (0, react.useCallback)((err) => {
2335
+ setCardError(err);
2336
+ setIsVgsSubmitting(false);
2337
+ }, []);
2338
+ (0, react.useEffect)(() => {
2339
+ onSuccessRef.current = handleVgsSuccess;
2340
+ onErrorRef.current = handleVgsError;
2341
+ }, [
2342
+ handleVgsSuccess,
2343
+ handleVgsError,
2344
+ onSuccessRef,
2345
+ onErrorRef
2346
+ ]);
2347
+ const handleClose = () => {
2348
+ resetVgs();
2349
+ reset();
2350
+ setCardError(void 0);
2351
+ setIsVgsSubmitting(false);
2352
+ onClose();
2353
+ };
2354
+ const handleFormSubmit = handleSubmit(() => {
2355
+ setIsVgsSubmitting(true);
2356
+ setCardError(void 0);
2357
+ submitCard();
2358
+ });
2359
+ const isBusy = isSubmitting || isVgsSubmitting;
2360
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Dialog, {
2361
+ open: isOpen,
2362
+ onOpenChange: (open) => !open && handleClose(),
2363
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogContent, {
2364
+ className: "max-h-[90vh] max-w-md overflow-y-auto rounded p-0 md:max-w-xl",
2365
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2366
+ className: "relative p-6",
2367
+ children: [
2368
+ (isVgsLoading || !isFormReady) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2369
+ className: "absolute inset-0 z-10 flex items-center justify-center rounded bg-white/80 backdrop-blur-[1px]",
2370
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2371
+ className: "flex items-center justify-center",
2372
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mr-3 h-5 w-5 animate-spin rounded-full border-2 border-t-2 border-blue-600 border-t-transparent" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2373
+ className: "text-sm font-medium text-gray-600",
2374
+ children: t("securing")
2375
+ })]
2376
+ })
2377
+ }),
2378
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DialogTitle, {
2379
+ className: "text-lg font-medium",
2380
+ children: t("add_credit_card")
2381
+ }) }),
2382
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2383
+ className: "space-y-4 pt-6",
2384
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(VgsCardForm, {
2385
+ isLoading: isVgsLoading,
2386
+ isFormReady,
2387
+ vgsFieldState,
2388
+ networkError: cardError ?? error,
2389
+ t
2390
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2391
+ className: "space-y-3 pt-2",
2392
+ children: [
2393
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2394
+ className: "text-sm font-medium text-gray-500",
2395
+ children: t("billing_address")
2396
+ }),
2397
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
2398
+ control,
2399
+ name: "country_code",
2400
+ placeholder: t("country"),
2401
+ options: countrySelectOptions,
2402
+ disabled: isBusy
2403
+ }),
2404
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
2405
+ control,
2406
+ name: "name",
2407
+ placeholder: t("name"),
2408
+ disabled: isBusy
2409
+ }),
2410
+ renderAddressAutocomplete ? renderAddressAutocomplete({
2411
+ control,
2412
+ setValue,
2413
+ countryCode: billingCountry
2414
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
2415
+ control,
2416
+ name: "address1",
2417
+ placeholder: t("address_line_1"),
2418
+ disabled: isBusy
2419
+ }),
2420
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
2421
+ control,
2422
+ name: "address2",
2423
+ placeholder: t("address_line_2"),
2424
+ disabled: isBusy
2425
+ }),
2426
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2427
+ className: "flex gap-3",
2428
+ children: [
2429
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
2430
+ control,
2431
+ name: "city",
2432
+ placeholder: t("city"),
2433
+ containerClassName: "flex-1",
2434
+ disabled: isBusy
2435
+ }),
2436
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
2437
+ control,
2438
+ name: "state",
2439
+ placeholder: config?.regionLabel ? t(config.regionLabel) : t("select_state"),
2440
+ options: stateSelectOptions,
2441
+ containerClassName: "flex-1",
2442
+ disabled: isBusy
2443
+ }),
2444
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField, {
2445
+ control,
2446
+ name: "zip",
2447
+ placeholder: config?.postalLabel ? t(config.postalLabel) : t("zip_code"),
2448
+ containerClassName: "flex-1",
2449
+ disabled: isBusy
2450
+ })
2451
+ ]
2452
+ })
2453
+ ]
2454
+ })]
2455
+ }),
2456
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2457
+ className: "mt-4 flex items-center justify-between",
2458
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2459
+ className: "flex items-center space-x-2",
2460
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2461
+ type: "checkbox",
2462
+ id: "set_as_default_cc",
2463
+ checked: setAsDefault,
2464
+ onChange: () => setValue("set_as_default", !setAsDefault),
2465
+ disabled: isBusy,
2466
+ className: "h-4 w-4"
2467
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2468
+ htmlFor: "set_as_default_cc",
2469
+ className: "text-sm",
2470
+ children: t("set_as_default_payment_method")
2471
+ })]
2472
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
2473
+ type: "submit",
2474
+ onClick: handleFormSubmit,
2475
+ disabled: isBusy,
2476
+ className: "rounded bg-gray-900 px-5 py-2.5 text-white hover:bg-gray-800",
2477
+ children: isBusy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-5 w-5 animate-spin rounded-full border-4 border-t-4 border-white border-t-transparent" }) : t("save_card")
2478
+ })]
2479
+ })
2480
+ ]
2481
+ })
2482
+ })
2483
+ });
2484
+ }
2485
+ //#endregion
2486
+ //#region src/screens/ProfileContentScreen.tsx
2487
+ const translations = {
2488
+ edit_profile: "Edit Profile",
2489
+ first_name: "First Name",
2490
+ last_name: "Last Name",
2491
+ phone_number: "Phone Number",
2492
+ language: "Language",
2493
+ first_name_is_required: "First name is required",
2494
+ last_name_is_required: "Last name is required",
2495
+ language_is_required: "Language is required",
2496
+ saving: "Saving...",
2497
+ save_changes: "Save Changes",
2498
+ select_an_option: "Select an option",
2499
+ points_history: "Points History",
2500
+ points_available: "Points Available",
2501
+ points_awarded: "Points Awarded",
2502
+ points_redeemed: "Points Redeemed",
2503
+ transaction: "Transaction",
2504
+ no_points_history_found: "No points history found",
2505
+ shipping_addresses: "Shipping Addresses",
2506
+ add_an_address: "Add an Address",
2507
+ delete_address: "Delete Address",
2508
+ delete_address_message: "Are you sure you want to delete this address? This action cannot be undone.",
2509
+ delete: "Delete",
2510
+ add_address: "Add Address",
2511
+ edit_address: "Edit Address",
2512
+ set_as_default_address: "Set as default address",
2513
+ save_address: "Save Address",
2514
+ card_number: "Card Number",
2515
+ expiration_date: "Expiration (MM / YY)",
2516
+ cvc: "CVC",
2517
+ cardholder_name: "Cardholder Name",
2518
+ add_credit_card: "Add Credit Card",
2519
+ save_card: "Save Card",
2520
+ securing: "Loading secure form...",
2521
+ payment_methods: "Payment Methods",
2522
+ add_payment_method: "Add Payment Method",
2523
+ delete_credit_card: "Delete Credit Card",
2524
+ delete_credit_card_message: "Are you sure you want to delete this payment method? This action cannot be undone.",
2525
+ edit_card: "Card Details",
2526
+ billing_address: "Billing Address",
2527
+ country: "Country",
2528
+ name: "Name",
2529
+ address_line_1: "Address Line 1",
2530
+ address_line_2: "Address Line 2",
2531
+ city: "City",
2532
+ state: "State",
2533
+ province: "Province",
2534
+ zip_code: "Zip Code",
2535
+ postal_code: "Postal Code",
2536
+ select_state: "Select state",
2537
+ set_as_default_payment_method: "Set as default payment method",
2538
+ cancel: "Cancel",
2539
+ save: "Save",
2540
+ close: "Close",
2541
+ edit: "Edit",
2542
+ default: "Default",
2543
+ card_expires: "Expires",
2544
+ no_billing_address: "No billing address on file",
2545
+ default_payment_method_updated: "Payment method updated",
2546
+ failed_to_set_default_payment_method: "Failed to update payment method"
2547
+ };
2548
+ function t(key) {
2549
+ if (translations[key]) return translations[key];
2550
+ return key.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
2551
+ }
2552
+ function adaptPointsLedger(entry) {
2553
+ return {
2554
+ id: entry.id,
2555
+ amount: entry.amount,
2556
+ company_id: 0,
2557
+ created_at: entry.created_at,
2558
+ customer_id: entry.customer_id,
2559
+ metadata: {
2560
+ transaction_type: entry.metadata?.transaction_type ?? void 0,
2561
+ source: entry.metadata?.source ?? void 0
2562
+ },
2563
+ total_balance: entry.total_balance ?? 0,
2564
+ updated_at: entry.created_at
2565
+ };
2566
+ }
2567
+ function ProfileContentScreen({ onToast, countryIso }) {
2568
+ const { token, user } = require_use_account_clients.useFluidAuth();
2569
+ const client = require_use_account_clients.useFluidPayClient();
2570
+ const sdkClient = require_use_account_clients.useSdkClient();
2571
+ const queryClient = (0, _tanstack_react_query.useQueryClient)();
2572
+ const jwt = token ?? "";
2573
+ const userId = user?.id;
2574
+ const { data: accountData, isLoading: isLoadingAccount, isError: isAccountError } = (0, _tanstack_react_query.useQuery)({
2575
+ queryKey: ["fluidPayAccount", userId],
2576
+ queryFn: () => require_use_account_clients.fetchCustomerAccount(client, jwt),
2577
+ enabled: !!jwt
2578
+ });
2579
+ const { data: addressesData, isLoading: isLoadingAddresses } = (0, _tanstack_react_query.useQuery)({
2580
+ queryKey: ["fluidPayAddresses", userId],
2581
+ queryFn: () => fetchCustomerAddresses(client, jwt),
2582
+ enabled: !!jwt
2583
+ });
2584
+ const { data: paymentMethodsData, isLoading: isLoadingPaymentMethods } = (0, _tanstack_react_query.useQuery)({
2585
+ queryKey: [
2586
+ "fluidPayPaymentMethods",
2587
+ userId,
2588
+ countryIso
2589
+ ],
2590
+ queryFn: () => fetchCustomerPaymentMethods(client, jwt, countryIso),
2591
+ enabled: !!jwt
2592
+ });
2593
+ const { data: countriesData } = (0, _tanstack_react_query.useQuery)({
2594
+ queryKey: ["sdk-countries"],
2595
+ queryFn: () => sdkClient.get("/countries"),
2596
+ initialData: []
2597
+ });
2598
+ const customerId = accountData?.customer?.id;
2599
+ const { data: pointsLedgerData, isLoading: isLoadingPointsLedger } = (0, _tanstack_react_query.useQuery)({
2600
+ queryKey: ["customer-points-ledger", customerId],
2601
+ queryFn: () => sdkClient.get(`${require_use_account_clients.API_VERSION}/customers/${customerId}/points_ledgers`),
2602
+ enabled: !!customerId
2603
+ });
2604
+ const updateCustomerMutation = (0, _tanstack_react_query.useMutation)({
2605
+ mutationFn: (data) => {
2606
+ const languageIso = adaptedLanguages?.find((l) => l.name === data.language)?.iso ?? "en";
2607
+ return require_use_account_clients.updateCustomer(client, jwt, {
2608
+ first_name: data.first_name,
2609
+ last_name: data.last_name,
2610
+ phone: data.phone_number,
2611
+ language_iso: languageIso
2612
+ });
2613
+ },
2614
+ onSuccess: () => {
2615
+ queryClient.invalidateQueries({ queryKey: ["fluidPayAccount", userId] });
2616
+ onToast("Profile updated", "success");
2617
+ },
2618
+ onError: () => {
2619
+ onToast("Failed to update profile", "error");
2620
+ }
2621
+ });
2622
+ const deleteAddressMutation = (0, _tanstack_react_query.useMutation)({
2623
+ mutationFn: (addressId) => deleteCustomerAddress(client, jwt, addressId),
2624
+ onSuccess: () => {
2625
+ queryClient.invalidateQueries({ queryKey: ["fluidPayAddresses", userId] });
2626
+ }
2627
+ });
2628
+ const deletePaymentMethodMutation = (0, _tanstack_react_query.useMutation)({
2629
+ mutationFn: (paymentMethodId) => deleteCustomerPaymentMethod(client, jwt, paymentMethodId),
2630
+ onSuccess: () => {
2631
+ queryClient.invalidateQueries({ queryKey: [
2632
+ "fluidPayPaymentMethods",
2633
+ userId,
2634
+ countryIso
2635
+ ] });
2636
+ }
2637
+ });
2638
+ const updatePaymentMethodMutation = (0, _tanstack_react_query.useMutation)({
2639
+ mutationFn: ({ paymentMethodId, data }) => updatePaymentMethod(client, jwt, paymentMethodId, {
2640
+ set_as_default: data.set_as_default,
2641
+ billing_address: data.billing_address
2642
+ }),
2643
+ onSuccess: () => {
2644
+ queryClient.invalidateQueries({ queryKey: [
2645
+ "fluidPayPaymentMethods",
2646
+ userId,
2647
+ countryIso
2648
+ ] });
2649
+ }
2650
+ });
2651
+ const createAddressMutation = (0, _tanstack_react_query.useMutation)({
2652
+ mutationFn: (body) => createCustomerAddress(client, jwt, body),
2653
+ onSuccess: () => {
2654
+ queryClient.invalidateQueries({ queryKey: ["fluidPayAddresses", userId] });
2655
+ onToast("Address created", "success");
2656
+ },
2657
+ onError: () => {
2658
+ onToast("Failed to create address", "error");
2659
+ }
2660
+ });
2661
+ const updateAddressMutation = (0, _tanstack_react_query.useMutation)({
2662
+ mutationFn: ({ addressId, body }) => updateCustomerAddress(client, jwt, addressId, body),
2663
+ onSuccess: () => {
2664
+ queryClient.invalidateQueries({ queryKey: ["fluidPayAddresses", userId] });
2665
+ onToast("Address updated", "success");
2666
+ },
2667
+ onError: () => {
2668
+ onToast("Failed to update address", "error");
2669
+ }
2670
+ });
2671
+ const addCreditCardMutation = (0, _tanstack_react_query.useMutation)({
2672
+ mutationFn: (data) => addCreditCardToCustomer(client, jwt, data),
2673
+ onSuccess: () => {
2674
+ queryClient.invalidateQueries({ queryKey: [
2675
+ "fluidPayPaymentMethods",
2676
+ userId,
2677
+ countryIso
2678
+ ] });
2679
+ onToast("Payment method added", "success");
2680
+ },
2681
+ onError: () => {
2682
+ onToast("Failed to add payment method", "error");
2683
+ }
2684
+ });
2685
+ const addresses = addressesData?.addresses ?? [];
2686
+ const paymentMethods = paymentMethodsData?.payment_methods ?? [];
2687
+ const adaptedPointsLedger = pointsLedgerData?.points_ledgers?.map(adaptPointsLedger) ?? [];
2688
+ const adaptedLanguages = [{
2689
+ id: 0,
2690
+ name: "English",
2691
+ iso: "en"
2692
+ }];
2693
+ const countryOptions = (0, react.useMemo)(() => [...countriesData].map((c) => ({
2694
+ iso: c.iso,
2695
+ name: c.name
2696
+ })).sort((a, b) => a.name.localeCompare(b.name)), [countriesData]);
2697
+ if (!token) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2698
+ className: "px-4 py-8 sm:px-9",
2699
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2700
+ className: "rounded-lg border p-4 text-center",
2701
+ children: "Login Required"
2702
+ })
2703
+ });
2704
+ if (isAccountError && !isLoadingAccount) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2705
+ className: "px-4 py-8 sm:px-9",
2706
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2707
+ className: "text-muted-foreground text-center text-sm",
2708
+ children: "Unable to load account data. Please try again later."
2709
+ })
2710
+ });
2711
+ if (isLoadingAccount || !accountData) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2712
+ className: "px-4 pt-4 sm:px-9 md:pt-8",
2713
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2714
+ className: "space-y-4",
2715
+ children: [
2716
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-16 animate-pulse rounded" }),
2717
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-32 animate-pulse rounded" }),
2718
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-32 animate-pulse rounded" })
2719
+ ]
2720
+ })
2721
+ });
2722
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2723
+ className: "px-4 pt-4 sm:px-9 md:pt-8",
2724
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProfileUIProvider, {
2725
+ t,
2726
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Profile, {
2727
+ customerAccount: accountData,
2728
+ languages: adaptedLanguages,
2729
+ onUpdateCustomer: async (data) => {
2730
+ await updateCustomerMutation.mutateAsync(data);
2731
+ },
2732
+ isUpdatingCustomer: updateCustomerMutation.isPending,
2733
+ rewardsPointsEnabled: adaptedPointsLedger.length > 0,
2734
+ pointsLedger: adaptedPointsLedger,
2735
+ isLoadingPointsLedger,
2736
+ addresses,
2737
+ isLoadingAddresses,
2738
+ onDeleteAddress: async (addressId) => {
2739
+ await deleteAddressMutation.mutateAsync(addressId);
2740
+ },
2741
+ isDeletingAddress: deleteAddressMutation.isPending,
2742
+ paymentMethods,
2743
+ isLoadingPaymentMethods,
2744
+ onDeletePaymentMethod: async (paymentMethodId) => {
2745
+ await deletePaymentMethodMutation.mutateAsync(paymentMethodId);
2746
+ },
2747
+ isDeletingPaymentMethod: deletePaymentMethodMutation.isPending,
2748
+ onUpdatePaymentMethod: async (paymentMethodId, data) => {
2749
+ await updatePaymentMethodMutation.mutateAsync({
2750
+ paymentMethodId,
2751
+ data
2752
+ });
2753
+ },
2754
+ isUpdatingPaymentMethod: updatePaymentMethodMutation.isPending,
2755
+ getBillingAddress: (pm) => pm.billing_address ?? null,
2756
+ countries: countryOptions,
2757
+ renderAddressDialog: ({ isOpen, onClose, selectedAddress }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddressFormDialog, {
2758
+ isOpen,
2759
+ onClose,
2760
+ selectedAddress,
2761
+ t,
2762
+ onSubmit: async (formData) => {
2763
+ if (selectedAddress) await updateAddressMutation.mutateAsync({
2764
+ addressId: selectedAddress.id,
2765
+ body: formData
2766
+ });
2767
+ else await createAddressMutation.mutateAsync(formData);
2768
+ onClose();
2769
+ },
2770
+ isSubmitting: createAddressMutation.isPending || updateAddressMutation.isPending,
2771
+ countries: countryOptions,
2772
+ renderAddressAutocomplete: ({ control, setValue: _setValue }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PlainAddressInput, {
2773
+ control,
2774
+ name: "address1"
2775
+ })
2776
+ }),
2777
+ renderCreditCardDialog: ({ isOpen, onClose }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditCardFormDialog, {
2778
+ isOpen,
2779
+ onClose,
2780
+ t,
2781
+ onSubmit: async (data) => {
2782
+ await addCreditCardMutation.mutateAsync(data);
2783
+ onClose();
2784
+ },
2785
+ isSubmitting: addCreditCardMutation.isPending,
2786
+ countries: countryOptions,
2787
+ jwt,
2788
+ client,
2789
+ renderAddressAutocomplete: ({ control, setValue: _setValue }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PlainAddressInput, {
2790
+ control,
2791
+ name: "address1"
2792
+ })
2793
+ })
2794
+ })
2795
+ })
2796
+ });
2797
+ }
2798
+ /**
2799
+ * Plain text input fallback for address autocomplete.
2800
+ * The SDK doesn't have Google Places integration.
2801
+ */
2802
+ function PlainAddressInput({ control, name }) {
2803
+ const { field } = (0, react_hook_form.useController)({
2804
+ control,
2805
+ name
2806
+ });
2807
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2808
+ type: "text",
2809
+ value: field.value ?? "",
2810
+ placeholder: "Address Line 1",
2811
+ className: "border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
2812
+ onChange: field.onChange
2813
+ });
2814
+ }
2815
+ //#endregion
2816
+ //#region src/screens/ProfileScreen.tsx
2817
+ function defaultToast(message, type) {
2818
+ if (type === "error" || type === "warning") console.warn("[Profile]", message);
2819
+ else console.info("[Profile]", message);
2820
+ }
2821
+ function ProfileScreen({ onToast, background, textColor, accentColor, padding, borderRadius, ...divProps }) {
2822
+ const { config } = require_FluidProvider.useFluidContext();
2823
+ const effectiveToast = onToast ?? defaultToast;
2824
+ const countryIso = config.countryIso ?? "US";
2825
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2826
+ ...divProps,
2827
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProfileContentScreen, {
2828
+ onToast: effectiveToast,
2829
+ countryIso
2830
+ })
2831
+ });
2832
+ }
2833
+ const profileScreenPropertySchema = {
2834
+ widgetType: "ProfileScreen",
2835
+ displayName: "Profile Screen",
2836
+ tabsConfig: [{
2837
+ id: "styling",
2838
+ label: "Styling"
2839
+ }],
2840
+ fields: []
2841
+ };
2842
+ //#endregion
2843
+ Object.defineProperty(exports, "ProfileScreen", {
2844
+ enumerable: true,
2845
+ get: function() {
2846
+ return ProfileScreen;
2847
+ }
2848
+ });
2849
+ Object.defineProperty(exports, "profileScreenPropertySchema", {
2850
+ enumerable: true,
2851
+ get: function() {
2852
+ return profileScreenPropertySchema;
2853
+ }
2854
+ });
2855
+
2856
+ //# sourceMappingURL=ProfileScreen-B6Dp7RLa.cjs.map