@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.
- package/dist/{AppNavigationContext-DrayF_RG.cjs → AppNavigationContext-DAcrNgXZ.cjs} +1 -1
- package/dist/{AppNavigationContext-DrayF_RG.cjs.map → AppNavigationContext-DAcrNgXZ.cjs.map} +1 -1
- package/dist/{AppNavigationContext-2nkMoO8F.mjs → AppNavigationContext-v_y8OYHo.mjs} +1 -1
- package/dist/{AppNavigationContext-2nkMoO8F.mjs.map → AppNavigationContext-v_y8OYHo.mjs.map} +1 -1
- package/dist/{ContactsScreen-GPOgZ-Wi.cjs → ContactsScreen-BL5Jlaz5.cjs} +2 -2
- package/dist/{ContactsScreen-GPOgZ-Wi.cjs.map → ContactsScreen-BL5Jlaz5.cjs.map} +1 -1
- package/dist/{ContactsScreen-BicHZ37M.mjs → ContactsScreen-CcNUC8xu.mjs} +2 -2
- package/dist/{ContactsScreen-BicHZ37M.mjs.map → ContactsScreen-CcNUC8xu.mjs.map} +1 -1
- package/dist/{CoreScreenPlaceholder-Cl_zuOBC.cjs → CoreScreenPlaceholder-B64M78iR.cjs} +1 -1
- package/dist/{CoreScreenPlaceholder-Cl_zuOBC.cjs.map → CoreScreenPlaceholder-B64M78iR.cjs.map} +1 -1
- package/dist/{CoreScreenPlaceholder-Cdyl97Wo.mjs → CoreScreenPlaceholder-DVVLc-OM.mjs} +1 -1
- package/dist/{CoreScreenPlaceholder-Cdyl97Wo.mjs.map → CoreScreenPlaceholder-DVVLc-OM.mjs.map} +1 -1
- package/dist/{CustomersScreen-Brz5zLkq.mjs → CustomersScreen-SuHGSUdb.mjs} +2 -2
- package/dist/{CustomersScreen-Brz5zLkq.mjs.map → CustomersScreen-SuHGSUdb.mjs.map} +1 -1
- package/dist/{CustomersScreen-CK1jJhvM.cjs → CustomersScreen-zl_vRzcJ.cjs} +2 -2
- package/dist/{CustomersScreen-CK1jJhvM.cjs.map → CustomersScreen-zl_vRzcJ.cjs.map} +1 -1
- package/dist/{MessagingScreen-DVU3c8fX.mjs → MessagingScreen-BGzfLD8k.mjs} +2 -2
- package/dist/{MessagingScreen-sAWF7pjl.cjs → MessagingScreen-CRLd91tP.cjs} +2 -2
- package/dist/{MessagingScreen-sAWF7pjl.cjs.map → MessagingScreen-CRLd91tP.cjs.map} +1 -1
- package/dist/{MessagingScreen-C33eDdna.cjs → MessagingScreen-DIZ72Tg0.cjs} +2 -2
- package/dist/{MessagingScreen-II_iNqLk.mjs → MessagingScreen-We1B2pka.mjs} +2 -2
- package/dist/{MessagingScreen-II_iNqLk.mjs.map → MessagingScreen-We1B2pka.mjs.map} +1 -1
- package/dist/OrdersScreen-Bu-ENmH6.cjs +133 -0
- package/dist/OrdersScreen-Bu-ENmH6.cjs.map +1 -0
- package/dist/OrdersScreen-TSXDDHZe.cjs +33 -0
- package/dist/OrdersScreen-afRAHf07.mjs +126 -0
- package/dist/OrdersScreen-afRAHf07.mjs.map +1 -0
- package/dist/{ProductsScreen-DrrBYFl0.mjs → ProductsScreen-B-oWUzvD.mjs} +3 -3
- package/dist/{ProductsScreen-BOngRxSO.mjs → ProductsScreen-ChvK61hX.mjs} +3 -3
- package/dist/{ProductsScreen-BOngRxSO.mjs.map → ProductsScreen-ChvK61hX.mjs.map} +1 -1
- package/dist/{ProductsScreen-DzD-TPh5.cjs → ProductsScreen-CkE2nyuw.cjs} +3 -3
- package/dist/{ProductsScreen-DzD-TPh5.cjs.map → ProductsScreen-CkE2nyuw.cjs.map} +1 -1
- package/dist/{ProductsScreen-CdP_m_Ok.cjs → ProductsScreen-PCg91SbX.cjs} +3 -3
- package/dist/ProfileScreen-B6Dp7RLa.cjs +2856 -0
- package/dist/ProfileScreen-B6Dp7RLa.cjs.map +1 -0
- package/dist/ProfileScreen-B83tzedh.mjs +2849 -0
- package/dist/ProfileScreen-B83tzedh.mjs.map +1 -0
- package/dist/{AccountScreen-Vzz8W4Iq.cjs → ProfileScreen-CH3B-IQz.cjs} +3 -3
- package/dist/{ShareablesScreen-DYPJgZ3z.cjs → ShareablesScreen-Bqj6dtOM.cjs} +3 -3
- package/dist/{ShareablesScreen-DYPJgZ3z.cjs.map → ShareablesScreen-Bqj6dtOM.cjs.map} +1 -1
- package/dist/{ShareablesScreen-jHqLmOC6.cjs → ShareablesScreen-BvJIBZvI.cjs} +3 -3
- package/dist/{ShareablesScreen-CQy39TAK.mjs → ShareablesScreen-ChS517hq.mjs} +3 -3
- package/dist/{ShareablesScreen-CQy39TAK.mjs.map → ShareablesScreen-ChS517hq.mjs.map} +1 -1
- package/dist/{ShareablesScreen-BsqZvRSK.mjs → ShareablesScreen-CqVj81Ol.mjs} +3 -3
- package/dist/{ShopScreen-BPCwix1m.cjs → ShopScreen-CjoTGnCJ.cjs} +2 -2
- package/dist/{ShopScreen-BPCwix1m.cjs.map → ShopScreen-CjoTGnCJ.cjs.map} +1 -1
- package/dist/{ShopScreen--pUsiUNt.cjs → ShopScreen-DS4p47Ry.cjs} +1 -1
- package/dist/{ShopScreen-BKBzgkr7.mjs → ShopScreen-KeU6x3PT.mjs} +2 -2
- package/dist/{ShopScreen-BKBzgkr7.mjs.map → ShopScreen-KeU6x3PT.mjs.map} +1 -1
- package/dist/SubscriptionsScreen-CHn_Q0zf.cjs +1288 -0
- package/dist/SubscriptionsScreen-CHn_Q0zf.cjs.map +1 -0
- package/dist/SubscriptionsScreen-D5_eJwBP.mjs +1281 -0
- package/dist/SubscriptionsScreen-D5_eJwBP.mjs.map +1 -0
- package/dist/SubscriptionsScreen-DGJ_YeX3.cjs +33 -0
- package/dist/{es-kNOrmozy.cjs → es-BtechuHV.cjs} +1 -1
- package/dist/{es-kNOrmozy.cjs.map → es-BtechuHV.cjs.map} +1 -1
- package/dist/{es-BL8VBBDa.mjs → es-DxWiENwN.mjs} +1 -1
- package/dist/{es-BL8VBBDa.mjs.map → es-DxWiENwN.mjs.map} +1 -1
- package/dist/index.cjs +166 -94
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -8
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +38 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +162 -92
- package/dist/index.mjs.map +1 -1
- package/dist/src-BZEkCfd4.mjs +973 -0
- package/dist/src-BZEkCfd4.mjs.map +1 -0
- package/dist/src-DXC-Jw6i.cjs +1009 -0
- package/dist/src-DXC-Jw6i.cjs.map +1 -0
- package/dist/{src-DMjlIMO9.cjs → src-vxm9rMYT.cjs} +2 -2
- package/dist/{src-DMjlIMO9.cjs.map → src-vxm9rMYT.cjs.map} +1 -1
- package/dist/{src-9pW9wS5O.mjs → src-wpQFW94i.mjs} +2 -2
- package/dist/{src-9pW9wS5O.mjs.map → src-wpQFW94i.mjs.map} +1 -1
- package/dist/use-account-clients-DYTyFvdN.mjs +134 -0
- package/dist/use-account-clients-DYTyFvdN.mjs.map +1 -0
- package/dist/use-account-clients-n2a8bdSP.cjs +182 -0
- package/dist/use-account-clients-n2a8bdSP.cjs.map +1 -0
- package/package.json +10 -10
- package/dist/AccountScreen-Dp6QFyEr.cjs +0 -5322
- package/dist/AccountScreen-Dp6QFyEr.cjs.map +0 -1
- package/dist/AccountScreen-E4ZBgOUS.mjs +0 -5309
- package/dist/AccountScreen-E4ZBgOUS.mjs.map +0 -1
- package/dist/OrdersScreen-DGt-CTBS.mjs +0 -24
- package/dist/OrdersScreen-DGt-CTBS.mjs.map +0 -1
- package/dist/OrdersScreen-Dy-JChVQ.cjs +0 -41
- package/dist/OrdersScreen-Dy-JChVQ.cjs.map +0 -1
|
@@ -0,0 +1,1281 @@
|
|
|
1
|
+
import { n as __exportAll } from "./chunk-ByhMGyNw.mjs";
|
|
2
|
+
import { Ft as AlertDialogDescription, It as AlertDialogFooter, Lt as AlertDialogHeader, Mt as AlertDialogAction, Nt as AlertDialogCancel, Pt as AlertDialogContent, Rt as AlertDialogTitle, jt as AlertDialog, u as Skeleton, y as Input, zt as Button } from "./src-PSNQSAUF.mjs";
|
|
3
|
+
import { a as useSubscriptionsClient$1 } from "./use-account-clients-DYTyFvdN.mjs";
|
|
4
|
+
import { i as PaginationFooter, o as useCustomerAccount, r as TableColumn } from "./src-BZEkCfd4.mjs";
|
|
5
|
+
import { n as useAppNavigation } from "./AppNavigationContext-v_y8OYHo.mjs";
|
|
6
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
7
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Pause, Play, RotateCcw, Search, SkipForward, XCircle } from "lucide-react";
|
|
10
|
+
import { clsx } from "clsx";
|
|
11
|
+
import { twMerge } from "tailwind-merge";
|
|
12
|
+
//#region ../../subscriptions/api-client/src/namespaces/subscriptions.ts
|
|
13
|
+
/**
|
|
14
|
+
* Fetch a paginated list of customer subscriptions.
|
|
15
|
+
* Endpoint: GET /subscriptions
|
|
16
|
+
*/
|
|
17
|
+
async function fetchCustomerSubscriptions(client, params) {
|
|
18
|
+
const input = {
|
|
19
|
+
customer_id: params.customerId.toString(),
|
|
20
|
+
page: (params.page ?? 1).toString(),
|
|
21
|
+
per_page: (params.perPage ?? 10).toString()
|
|
22
|
+
};
|
|
23
|
+
if (params.status != null) input.status = params.status;
|
|
24
|
+
if (params.search != null) input.search = params.search;
|
|
25
|
+
if (params.sortBy != null) input.sort_by = params.sortBy;
|
|
26
|
+
if (params.sortDirection != null) input.sort_direction = params.sortDirection;
|
|
27
|
+
return client.get("/subscriptions", input);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetch a single subscription by token.
|
|
31
|
+
* Endpoint: GET /subscriptions/{token}
|
|
32
|
+
*/
|
|
33
|
+
async function fetchSubscription(client, subscriptionToken) {
|
|
34
|
+
return client.get(`/subscriptions/${subscriptionToken}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Pause a subscription.
|
|
38
|
+
* Endpoint: POST /subscriptions/{token}/pause
|
|
39
|
+
*/
|
|
40
|
+
async function pauseSubscription(client, subscriptionToken, params) {
|
|
41
|
+
const queryParams = { customer_id: params.customerId.toString() };
|
|
42
|
+
if (params.nextBillDate != null) queryParams.next_bill_date = params.nextBillDate;
|
|
43
|
+
if (params.numberOfOrders != null) queryParams.number_of_orders = params.numberOfOrders.toString();
|
|
44
|
+
const query = new URLSearchParams(queryParams).toString();
|
|
45
|
+
return client.post(`/subscriptions/${subscriptionToken}/pause?${query}`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resume a paused subscription.
|
|
49
|
+
* Endpoint: POST /subscriptions/{token}/resume
|
|
50
|
+
*/
|
|
51
|
+
async function resumeSubscription(client, subscriptionToken, params) {
|
|
52
|
+
const query = new URLSearchParams({
|
|
53
|
+
customer_id: params.customerId.toString(),
|
|
54
|
+
next_bill_date: params.nextBillDate
|
|
55
|
+
}).toString();
|
|
56
|
+
return client.post(`/subscriptions/${subscriptionToken}/resume?${query}`);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Skip the next billing cycle.
|
|
60
|
+
* Endpoint: POST /subscriptions/{token}/skip_next_billing
|
|
61
|
+
*/
|
|
62
|
+
async function skipSubscription(client, subscriptionToken, params) {
|
|
63
|
+
const query = new URLSearchParams({
|
|
64
|
+
customer_id: params.customerId.toString(),
|
|
65
|
+
next_bill_date: params.nextBillDate
|
|
66
|
+
}).toString();
|
|
67
|
+
return client.post(`/subscriptions/${subscriptionToken}/skip_next_billing?${query}`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Cancel a subscription.
|
|
71
|
+
* Endpoint: POST /subscriptions/{token}/cancel
|
|
72
|
+
*/
|
|
73
|
+
async function cancelSubscription(client, subscriptionToken, customerId) {
|
|
74
|
+
const query = new URLSearchParams({ customer_id: customerId.toString() }).toString();
|
|
75
|
+
return client.post(`/subscriptions/${subscriptionToken}/cancel?${query}`);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Reactivate a cancelled subscription.
|
|
79
|
+
* Endpoint: POST /subscriptions/{token}/reactivate
|
|
80
|
+
*/
|
|
81
|
+
async function reactivateSubscription(client, subscriptionToken, params) {
|
|
82
|
+
const body = params.process_immediately === true ? { process_immediately: true } : params.next_bill_date ? { next_bill_date: params.next_bill_date } : {};
|
|
83
|
+
return client.post(`/subscriptions/${subscriptionToken}/reactivate`, Object.keys(body).length > 0 ? body : void 0);
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region ../../subscriptions/core/src/context.ts
|
|
87
|
+
const SubscriptionsClientContext = createContext(null);
|
|
88
|
+
const SubscriptionsClientProvider = SubscriptionsClientContext.Provider;
|
|
89
|
+
function useSubscriptionsClient() {
|
|
90
|
+
const client = useContext(SubscriptionsClientContext);
|
|
91
|
+
if (!client) throw new Error("useSubscriptionsClient must be used within a SubscriptionsCoreProvider");
|
|
92
|
+
return client;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region ../../subscriptions/core/src/provider.tsx
|
|
96
|
+
function SubscriptionsCoreProvider({ client, children }) {
|
|
97
|
+
return /* @__PURE__ */ jsx(SubscriptionsClientProvider, {
|
|
98
|
+
value: client,
|
|
99
|
+
children
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region ../../subscriptions/core/src/query-keys.ts
|
|
104
|
+
const subscriptionsKeys = {
|
|
105
|
+
all: ["subscriptions"],
|
|
106
|
+
list: (params) => [
|
|
107
|
+
...subscriptionsKeys.all,
|
|
108
|
+
"list",
|
|
109
|
+
params
|
|
110
|
+
],
|
|
111
|
+
detail: (token) => [
|
|
112
|
+
...subscriptionsKeys.all,
|
|
113
|
+
"detail",
|
|
114
|
+
token
|
|
115
|
+
]
|
|
116
|
+
};
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region ../../subscriptions/core/src/hooks/use-subscriptions.ts
|
|
119
|
+
function useSubscriptions(params, options) {
|
|
120
|
+
const client = useSubscriptionsClient();
|
|
121
|
+
return useQuery({
|
|
122
|
+
queryKey: subscriptionsKeys.list(params),
|
|
123
|
+
queryFn: () => fetchCustomerSubscriptions(client, params),
|
|
124
|
+
enabled: options?.enabled ?? !!params.customerId
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region ../../subscriptions/core/src/hooks/use-subscription.ts
|
|
129
|
+
function useSubscription(token, options) {
|
|
130
|
+
const client = useSubscriptionsClient();
|
|
131
|
+
return useQuery({
|
|
132
|
+
queryKey: subscriptionsKeys.detail(token),
|
|
133
|
+
queryFn: () => fetchSubscription(client, token),
|
|
134
|
+
enabled: (options?.enabled ?? true) && !!token
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region ../../subscriptions/core/src/hooks/use-pause-subscription.ts
|
|
139
|
+
function usePauseSubscription(options) {
|
|
140
|
+
const client = useSubscriptionsClient();
|
|
141
|
+
const queryClient = useQueryClient();
|
|
142
|
+
return useMutation({
|
|
143
|
+
mutationFn: (params) => pauseSubscription(client, params.subscriptionToken, params.pauseParams),
|
|
144
|
+
onSuccess: () => {
|
|
145
|
+
queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });
|
|
146
|
+
options?.onSuccess?.();
|
|
147
|
+
},
|
|
148
|
+
onError: options?.onError
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region ../../subscriptions/core/src/hooks/use-resume-subscription.ts
|
|
153
|
+
function useResumeSubscription(options) {
|
|
154
|
+
const client = useSubscriptionsClient();
|
|
155
|
+
const queryClient = useQueryClient();
|
|
156
|
+
return useMutation({
|
|
157
|
+
mutationFn: (params) => resumeSubscription(client, params.subscriptionToken, params.resumeParams),
|
|
158
|
+
onSuccess: () => {
|
|
159
|
+
queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });
|
|
160
|
+
options?.onSuccess?.();
|
|
161
|
+
},
|
|
162
|
+
onError: options?.onError
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region ../../subscriptions/core/src/hooks/use-skip-subscription.ts
|
|
167
|
+
function useSkipSubscription(options) {
|
|
168
|
+
const client = useSubscriptionsClient();
|
|
169
|
+
const queryClient = useQueryClient();
|
|
170
|
+
return useMutation({
|
|
171
|
+
mutationFn: (params) => skipSubscription(client, params.subscriptionToken, params.skipParams),
|
|
172
|
+
onSuccess: () => {
|
|
173
|
+
queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });
|
|
174
|
+
options?.onSuccess?.();
|
|
175
|
+
},
|
|
176
|
+
onError: options?.onError
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region ../../subscriptions/core/src/hooks/use-cancel-subscription.ts
|
|
181
|
+
function useCancelSubscription(options) {
|
|
182
|
+
const client = useSubscriptionsClient();
|
|
183
|
+
const queryClient = useQueryClient();
|
|
184
|
+
return useMutation({
|
|
185
|
+
mutationFn: (params) => cancelSubscription(client, params.subscriptionToken, params.customerId),
|
|
186
|
+
onSuccess: () => {
|
|
187
|
+
queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });
|
|
188
|
+
options?.onSuccess?.();
|
|
189
|
+
},
|
|
190
|
+
onError: options?.onError
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region ../../subscriptions/core/src/hooks/use-reactivate-subscription.ts
|
|
195
|
+
function useReactivateSubscription(options) {
|
|
196
|
+
const client = useSubscriptionsClient();
|
|
197
|
+
const queryClient = useQueryClient();
|
|
198
|
+
return useMutation({
|
|
199
|
+
mutationFn: (params) => reactivateSubscription(client, params.subscriptionToken, params.reactivateParams),
|
|
200
|
+
onSuccess: () => {
|
|
201
|
+
queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });
|
|
202
|
+
options?.onSuccess?.();
|
|
203
|
+
},
|
|
204
|
+
onError: options?.onError
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region ../../subscriptions/core/src/utils/subscription-helpers.ts
|
|
209
|
+
function formatSubscriptionFrequency(frequency) {
|
|
210
|
+
if (frequency === "day") return "Daily";
|
|
211
|
+
if (frequency === "week") return "Weekly";
|
|
212
|
+
if (frequency === "month") return "Monthly";
|
|
213
|
+
if (frequency === "year") return "Yearly";
|
|
214
|
+
return frequency;
|
|
215
|
+
}
|
|
216
|
+
function calculateNextBillDate(billingInterval = 1, billingIntervalUnit = "month") {
|
|
217
|
+
const now = /* @__PURE__ */ new Date();
|
|
218
|
+
const nextBillDate = new Date(now);
|
|
219
|
+
switch (billingIntervalUnit.toLowerCase()) {
|
|
220
|
+
case "day":
|
|
221
|
+
nextBillDate.setDate(now.getDate() + billingInterval);
|
|
222
|
+
break;
|
|
223
|
+
case "week":
|
|
224
|
+
nextBillDate.setDate(now.getDate() + billingInterval * 7);
|
|
225
|
+
break;
|
|
226
|
+
case "month":
|
|
227
|
+
nextBillDate.setMonth(now.getMonth() + billingInterval);
|
|
228
|
+
break;
|
|
229
|
+
case "year":
|
|
230
|
+
nextBillDate.setFullYear(now.getFullYear() + billingInterval);
|
|
231
|
+
break;
|
|
232
|
+
default: nextBillDate.setMonth(now.getMonth() + billingInterval);
|
|
233
|
+
}
|
|
234
|
+
return nextBillDate.toISOString().split("T")[0] || "";
|
|
235
|
+
}
|
|
236
|
+
function formatDate(dateString, isCancelled = false) {
|
|
237
|
+
if (isCancelled) return "Cancelled";
|
|
238
|
+
if (!dateString) return "Paused";
|
|
239
|
+
const parts = dateString.split("-");
|
|
240
|
+
if (parts.length !== 3) return "Invalid date";
|
|
241
|
+
const [year, month, day] = parts.map(Number);
|
|
242
|
+
if (!year || !month || !day) return "Invalid date";
|
|
243
|
+
const date = new Date(year, month - 1, day);
|
|
244
|
+
const monthNames = [
|
|
245
|
+
"January",
|
|
246
|
+
"February",
|
|
247
|
+
"March",
|
|
248
|
+
"April",
|
|
249
|
+
"May",
|
|
250
|
+
"June",
|
|
251
|
+
"July",
|
|
252
|
+
"August",
|
|
253
|
+
"September",
|
|
254
|
+
"October",
|
|
255
|
+
"November",
|
|
256
|
+
"December"
|
|
257
|
+
];
|
|
258
|
+
const dayNum = date.getDate();
|
|
259
|
+
const monthName = monthNames[date.getMonth()];
|
|
260
|
+
const yearNum = date.getFullYear();
|
|
261
|
+
const ordinalSuffix = (d) => {
|
|
262
|
+
if (d > 3 && d < 21) return "th";
|
|
263
|
+
switch (d % 10) {
|
|
264
|
+
case 1: return "st";
|
|
265
|
+
case 2: return "nd";
|
|
266
|
+
case 3: return "rd";
|
|
267
|
+
default: return "th";
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
return `${monthName} ${dayNum}${ordinalSuffix(dayNum)}, ${yearNum}`;
|
|
271
|
+
}
|
|
272
|
+
function getNextBillDisplay(subscription) {
|
|
273
|
+
if (subscription?.status === "cancelled") return "Cancelled";
|
|
274
|
+
if (subscription?.next_bill_date) return formatDate(subscription.next_bill_date);
|
|
275
|
+
if (subscription?.status === "paused") return "Paused";
|
|
276
|
+
return "N/A";
|
|
277
|
+
}
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region ../../subscriptions/ui/src/lib/cn.ts
|
|
280
|
+
function cn(...inputs) {
|
|
281
|
+
return twMerge(clsx(inputs));
|
|
282
|
+
}
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region ../../subscriptions/ui/src/lib/format.ts
|
|
285
|
+
/**
|
|
286
|
+
* Format a number as currency (USD).
|
|
287
|
+
*/
|
|
288
|
+
function formatCurrency(value) {
|
|
289
|
+
return new Intl.NumberFormat("en-US", {
|
|
290
|
+
style: "currency",
|
|
291
|
+
currency: "USD"
|
|
292
|
+
}).format(value);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Convert a snake_case or lowercase string to Start Case.
|
|
296
|
+
* Replaces lodash startCase for simple status strings.
|
|
297
|
+
*/
|
|
298
|
+
function startCase(str) {
|
|
299
|
+
if (!str) return "";
|
|
300
|
+
return str.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Format a next bill date string to M/D/YYYY (UTC).
|
|
304
|
+
*/
|
|
305
|
+
function formatNextBillDate(nextBillDate) {
|
|
306
|
+
if (!nextBillDate) return "N/A";
|
|
307
|
+
const date = new Date(nextBillDate);
|
|
308
|
+
if (isNaN(date.getTime())) return "N/A";
|
|
309
|
+
return `${date.getUTCMonth() + 1}/${date.getUTCDate()}/${date.getUTCFullYear()}`;
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
312
|
+
//#region ../../subscriptions/ui/src/components/status-pill.tsx
|
|
313
|
+
const STATUS_COLORS = {
|
|
314
|
+
active: "bg-green-100 text-green-800",
|
|
315
|
+
paused: "bg-gray-100 text-gray-800",
|
|
316
|
+
cancelled: "bg-red-100 text-red-800",
|
|
317
|
+
pending: "bg-yellow-100 text-yellow-800",
|
|
318
|
+
inactive: "bg-gray-100 text-gray-800",
|
|
319
|
+
disabled: "bg-red-100 text-red-800",
|
|
320
|
+
past_due: "bg-gray-100 text-gray-800"
|
|
321
|
+
};
|
|
322
|
+
const STATUS_DOT_COLORS = {
|
|
323
|
+
active: "bg-green-500",
|
|
324
|
+
paused: "bg-gray-400",
|
|
325
|
+
cancelled: "bg-red-500",
|
|
326
|
+
pending: "bg-yellow-500",
|
|
327
|
+
inactive: "bg-gray-400",
|
|
328
|
+
disabled: "bg-red-500",
|
|
329
|
+
past_due: "bg-gray-400"
|
|
330
|
+
};
|
|
331
|
+
function StatusPill({ status, children }) {
|
|
332
|
+
const key = status?.toLowerCase() ?? "";
|
|
333
|
+
const pillColor = STATUS_COLORS[key] ?? "bg-gray-100 text-gray-800";
|
|
334
|
+
const dotColor = STATUS_DOT_COLORS[key] ?? "bg-gray-400";
|
|
335
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
336
|
+
className: cn("inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium", pillColor),
|
|
337
|
+
children: [/* @__PURE__ */ jsx("span", { className: cn("h-1.5 w-1.5 rounded-full", dotColor) }), children]
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
//#endregion
|
|
341
|
+
//#region ../../subscriptions/ui/src/components/subscriptions-list.tsx
|
|
342
|
+
function SubscriptionsList({ customerId, onSubscriptionClick, t, pageSize = 10 }) {
|
|
343
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
344
|
+
const [statusFilter, setStatusFilter] = useState(null);
|
|
345
|
+
const [search, setSearch] = useState(null);
|
|
346
|
+
const [sortBy, setSortBy] = useState({
|
|
347
|
+
column: "next_bill_date",
|
|
348
|
+
direction: "desc"
|
|
349
|
+
});
|
|
350
|
+
const { data, isLoading } = useSubscriptions({
|
|
351
|
+
customerId: customerId ?? 0,
|
|
352
|
+
page: currentPage,
|
|
353
|
+
perPage: pageSize,
|
|
354
|
+
status: statusFilter,
|
|
355
|
+
search,
|
|
356
|
+
sortBy: sortBy.column,
|
|
357
|
+
sortDirection: sortBy.direction
|
|
358
|
+
}, { enabled: !!customerId });
|
|
359
|
+
useEffect(() => {
|
|
360
|
+
setCurrentPage(1);
|
|
361
|
+
}, [
|
|
362
|
+
statusFilter,
|
|
363
|
+
search,
|
|
364
|
+
sortBy
|
|
365
|
+
]);
|
|
366
|
+
const items = data?.subscriptions ?? [];
|
|
367
|
+
const totalItems = data?.meta?.pagination?.total_count ?? 0;
|
|
368
|
+
const totalPages = data?.meta?.pagination?.total_pages ?? 1;
|
|
369
|
+
const handleSubscriptionClick = (token) => {
|
|
370
|
+
if (token) onSubscriptionClick(token);
|
|
371
|
+
};
|
|
372
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
373
|
+
className: "border-border overflow-hidden rounded-lg border shadow-sm",
|
|
374
|
+
children: [
|
|
375
|
+
/* @__PURE__ */ jsxs("div", {
|
|
376
|
+
className: "flex flex-col gap-2 p-3 sm:flex-row sm:items-center sm:justify-between",
|
|
377
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
378
|
+
className: "flex gap-1",
|
|
379
|
+
children: [
|
|
380
|
+
/* @__PURE__ */ jsx(Button, {
|
|
381
|
+
variant: "ghost",
|
|
382
|
+
size: "sm",
|
|
383
|
+
onClick: () => setStatusFilter(null),
|
|
384
|
+
className: cn("rounded-md text-xs", statusFilter === null && "bg-muted-foreground font-bold"),
|
|
385
|
+
children: t("all")
|
|
386
|
+
}),
|
|
387
|
+
/* @__PURE__ */ jsx(Button, {
|
|
388
|
+
variant: "ghost",
|
|
389
|
+
size: "sm",
|
|
390
|
+
onClick: () => setStatusFilter("active"),
|
|
391
|
+
className: cn("rounded-md text-xs", statusFilter === "active" && "bg-muted-foreground font-bold"),
|
|
392
|
+
children: t("active")
|
|
393
|
+
}),
|
|
394
|
+
/* @__PURE__ */ jsx(Button, {
|
|
395
|
+
variant: "ghost",
|
|
396
|
+
size: "sm",
|
|
397
|
+
onClick: () => setStatusFilter("inactive"),
|
|
398
|
+
className: cn("rounded-md text-xs", statusFilter === "inactive" && "bg-muted-foreground font-bold"),
|
|
399
|
+
children: t("inactive")
|
|
400
|
+
})
|
|
401
|
+
]
|
|
402
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
403
|
+
className: "relative w-full sm:w-auto sm:min-w-[220px]",
|
|
404
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
405
|
+
className: "pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3",
|
|
406
|
+
children: /* @__PURE__ */ jsx(Search, { className: "text-muted-foreground h-4 w-4" })
|
|
407
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
408
|
+
type: "search",
|
|
409
|
+
value: search ?? "",
|
|
410
|
+
onChange: (e) => setSearch(e.target.value || null),
|
|
411
|
+
className: "h-10 w-full pl-10",
|
|
412
|
+
placeholder: t("subscriptions")
|
|
413
|
+
})]
|
|
414
|
+
})]
|
|
415
|
+
}),
|
|
416
|
+
/* @__PURE__ */ jsx("div", {
|
|
417
|
+
className: "block md:hidden",
|
|
418
|
+
children: isLoading ? Array(5).fill(0).map((_, index) => /* @__PURE__ */ jsx("div", {
|
|
419
|
+
className: "border-border border-b p-4",
|
|
420
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
421
|
+
className: "flex space-x-3",
|
|
422
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-12 rounded-md" }), /* @__PURE__ */ jsxs("div", {
|
|
423
|
+
className: "flex-1 space-y-2",
|
|
424
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-1/2" })]
|
|
425
|
+
})]
|
|
426
|
+
})
|
|
427
|
+
}, `skeleton-${index}`)) : items.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
428
|
+
className: "text-muted-foreground px-3 py-8 text-center text-sm",
|
|
429
|
+
children: t("no_subscriptions_found")
|
|
430
|
+
}) : items.map((subscription) => /* @__PURE__ */ jsx("div", {
|
|
431
|
+
className: "border-border hover:bg-accent cursor-pointer border-b p-4 transition-colors duration-200 ease-in-out last:border-b-0",
|
|
432
|
+
onClick: () => handleSubscriptionClick(subscription.subscription_token),
|
|
433
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
434
|
+
className: "flex items-start space-x-3",
|
|
435
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
436
|
+
src: subscription.variant?.product?.image_url,
|
|
437
|
+
alt: subscription.variant?.product?.title,
|
|
438
|
+
width: 48,
|
|
439
|
+
height: 48,
|
|
440
|
+
className: "h-12 w-12 flex-shrink-0 rounded-md object-cover"
|
|
441
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
442
|
+
className: "w-0 min-w-0 flex-1",
|
|
443
|
+
children: [
|
|
444
|
+
/* @__PURE__ */ jsx("p", {
|
|
445
|
+
className: "text-foreground truncate text-sm font-medium",
|
|
446
|
+
children: subscription.variant?.product?.title
|
|
447
|
+
}),
|
|
448
|
+
/* @__PURE__ */ jsxs("div", {
|
|
449
|
+
className: "mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-sm",
|
|
450
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", {
|
|
451
|
+
className: "text-muted-foreground block text-xs",
|
|
452
|
+
children: t("next_bill_date")
|
|
453
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
454
|
+
className: "text-muted-foreground",
|
|
455
|
+
children: formatNextBillDate(subscription.next_bill_date ?? "")
|
|
456
|
+
})] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", {
|
|
457
|
+
className: "text-muted-foreground block text-xs",
|
|
458
|
+
children: t("price")
|
|
459
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
460
|
+
className: "text-foreground font-medium",
|
|
461
|
+
children: formatCurrency(subscription.price * subscription.quantity)
|
|
462
|
+
})] })]
|
|
463
|
+
}),
|
|
464
|
+
/* @__PURE__ */ jsxs("div", {
|
|
465
|
+
className: "mt-2",
|
|
466
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
467
|
+
className: "text-muted-foreground block text-xs",
|
|
468
|
+
children: t("status")
|
|
469
|
+
}), /* @__PURE__ */ jsx(StatusPill, {
|
|
470
|
+
status: subscription.status,
|
|
471
|
+
children: startCase(subscription.status) || t("unknown_status")
|
|
472
|
+
})]
|
|
473
|
+
})
|
|
474
|
+
]
|
|
475
|
+
})]
|
|
476
|
+
})
|
|
477
|
+
}, subscription.subscription_token))
|
|
478
|
+
}),
|
|
479
|
+
/* @__PURE__ */ jsx("div", {
|
|
480
|
+
className: "hidden overflow-x-auto md:block",
|
|
481
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
482
|
+
className: "min-w-full table-fixed",
|
|
483
|
+
children: [
|
|
484
|
+
/* @__PURE__ */ jsxs("colgroup", { children: [
|
|
485
|
+
/* @__PURE__ */ jsx("col", { className: "w-[45%] min-w-[240px]" }),
|
|
486
|
+
/* @__PURE__ */ jsx("col", { className: "w-[20%] min-w-[100px]" }),
|
|
487
|
+
/* @__PURE__ */ jsx("col", { className: "w-[15%] min-w-[100px]" }),
|
|
488
|
+
/* @__PURE__ */ jsx("col", { className: "w-[20%] min-w-[100px]" })
|
|
489
|
+
] }),
|
|
490
|
+
/* @__PURE__ */ jsx("thead", {
|
|
491
|
+
className: "bg-muted",
|
|
492
|
+
children: /* @__PURE__ */ jsxs("tr", {
|
|
493
|
+
className: "h-10",
|
|
494
|
+
children: [
|
|
495
|
+
/* @__PURE__ */ jsx(TableColumn, {
|
|
496
|
+
label: t("product"),
|
|
497
|
+
sortable: false
|
|
498
|
+
}),
|
|
499
|
+
/* @__PURE__ */ jsx(TableColumn, {
|
|
500
|
+
label: t("next_bill_date"),
|
|
501
|
+
sortBy: "next_bill_date",
|
|
502
|
+
sortData: sortBy,
|
|
503
|
+
onSortClick: (value) => setSortBy({
|
|
504
|
+
column: value,
|
|
505
|
+
direction: sortBy.direction === "asc" ? "desc" : "asc"
|
|
506
|
+
})
|
|
507
|
+
}),
|
|
508
|
+
/* @__PURE__ */ jsx(TableColumn, {
|
|
509
|
+
label: t("price"),
|
|
510
|
+
sortable: false
|
|
511
|
+
}),
|
|
512
|
+
/* @__PURE__ */ jsx(TableColumn, {
|
|
513
|
+
label: t("status"),
|
|
514
|
+
sortable: false
|
|
515
|
+
})
|
|
516
|
+
]
|
|
517
|
+
})
|
|
518
|
+
}),
|
|
519
|
+
/* @__PURE__ */ jsx("tbody", {
|
|
520
|
+
className: "divide-border bg-background divide-y",
|
|
521
|
+
children: isLoading ? Array(5).fill(0).map((_, index) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
522
|
+
/* @__PURE__ */ jsx("td", {
|
|
523
|
+
className: "px-3 py-4",
|
|
524
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
525
|
+
className: "flex items-center space-x-2",
|
|
526
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-9 rounded-md" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" })]
|
|
527
|
+
})
|
|
528
|
+
}),
|
|
529
|
+
/* @__PURE__ */ jsx("td", {
|
|
530
|
+
className: "px-3 py-4",
|
|
531
|
+
children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24" })
|
|
532
|
+
}),
|
|
533
|
+
/* @__PURE__ */ jsx("td", {
|
|
534
|
+
className: "px-3 py-4",
|
|
535
|
+
children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24" })
|
|
536
|
+
}),
|
|
537
|
+
/* @__PURE__ */ jsx("td", {
|
|
538
|
+
className: "px-3 py-4",
|
|
539
|
+
children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-16" })
|
|
540
|
+
})
|
|
541
|
+
] }, `skeleton-${index}`)) : items.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
542
|
+
colSpan: 4,
|
|
543
|
+
className: "text-muted-foreground px-3 py-8 text-center text-sm",
|
|
544
|
+
children: t("no_subscriptions_found")
|
|
545
|
+
}) }) : items.map((subscription) => /* @__PURE__ */ jsxs("tr", {
|
|
546
|
+
className: "hover:bg-muted cursor-pointer transition-colors duration-200 ease-in-out",
|
|
547
|
+
onClick: () => handleSubscriptionClick(subscription.subscription_token),
|
|
548
|
+
children: [
|
|
549
|
+
/* @__PURE__ */ jsxs("td", {
|
|
550
|
+
className: "text-muted-foreground flex max-w-[280px] items-center space-x-3 py-4 pr-3 pl-3 text-sm",
|
|
551
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
552
|
+
src: subscription.variant?.product?.image_url,
|
|
553
|
+
alt: subscription.variant?.product?.title,
|
|
554
|
+
width: 48,
|
|
555
|
+
height: 48,
|
|
556
|
+
className: "h-12 w-12 flex-shrink-0 rounded-md object-cover"
|
|
557
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
558
|
+
className: "text-foreground truncate text-sm font-medium",
|
|
559
|
+
children: subscription.variant?.product?.title
|
|
560
|
+
})]
|
|
561
|
+
}),
|
|
562
|
+
/* @__PURE__ */ jsx("td", {
|
|
563
|
+
className: "text-muted-foreground px-3 py-4 text-sm whitespace-nowrap",
|
|
564
|
+
children: formatNextBillDate(subscription.next_bill_date ?? "")
|
|
565
|
+
}),
|
|
566
|
+
/* @__PURE__ */ jsx("td", {
|
|
567
|
+
className: "px-3 py-4 text-sm whitespace-nowrap",
|
|
568
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
569
|
+
className: "text-muted-foreground",
|
|
570
|
+
children: formatCurrency(subscription.price * subscription.quantity)
|
|
571
|
+
})
|
|
572
|
+
}),
|
|
573
|
+
/* @__PURE__ */ jsx("td", {
|
|
574
|
+
className: "px-3 py-4 text-sm whitespace-nowrap",
|
|
575
|
+
children: /* @__PURE__ */ jsx(StatusPill, {
|
|
576
|
+
status: subscription.status,
|
|
577
|
+
children: startCase(subscription.status) || t("unknown_status")
|
|
578
|
+
})
|
|
579
|
+
})
|
|
580
|
+
]
|
|
581
|
+
}, subscription.subscription_token))
|
|
582
|
+
})
|
|
583
|
+
]
|
|
584
|
+
})
|
|
585
|
+
}),
|
|
586
|
+
/* @__PURE__ */ jsx(PaginationFooter, {
|
|
587
|
+
currentPage,
|
|
588
|
+
totalPages,
|
|
589
|
+
pageSize,
|
|
590
|
+
totalItems,
|
|
591
|
+
onPageChange: setCurrentPage,
|
|
592
|
+
t
|
|
593
|
+
})
|
|
594
|
+
]
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
//#endregion
|
|
598
|
+
//#region ../../subscriptions/ui/src/components/confirm-dialog.tsx
|
|
599
|
+
function ConfirmDialog({ title, description, actionButtonText = "Delete", cancelButtonText = "Cancel", open, setOpen, onConfirm }) {
|
|
600
|
+
const [isPending, setIsPending] = useState(false);
|
|
601
|
+
const handleConfirm = async () => {
|
|
602
|
+
try {
|
|
603
|
+
const result = onConfirm();
|
|
604
|
+
if (result instanceof Promise) {
|
|
605
|
+
setIsPending(true);
|
|
606
|
+
await result;
|
|
607
|
+
}
|
|
608
|
+
} catch (error) {
|
|
609
|
+
console.error("ConfirmDialog: action rejected", error);
|
|
610
|
+
} finally {
|
|
611
|
+
setIsPending(false);
|
|
612
|
+
setOpen(false);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
return /* @__PURE__ */ jsx(AlertDialog, {
|
|
616
|
+
open,
|
|
617
|
+
onOpenChange: (v) => !isPending && setOpen(v),
|
|
618
|
+
children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: title }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: description })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, {
|
|
619
|
+
disabled: isPending,
|
|
620
|
+
children: cancelButtonText
|
|
621
|
+
}), /* @__PURE__ */ jsx(AlertDialogAction, {
|
|
622
|
+
onClick: handleConfirm,
|
|
623
|
+
disabled: isPending,
|
|
624
|
+
className: "bg-red-600 text-white hover:bg-red-500",
|
|
625
|
+
children: isPending ? "..." : actionButtonText
|
|
626
|
+
})] })] })
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region ../../subscriptions/ui/src/components/subscription-detail.tsx
|
|
631
|
+
function SubscriptionDetailSkeleton() {
|
|
632
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
633
|
+
className: "flex flex-col lg:grid lg:grid-cols-8",
|
|
634
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
635
|
+
className: "bg-muted flex flex-col items-center px-8 lg:col-span-4",
|
|
636
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
637
|
+
className: "w-full max-w-lg py-6",
|
|
638
|
+
children: [
|
|
639
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "mb-4 h-6 w-48" }),
|
|
640
|
+
/* @__PURE__ */ jsxs("div", {
|
|
641
|
+
className: "grid grid-cols-2 gap-4",
|
|
642
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-16 w-full rounded" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-16 w-full rounded" })]
|
|
643
|
+
}),
|
|
644
|
+
/* @__PURE__ */ jsxs("div", {
|
|
645
|
+
className: "mt-6 flex items-center space-x-4",
|
|
646
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-24 w-24 rounded" }), /* @__PURE__ */ jsxs("div", {
|
|
647
|
+
className: "flex-1 space-y-2",
|
|
648
|
+
children: [
|
|
649
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }),
|
|
650
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/2" }),
|
|
651
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" })
|
|
652
|
+
]
|
|
653
|
+
})]
|
|
654
|
+
}),
|
|
655
|
+
/* @__PURE__ */ jsxs("div", {
|
|
656
|
+
className: "mt-6 space-y-2",
|
|
657
|
+
children: [
|
|
658
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }),
|
|
659
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }),
|
|
660
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-full" })
|
|
661
|
+
]
|
|
662
|
+
})
|
|
663
|
+
]
|
|
664
|
+
})
|
|
665
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
666
|
+
className: "bg-background col-span-4 px-8 pt-4",
|
|
667
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
668
|
+
className: "mx-auto max-w-lg",
|
|
669
|
+
children: [
|
|
670
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "mb-3 h-5 w-32" }),
|
|
671
|
+
/* @__PURE__ */ jsxs("div", {
|
|
672
|
+
className: "grid grid-cols-2 gap-3",
|
|
673
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full rounded" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full rounded" })]
|
|
674
|
+
}),
|
|
675
|
+
/* @__PURE__ */ jsxs("div", {
|
|
676
|
+
className: "mt-6 space-y-4",
|
|
677
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-40" }), /* @__PURE__ */ jsxs("div", {
|
|
678
|
+
className: "flex gap-4",
|
|
679
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-12 flex-1 rounded" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-12 flex-1 rounded" })]
|
|
680
|
+
})]
|
|
681
|
+
}),
|
|
682
|
+
/* @__PURE__ */ jsxs("div", {
|
|
683
|
+
className: "mt-6 space-y-4",
|
|
684
|
+
children: [
|
|
685
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-40" }),
|
|
686
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-16 w-full rounded" }),
|
|
687
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-16 w-full rounded" })
|
|
688
|
+
]
|
|
689
|
+
})
|
|
690
|
+
]
|
|
691
|
+
})
|
|
692
|
+
})]
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
function SubscriptionItemsSection({ subscription }) {
|
|
696
|
+
const variant = subscription.variant;
|
|
697
|
+
const product = variant?.product;
|
|
698
|
+
const quantity = subscription.quantity;
|
|
699
|
+
const totalPrice = formatCurrency(subscription.price * quantity);
|
|
700
|
+
const discount = subscription.original_price != null ? subscription.original_price - subscription.price : 0;
|
|
701
|
+
const subtotal = discount > 0 ? formatCurrency(subscription.original_price * quantity) : totalPrice;
|
|
702
|
+
return /* @__PURE__ */ jsx("section", {
|
|
703
|
+
className: "bg-muted flex w-full flex-col items-center px-8 lg:col-span-4",
|
|
704
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
705
|
+
className: "flex w-full max-w-lg flex-col",
|
|
706
|
+
children: [
|
|
707
|
+
/* @__PURE__ */ jsxs("div", {
|
|
708
|
+
className: "mt-4",
|
|
709
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
710
|
+
className: "text-foreground mb-2 text-lg font-medium",
|
|
711
|
+
children: "Your Upcoming Order"
|
|
712
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
713
|
+
className: "text-muted-foreground",
|
|
714
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
715
|
+
className: "grid grid-cols-2 gap-4",
|
|
716
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
717
|
+
className: "border-border border-r pr-4",
|
|
718
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
719
|
+
className: "text-muted-foreground mb-1 text-sm",
|
|
720
|
+
children: "Next Order Date"
|
|
721
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
722
|
+
className: "text-foreground text-2xl font-bold",
|
|
723
|
+
children: getNextBillDisplay(subscription)
|
|
724
|
+
})]
|
|
725
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
726
|
+
className: "pl-4",
|
|
727
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
728
|
+
className: "text-muted-foreground mb-1 text-sm",
|
|
729
|
+
children: "Next Bill Amount"
|
|
730
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
731
|
+
className: "text-foreground text-2xl font-bold",
|
|
732
|
+
children: formatCurrency(subscription.price * quantity)
|
|
733
|
+
})]
|
|
734
|
+
})]
|
|
735
|
+
}), /* @__PURE__ */ jsx("hr", { className: "border-border mt-4" })]
|
|
736
|
+
})]
|
|
737
|
+
}),
|
|
738
|
+
/* @__PURE__ */ jsx("div", {
|
|
739
|
+
className: "py-6",
|
|
740
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
741
|
+
className: "flex flex-row items-center space-x-4",
|
|
742
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
743
|
+
className: "flex min-w-0 flex-1 flex-row space-x-4",
|
|
744
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
745
|
+
className: "relative shrink-0",
|
|
746
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
747
|
+
className: "bg-muted h-24 w-24 overflow-hidden rounded",
|
|
748
|
+
children: [product?.image_url ? /* @__PURE__ */ jsx("img", {
|
|
749
|
+
src: product.image_url,
|
|
750
|
+
alt: variant?.title || "Product image",
|
|
751
|
+
width: 96,
|
|
752
|
+
height: 96,
|
|
753
|
+
className: "h-full w-full object-cover"
|
|
754
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
755
|
+
className: "text-muted-foreground flex h-full w-full items-center justify-center",
|
|
756
|
+
children: "No image"
|
|
757
|
+
}), quantity > 1 && /* @__PURE__ */ jsx("span", {
|
|
758
|
+
className: "bg-foreground text-background absolute -top-2 -right-2 z-10 flex h-6 w-6 items-center justify-center rounded-full text-xs font-medium",
|
|
759
|
+
children: quantity
|
|
760
|
+
})]
|
|
761
|
+
})
|
|
762
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
763
|
+
className: "flex min-w-0 flex-col space-y-0.5",
|
|
764
|
+
children: [
|
|
765
|
+
/* @__PURE__ */ jsx("p", {
|
|
766
|
+
className: "text-foreground truncate text-sm font-medium",
|
|
767
|
+
title: product?.title,
|
|
768
|
+
children: product?.title
|
|
769
|
+
}),
|
|
770
|
+
variant?.title && product?.title && /* @__PURE__ */ jsx("p", {
|
|
771
|
+
className: "text-muted-foreground text-sm",
|
|
772
|
+
children: variant.title
|
|
773
|
+
}),
|
|
774
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", {
|
|
775
|
+
className: "text-foreground text-sm font-medium",
|
|
776
|
+
children: formatCurrency(subscription.price * quantity)
|
|
777
|
+
}) })
|
|
778
|
+
]
|
|
779
|
+
})]
|
|
780
|
+
})
|
|
781
|
+
})
|
|
782
|
+
}),
|
|
783
|
+
/* @__PURE__ */ jsxs("div", {
|
|
784
|
+
className: "mb-4",
|
|
785
|
+
children: [
|
|
786
|
+
discount > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
787
|
+
className: "flex justify-between text-sm",
|
|
788
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
789
|
+
className: "text-muted-foreground text-sm font-medium",
|
|
790
|
+
children: "Subtotal"
|
|
791
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
792
|
+
className: "text-muted-foreground text-sm font-medium",
|
|
793
|
+
children: subtotal
|
|
794
|
+
})]
|
|
795
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
796
|
+
className: "mt-2 flex justify-between text-sm",
|
|
797
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
798
|
+
className: "text-muted-foreground text-sm font-medium",
|
|
799
|
+
children: "Discount"
|
|
800
|
+
}), /* @__PURE__ */ jsxs("p", {
|
|
801
|
+
className: "text-muted-foreground text-sm font-medium",
|
|
802
|
+
children: ["-", formatCurrency(discount * quantity)]
|
|
803
|
+
})]
|
|
804
|
+
})] }),
|
|
805
|
+
/* @__PURE__ */ jsxs("div", {
|
|
806
|
+
className: "mt-4 flex items-center justify-between text-base font-medium",
|
|
807
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
808
|
+
className: "text-muted-foreground text-sm font-medium",
|
|
809
|
+
children: "Total"
|
|
810
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
811
|
+
className: "text-foreground text-base font-bold",
|
|
812
|
+
children: formatCurrency(subscription.price * quantity)
|
|
813
|
+
})]
|
|
814
|
+
}),
|
|
815
|
+
/* @__PURE__ */ jsx("span", {
|
|
816
|
+
className: "text-muted-foreground text-xs",
|
|
817
|
+
children: "*Tax and shipping calculated at checkout"
|
|
818
|
+
})
|
|
819
|
+
]
|
|
820
|
+
})
|
|
821
|
+
]
|
|
822
|
+
})
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
function SubscriptionManagementSection({ subscription, isActive, isPaused, isCancelled, isMutating, onSkip, onPause, onResume, onCancel, onReactivate }) {
|
|
826
|
+
const plan = subscription.subscription_plan;
|
|
827
|
+
const quantity = subscription.quantity;
|
|
828
|
+
const totalPrice = formatCurrency(subscription.price * quantity);
|
|
829
|
+
const paymentMethod = subscription.payment_method;
|
|
830
|
+
const paymentDetails = paymentMethod?.details;
|
|
831
|
+
const actionButtonClass = "flex h-auto flex-row items-center justify-center gap-2 overflow-hidden border border-border bg-muted py-2 text-xs whitespace-nowrap text-foreground hover:bg-accent sm:text-sm";
|
|
832
|
+
return /* @__PURE__ */ jsx("div", {
|
|
833
|
+
className: "bg-background col-span-4 flex-auto px-8 pt-4",
|
|
834
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
835
|
+
className: "mx-auto max-w-lg lg:mx-0 lg:mr-auto",
|
|
836
|
+
children: [
|
|
837
|
+
/* @__PURE__ */ jsxs("div", {
|
|
838
|
+
className: "border-border mb-6 border-b pb-6",
|
|
839
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
840
|
+
className: "text-foreground mb-3 text-sm/6 font-semibold",
|
|
841
|
+
children: "Order Actions"
|
|
842
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
843
|
+
className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
|
|
844
|
+
children: [
|
|
845
|
+
isActive && plan.allow_skipping && /* @__PURE__ */ jsxs(Button, {
|
|
846
|
+
variant: "outline",
|
|
847
|
+
onClick: onSkip,
|
|
848
|
+
disabled: isMutating || !subscription.next_bill_date,
|
|
849
|
+
className: actionButtonClass,
|
|
850
|
+
children: [/* @__PURE__ */ jsx(SkipForward, { className: "h-3 w-3 shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
851
|
+
className: "truncate",
|
|
852
|
+
children: "Skip Next Order"
|
|
853
|
+
})]
|
|
854
|
+
}),
|
|
855
|
+
isActive && /* @__PURE__ */ jsxs(Button, {
|
|
856
|
+
variant: "outline",
|
|
857
|
+
onClick: onPause,
|
|
858
|
+
disabled: isMutating,
|
|
859
|
+
className: actionButtonClass,
|
|
860
|
+
children: [/* @__PURE__ */ jsx(Pause, { className: "h-3 w-3 shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
861
|
+
className: "truncate",
|
|
862
|
+
children: "Pause Subscription"
|
|
863
|
+
})]
|
|
864
|
+
}),
|
|
865
|
+
isPaused && /* @__PURE__ */ jsxs(Button, {
|
|
866
|
+
variant: "outline",
|
|
867
|
+
onClick: onResume,
|
|
868
|
+
disabled: isMutating,
|
|
869
|
+
className: actionButtonClass,
|
|
870
|
+
children: [/* @__PURE__ */ jsx(Play, { className: "h-3 w-3 shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
871
|
+
className: "truncate",
|
|
872
|
+
children: "Resume Subscription"
|
|
873
|
+
})]
|
|
874
|
+
}),
|
|
875
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
876
|
+
variant: "outline",
|
|
877
|
+
onClick: onCancel,
|
|
878
|
+
disabled: isMutating || isCancelled,
|
|
879
|
+
className: actionButtonClass,
|
|
880
|
+
children: [/* @__PURE__ */ jsx(XCircle, { className: "h-3 w-3 shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
881
|
+
className: "truncate",
|
|
882
|
+
children: isCancelled ? "Cancelled" : "Cancel Subscription"
|
|
883
|
+
})]
|
|
884
|
+
}),
|
|
885
|
+
isCancelled && /* @__PURE__ */ jsxs(Button, {
|
|
886
|
+
variant: "outline",
|
|
887
|
+
onClick: onReactivate,
|
|
888
|
+
disabled: isMutating,
|
|
889
|
+
className: actionButtonClass,
|
|
890
|
+
children: [/* @__PURE__ */ jsx(RotateCcw, { className: "h-3 w-3 shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
891
|
+
className: "truncate",
|
|
892
|
+
children: "Reactivate Subscription"
|
|
893
|
+
})]
|
|
894
|
+
})
|
|
895
|
+
]
|
|
896
|
+
})]
|
|
897
|
+
}),
|
|
898
|
+
/* @__PURE__ */ jsxs("div", {
|
|
899
|
+
className: "border-border mb-4 border-b",
|
|
900
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
901
|
+
className: "mb-4 flex items-center justify-between",
|
|
902
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
903
|
+
className: "text-foreground text-sm/6 font-semibold",
|
|
904
|
+
children: "Subscription Details"
|
|
905
|
+
}), /* @__PURE__ */ jsx(StatusPill, {
|
|
906
|
+
status: subscription.status,
|
|
907
|
+
children: startCase(subscription.status)
|
|
908
|
+
})]
|
|
909
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
910
|
+
className: "divide-border mb-4 flex divide-x",
|
|
911
|
+
children: [
|
|
912
|
+
/* @__PURE__ */ jsxs("div", {
|
|
913
|
+
className: "flex-1 pr-4",
|
|
914
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
915
|
+
className: "text-muted-foreground text-sm",
|
|
916
|
+
children: "Order Frequency"
|
|
917
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
918
|
+
className: "text-foreground font-medium",
|
|
919
|
+
children: formatSubscriptionFrequency(plan.billing_interval_unit)
|
|
920
|
+
})]
|
|
921
|
+
}),
|
|
922
|
+
/* @__PURE__ */ jsxs("div", {
|
|
923
|
+
className: "flex-1 px-4",
|
|
924
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
925
|
+
className: "text-muted-foreground text-sm",
|
|
926
|
+
children: "Next Payment"
|
|
927
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
928
|
+
className: "text-foreground font-medium",
|
|
929
|
+
children: totalPrice
|
|
930
|
+
})]
|
|
931
|
+
}),
|
|
932
|
+
subscription.last_bill_date && /* @__PURE__ */ jsxs("div", {
|
|
933
|
+
className: "flex-1 pl-4 text-right",
|
|
934
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
935
|
+
className: "text-muted-foreground text-sm",
|
|
936
|
+
children: "Last Billed"
|
|
937
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
938
|
+
className: "text-foreground font-medium",
|
|
939
|
+
children: formatDate(subscription.last_bill_date)
|
|
940
|
+
})]
|
|
941
|
+
})
|
|
942
|
+
]
|
|
943
|
+
})]
|
|
944
|
+
}),
|
|
945
|
+
/* @__PURE__ */ jsxs("div", {
|
|
946
|
+
className: "pt-2",
|
|
947
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
948
|
+
className: "text-foreground text-sm/6 font-semibold",
|
|
949
|
+
children: "Payment & Shipping"
|
|
950
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
951
|
+
className: "flex flex-col",
|
|
952
|
+
children: [subscription.address && /* @__PURE__ */ jsxs("div", {
|
|
953
|
+
className: "border-border mb-6 border-b pb-4",
|
|
954
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
955
|
+
className: "text-muted-foreground mt-3 mb-1 text-sm",
|
|
956
|
+
children: "Shipping Address"
|
|
957
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
958
|
+
className: "text-foreground text-sm",
|
|
959
|
+
children: [
|
|
960
|
+
/* @__PURE__ */ jsx("p", {
|
|
961
|
+
className: "font-medium",
|
|
962
|
+
children: subscription.address.name
|
|
963
|
+
}),
|
|
964
|
+
/* @__PURE__ */ jsx("p", { children: subscription.address.address1 }),
|
|
965
|
+
subscription.address.address2 && /* @__PURE__ */ jsx("p", { children: subscription.address.address2 }),
|
|
966
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
967
|
+
[subscription.address.city, subscription.address.state].filter(Boolean).join(", "),
|
|
968
|
+
" ",
|
|
969
|
+
subscription.address.postal_code
|
|
970
|
+
] }),
|
|
971
|
+
subscription.address.country_code && /* @__PURE__ */ jsx("p", { children: subscription.address.country_code })
|
|
972
|
+
]
|
|
973
|
+
})]
|
|
974
|
+
}), paymentMethod && /* @__PURE__ */ jsxs("div", {
|
|
975
|
+
className: "border-border mb-6 border-b pb-4",
|
|
976
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
977
|
+
className: "text-muted-foreground mb-1 text-sm",
|
|
978
|
+
children: "Payment Method"
|
|
979
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
980
|
+
className: "text-foreground flex items-center gap-2 text-sm",
|
|
981
|
+
children: [paymentDetails?.logo_url && /* @__PURE__ */ jsx("img", {
|
|
982
|
+
src: paymentDetails.logo_url,
|
|
983
|
+
alt: paymentDetails.card_type ?? "Card",
|
|
984
|
+
className: "h-6"
|
|
985
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
986
|
+
className: "font-medium",
|
|
987
|
+
children: [paymentDetails?.card_type ? startCase(paymentDetails.card_type) : paymentMethod.payment_type, paymentDetails?.last4 ? ` ending in ${paymentDetails.last4}` : ""]
|
|
988
|
+
})]
|
|
989
|
+
})]
|
|
990
|
+
})]
|
|
991
|
+
})]
|
|
992
|
+
}),
|
|
993
|
+
subscription.orders.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
994
|
+
className: "border-border mb-4 border-b pb-4",
|
|
995
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
996
|
+
className: "text-foreground mb-3 text-sm/6 font-semibold",
|
|
997
|
+
children: "Order History"
|
|
998
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
999
|
+
className: "overflow-x-auto",
|
|
1000
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
1001
|
+
className: "divide-border min-w-full divide-y text-sm",
|
|
1002
|
+
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1003
|
+
/* @__PURE__ */ jsx("th", {
|
|
1004
|
+
className: "text-muted-foreground py-2 pr-3 text-left font-medium",
|
|
1005
|
+
children: "Order"
|
|
1006
|
+
}),
|
|
1007
|
+
/* @__PURE__ */ jsx("th", {
|
|
1008
|
+
className: "text-muted-foreground px-3 py-2 text-left font-medium",
|
|
1009
|
+
children: "Date"
|
|
1010
|
+
}),
|
|
1011
|
+
/* @__PURE__ */ jsx("th", {
|
|
1012
|
+
className: "text-muted-foreground px-3 py-2 text-left font-medium",
|
|
1013
|
+
children: "Status"
|
|
1014
|
+
}),
|
|
1015
|
+
/* @__PURE__ */ jsx("th", {
|
|
1016
|
+
className: "text-muted-foreground py-2 pl-3 text-right font-medium",
|
|
1017
|
+
children: "Amount"
|
|
1018
|
+
})
|
|
1019
|
+
] }) }), /* @__PURE__ */ jsx("tbody", {
|
|
1020
|
+
className: "divide-border divide-y",
|
|
1021
|
+
children: subscription.orders.map((order) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
1022
|
+
/* @__PURE__ */ jsx("td", {
|
|
1023
|
+
className: "text-foreground py-2 pr-3 font-medium",
|
|
1024
|
+
children: order.order_number ?? `#${order.id}`
|
|
1025
|
+
}),
|
|
1026
|
+
/* @__PURE__ */ jsx("td", {
|
|
1027
|
+
className: "text-muted-foreground px-3 py-2",
|
|
1028
|
+
children: formatDate(order.created_at.split("T")[0] ?? "")
|
|
1029
|
+
}),
|
|
1030
|
+
/* @__PURE__ */ jsx("td", {
|
|
1031
|
+
className: "px-3 py-2",
|
|
1032
|
+
children: /* @__PURE__ */ jsx(StatusPill, {
|
|
1033
|
+
status: order.status,
|
|
1034
|
+
children: startCase(order.status)
|
|
1035
|
+
})
|
|
1036
|
+
}),
|
|
1037
|
+
/* @__PURE__ */ jsx("td", {
|
|
1038
|
+
className: "text-foreground py-2 pl-3 text-right",
|
|
1039
|
+
children: order.amount != null ? formatCurrency(Number(order.amount)) : "N/A"
|
|
1040
|
+
})
|
|
1041
|
+
] }, order.id))
|
|
1042
|
+
})]
|
|
1043
|
+
})
|
|
1044
|
+
})]
|
|
1045
|
+
})
|
|
1046
|
+
]
|
|
1047
|
+
})
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
function SubscriptionDetail({ token, onNotFound, onError, onSuccess, onMutationError }) {
|
|
1051
|
+
const [showCancelModal, setShowCancelModal] = useState(false);
|
|
1052
|
+
const { data, isLoading, error } = useSubscription(token);
|
|
1053
|
+
const subscription = data?.subscription;
|
|
1054
|
+
const customerId = subscription?.customer?.id ?? 0;
|
|
1055
|
+
const pauseMutation = usePauseSubscription({
|
|
1056
|
+
onSuccess: () => onSuccess?.("Subscription paused"),
|
|
1057
|
+
onError: (err) => onMutationError?.("Failed to pause subscription", err)
|
|
1058
|
+
});
|
|
1059
|
+
const resumeMutation = useResumeSubscription({
|
|
1060
|
+
onSuccess: () => onSuccess?.("Subscription resumed"),
|
|
1061
|
+
onError: (err) => onMutationError?.("Failed to resume subscription", err)
|
|
1062
|
+
});
|
|
1063
|
+
const skipMutation = useSkipSubscription({
|
|
1064
|
+
onSuccess: () => onSuccess?.("Next billing skipped"),
|
|
1065
|
+
onError: (err) => onMutationError?.("Failed to skip billing", err)
|
|
1066
|
+
});
|
|
1067
|
+
const cancelMutation = useCancelSubscription({
|
|
1068
|
+
onSuccess: () => {
|
|
1069
|
+
onSuccess?.("Subscription cancelled");
|
|
1070
|
+
setShowCancelModal(false);
|
|
1071
|
+
},
|
|
1072
|
+
onError: (err) => onMutationError?.("Failed to cancel subscription", err)
|
|
1073
|
+
});
|
|
1074
|
+
const reactivateMutation = useReactivateSubscription({
|
|
1075
|
+
onSuccess: () => onSuccess?.("Subscription reactivated"),
|
|
1076
|
+
onError: (err) => onMutationError?.("Failed to reactivate subscription", err)
|
|
1077
|
+
});
|
|
1078
|
+
useEffect(() => {
|
|
1079
|
+
if (!isLoading && error) onError?.(error);
|
|
1080
|
+
}, [
|
|
1081
|
+
isLoading,
|
|
1082
|
+
error,
|
|
1083
|
+
onError
|
|
1084
|
+
]);
|
|
1085
|
+
useEffect(() => {
|
|
1086
|
+
if (!isLoading && !error && !subscription) onNotFound?.();
|
|
1087
|
+
}, [
|
|
1088
|
+
isLoading,
|
|
1089
|
+
error,
|
|
1090
|
+
subscription,
|
|
1091
|
+
onNotFound
|
|
1092
|
+
]);
|
|
1093
|
+
if (isLoading) return /* @__PURE__ */ jsx(SubscriptionDetailSkeleton, {});
|
|
1094
|
+
if (!subscription) return null;
|
|
1095
|
+
const plan = subscription.subscription_plan;
|
|
1096
|
+
const isActive = subscription.status === "active";
|
|
1097
|
+
const isPaused = subscription.status === "paused";
|
|
1098
|
+
const isCancelled = subscription.status === "cancelled";
|
|
1099
|
+
const isMutating = pauseMutation.isPending || resumeMutation.isPending || skipMutation.isPending || cancelMutation.isPending || reactivateMutation.isPending;
|
|
1100
|
+
const handlePause = () => {
|
|
1101
|
+
pauseMutation.mutate({
|
|
1102
|
+
subscriptionToken: token,
|
|
1103
|
+
pauseParams: { customerId }
|
|
1104
|
+
});
|
|
1105
|
+
};
|
|
1106
|
+
const handleResume = () => {
|
|
1107
|
+
const nextBillDate = calculateNextBillDate(plan.billing_interval, plan.billing_interval_unit);
|
|
1108
|
+
resumeMutation.mutate({
|
|
1109
|
+
subscriptionToken: token,
|
|
1110
|
+
resumeParams: {
|
|
1111
|
+
customerId,
|
|
1112
|
+
nextBillDate
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
};
|
|
1116
|
+
const handleSkip = () => {
|
|
1117
|
+
const nextBillDate = calculateNextBillDate(plan.billing_interval, plan.billing_interval_unit);
|
|
1118
|
+
skipMutation.mutate({
|
|
1119
|
+
subscriptionToken: token,
|
|
1120
|
+
skipParams: {
|
|
1121
|
+
customerId,
|
|
1122
|
+
nextBillDate
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
};
|
|
1126
|
+
const handleCancel = () => {
|
|
1127
|
+
cancelMutation.mutate({
|
|
1128
|
+
subscriptionToken: token,
|
|
1129
|
+
customerId
|
|
1130
|
+
});
|
|
1131
|
+
};
|
|
1132
|
+
const handleReactivate = () => {
|
|
1133
|
+
reactivateMutation.mutate({
|
|
1134
|
+
subscriptionToken: token,
|
|
1135
|
+
reactivateParams: {}
|
|
1136
|
+
});
|
|
1137
|
+
};
|
|
1138
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
1139
|
+
className: "flex flex-col lg:grid lg:grid-cols-8",
|
|
1140
|
+
children: [/* @__PURE__ */ jsx(SubscriptionItemsSection, { subscription }), /* @__PURE__ */ jsx(SubscriptionManagementSection, {
|
|
1141
|
+
subscription,
|
|
1142
|
+
isActive,
|
|
1143
|
+
isPaused,
|
|
1144
|
+
isCancelled,
|
|
1145
|
+
isMutating,
|
|
1146
|
+
onSkip: handleSkip,
|
|
1147
|
+
onPause: handlePause,
|
|
1148
|
+
onResume: handleResume,
|
|
1149
|
+
onCancel: () => setShowCancelModal(true),
|
|
1150
|
+
onReactivate: handleReactivate
|
|
1151
|
+
})]
|
|
1152
|
+
}), /* @__PURE__ */ jsx(ConfirmDialog, {
|
|
1153
|
+
title: "Cancel Subscription",
|
|
1154
|
+
actionButtonText: "Cancel Subscription",
|
|
1155
|
+
description: "Are you sure you want to cancel this subscription? You can reactivate it later.",
|
|
1156
|
+
open: showCancelModal,
|
|
1157
|
+
setOpen: setShowCancelModal,
|
|
1158
|
+
onConfirm: handleCancel
|
|
1159
|
+
})] });
|
|
1160
|
+
}
|
|
1161
|
+
//#endregion
|
|
1162
|
+
//#region src/screens/SubscriptionsListScreen.tsx
|
|
1163
|
+
const translations = {
|
|
1164
|
+
all: "All",
|
|
1165
|
+
active: "Active",
|
|
1166
|
+
inactive: "Inactive",
|
|
1167
|
+
search: "Search",
|
|
1168
|
+
subscriptions: "Search subscriptions...",
|
|
1169
|
+
product: "Product",
|
|
1170
|
+
next_bill_date: "Next Bill Date",
|
|
1171
|
+
price: "Price",
|
|
1172
|
+
status: "Status",
|
|
1173
|
+
no_subscriptions_found: "No subscriptions found",
|
|
1174
|
+
unknown_status: "Unknown",
|
|
1175
|
+
total: "Total",
|
|
1176
|
+
results: "results",
|
|
1177
|
+
previous: "Previous",
|
|
1178
|
+
next: "Next",
|
|
1179
|
+
pagination: "Pagination"
|
|
1180
|
+
};
|
|
1181
|
+
function SubscriptionsListScreen({ customerId, isLoadingCustomer }) {
|
|
1182
|
+
const subscriptionsClient = useSubscriptionsClient$1();
|
|
1183
|
+
const { navigate } = useAppNavigation();
|
|
1184
|
+
if (isLoadingCustomer) return /* @__PURE__ */ jsx("div", {
|
|
1185
|
+
className: "mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8",
|
|
1186
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1187
|
+
className: "space-y-3",
|
|
1188
|
+
children: [/* @__PURE__ */ jsx("div", { className: "bg-muted h-10 animate-pulse rounded" }), /* @__PURE__ */ jsx("div", { className: "bg-muted h-64 animate-pulse rounded" })]
|
|
1189
|
+
})
|
|
1190
|
+
});
|
|
1191
|
+
return /* @__PURE__ */ jsx(SubscriptionsCoreProvider, {
|
|
1192
|
+
client: subscriptionsClient,
|
|
1193
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1194
|
+
className: "mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8",
|
|
1195
|
+
children: /* @__PURE__ */ jsx(SubscriptionsList, {
|
|
1196
|
+
customerId,
|
|
1197
|
+
onSubscriptionClick: (subscriptionToken) => navigate(`subscriptions/${subscriptionToken}`),
|
|
1198
|
+
t: (key) => translations[key] ?? key
|
|
1199
|
+
})
|
|
1200
|
+
})
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
//#endregion
|
|
1204
|
+
//#region src/screens/SubscriptionDetailScreen.tsx
|
|
1205
|
+
function SubscriptionDetailScreen({ token, onToast }) {
|
|
1206
|
+
const client = useSubscriptionsClient$1();
|
|
1207
|
+
const { navigate } = useAppNavigation();
|
|
1208
|
+
return /* @__PURE__ */ jsx(SubscriptionsCoreProvider, {
|
|
1209
|
+
client,
|
|
1210
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1211
|
+
className: "mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8",
|
|
1212
|
+
children: /* @__PURE__ */ jsx(SubscriptionDetail, {
|
|
1213
|
+
token,
|
|
1214
|
+
onNotFound: () => {
|
|
1215
|
+
onToast("Subscription not found", "warning");
|
|
1216
|
+
navigate("subscriptions");
|
|
1217
|
+
},
|
|
1218
|
+
onError: (err) => {
|
|
1219
|
+
onToast(`Failed to load subscription: ${err instanceof Error ? err.message : "An error occurred"}`, "error");
|
|
1220
|
+
},
|
|
1221
|
+
onSuccess: (message) => {
|
|
1222
|
+
onToast(message, "success");
|
|
1223
|
+
},
|
|
1224
|
+
onMutationError: (message, err) => {
|
|
1225
|
+
onToast(`${message}: ${err instanceof Error ? err.message : "An error occurred"}`, "error");
|
|
1226
|
+
}
|
|
1227
|
+
})
|
|
1228
|
+
})
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
//#endregion
|
|
1232
|
+
//#region src/screens/SubscriptionsScreen.tsx
|
|
1233
|
+
var SubscriptionsScreen_exports = /* @__PURE__ */ __exportAll({
|
|
1234
|
+
SubscriptionsScreen: () => SubscriptionsScreen,
|
|
1235
|
+
subscriptionsScreenPropertySchema: () => subscriptionsScreenPropertySchema
|
|
1236
|
+
});
|
|
1237
|
+
function defaultToast(message, type) {
|
|
1238
|
+
if (type === "error" || type === "warning") console.warn("[Subscriptions]", message);
|
|
1239
|
+
else console.info("[Subscriptions]", message);
|
|
1240
|
+
}
|
|
1241
|
+
function SubscriptionsScreen({ onToast, background, textColor, accentColor, padding, borderRadius, ...divProps }) {
|
|
1242
|
+
const { currentSlug } = useAppNavigation();
|
|
1243
|
+
const effectiveToast = onToast ?? defaultToast;
|
|
1244
|
+
const detailToken = currentSlug.split("/")[1];
|
|
1245
|
+
const isDetailView = detailToken !== void 0;
|
|
1246
|
+
const { customerId, isLoadingCustomer, isCustomerError } = useCustomerAccount({ enabled: !isDetailView });
|
|
1247
|
+
if (isDetailView) return /* @__PURE__ */ jsx("div", {
|
|
1248
|
+
...divProps,
|
|
1249
|
+
children: /* @__PURE__ */ jsx(SubscriptionDetailScreen, {
|
|
1250
|
+
token: detailToken,
|
|
1251
|
+
onToast: effectiveToast
|
|
1252
|
+
})
|
|
1253
|
+
});
|
|
1254
|
+
if (isCustomerError && !isLoadingCustomer) return /* @__PURE__ */ jsx("div", {
|
|
1255
|
+
...divProps,
|
|
1256
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1257
|
+
className: "text-muted-foreground px-4 py-8 text-center text-sm",
|
|
1258
|
+
children: "Unable to load account data. Please try again later."
|
|
1259
|
+
})
|
|
1260
|
+
});
|
|
1261
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1262
|
+
...divProps,
|
|
1263
|
+
children: /* @__PURE__ */ jsx(SubscriptionsListScreen, {
|
|
1264
|
+
customerId,
|
|
1265
|
+
isLoadingCustomer
|
|
1266
|
+
})
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
const subscriptionsScreenPropertySchema = {
|
|
1270
|
+
widgetType: "SubscriptionsScreen",
|
|
1271
|
+
displayName: "Subscriptions Screen",
|
|
1272
|
+
tabsConfig: [{
|
|
1273
|
+
id: "styling",
|
|
1274
|
+
label: "Styling"
|
|
1275
|
+
}],
|
|
1276
|
+
fields: []
|
|
1277
|
+
};
|
|
1278
|
+
//#endregion
|
|
1279
|
+
export { SubscriptionsScreen_exports as n, subscriptionsScreenPropertySchema as r, SubscriptionsScreen as t };
|
|
1280
|
+
|
|
1281
|
+
//# sourceMappingURL=SubscriptionsScreen-D5_eJwBP.mjs.map
|