@fluid-app/portal-sdk 0.1.162 → 0.1.164
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{MySiteScreen-g8Esyofu.mjs → MySiteScreen-CG2DnzQH.mjs} +2 -2
- package/dist/{MySiteScreen-g8Esyofu.mjs.map → MySiteScreen-CG2DnzQH.mjs.map} +1 -1
- package/dist/{MySiteScreen-Cos0jTa_.cjs → MySiteScreen-DRMrEMEI.cjs} +2 -2
- package/dist/{MySiteScreen-Xcg07a3M.cjs → MySiteScreen-Lr2SbrXz.cjs} +2 -2
- package/dist/{MySiteScreen-Xcg07a3M.cjs.map → MySiteScreen-Lr2SbrXz.cjs.map} +1 -1
- package/dist/{OrdersScreen-DZyOBKmU.cjs → OrdersScreen-B6n41CbG.cjs} +1 -1
- package/dist/{OrdersScreen-ZGUm8buk.cjs → OrdersScreen-BKCQdz5A.cjs} +55 -56
- package/dist/OrdersScreen-BKCQdz5A.cjs.map +1 -0
- package/dist/{OrdersScreen-DeLoyVGI.mjs → OrdersScreen-CFRVfzez.mjs} +55 -56
- package/dist/OrdersScreen-CFRVfzez.mjs.map +1 -0
- package/dist/{use-portal-shareables-api-DRK9Y5dp.mjs → PortalContentApiProvider-CW0ADhPi.mjs} +285 -94
- package/dist/PortalContentApiProvider-CW0ADhPi.mjs.map +1 -0
- package/dist/{use-portal-shareables-api-DcjYlAOy.cjs → PortalContentApiProvider-Di5emtYd.cjs} +290 -129
- package/dist/PortalContentApiProvider-Di5emtYd.cjs.map +1 -0
- package/dist/PortalProductsApiProvider-BCXX9NGK.mjs +780 -0
- package/dist/PortalProductsApiProvider-BCXX9NGK.mjs.map +1 -0
- package/dist/PortalProductsApiProvider-BquMHwvt.cjs +816 -0
- package/dist/PortalProductsApiProvider-BquMHwvt.cjs.map +1 -0
- package/dist/{ProductsScreen-B2SKzTE4.cjs → ProductsScreen-C6eNgxjP.cjs} +4 -3
- package/dist/{ProductsScreen-D6eoU86k.mjs → ProductsScreen-CVNJudq9.mjs} +39 -44
- package/dist/ProductsScreen-CVNJudq9.mjs.map +1 -0
- package/dist/{ProductsScreen-DbwSCY7G.cjs → ProductsScreen-KjjhlDGo.cjs} +39 -44
- package/dist/ProductsScreen-KjjhlDGo.cjs.map +1 -0
- package/dist/{ProductsScreen-BGah2tcD.mjs → ProductsScreen-nHmUftQn.mjs} +4 -3
- package/dist/{ShareablesScreen-DRUT-yoi.mjs → ShareablesScreen-CdTyyDRO.mjs} +4 -3
- package/dist/{ShareablesScreen-Dy04EXe5.cjs → ShareablesScreen-DUzo8kRi.cjs} +4 -3
- package/dist/ShareablesScreen-DpEP_6u0.mjs +132 -0
- package/dist/ShareablesScreen-DpEP_6u0.mjs.map +1 -0
- package/dist/ShareablesScreen-Dz8w2l3e.cjs +144 -0
- package/dist/ShareablesScreen-Dz8w2l3e.cjs.map +1 -0
- package/dist/{ShopScreen-CQ48b1c8.mjs → ShopScreen-BH6zQndJ.mjs} +10 -724
- package/dist/ShopScreen-BH6zQndJ.mjs.map +1 -0
- package/dist/{ShopScreen-CFqoT4IC.cjs → ShopScreen-BUXUtEuj.cjs} +13 -727
- package/dist/ShopScreen-BUXUtEuj.cjs.map +1 -0
- package/dist/{ShopScreen-B7faQx84.cjs → ShopScreen-BbucUNI7.cjs} +2 -1
- package/dist/{SubscriptionsScreen-C2iORyT_.cjs → SubscriptionsScreen-BdGF5OLE.cjs} +408 -409
- package/dist/SubscriptionsScreen-BdGF5OLE.cjs.map +1 -0
- package/dist/{SubscriptionsScreen-ClWrrqPK.cjs → SubscriptionsScreen-Cwa2lR1D.cjs} +1 -1
- package/dist/{SubscriptionsScreen-BfdK8067.mjs → SubscriptionsScreen-Dn3AEUJi.mjs} +408 -409
- package/dist/SubscriptionsScreen-Dn3AEUJi.mjs.map +1 -0
- package/dist/{dist-lO2OG0T5.cjs → dist-BF_4vk1z.cjs} +1 -1
- package/dist/{dist-lO2OG0T5.cjs.map → dist-BF_4vk1z.cjs.map} +1 -1
- package/dist/index.cjs +21 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +21 -20
- package/dist/index.mjs.map +1 -1
- package/dist/{sortable.esm-DSrWP4x9.mjs → sortable.esm-E6JdQn7I.mjs} +1 -1
- package/dist/{sortable.esm-DSrWP4x9.mjs.map → sortable.esm-E6JdQn7I.mjs.map} +1 -1
- package/package.json +17 -17
- package/dist/OrdersScreen-DeLoyVGI.mjs.map +0 -1
- package/dist/OrdersScreen-ZGUm8buk.cjs.map +0 -1
- package/dist/ProductsScreen-D6eoU86k.mjs.map +0 -1
- package/dist/ProductsScreen-DbwSCY7G.cjs.map +0 -1
- package/dist/ShareablesScreen-DPHZMh-V.cjs +0 -391
- package/dist/ShareablesScreen-DPHZMh-V.cjs.map +0 -1
- package/dist/ShareablesScreen-DrQDQ1-U.mjs +0 -379
- package/dist/ShareablesScreen-DrQDQ1-U.mjs.map +0 -1
- package/dist/ShopScreen-CFqoT4IC.cjs.map +0 -1
- package/dist/ShopScreen-CQ48b1c8.mjs.map +0 -1
- package/dist/SubscriptionsScreen-BfdK8067.mjs.map +0 -1
- package/dist/SubscriptionsScreen-C2iORyT_.cjs.map +0 -1
- package/dist/use-portal-products-client-BUFD20ZY.mjs +0 -65
- package/dist/use-portal-products-client-BUFD20ZY.mjs.map +0 -1
- package/dist/use-portal-products-client-DTkFvOal.cjs +0 -71
- package/dist/use-portal-products-client-DTkFvOal.cjs.map +0 -1
- package/dist/use-portal-shareables-api-DRK9Y5dp.mjs.map +0 -1
- package/dist/use-portal-shareables-api-DcjYlAOy.cjs.map +0 -1
|
@@ -206,342 +206,6 @@ function getNextBillDisplay(subscription) {
|
|
|
206
206
|
return "N/A";
|
|
207
207
|
}
|
|
208
208
|
//#endregion
|
|
209
|
-
//#region ../../subscriptions/ui/src/lib/format.ts
|
|
210
|
-
/**
|
|
211
|
-
* Format a number as currency (USD).
|
|
212
|
-
*/
|
|
213
|
-
function formatCurrency(value) {
|
|
214
|
-
return new Intl.NumberFormat("en-US", {
|
|
215
|
-
style: "currency",
|
|
216
|
-
currency: "USD"
|
|
217
|
-
}).format(value);
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Convert a snake_case or lowercase string to Start Case.
|
|
221
|
-
* Replaces lodash startCase for simple status strings.
|
|
222
|
-
*/
|
|
223
|
-
function startCase(str) {
|
|
224
|
-
if (!str) return "";
|
|
225
|
-
return str.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Format a next bill date string to M/D/YYYY (UTC).
|
|
229
|
-
*/
|
|
230
|
-
function formatNextBillDate(nextBillDate) {
|
|
231
|
-
if (!nextBillDate) return "N/A";
|
|
232
|
-
const date = new Date(nextBillDate);
|
|
233
|
-
if (isNaN(date.getTime())) return "N/A";
|
|
234
|
-
return `${date.getUTCMonth() + 1}/${date.getUTCDate()}/${date.getUTCFullYear()}`;
|
|
235
|
-
}
|
|
236
|
-
//#endregion
|
|
237
|
-
//#region ../../subscriptions/ui/src/lib/cn.ts
|
|
238
|
-
function cn(...inputs) {
|
|
239
|
-
return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
|
|
240
|
-
}
|
|
241
|
-
//#endregion
|
|
242
|
-
//#region ../../subscriptions/ui/src/components/status-pill.tsx
|
|
243
|
-
const STATUS_COLORS = {
|
|
244
|
-
active: "bg-green-100 text-green-800",
|
|
245
|
-
paused: "bg-gray-100 text-gray-800",
|
|
246
|
-
cancelled: "bg-red-100 text-red-800",
|
|
247
|
-
pending: "bg-yellow-100 text-yellow-800",
|
|
248
|
-
inactive: "bg-gray-100 text-gray-800",
|
|
249
|
-
disabled: "bg-red-100 text-red-800",
|
|
250
|
-
past_due: "bg-gray-100 text-gray-800"
|
|
251
|
-
};
|
|
252
|
-
const STATUS_DOT_COLORS = {
|
|
253
|
-
active: "bg-green-500",
|
|
254
|
-
paused: "bg-gray-400",
|
|
255
|
-
cancelled: "bg-red-500",
|
|
256
|
-
pending: "bg-yellow-500",
|
|
257
|
-
inactive: "bg-gray-400",
|
|
258
|
-
disabled: "bg-red-500",
|
|
259
|
-
past_due: "bg-gray-400"
|
|
260
|
-
};
|
|
261
|
-
function StatusPill({ status, children }) {
|
|
262
|
-
const key = status?.toLowerCase() ?? "";
|
|
263
|
-
const pillColor = STATUS_COLORS[key] ?? "bg-gray-100 text-gray-800";
|
|
264
|
-
const dotColor = STATUS_DOT_COLORS[key] ?? "bg-gray-400";
|
|
265
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
266
|
-
className: cn("inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium", pillColor),
|
|
267
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cn("h-1.5 w-1.5 rounded-full", dotColor) }), children]
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
//#endregion
|
|
271
|
-
//#region ../../subscriptions/ui/src/components/subscriptions-list.tsx
|
|
272
|
-
function SubscriptionsList({ customerId, onSubscriptionClick, t, pageSize = 10 }) {
|
|
273
|
-
const [currentPage, setCurrentPage] = (0, react.useState)(1);
|
|
274
|
-
const [statusFilter, setStatusFilter] = (0, react.useState)(null);
|
|
275
|
-
const [search, setSearch] = (0, react.useState)(null);
|
|
276
|
-
const [sortBy, setSortBy] = (0, react.useState)({
|
|
277
|
-
column: "next_bill_date",
|
|
278
|
-
direction: "desc"
|
|
279
|
-
});
|
|
280
|
-
const { data, isLoading } = useSubscriptions({
|
|
281
|
-
customerId: customerId ?? 0,
|
|
282
|
-
page: currentPage,
|
|
283
|
-
perPage: pageSize,
|
|
284
|
-
status: statusFilter,
|
|
285
|
-
search,
|
|
286
|
-
sortBy: sortBy.column,
|
|
287
|
-
sortDirection: sortBy.direction
|
|
288
|
-
}, { enabled: !!customerId });
|
|
289
|
-
(0, react.useEffect)(() => {
|
|
290
|
-
setCurrentPage(1);
|
|
291
|
-
}, [
|
|
292
|
-
statusFilter,
|
|
293
|
-
search,
|
|
294
|
-
sortBy
|
|
295
|
-
]);
|
|
296
|
-
const items = data?.subscriptions ?? [];
|
|
297
|
-
const totalItems = data?.meta?.pagination?.total_count ?? 0;
|
|
298
|
-
const totalPages = data?.meta?.pagination?.total_pages ?? 1;
|
|
299
|
-
const handleSubscriptionClick = (token) => {
|
|
300
|
-
if (token) onSubscriptionClick(token);
|
|
301
|
-
};
|
|
302
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
303
|
-
className: "border-border overflow-hidden rounded-lg border shadow-sm",
|
|
304
|
-
children: [
|
|
305
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
306
|
-
className: "flex flex-col gap-2 p-3 sm:flex-row sm:items-center sm:justify-between",
|
|
307
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.ToggleGroup, {
|
|
308
|
-
type: "single",
|
|
309
|
-
value: statusFilter ?? "all",
|
|
310
|
-
onValueChange: (v) => {
|
|
311
|
-
if (v) setStatusFilter(v === "all" ? null : v);
|
|
312
|
-
},
|
|
313
|
-
variant: "ghost",
|
|
314
|
-
children: [
|
|
315
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ToggleGroupItem, {
|
|
316
|
-
value: "all",
|
|
317
|
-
children: t("all")
|
|
318
|
-
}),
|
|
319
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ToggleGroupItem, {
|
|
320
|
-
value: "active",
|
|
321
|
-
children: t("active")
|
|
322
|
-
}),
|
|
323
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ToggleGroupItem, {
|
|
324
|
-
value: "inactive",
|
|
325
|
-
children: t("inactive")
|
|
326
|
-
})
|
|
327
|
-
]
|
|
328
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
329
|
-
className: "w-full max-w-sm",
|
|
330
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SearchSort.SearchSort, {
|
|
331
|
-
searchValue: search ?? "",
|
|
332
|
-
onSearchChange: (v) => setSearch(v || null),
|
|
333
|
-
placeholder: t("search_subscriptions")
|
|
334
|
-
})
|
|
335
|
-
})]
|
|
336
|
-
}),
|
|
337
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
338
|
-
className: "block md:hidden",
|
|
339
|
-
children: isLoading ? Array(5).fill(0).map((_, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
340
|
-
className: "border-border border-b p-4",
|
|
341
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
342
|
-
className: "flex space-x-3",
|
|
343
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-12 w-12 rounded-md" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
344
|
-
className: "flex-1 space-y-2",
|
|
345
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-3 w-1/2" })]
|
|
346
|
-
})]
|
|
347
|
-
})
|
|
348
|
-
}, `skeleton-${index}`)) : items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
349
|
-
className: "text-muted-foreground px-3 py-8 text-center text-sm",
|
|
350
|
-
children: t("no_subscriptions_found")
|
|
351
|
-
}) : items.map((subscription) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
352
|
-
className: "border-border hover:bg-accent cursor-pointer border-b p-4 transition-colors duration-200 ease-in-out last:border-b-0",
|
|
353
|
-
onClick: () => handleSubscriptionClick(subscription.subscription_token),
|
|
354
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
355
|
-
className: "flex items-start space-x-3",
|
|
356
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
357
|
-
src: subscription.variant?.product?.image_url,
|
|
358
|
-
alt: subscription.variant?.product?.title,
|
|
359
|
-
width: 48,
|
|
360
|
-
height: 48,
|
|
361
|
-
className: "h-12 w-12 flex-shrink-0 rounded-md object-cover"
|
|
362
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
363
|
-
className: "w-0 min-w-0 flex-1",
|
|
364
|
-
children: [
|
|
365
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
366
|
-
className: "text-foreground truncate text-sm font-medium",
|
|
367
|
-
children: subscription.variant?.product?.title
|
|
368
|
-
}),
|
|
369
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
370
|
-
className: "mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-sm",
|
|
371
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
372
|
-
className: "text-muted-foreground block text-xs",
|
|
373
|
-
children: t("next_bill_date")
|
|
374
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
375
|
-
className: "text-muted-foreground",
|
|
376
|
-
children: formatNextBillDate(subscription.next_bill_date ?? "")
|
|
377
|
-
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
378
|
-
className: "text-muted-foreground block text-xs",
|
|
379
|
-
children: t("price")
|
|
380
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
381
|
-
className: "text-foreground font-medium",
|
|
382
|
-
children: formatCurrency(subscription.price * subscription.quantity)
|
|
383
|
-
})] })]
|
|
384
|
-
}),
|
|
385
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
386
|
-
className: "mt-2",
|
|
387
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
388
|
-
className: "text-muted-foreground block text-xs",
|
|
389
|
-
children: t("status")
|
|
390
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusPill, {
|
|
391
|
-
status: subscription.status,
|
|
392
|
-
children: startCase(subscription.status) || t("unknown_status")
|
|
393
|
-
})]
|
|
394
|
-
})
|
|
395
|
-
]
|
|
396
|
-
})]
|
|
397
|
-
})
|
|
398
|
-
}, subscription.subscription_token))
|
|
399
|
-
}),
|
|
400
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
401
|
-
className: "hidden md:block",
|
|
402
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Table, {
|
|
403
|
-
className: "min-w-full table-fixed",
|
|
404
|
-
children: [
|
|
405
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("colgroup", { children: [
|
|
406
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[45%] min-w-[240px]" }),
|
|
407
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[20%] min-w-[100px]" }),
|
|
408
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[15%] min-w-[100px]" }),
|
|
409
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[20%] min-w-[100px]" })
|
|
410
|
-
] }),
|
|
411
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableHeader, {
|
|
412
|
-
className: "bg-muted",
|
|
413
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableRow, {
|
|
414
|
-
className: "hover:bg-muted h-10",
|
|
415
|
-
children: [
|
|
416
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
417
|
-
label: t("product"),
|
|
418
|
-
sortable: false
|
|
419
|
-
}),
|
|
420
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
421
|
-
label: t("next_bill_date"),
|
|
422
|
-
sortBy: "next_bill_date",
|
|
423
|
-
sortData: sortBy,
|
|
424
|
-
onSortClick: (value) => setSortBy({
|
|
425
|
-
column: value,
|
|
426
|
-
direction: sortBy.direction === "asc" ? "desc" : "asc"
|
|
427
|
-
})
|
|
428
|
-
}),
|
|
429
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
430
|
-
label: t("price"),
|
|
431
|
-
sortable: false
|
|
432
|
-
}),
|
|
433
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
434
|
-
label: t("status"),
|
|
435
|
-
sortable: false
|
|
436
|
-
})
|
|
437
|
-
]
|
|
438
|
-
})
|
|
439
|
-
}),
|
|
440
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableBody, {
|
|
441
|
-
className: "bg-background",
|
|
442
|
-
children: isLoading ? Array(5).fill(0).map((_, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableRow, { children: [
|
|
443
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
444
|
-
className: "px-3 py-4",
|
|
445
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
446
|
-
className: "flex items-center space-x-2",
|
|
447
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-9 w-9 rounded-md" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-32" })]
|
|
448
|
-
})
|
|
449
|
-
}),
|
|
450
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
451
|
-
className: "px-3 py-4",
|
|
452
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-24" })
|
|
453
|
-
}),
|
|
454
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
455
|
-
className: "px-3 py-4",
|
|
456
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-24" })
|
|
457
|
-
}),
|
|
458
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
459
|
-
className: "px-3 py-4",
|
|
460
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-16" })
|
|
461
|
-
})
|
|
462
|
-
] }, `skeleton-${index}`)) : items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableRow, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
463
|
-
colSpan: 4,
|
|
464
|
-
className: "text-muted-foreground px-3 py-8 text-center text-sm",
|
|
465
|
-
children: t("no_subscriptions_found")
|
|
466
|
-
}) }) : items.map((subscription) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableRow, {
|
|
467
|
-
className: "cursor-pointer",
|
|
468
|
-
onClick: () => handleSubscriptionClick(subscription.subscription_token),
|
|
469
|
-
children: [
|
|
470
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableCell, {
|
|
471
|
-
className: "text-muted-foreground flex max-w-[280px] items-center space-x-3 py-4 pr-3 pl-3 text-sm",
|
|
472
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
473
|
-
src: subscription.variant?.product?.image_url,
|
|
474
|
-
alt: subscription.variant?.product?.title,
|
|
475
|
-
width: 48,
|
|
476
|
-
height: 48,
|
|
477
|
-
className: "h-12 w-12 flex-shrink-0 rounded-md object-cover"
|
|
478
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
479
|
-
className: "text-foreground truncate text-sm font-medium",
|
|
480
|
-
children: subscription.variant?.product?.title
|
|
481
|
-
})]
|
|
482
|
-
}),
|
|
483
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
484
|
-
className: "text-muted-foreground px-3 py-4 text-sm whitespace-nowrap",
|
|
485
|
-
children: formatNextBillDate(subscription.next_bill_date ?? "")
|
|
486
|
-
}),
|
|
487
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
488
|
-
className: "px-3 py-4 text-sm whitespace-nowrap",
|
|
489
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
490
|
-
className: "text-muted-foreground",
|
|
491
|
-
children: formatCurrency(subscription.price * subscription.quantity)
|
|
492
|
-
})
|
|
493
|
-
}),
|
|
494
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
495
|
-
className: "px-3 py-4 text-sm whitespace-nowrap",
|
|
496
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusPill, {
|
|
497
|
-
status: subscription.status,
|
|
498
|
-
children: startCase(subscription.status) || t("unknown_status")
|
|
499
|
-
})
|
|
500
|
-
})
|
|
501
|
-
]
|
|
502
|
-
}, subscription.subscription_token))
|
|
503
|
-
})
|
|
504
|
-
]
|
|
505
|
-
})
|
|
506
|
-
}),
|
|
507
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.PaginationFooter, {
|
|
508
|
-
currentPage,
|
|
509
|
-
totalPages,
|
|
510
|
-
pageSize,
|
|
511
|
-
totalItems,
|
|
512
|
-
onPageChange: setCurrentPage,
|
|
513
|
-
t
|
|
514
|
-
})
|
|
515
|
-
]
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
//#endregion
|
|
519
|
-
//#region ../../subscriptions/ui/src/screens/SubscriptionsListScreen.tsx
|
|
520
|
-
function SubscriptionsListScreen$1({ customerId, onSubscriptionClick, t, isLoadingCustomer }) {
|
|
521
|
-
require_ScreenHeaderContext.useScreenHeaderBreadcrumbs((0, react.useMemo)(() => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Breadcrumb, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbList, {
|
|
522
|
-
className: "text-lg",
|
|
523
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbPage, {
|
|
524
|
-
className: "font-semibold",
|
|
525
|
-
children: "Subscriptions"
|
|
526
|
-
}) })
|
|
527
|
-
}) }), []));
|
|
528
|
-
if (isLoadingCustomer) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
529
|
-
className: "mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8",
|
|
530
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
531
|
-
className: "space-y-3",
|
|
532
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-10 animate-pulse rounded" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-64 animate-pulse rounded" })]
|
|
533
|
-
})
|
|
534
|
-
});
|
|
535
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
536
|
-
className: "mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8",
|
|
537
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionsList, {
|
|
538
|
-
customerId,
|
|
539
|
-
onSubscriptionClick,
|
|
540
|
-
t
|
|
541
|
-
})
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
//#endregion
|
|
545
209
|
//#region src/adapters/subscriptions-api-adapter.ts
|
|
546
210
|
/**
|
|
547
211
|
* Maps the BFF meta envelope to the port's expected shape.
|
|
@@ -795,43 +459,388 @@ function mapSubscriptionList(response) {
|
|
|
795
459
|
meta: mapMeta(response.meta ?? {})
|
|
796
460
|
};
|
|
797
461
|
}
|
|
798
|
-
/**
|
|
799
|
-
* Creates a SubscriptionsApi-compatible adapter backed by the portal-tenant BFF.
|
|
800
|
-
*
|
|
801
|
-
* Uses async/await with explicit field mapping. The BFF returns simplified
|
|
802
|
-
* subscription types compared to the full admin API; the adapter maps the
|
|
803
|
-
* response envelope and provides runtime defaults for optional fields.
|
|
804
|
-
*/
|
|
805
|
-
function createPortalSubscriptionsAdapter(client) {
|
|
806
|
-
return {
|
|
807
|
-
fetchCustomerSubscriptions: async (params) => {
|
|
808
|
-
return mapSubscriptionList(await require_portal_tenant.subscriptions_list(client, {
|
|
809
|
-
"page[cursor]": params.cursor,
|
|
810
|
-
"page[limit]": params.limit ?? params.perPage
|
|
811
|
-
}));
|
|
812
|
-
},
|
|
813
|
-
fetchSubscription: async (subscriptionToken) => {
|
|
814
|
-
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_show(client, subscriptionToken));
|
|
815
|
-
},
|
|
816
|
-
pauseSubscription: async (subscriptionToken, _params) => {
|
|
817
|
-
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_pause(client, subscriptionToken));
|
|
818
|
-
},
|
|
819
|
-
resumeSubscription: async (subscriptionToken, _params) => {
|
|
820
|
-
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_resume(client, subscriptionToken));
|
|
821
|
-
},
|
|
822
|
-
skipSubscription: async (subscriptionToken, _params) => {
|
|
823
|
-
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_skip(client, subscriptionToken));
|
|
824
|
-
},
|
|
825
|
-
cancelSubscription: async (subscriptionToken, _customerId) => {
|
|
826
|
-
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_cancel(client, subscriptionToken));
|
|
827
|
-
},
|
|
828
|
-
reactivateSubscription: async (subscriptionToken, _params) => {
|
|
829
|
-
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_reactivate(client, subscriptionToken));
|
|
830
|
-
},
|
|
831
|
-
updateSubscriptionInfo: async (subscriptionToken, body) => {
|
|
832
|
-
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_update(client, subscriptionToken, { subscription: { payment_method_id: body.payment_method_id } }));
|
|
833
|
-
}
|
|
834
|
-
};
|
|
462
|
+
/**
|
|
463
|
+
* Creates a SubscriptionsApi-compatible adapter backed by the portal-tenant BFF.
|
|
464
|
+
*
|
|
465
|
+
* Uses async/await with explicit field mapping. The BFF returns simplified
|
|
466
|
+
* subscription types compared to the full admin API; the adapter maps the
|
|
467
|
+
* response envelope and provides runtime defaults for optional fields.
|
|
468
|
+
*/
|
|
469
|
+
function createPortalSubscriptionsAdapter(client) {
|
|
470
|
+
return {
|
|
471
|
+
fetchCustomerSubscriptions: async (params) => {
|
|
472
|
+
return mapSubscriptionList(await require_portal_tenant.subscriptions_list(client, {
|
|
473
|
+
"page[cursor]": params.cursor,
|
|
474
|
+
"page[limit]": params.limit ?? params.perPage
|
|
475
|
+
}));
|
|
476
|
+
},
|
|
477
|
+
fetchSubscription: async (subscriptionToken) => {
|
|
478
|
+
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_show(client, subscriptionToken));
|
|
479
|
+
},
|
|
480
|
+
pauseSubscription: async (subscriptionToken, _params) => {
|
|
481
|
+
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_pause(client, subscriptionToken));
|
|
482
|
+
},
|
|
483
|
+
resumeSubscription: async (subscriptionToken, _params) => {
|
|
484
|
+
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_resume(client, subscriptionToken));
|
|
485
|
+
},
|
|
486
|
+
skipSubscription: async (subscriptionToken, _params) => {
|
|
487
|
+
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_skip(client, subscriptionToken));
|
|
488
|
+
},
|
|
489
|
+
cancelSubscription: async (subscriptionToken, _customerId) => {
|
|
490
|
+
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_cancel(client, subscriptionToken));
|
|
491
|
+
},
|
|
492
|
+
reactivateSubscription: async (subscriptionToken, _params) => {
|
|
493
|
+
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_reactivate(client, subscriptionToken));
|
|
494
|
+
},
|
|
495
|
+
updateSubscriptionInfo: async (subscriptionToken, body) => {
|
|
496
|
+
return mapSubscriptionDetail(await require_portal_tenant.subscriptions_update(client, subscriptionToken, { subscription: { payment_method_id: body.payment_method_id } }));
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
//#endregion
|
|
501
|
+
//#region src/subscriptions/PortalSubscriptionsApiProvider.tsx
|
|
502
|
+
function PortalSubscriptionsApiProvider({ children }) {
|
|
503
|
+
const client = require_PortalTenantClientProvider.usePortalTenantClient();
|
|
504
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionsCoreProvider, {
|
|
505
|
+
api: (0, react.useMemo)(() => createPortalSubscriptionsAdapter(client), [client]),
|
|
506
|
+
children
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region ../../subscriptions/ui/src/lib/format.ts
|
|
511
|
+
/**
|
|
512
|
+
* Format a number as currency (USD).
|
|
513
|
+
*/
|
|
514
|
+
function formatCurrency(value) {
|
|
515
|
+
return new Intl.NumberFormat("en-US", {
|
|
516
|
+
style: "currency",
|
|
517
|
+
currency: "USD"
|
|
518
|
+
}).format(value);
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Convert a snake_case or lowercase string to Start Case.
|
|
522
|
+
* Replaces lodash startCase for simple status strings.
|
|
523
|
+
*/
|
|
524
|
+
function startCase(str) {
|
|
525
|
+
if (!str) return "";
|
|
526
|
+
return str.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Format a next bill date string to M/D/YYYY (UTC).
|
|
530
|
+
*/
|
|
531
|
+
function formatNextBillDate(nextBillDate) {
|
|
532
|
+
if (!nextBillDate) return "N/A";
|
|
533
|
+
const date = new Date(nextBillDate);
|
|
534
|
+
if (isNaN(date.getTime())) return "N/A";
|
|
535
|
+
return `${date.getUTCMonth() + 1}/${date.getUTCDate()}/${date.getUTCFullYear()}`;
|
|
536
|
+
}
|
|
537
|
+
//#endregion
|
|
538
|
+
//#region ../../subscriptions/ui/src/lib/cn.ts
|
|
539
|
+
function cn(...inputs) {
|
|
540
|
+
return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
|
|
541
|
+
}
|
|
542
|
+
//#endregion
|
|
543
|
+
//#region ../../subscriptions/ui/src/components/status-pill.tsx
|
|
544
|
+
const STATUS_COLORS = {
|
|
545
|
+
active: "bg-green-100 text-green-800",
|
|
546
|
+
paused: "bg-gray-100 text-gray-800",
|
|
547
|
+
cancelled: "bg-red-100 text-red-800",
|
|
548
|
+
pending: "bg-yellow-100 text-yellow-800",
|
|
549
|
+
inactive: "bg-gray-100 text-gray-800",
|
|
550
|
+
disabled: "bg-red-100 text-red-800",
|
|
551
|
+
past_due: "bg-gray-100 text-gray-800"
|
|
552
|
+
};
|
|
553
|
+
const STATUS_DOT_COLORS = {
|
|
554
|
+
active: "bg-green-500",
|
|
555
|
+
paused: "bg-gray-400",
|
|
556
|
+
cancelled: "bg-red-500",
|
|
557
|
+
pending: "bg-yellow-500",
|
|
558
|
+
inactive: "bg-gray-400",
|
|
559
|
+
disabled: "bg-red-500",
|
|
560
|
+
past_due: "bg-gray-400"
|
|
561
|
+
};
|
|
562
|
+
function StatusPill({ status, children }) {
|
|
563
|
+
const key = status?.toLowerCase() ?? "";
|
|
564
|
+
const pillColor = STATUS_COLORS[key] ?? "bg-gray-100 text-gray-800";
|
|
565
|
+
const dotColor = STATUS_DOT_COLORS[key] ?? "bg-gray-400";
|
|
566
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
567
|
+
className: cn("inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium", pillColor),
|
|
568
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cn("h-1.5 w-1.5 rounded-full", dotColor) }), children]
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region ../../subscriptions/ui/src/components/subscriptions-list.tsx
|
|
573
|
+
function SubscriptionsList({ customerId, onSubscriptionClick, t, pageSize = 10 }) {
|
|
574
|
+
const [currentPage, setCurrentPage] = (0, react.useState)(1);
|
|
575
|
+
const [statusFilter, setStatusFilter] = (0, react.useState)(null);
|
|
576
|
+
const [search, setSearch] = (0, react.useState)(null);
|
|
577
|
+
const [sortBy, setSortBy] = (0, react.useState)({
|
|
578
|
+
column: "next_bill_date",
|
|
579
|
+
direction: "desc"
|
|
580
|
+
});
|
|
581
|
+
const { data, isLoading } = useSubscriptions({
|
|
582
|
+
customerId: customerId ?? 0,
|
|
583
|
+
page: currentPage,
|
|
584
|
+
perPage: pageSize,
|
|
585
|
+
status: statusFilter,
|
|
586
|
+
search,
|
|
587
|
+
sortBy: sortBy.column,
|
|
588
|
+
sortDirection: sortBy.direction
|
|
589
|
+
}, { enabled: !!customerId });
|
|
590
|
+
(0, react.useEffect)(() => {
|
|
591
|
+
setCurrentPage(1);
|
|
592
|
+
}, [
|
|
593
|
+
statusFilter,
|
|
594
|
+
search,
|
|
595
|
+
sortBy
|
|
596
|
+
]);
|
|
597
|
+
const items = data?.subscriptions ?? [];
|
|
598
|
+
const totalItems = data?.meta?.pagination?.total_count ?? 0;
|
|
599
|
+
const totalPages = data?.meta?.pagination?.total_pages ?? 1;
|
|
600
|
+
const handleSubscriptionClick = (token) => {
|
|
601
|
+
if (token) onSubscriptionClick(token);
|
|
602
|
+
};
|
|
603
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
604
|
+
className: "border-border overflow-hidden rounded-lg border shadow-sm",
|
|
605
|
+
children: [
|
|
606
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
607
|
+
className: "flex flex-col gap-2 p-3 sm:flex-row sm:items-center sm:justify-between",
|
|
608
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.ToggleGroup, {
|
|
609
|
+
type: "single",
|
|
610
|
+
value: statusFilter ?? "all",
|
|
611
|
+
onValueChange: (v) => {
|
|
612
|
+
if (v) setStatusFilter(v === "all" ? null : v);
|
|
613
|
+
},
|
|
614
|
+
variant: "ghost",
|
|
615
|
+
children: [
|
|
616
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ToggleGroupItem, {
|
|
617
|
+
value: "all",
|
|
618
|
+
children: t("all")
|
|
619
|
+
}),
|
|
620
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ToggleGroupItem, {
|
|
621
|
+
value: "active",
|
|
622
|
+
children: t("active")
|
|
623
|
+
}),
|
|
624
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ToggleGroupItem, {
|
|
625
|
+
value: "inactive",
|
|
626
|
+
children: t("inactive")
|
|
627
|
+
})
|
|
628
|
+
]
|
|
629
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
630
|
+
className: "w-full max-w-sm",
|
|
631
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SearchSort.SearchSort, {
|
|
632
|
+
searchValue: search ?? "",
|
|
633
|
+
onSearchChange: (v) => setSearch(v || null),
|
|
634
|
+
placeholder: t("search_subscriptions")
|
|
635
|
+
})
|
|
636
|
+
})]
|
|
637
|
+
}),
|
|
638
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
639
|
+
className: "block md:hidden",
|
|
640
|
+
children: isLoading ? Array(5).fill(0).map((_, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
641
|
+
className: "border-border border-b p-4",
|
|
642
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
643
|
+
className: "flex space-x-3",
|
|
644
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-12 w-12 rounded-md" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
645
|
+
className: "flex-1 space-y-2",
|
|
646
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-3 w-1/2" })]
|
|
647
|
+
})]
|
|
648
|
+
})
|
|
649
|
+
}, `skeleton-${index}`)) : items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
650
|
+
className: "text-muted-foreground px-3 py-8 text-center text-sm",
|
|
651
|
+
children: t("no_subscriptions_found")
|
|
652
|
+
}) : items.map((subscription) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
653
|
+
className: "border-border hover:bg-accent cursor-pointer border-b p-4 transition-colors duration-200 ease-in-out last:border-b-0",
|
|
654
|
+
onClick: () => handleSubscriptionClick(subscription.subscription_token),
|
|
655
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
656
|
+
className: "flex items-start space-x-3",
|
|
657
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
658
|
+
src: subscription.variant?.product?.image_url,
|
|
659
|
+
alt: subscription.variant?.product?.title,
|
|
660
|
+
width: 48,
|
|
661
|
+
height: 48,
|
|
662
|
+
className: "h-12 w-12 flex-shrink-0 rounded-md object-cover"
|
|
663
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
664
|
+
className: "w-0 min-w-0 flex-1",
|
|
665
|
+
children: [
|
|
666
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
667
|
+
className: "text-foreground truncate text-sm font-medium",
|
|
668
|
+
children: subscription.variant?.product?.title
|
|
669
|
+
}),
|
|
670
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
671
|
+
className: "mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-sm",
|
|
672
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
673
|
+
className: "text-muted-foreground block text-xs",
|
|
674
|
+
children: t("next_bill_date")
|
|
675
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
676
|
+
className: "text-muted-foreground",
|
|
677
|
+
children: formatNextBillDate(subscription.next_bill_date ?? "")
|
|
678
|
+
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
679
|
+
className: "text-muted-foreground block text-xs",
|
|
680
|
+
children: t("price")
|
|
681
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
682
|
+
className: "text-foreground font-medium",
|
|
683
|
+
children: formatCurrency(subscription.price * subscription.quantity)
|
|
684
|
+
})] })]
|
|
685
|
+
}),
|
|
686
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
687
|
+
className: "mt-2",
|
|
688
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
689
|
+
className: "text-muted-foreground block text-xs",
|
|
690
|
+
children: t("status")
|
|
691
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusPill, {
|
|
692
|
+
status: subscription.status,
|
|
693
|
+
children: startCase(subscription.status) || t("unknown_status")
|
|
694
|
+
})]
|
|
695
|
+
})
|
|
696
|
+
]
|
|
697
|
+
})]
|
|
698
|
+
})
|
|
699
|
+
}, subscription.subscription_token))
|
|
700
|
+
}),
|
|
701
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
702
|
+
className: "hidden md:block",
|
|
703
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Table, {
|
|
704
|
+
className: "min-w-full table-fixed",
|
|
705
|
+
children: [
|
|
706
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("colgroup", { children: [
|
|
707
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[45%] min-w-[240px]" }),
|
|
708
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[20%] min-w-[100px]" }),
|
|
709
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[15%] min-w-[100px]" }),
|
|
710
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: "w-[20%] min-w-[100px]" })
|
|
711
|
+
] }),
|
|
712
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableHeader, {
|
|
713
|
+
className: "bg-muted",
|
|
714
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableRow, {
|
|
715
|
+
className: "hover:bg-muted h-10",
|
|
716
|
+
children: [
|
|
717
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
718
|
+
label: t("product"),
|
|
719
|
+
sortable: false
|
|
720
|
+
}),
|
|
721
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
722
|
+
label: t("next_bill_date"),
|
|
723
|
+
sortBy: "next_bill_date",
|
|
724
|
+
sortData: sortBy,
|
|
725
|
+
onSortClick: (value) => setSortBy({
|
|
726
|
+
column: value,
|
|
727
|
+
direction: sortBy.direction === "asc" ? "desc" : "asc"
|
|
728
|
+
})
|
|
729
|
+
}),
|
|
730
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
731
|
+
label: t("price"),
|
|
732
|
+
sortable: false
|
|
733
|
+
}),
|
|
734
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.TableColumn, {
|
|
735
|
+
label: t("status"),
|
|
736
|
+
sortable: false
|
|
737
|
+
})
|
|
738
|
+
]
|
|
739
|
+
})
|
|
740
|
+
}),
|
|
741
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableBody, {
|
|
742
|
+
className: "bg-background",
|
|
743
|
+
children: isLoading ? Array(5).fill(0).map((_, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableRow, { children: [
|
|
744
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
745
|
+
className: "px-3 py-4",
|
|
746
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
747
|
+
className: "flex items-center space-x-2",
|
|
748
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-9 w-9 rounded-md" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-32" })]
|
|
749
|
+
})
|
|
750
|
+
}),
|
|
751
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
752
|
+
className: "px-3 py-4",
|
|
753
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-24" })
|
|
754
|
+
}),
|
|
755
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
756
|
+
className: "px-3 py-4",
|
|
757
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-24" })
|
|
758
|
+
}),
|
|
759
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
760
|
+
className: "px-3 py-4",
|
|
761
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Skeleton, { className: "h-4 w-16" })
|
|
762
|
+
})
|
|
763
|
+
] }, `skeleton-${index}`)) : items.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableRow, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
764
|
+
colSpan: 4,
|
|
765
|
+
className: "text-muted-foreground px-3 py-8 text-center text-sm",
|
|
766
|
+
children: t("no_subscriptions_found")
|
|
767
|
+
}) }) : items.map((subscription) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableRow, {
|
|
768
|
+
className: "cursor-pointer",
|
|
769
|
+
onClick: () => handleSubscriptionClick(subscription.subscription_token),
|
|
770
|
+
children: [
|
|
771
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.TableCell, {
|
|
772
|
+
className: "text-muted-foreground flex max-w-[280px] items-center space-x-3 py-4 pr-3 pl-3 text-sm",
|
|
773
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
774
|
+
src: subscription.variant?.product?.image_url,
|
|
775
|
+
alt: subscription.variant?.product?.title,
|
|
776
|
+
width: 48,
|
|
777
|
+
height: 48,
|
|
778
|
+
className: "h-12 w-12 flex-shrink-0 rounded-md object-cover"
|
|
779
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
780
|
+
className: "text-foreground truncate text-sm font-medium",
|
|
781
|
+
children: subscription.variant?.product?.title
|
|
782
|
+
})]
|
|
783
|
+
}),
|
|
784
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
785
|
+
className: "text-muted-foreground px-3 py-4 text-sm whitespace-nowrap",
|
|
786
|
+
children: formatNextBillDate(subscription.next_bill_date ?? "")
|
|
787
|
+
}),
|
|
788
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
789
|
+
className: "px-3 py-4 text-sm whitespace-nowrap",
|
|
790
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
791
|
+
className: "text-muted-foreground",
|
|
792
|
+
children: formatCurrency(subscription.price * subscription.quantity)
|
|
793
|
+
})
|
|
794
|
+
}),
|
|
795
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.TableCell, {
|
|
796
|
+
className: "px-3 py-4 text-sm whitespace-nowrap",
|
|
797
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusPill, {
|
|
798
|
+
status: subscription.status,
|
|
799
|
+
children: startCase(subscription.status) || t("unknown_status")
|
|
800
|
+
})
|
|
801
|
+
})
|
|
802
|
+
]
|
|
803
|
+
}, subscription.subscription_token))
|
|
804
|
+
})
|
|
805
|
+
]
|
|
806
|
+
})
|
|
807
|
+
}),
|
|
808
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_order_status_badge.PaginationFooter, {
|
|
809
|
+
currentPage,
|
|
810
|
+
totalPages,
|
|
811
|
+
pageSize,
|
|
812
|
+
totalItems,
|
|
813
|
+
onPageChange: setCurrentPage,
|
|
814
|
+
t
|
|
815
|
+
})
|
|
816
|
+
]
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
//#endregion
|
|
820
|
+
//#region ../../subscriptions/ui/src/screens/SubscriptionsListScreen.tsx
|
|
821
|
+
function SubscriptionsListScreen$1({ customerId, onSubscriptionClick, t, isLoadingCustomer }) {
|
|
822
|
+
require_ScreenHeaderContext.useScreenHeaderBreadcrumbs((0, react.useMemo)(() => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Breadcrumb, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbList, {
|
|
823
|
+
className: "text-lg",
|
|
824
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbPage, {
|
|
825
|
+
className: "font-semibold",
|
|
826
|
+
children: "Subscriptions"
|
|
827
|
+
}) })
|
|
828
|
+
}) }), []));
|
|
829
|
+
if (isLoadingCustomer) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
830
|
+
className: "mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8",
|
|
831
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
832
|
+
className: "space-y-3",
|
|
833
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-10 animate-pulse rounded" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-64 animate-pulse rounded" })]
|
|
834
|
+
})
|
|
835
|
+
});
|
|
836
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
837
|
+
className: "mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8",
|
|
838
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionsList, {
|
|
839
|
+
customerId,
|
|
840
|
+
onSubscriptionClick,
|
|
841
|
+
t
|
|
842
|
+
})
|
|
843
|
+
});
|
|
835
844
|
}
|
|
836
845
|
//#endregion
|
|
837
846
|
//#region src/screens/SubscriptionsListScreen.tsx
|
|
@@ -854,17 +863,12 @@ const translations = {
|
|
|
854
863
|
pagination: "Pagination"
|
|
855
864
|
};
|
|
856
865
|
function SubscriptionsListScreen({ customerId, isLoadingCustomer }) {
|
|
857
|
-
const client = require_PortalTenantClientProvider.usePortalTenantClient();
|
|
858
|
-
const subscriptionsApi = (0, react.useMemo)(() => createPortalSubscriptionsAdapter(client), [client]);
|
|
859
866
|
const { navigate } = require_AppNavigationContext.useAppNavigation();
|
|
860
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
onSubscriptionClick: (subscriptionToken) => navigate(`subscriptions/${subscriptionToken}`),
|
|
866
|
-
t: (key) => translations[key] ?? key
|
|
867
|
-
})
|
|
867
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionsListScreen$1, {
|
|
868
|
+
customerId,
|
|
869
|
+
isLoadingCustomer,
|
|
870
|
+
onSubscriptionClick: (subscriptionToken) => navigate(`subscriptions/${subscriptionToken}`),
|
|
871
|
+
t: (key) => translations[key] ?? key
|
|
868
872
|
});
|
|
869
873
|
}
|
|
870
874
|
//#endregion
|
|
@@ -1465,28 +1469,23 @@ function SubscriptionDetailScreen$1({ token, onNavigateToList, onNotFound, onErr
|
|
|
1465
1469
|
//#endregion
|
|
1466
1470
|
//#region src/screens/SubscriptionDetailScreen.tsx
|
|
1467
1471
|
function SubscriptionDetailScreen({ token, onToast }) {
|
|
1468
|
-
const client = require_PortalTenantClientProvider.usePortalTenantClient();
|
|
1469
|
-
const subscriptionsApi = (0, react.useMemo)(() => createPortalSubscriptionsAdapter(client), [client]);
|
|
1470
1472
|
const { navigate } = require_AppNavigationContext.useAppNavigation();
|
|
1471
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
onToast(`${message}: ${err instanceof Error ? err.message : "An error occurred"}`, "error");
|
|
1488
|
-
}
|
|
1489
|
-
})
|
|
1473
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionDetailScreen$1, {
|
|
1474
|
+
token,
|
|
1475
|
+
onNavigateToList: () => navigate("subscriptions"),
|
|
1476
|
+
onNotFound: () => {
|
|
1477
|
+
onToast("Subscription not found", "warning");
|
|
1478
|
+
navigate("subscriptions");
|
|
1479
|
+
},
|
|
1480
|
+
onError: (err) => {
|
|
1481
|
+
onToast(`Failed to load subscription: ${err instanceof Error ? err.message : "An error occurred"}`, "error");
|
|
1482
|
+
},
|
|
1483
|
+
onSuccess: (message) => {
|
|
1484
|
+
onToast(message, "success");
|
|
1485
|
+
},
|
|
1486
|
+
onMutationError: (message, err) => {
|
|
1487
|
+
onToast(`${message}: ${err instanceof Error ? err.message : "An error occurred"}`, "error");
|
|
1488
|
+
}
|
|
1490
1489
|
});
|
|
1491
1490
|
}
|
|
1492
1491
|
//#endregion
|
|
@@ -1505,17 +1504,17 @@ function SubscriptionsScreen({ onToast, background, textColor, accentColor, padd
|
|
|
1505
1504
|
const isLoadingCustomer = account === void 0;
|
|
1506
1505
|
if (isDetailView) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1507
1506
|
...divProps,
|
|
1508
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionDetailScreen, {
|
|
1507
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PortalSubscriptionsApiProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionDetailScreen, {
|
|
1509
1508
|
token: detailToken,
|
|
1510
1509
|
onToast: effectiveToast
|
|
1511
|
-
})
|
|
1510
|
+
}) })
|
|
1512
1511
|
});
|
|
1513
1512
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1514
1513
|
...divProps,
|
|
1515
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionsListScreen, {
|
|
1514
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PortalSubscriptionsApiProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubscriptionsListScreen, {
|
|
1516
1515
|
customerId,
|
|
1517
1516
|
isLoadingCustomer
|
|
1518
|
-
})
|
|
1517
|
+
}) })
|
|
1519
1518
|
});
|
|
1520
1519
|
}
|
|
1521
1520
|
const subscriptionsScreenPropertySchema = {
|
|
@@ -1541,4 +1540,4 @@ Object.defineProperty(exports, "subscriptionsScreenPropertySchema", {
|
|
|
1541
1540
|
}
|
|
1542
1541
|
});
|
|
1543
1542
|
|
|
1544
|
-
//# sourceMappingURL=SubscriptionsScreen-
|
|
1543
|
+
//# sourceMappingURL=SubscriptionsScreen-BdGF5OLE.cjs.map
|