@burdenoff/microfe-coolandlovely 2026.1028.1 → 2026.1028.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coolandlovely/components/ReturnRequests.d.ts +15 -0
- package/dist/coolandlovely/components/ReturnRequests.d.ts.map +1 -0
- package/dist/coolandlovely/components/ReturnRequests.js +218 -0
- package/dist/coolandlovely/components/ReturnRequests.js.map +1 -0
- package/dist/coolandlovely/components/StatusBadge.d.ts.map +1 -1
- package/dist/coolandlovely/components/StatusBadge.js +5 -1
- package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts +10 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js +99 -30
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts +8 -1
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.js +47 -31
- package/dist/coolandlovely/hooks/useCommerceApi.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.d.ts +3 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js +129 -97
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.d.ts +2 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.js +124 -122
- package/dist/coolandlovely/pages/commerce/OrdersPage.js.map +1 -1
- package/dist/coolandlovely/types/commerce.d.ts +45 -0
- package/dist/coolandlovely/types/commerce.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -11,13 +11,14 @@ import { EmptyState as u } from "../../components/EmptyState.js";
|
|
|
11
11
|
import { useCancelOrder as d, useMyOrder as f, useMyOrders as p, useResumeOrderPayment as m, useSyncOrderPayment as h } from "../../hooks/useCommerceApi.js";
|
|
12
12
|
import { PayForOrder as g } from "../../components/PayForOrder.js";
|
|
13
13
|
import { FulfilmentTimeline as _ } from "../../components/FulfilmentTimeline.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
14
|
+
import { OrderReturns as v } from "../../components/ReturnRequests.js";
|
|
15
|
+
import { useState as y } from "react";
|
|
16
|
+
import { ArrowLeft as b, ChevronRight as x, Loader2 as S, Package as C, RefreshCw as w, Sparkles as T, XCircle as E } from "lucide-react";
|
|
17
|
+
import { useParams as D } from "react-router";
|
|
18
|
+
import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
|
|
19
|
+
import { GlassCard as j } from "@burdenoff/fe-libs/ui";
|
|
19
20
|
//#region src/coolandlovely/pages/commerce/OrdersPage.tsx
|
|
20
|
-
var
|
|
21
|
+
var M = [
|
|
21
22
|
{
|
|
22
23
|
value: void 0,
|
|
23
24
|
key: "coolandlovely.orders.filterAll",
|
|
@@ -48,16 +49,16 @@ var j = [
|
|
|
48
49
|
key: "coolandlovely.orders.filterCancelled",
|
|
49
50
|
label: "Cancelled"
|
|
50
51
|
}
|
|
51
|
-
],
|
|
52
|
-
function
|
|
53
|
-
let s = r(), { navigateTo: d } = e(), [f, m] =
|
|
54
|
-
return /* @__PURE__ */
|
|
52
|
+
], N = "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50";
|
|
53
|
+
function P() {
|
|
54
|
+
let s = r(), { navigateTo: d } = e(), [f, m] = y(void 0), h = p(f);
|
|
55
|
+
return /* @__PURE__ */ A(n, {
|
|
55
56
|
title: s("coolandlovely.orders.title", "My orders"),
|
|
56
57
|
description: s("coolandlovely.orders.description", "Everything you have ordered."),
|
|
57
|
-
children: [/* @__PURE__ */
|
|
58
|
+
children: [/* @__PURE__ */ k("div", {
|
|
58
59
|
className: "mb-4 flex flex-wrap gap-2",
|
|
59
60
|
role: "tablist",
|
|
60
|
-
children:
|
|
61
|
+
children: M.map((e) => /* @__PURE__ */ k("button", {
|
|
61
62
|
type: "button",
|
|
62
63
|
role: "tab",
|
|
63
64
|
"aria-selected": f === e.value,
|
|
@@ -65,24 +66,24 @@ function N() {
|
|
|
65
66
|
className: t("rounded-full border px-3 py-1 text-sm font-medium transition-colors", f === e.value ? "border-action-primary-bg bg-action-primary-bg text-action-primary-text" : "border-border-seam text-text-primary hover:bg-bg-sunken"),
|
|
66
67
|
children: s(e.key, e.label)
|
|
67
68
|
}, e.key))
|
|
68
|
-
}), h.isLoading ? /* @__PURE__ */
|
|
69
|
-
icon: /* @__PURE__ */
|
|
69
|
+
}), h.isLoading ? /* @__PURE__ */ k(o, { label: s("coolandlovely.orders.loading", "Loading orders…") }) : h.isError || !h.data ? /* @__PURE__ */ k(a, { onRetry: () => void h.refetch() }) : h.data.items.length === 0 ? /* @__PURE__ */ k(u, {
|
|
70
|
+
icon: /* @__PURE__ */ k(C, { className: "h-8 w-8" }),
|
|
70
71
|
title: s("coolandlovely.orders.emptyTitle", "No orders yet"),
|
|
71
72
|
description: s("coolandlovely.orders.emptyDescription", "Orders you place appear here.")
|
|
72
|
-
}) : /* @__PURE__ */
|
|
73
|
+
}) : /* @__PURE__ */ k("div", {
|
|
73
74
|
className: "space-y-3",
|
|
74
75
|
"data-testid": "orders-list",
|
|
75
|
-
children: h.data.items.map((e) => /* @__PURE__ */
|
|
76
|
+
children: h.data.items.map((e) => /* @__PURE__ */ A("button", {
|
|
76
77
|
type: "button",
|
|
77
78
|
onClick: () => d(`/orders/${e.id}`),
|
|
78
79
|
className: "flex w-full items-center gap-4 rounded-xl border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50",
|
|
79
80
|
children: [
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
+
/* @__PURE__ */ A("div", {
|
|
81
82
|
className: "min-w-0 flex-1",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
83
|
+
children: [/* @__PURE__ */ k("p", {
|
|
83
84
|
className: "font-mono text-sm font-medium text-text-primary",
|
|
84
85
|
children: e.orderNumber
|
|
85
|
-
}), /* @__PURE__ */
|
|
86
|
+
}), /* @__PURE__ */ A("p", {
|
|
86
87
|
className: "truncate text-xs text-text-secondary",
|
|
87
88
|
children: [
|
|
88
89
|
c(e.createdAt),
|
|
@@ -92,146 +93,147 @@ function N() {
|
|
|
92
93
|
]
|
|
93
94
|
})]
|
|
94
95
|
}),
|
|
95
|
-
/* @__PURE__ */
|
|
96
|
-
/* @__PURE__ */
|
|
96
|
+
/* @__PURE__ */ k(i, { status: e.status }),
|
|
97
|
+
/* @__PURE__ */ k("span", {
|
|
97
98
|
className: "w-28 text-right text-sm font-semibold tabular-nums text-text-primary",
|
|
98
99
|
children: l(e.total, e.currency)
|
|
99
100
|
}),
|
|
100
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ k(x, { className: "h-4 w-4 text-text-secondary" })
|
|
101
102
|
]
|
|
102
103
|
}, e.id))
|
|
103
104
|
})]
|
|
104
105
|
});
|
|
105
106
|
}
|
|
106
|
-
function
|
|
107
|
-
let u = r(), { orderId: p } =
|
|
108
|
-
if (
|
|
109
|
-
title:
|
|
110
|
-
children: /* @__PURE__ */
|
|
107
|
+
function F() {
|
|
108
|
+
let u = r(), { orderId: p } = D(), { navigateTo: x } = e(), M = f(p), P = m(), F = h(), I = d(), [L, R] = y(null), z = u("coolandlovely.orders.detailTitle", "Order");
|
|
109
|
+
if (M.isLoading) return /* @__PURE__ */ k(n, {
|
|
110
|
+
title: z,
|
|
111
|
+
children: /* @__PURE__ */ k(o, {})
|
|
111
112
|
});
|
|
112
|
-
if (
|
|
113
|
-
title:
|
|
114
|
-
children: /* @__PURE__ */
|
|
113
|
+
if (M.isError || !M.data) return /* @__PURE__ */ k(n, {
|
|
114
|
+
title: z,
|
|
115
|
+
children: /* @__PURE__ */ k(a, {
|
|
115
116
|
title: u("coolandlovely.orders.notFound", "Order not found"),
|
|
116
|
-
onRetry: () => void
|
|
117
|
+
onRetry: () => void M.refetch()
|
|
117
118
|
})
|
|
118
119
|
});
|
|
119
|
-
let
|
|
120
|
-
return /* @__PURE__ */
|
|
121
|
-
title:
|
|
122
|
-
description: c(
|
|
123
|
-
actions: /* @__PURE__ */
|
|
120
|
+
let B = M.data, V = B.status === "PENDING_PAYMENT", H = P.error ?? F.error ?? I.error;
|
|
121
|
+
return /* @__PURE__ */ k(n, {
|
|
122
|
+
title: B.orderNumber,
|
|
123
|
+
description: c(B.createdAt),
|
|
124
|
+
actions: /* @__PURE__ */ A("div", {
|
|
124
125
|
className: "flex flex-wrap items-center gap-2",
|
|
125
|
-
children: [/* @__PURE__ */
|
|
126
|
+
children: [/* @__PURE__ */ A("button", {
|
|
126
127
|
type: "button",
|
|
127
|
-
onClick: () =>
|
|
128
|
-
className:
|
|
128
|
+
onClick: () => x("/orders"),
|
|
129
|
+
className: N,
|
|
129
130
|
children: [
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ k(b, { className: "h-4 w-4" }),
|
|
131
132
|
" ",
|
|
132
133
|
u("coolandlovely.common.back", "Back")
|
|
133
134
|
]
|
|
134
|
-
}),
|
|
135
|
-
type: "button",
|
|
136
|
-
disabled: P.isPending,
|
|
137
|
-
onClick: () => P.mutate(z.id),
|
|
138
|
-
className: M,
|
|
139
|
-
children: [P.isPending ? /* @__PURE__ */ O(x, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ O(C, { className: "h-4 w-4" }), u("coolandlovely.orders.checkPayment", "Check payment")]
|
|
140
|
-
}), /* @__PURE__ */ k("button", {
|
|
135
|
+
}), V && /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ A("button", {
|
|
141
136
|
type: "button",
|
|
142
137
|
disabled: F.isPending,
|
|
143
|
-
onClick: () => F.mutate(
|
|
144
|
-
className:
|
|
138
|
+
onClick: () => F.mutate(B.id),
|
|
139
|
+
className: N,
|
|
140
|
+
children: [F.isPending ? /* @__PURE__ */ k(S, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ k(w, { className: "h-4 w-4" }), u("coolandlovely.orders.checkPayment", "Check payment")]
|
|
141
|
+
}), /* @__PURE__ */ A("button", {
|
|
142
|
+
type: "button",
|
|
143
|
+
disabled: I.isPending,
|
|
144
|
+
onClick: () => I.mutate(B.id),
|
|
145
|
+
className: t(N, "text-status-error-text hover:bg-status-error-bg-subtle"),
|
|
145
146
|
children: [
|
|
146
|
-
/* @__PURE__ */
|
|
147
|
+
/* @__PURE__ */ k(E, { className: "h-4 w-4" }),
|
|
147
148
|
" ",
|
|
148
149
|
u("coolandlovely.orders.cancel", "Cancel order")
|
|
149
150
|
]
|
|
150
151
|
})] })]
|
|
151
152
|
}),
|
|
152
|
-
children: /* @__PURE__ */
|
|
153
|
+
children: /* @__PURE__ */ A("div", {
|
|
153
154
|
className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
|
|
154
|
-
children: [/* @__PURE__ */
|
|
155
|
+
children: [/* @__PURE__ */ A("div", {
|
|
155
156
|
className: "space-y-3 lg:col-span-2",
|
|
156
157
|
children: [
|
|
157
|
-
(
|
|
158
|
+
(B.refunds?.length ?? 0) > 0 && /* @__PURE__ */ A(j, {
|
|
158
159
|
treatment: "plain",
|
|
159
160
|
className: "space-y-3 p-4",
|
|
160
161
|
"data-testid": "order-refunds",
|
|
161
|
-
children: [/* @__PURE__ */
|
|
162
|
+
children: [/* @__PURE__ */ k("p", {
|
|
162
163
|
className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
|
|
163
164
|
children: u("coolandlovely.orders.refunds", "Refunds")
|
|
164
|
-
}),
|
|
165
|
+
}), B.refunds?.map((e) => /* @__PURE__ */ A("div", {
|
|
165
166
|
className: "space-y-1",
|
|
166
167
|
"data-testid": "order-refund",
|
|
167
168
|
children: [
|
|
168
|
-
/* @__PURE__ */
|
|
169
|
+
/* @__PURE__ */ A("div", {
|
|
169
170
|
className: "flex items-center justify-between gap-2",
|
|
170
|
-
children: [/* @__PURE__ */
|
|
171
|
+
children: [/* @__PURE__ */ k("span", {
|
|
171
172
|
className: "text-sm font-medium text-text-primary",
|
|
172
173
|
children: e.brandName ?? u("coolandlovely.orders.brand", "Brand")
|
|
173
|
-
}), /* @__PURE__ */
|
|
174
|
+
}), /* @__PURE__ */ A("span", {
|
|
174
175
|
className: "flex items-center gap-2",
|
|
175
|
-
children: [/* @__PURE__ */
|
|
176
|
+
children: [/* @__PURE__ */ k("span", {
|
|
176
177
|
className: "text-sm font-semibold tabular-nums text-text-primary",
|
|
177
178
|
children: l(e.amount, e.currency)
|
|
178
|
-
}), /* @__PURE__ */
|
|
179
|
+
}), /* @__PURE__ */ k(i, { status: e.status })]
|
|
179
180
|
})]
|
|
180
181
|
}),
|
|
181
|
-
/* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ k("p", {
|
|
182
183
|
className: "text-xs text-text-secondary",
|
|
183
184
|
children: e.reason
|
|
184
185
|
}),
|
|
185
|
-
e.status === "COMPLETED" && /* @__PURE__ */
|
|
186
|
+
e.status === "COMPLETED" && /* @__PURE__ */ k("p", {
|
|
186
187
|
className: "text-xs text-text-secondary",
|
|
187
188
|
children: u("coolandlovely.orders.refundedToMethod", "Refunded {{date}} to your original payment method.", { date: c(e.refundedAt ?? e.createdAt) })
|
|
188
189
|
})
|
|
189
190
|
]
|
|
190
191
|
}, e.id))]
|
|
191
192
|
}),
|
|
192
|
-
|
|
193
|
+
/* @__PURE__ */ k(v, { order: B }),
|
|
194
|
+
(B.status === "PAID" || B.status === "PARTIALLY_REFUNDED") && (B.fulfilments?.length ?? 0) > 0 && /* @__PURE__ */ A(j, {
|
|
193
195
|
treatment: "plain",
|
|
194
196
|
className: "space-y-4 p-4",
|
|
195
|
-
children: [/* @__PURE__ */
|
|
197
|
+
children: [/* @__PURE__ */ k("p", {
|
|
196
198
|
className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
|
|
197
199
|
children: u("coolandlovely.orders.delivery", "Delivery")
|
|
198
|
-
}),
|
|
200
|
+
}), B.fulfilments?.map((e) => /* @__PURE__ */ A("div", {
|
|
199
201
|
className: "space-y-2",
|
|
200
202
|
"data-testid": "order-fulfilment",
|
|
201
|
-
children: [/* @__PURE__ */
|
|
203
|
+
children: [/* @__PURE__ */ A("div", {
|
|
202
204
|
className: "flex items-center justify-between gap-2",
|
|
203
|
-
children: [/* @__PURE__ */
|
|
205
|
+
children: [/* @__PURE__ */ k("span", {
|
|
204
206
|
className: "text-sm font-medium text-text-primary",
|
|
205
207
|
children: e.brandName ?? u("coolandlovely.orders.brand", "Brand")
|
|
206
|
-
}), /* @__PURE__ */
|
|
207
|
-
}), e.refunded ? /* @__PURE__ */
|
|
208
|
+
}), /* @__PURE__ */ k(i, { status: e.refunded ? "REFUNDED" : e.status })]
|
|
209
|
+
}), e.refunded ? /* @__PURE__ */ k("p", {
|
|
208
210
|
className: "text-xs text-text-secondary",
|
|
209
211
|
children: u("coolandlovely.orders.brandRefunded", "The brand refunded these pieces, so they will not be shipped.")
|
|
210
|
-
}) : e.status === "UNFULFILLED" ? /* @__PURE__ */
|
|
212
|
+
}) : e.status === "UNFULFILLED" ? /* @__PURE__ */ k("p", {
|
|
211
213
|
className: "text-xs text-text-secondary",
|
|
212
214
|
children: u("coolandlovely.orders.awaitingBrand", "Waiting for the brand to confirm your pieces.")
|
|
213
|
-
}) : /* @__PURE__ */
|
|
215
|
+
}) : /* @__PURE__ */ k(_, { fulfilment: e })]
|
|
214
216
|
}, e.brandId))]
|
|
215
217
|
}),
|
|
216
|
-
|
|
218
|
+
B.items.map((e) => /* @__PURE__ */ A(j, {
|
|
217
219
|
treatment: "plain",
|
|
218
220
|
className: "flex items-center gap-4 p-4",
|
|
219
221
|
children: [
|
|
220
|
-
/* @__PURE__ */
|
|
221
|
-
icon: /* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ k(s, {
|
|
223
|
+
icon: /* @__PURE__ */ k(C, { className: "h-5 w-5" }),
|
|
222
224
|
seed: e.styleItemId,
|
|
223
225
|
fileId: e.image?.id,
|
|
224
226
|
alt: e.name,
|
|
225
227
|
className: "h-14 w-14 shrink-0"
|
|
226
228
|
}),
|
|
227
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ A("div", {
|
|
228
230
|
className: "min-w-0 flex-1",
|
|
229
231
|
children: [
|
|
230
|
-
/* @__PURE__ */
|
|
232
|
+
/* @__PURE__ */ k("p", {
|
|
231
233
|
className: "truncate text-sm font-medium text-text-primary",
|
|
232
234
|
children: e.name
|
|
233
235
|
}),
|
|
234
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ k("p", {
|
|
235
237
|
className: "truncate text-xs text-text-secondary",
|
|
236
238
|
children: [
|
|
237
239
|
e.size,
|
|
@@ -239,118 +241,118 @@ function P() {
|
|
|
239
241
|
`× ${e.quantity}`
|
|
240
242
|
].filter(Boolean).join(" · ")
|
|
241
243
|
}),
|
|
242
|
-
e.isCreatorAttributed && /* @__PURE__ */
|
|
244
|
+
e.isCreatorAttributed && /* @__PURE__ */ A("p", {
|
|
243
245
|
className: "mt-0.5 inline-flex items-center gap-1 text-xs text-accent-primary",
|
|
244
|
-
children: [/* @__PURE__ */
|
|
246
|
+
children: [/* @__PURE__ */ k(T, { className: "h-3 w-3" }), u("coolandlovely.orders.supportsCreator", "Supports the creator of the look")]
|
|
245
247
|
})
|
|
246
248
|
]
|
|
247
249
|
}),
|
|
248
|
-
/* @__PURE__ */
|
|
250
|
+
/* @__PURE__ */ k("span", {
|
|
249
251
|
className: "text-sm font-semibold tabular-nums text-text-primary",
|
|
250
|
-
children: l(e.lineTotal,
|
|
252
|
+
children: l(e.lineTotal, B.currency)
|
|
251
253
|
})
|
|
252
254
|
]
|
|
253
255
|
}, e.id))
|
|
254
256
|
]
|
|
255
|
-
}), /* @__PURE__ */
|
|
257
|
+
}), /* @__PURE__ */ A(j, {
|
|
256
258
|
treatment: "glass",
|
|
257
259
|
className: "h-fit space-y-4 p-6",
|
|
258
260
|
children: [
|
|
259
|
-
/* @__PURE__ */
|
|
261
|
+
/* @__PURE__ */ A("div", {
|
|
260
262
|
className: "flex items-center justify-between",
|
|
261
|
-
children: [/* @__PURE__ */
|
|
263
|
+
children: [/* @__PURE__ */ k("span", {
|
|
262
264
|
className: "text-sm text-text-secondary",
|
|
263
265
|
children: u("coolandlovely.orders.status", "Status")
|
|
264
|
-
}), /* @__PURE__ */
|
|
266
|
+
}), /* @__PURE__ */ k("span", {
|
|
265
267
|
"data-testid": "order-status",
|
|
266
|
-
children: /* @__PURE__ */
|
|
268
|
+
children: /* @__PURE__ */ k(i, { status: B.status })
|
|
267
269
|
})]
|
|
268
270
|
}),
|
|
269
|
-
/* @__PURE__ */
|
|
271
|
+
/* @__PURE__ */ A("dl", {
|
|
270
272
|
className: "space-y-2 text-sm",
|
|
271
273
|
children: [
|
|
272
|
-
/* @__PURE__ */
|
|
274
|
+
/* @__PURE__ */ A("div", {
|
|
273
275
|
className: "flex justify-between",
|
|
274
|
-
children: [/* @__PURE__ */
|
|
276
|
+
children: [/* @__PURE__ */ k("dt", {
|
|
275
277
|
className: "text-text-secondary",
|
|
276
278
|
children: u("coolandlovely.checkout.subtotal", "Subtotal")
|
|
277
|
-
}), /* @__PURE__ */
|
|
279
|
+
}), /* @__PURE__ */ k("dd", {
|
|
278
280
|
className: "tabular-nums text-text-primary",
|
|
279
|
-
children: l(
|
|
281
|
+
children: l(B.subtotal, B.currency)
|
|
280
282
|
})]
|
|
281
283
|
}),
|
|
282
|
-
/* @__PURE__ */
|
|
284
|
+
/* @__PURE__ */ A("div", {
|
|
283
285
|
className: "flex justify-between",
|
|
284
|
-
children: [/* @__PURE__ */
|
|
286
|
+
children: [/* @__PURE__ */ k("dt", {
|
|
285
287
|
className: "text-text-secondary",
|
|
286
288
|
children: u("coolandlovely.checkout.tax", "Tax")
|
|
287
|
-
}), /* @__PURE__ */
|
|
289
|
+
}), /* @__PURE__ */ k("dd", {
|
|
288
290
|
className: "tabular-nums text-text-primary",
|
|
289
|
-
children: l(
|
|
291
|
+
children: l(B.taxAmount, B.currency)
|
|
290
292
|
})]
|
|
291
293
|
}),
|
|
292
|
-
/* @__PURE__ */
|
|
294
|
+
/* @__PURE__ */ A("div", {
|
|
293
295
|
className: "flex justify-between border-t border-border-seam pt-2 text-base font-semibold",
|
|
294
|
-
children: [/* @__PURE__ */
|
|
296
|
+
children: [/* @__PURE__ */ k("dt", {
|
|
295
297
|
className: "text-text-primary",
|
|
296
298
|
children: u("coolandlovely.checkout.total", "Total")
|
|
297
|
-
}), /* @__PURE__ */
|
|
299
|
+
}), /* @__PURE__ */ k("dd", {
|
|
298
300
|
className: "tabular-nums text-text-primary",
|
|
299
|
-
children: l(
|
|
301
|
+
children: l(B.total, B.currency)
|
|
300
302
|
})]
|
|
301
303
|
}),
|
|
302
|
-
|
|
304
|
+
B.refundedAmount > 0 && /* @__PURE__ */ A("div", {
|
|
303
305
|
className: "flex justify-between",
|
|
304
306
|
"data-testid": "order-refunded-amount",
|
|
305
|
-
children: [/* @__PURE__ */
|
|
307
|
+
children: [/* @__PURE__ */ k("dt", {
|
|
306
308
|
className: "text-text-secondary",
|
|
307
309
|
children: u("coolandlovely.orders.refunded", "Refunded")
|
|
308
|
-
}), /* @__PURE__ */
|
|
310
|
+
}), /* @__PURE__ */ A("dd", {
|
|
309
311
|
className: "tabular-nums text-text-primary",
|
|
310
|
-
children: ["− ", l(
|
|
312
|
+
children: ["− ", l(B.refundedAmount, B.currency)]
|
|
311
313
|
})]
|
|
312
314
|
})
|
|
313
315
|
]
|
|
314
316
|
}),
|
|
315
|
-
|
|
317
|
+
B.shippingAddress && /* @__PURE__ */ A("div", {
|
|
316
318
|
className: "border-t border-border-seam pt-3 text-sm",
|
|
317
319
|
children: [
|
|
318
|
-
/* @__PURE__ */
|
|
320
|
+
/* @__PURE__ */ k("p", {
|
|
319
321
|
className: "mb-1 text-xs font-medium uppercase tracking-wide text-text-secondary",
|
|
320
322
|
children: u("coolandlovely.orders.shipTo", "Ship to")
|
|
321
323
|
}),
|
|
322
|
-
/* @__PURE__ */
|
|
324
|
+
/* @__PURE__ */ k("p", {
|
|
323
325
|
className: "text-text-primary",
|
|
324
|
-
children:
|
|
326
|
+
children: B.shippingName
|
|
325
327
|
}),
|
|
326
|
-
/* @__PURE__ */
|
|
328
|
+
/* @__PURE__ */ k("p", {
|
|
327
329
|
className: "whitespace-pre-line text-text-secondary",
|
|
328
|
-
children:
|
|
330
|
+
children: B.shippingAddress
|
|
329
331
|
})
|
|
330
332
|
]
|
|
331
333
|
}),
|
|
332
|
-
|
|
334
|
+
B.paidAt && /* @__PURE__ */ k("p", {
|
|
333
335
|
className: "text-xs text-text-secondary",
|
|
334
336
|
children: u("coolandlovely.orders.paidOn", "Paid {{date}} via {{provider}}", {
|
|
335
|
-
date: c(
|
|
336
|
-
provider:
|
|
337
|
+
date: c(B.paidAt),
|
|
338
|
+
provider: B.paymentProvider ?? "—"
|
|
337
339
|
})
|
|
338
340
|
}),
|
|
339
|
-
|
|
341
|
+
H && /* @__PURE__ */ k("p", {
|
|
340
342
|
className: "text-sm text-status-error-text",
|
|
341
|
-
children:
|
|
343
|
+
children: H.message
|
|
342
344
|
}),
|
|
343
|
-
|
|
344
|
-
checkout:
|
|
345
|
+
V && (L ? /* @__PURE__ */ k(g, {
|
|
346
|
+
checkout: L,
|
|
345
347
|
onSettle: async () => {
|
|
346
|
-
await
|
|
348
|
+
await F.mutateAsync(B.id).catch(() => void 0), R(null);
|
|
347
349
|
}
|
|
348
|
-
}) : /* @__PURE__ */
|
|
350
|
+
}) : /* @__PURE__ */ A("button", {
|
|
349
351
|
type: "button",
|
|
350
|
-
disabled:
|
|
351
|
-
onClick: () =>
|
|
352
|
+
disabled: P.isPending,
|
|
353
|
+
onClick: () => P.mutate(B.id, { onSuccess: (e) => R(e) }),
|
|
352
354
|
className: "inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2.5 text-sm font-semibold text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50",
|
|
353
|
-
children: [
|
|
355
|
+
children: [P.isPending && /* @__PURE__ */ k(S, { className: "h-4 w-4 animate-spin" }), u("coolandlovely.orders.payNow", "Pay now")]
|
|
354
356
|
}))
|
|
355
357
|
]
|
|
356
358
|
})]
|
|
@@ -358,6 +360,6 @@ function P() {
|
|
|
358
360
|
});
|
|
359
361
|
}
|
|
360
362
|
//#endregion
|
|
361
|
-
export {
|
|
363
|
+
export { F as OrderDetailPage, P as OrdersPage };
|
|
362
364
|
|
|
363
365
|
//# sourceMappingURL=OrdersPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrdersPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/commerce/OrdersPage.tsx"],"sourcesContent":["/**\n * My Orders + Order detail (BOFF-3370)\n * @module coolandlovely/pages/commerce\n *\n * The shopper's own orders (`cooMyOrders` / `cooMyOrder`). An unpaid order can be paid\n * (`cooResumeOrderPayment` re-uses its billing order), re-checked against billing\n * (`cooSyncOrderPayment`) or cancelled (`cooCancelOrder`). Brand refunds (BOFF-9702) show on\n * the order with their amount and reason.\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router';\nimport {\n ArrowLeft,\n ChevronRight,\n Loader2,\n Package,\n RefreshCw,\n Sparkles,\n XCircle,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\n\nimport { EmptyState } from '../../components/EmptyState';\nimport { FulfilmentTimeline } from '../../components/FulfilmentTimeline';\nimport { PageLayout } from '../../components/PageLayout';\nimport { PayForOrder } from '../../components/PayForOrder';\nimport { ErrorView, LoadingView } from '../../components/StateViews';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useTr } from '../../hooks';\nimport {\n useCancelOrder,\n useMyOrder,\n useMyOrders,\n useResumeOrderPayment,\n useSyncOrderPayment,\n} from '../../hooks/useCommerceApi';\nimport type { CooOrderCheckout, CooOrderStatus } from '../../types';\nimport { cn } from '../../utils/cn';\nimport { formatDate, formatPrice } from '../../utils/formatters';\n\nconst FILTERS: Array<{ value: CooOrderStatus | undefined; key: string; label: string }> = [\n { value: undefined, key: 'coolandlovely.orders.filterAll', label: 'All' },\n {\n value: 'PENDING_PAYMENT',\n key: 'coolandlovely.orders.filterPending',\n label: 'Awaiting payment',\n },\n { value: 'PAID', key: 'coolandlovely.orders.filterPaid', label: 'Paid' },\n {\n value: 'PARTIALLY_REFUNDED',\n key: 'coolandlovely.orders.filterPartiallyRefunded',\n label: 'Partly refunded',\n },\n { value: 'REFUNDED', key: 'coolandlovely.orders.filterRefunded', label: 'Refunded' },\n { value: 'CANCELLED', key: 'coolandlovely.orders.filterCancelled', label: 'Cancelled' },\n];\n\nconst secondaryButton =\n 'inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50';\n\nexport function OrdersPage() {\n const tr = useTr();\n const { navigateTo } = useCoolAndLovely();\n const [status, setStatus] = useState<CooOrderStatus | undefined>(undefined);\n const orders = useMyOrders(status);\n const title = tr('coolandlovely.orders.title', 'My orders');\n\n return (\n <PageLayout\n title={title}\n description={tr('coolandlovely.orders.description', 'Everything you have ordered.')}\n >\n <div className=\"mb-4 flex flex-wrap gap-2\" role=\"tablist\">\n {FILTERS.map((filter) => (\n <button\n key={filter.key}\n type=\"button\"\n role=\"tab\"\n aria-selected={status === filter.value}\n onClick={() => setStatus(filter.value)}\n className={cn(\n 'rounded-full border px-3 py-1 text-sm font-medium transition-colors',\n status === filter.value\n ? 'border-action-primary-bg bg-action-primary-bg text-action-primary-text'\n : 'border-border-seam text-text-primary hover:bg-bg-sunken'\n )}\n >\n {tr(filter.key, filter.label)}\n </button>\n ))}\n </div>\n {orders.isLoading ? (\n <LoadingView label={tr('coolandlovely.orders.loading', 'Loading orders…')} />\n ) : orders.isError || !orders.data ? (\n <ErrorView onRetry={() => void orders.refetch()} />\n ) : orders.data.items.length === 0 ? (\n <EmptyState\n icon={<Package className=\"h-8 w-8\" />}\n title={tr('coolandlovely.orders.emptyTitle', 'No orders yet')}\n description={tr('coolandlovely.orders.emptyDescription', 'Orders you place appear here.')}\n />\n ) : (\n <div className=\"space-y-3\" data-testid=\"orders-list\">\n {orders.data.items.map((order) => (\n <button\n key={order.id}\n type=\"button\"\n onClick={() => navigateTo(`/orders/${order.id}`)}\n className=\"flex w-full items-center gap-4 rounded-xl border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-mono text-sm font-medium text-text-primary\">\n {order.orderNumber}\n </p>\n <p className=\"truncate text-xs text-text-secondary\">\n {formatDate(order.createdAt)} ·{' '}\n {tr('coolandlovely.orders.pieces', '{{count}} pieces', {\n count: order.itemCount,\n })}\n </p>\n </div>\n <StatusBadge status={order.status} />\n <span className=\"w-28 text-right text-sm font-semibold tabular-nums text-text-primary\">\n {formatPrice(order.total, order.currency)}\n </span>\n <ChevronRight className=\"h-4 w-4 text-text-secondary\" />\n </button>\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n\nexport function OrderDetailPage() {\n const tr = useTr();\n const { orderId } = useParams<{ orderId: string }>();\n const { navigateTo } = useCoolAndLovely();\n const order = useMyOrder(orderId);\n const resume = useResumeOrderPayment();\n const sync = useSyncOrderPayment();\n const cancel = useCancelOrder();\n const [session, setSession] = useState<CooOrderCheckout | null>(null);\n const title = tr('coolandlovely.orders.detailTitle', 'Order');\n\n if (order.isLoading) {\n return (\n <PageLayout title={title}>\n <LoadingView />\n </PageLayout>\n );\n }\n if (order.isError || !order.data) {\n return (\n <PageLayout title={title}>\n <ErrorView\n title={tr('coolandlovely.orders.notFound', 'Order not found')}\n onRetry={() => void order.refetch()}\n />\n </PageLayout>\n );\n }\n\n const data = order.data;\n const pending = data.status === 'PENDING_PAYMENT';\n const actionError = resume.error ?? sync.error ?? cancel.error;\n\n const settle = async () => {\n await sync.mutateAsync(data.id).catch(() => undefined);\n setSession(null);\n };\n\n return (\n <PageLayout\n title={data.orderNumber}\n description={formatDate(data.createdAt)}\n actions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <button type=\"button\" onClick={() => navigateTo('/orders')} className={secondaryButton}>\n <ArrowLeft className=\"h-4 w-4\" /> {tr('coolandlovely.common.back', 'Back')}\n </button>\n {pending && (\n <>\n <button\n type=\"button\"\n disabled={sync.isPending}\n onClick={() => sync.mutate(data.id)}\n className={secondaryButton}\n >\n {sync.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <RefreshCw className=\"h-4 w-4\" />\n )}\n {tr('coolandlovely.orders.checkPayment', 'Check payment')}\n </button>\n <button\n type=\"button\"\n disabled={cancel.isPending}\n onClick={() => cancel.mutate(data.id)}\n className={cn(\n secondaryButton,\n 'text-status-error-text hover:bg-status-error-bg-subtle'\n )}\n >\n <XCircle className=\"h-4 w-4\" /> {tr('coolandlovely.orders.cancel', 'Cancel order')}\n </button>\n </>\n )}\n </div>\n }\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <div className=\"space-y-3 lg:col-span-2\">\n {(data.refunds?.length ?? 0) > 0 && (\n <GlassCard treatment=\"plain\" className=\"space-y-3 p-4\" data-testid=\"order-refunds\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.orders.refunds', 'Refunds')}\n </p>\n {data.refunds?.map((refund) => (\n <div key={refund.id} className=\"space-y-1\" data-testid=\"order-refund\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {refund.brandName ?? tr('coolandlovely.orders.brand', 'Brand')}\n </span>\n <span className=\"flex items-center gap-2\">\n <span className=\"text-sm font-semibold tabular-nums text-text-primary\">\n {formatPrice(refund.amount, refund.currency)}\n </span>\n <StatusBadge status={refund.status} />\n </span>\n </div>\n <p className=\"text-xs text-text-secondary\">{refund.reason}</p>\n {refund.status === 'COMPLETED' && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'coolandlovely.orders.refundedToMethod',\n 'Refunded {{date}} to your original payment method.',\n { date: formatDate(refund.refundedAt ?? refund.createdAt) }\n )}\n </p>\n )}\n </div>\n ))}\n </GlassCard>\n )}\n {(data.status === 'PAID' || data.status === 'PARTIALLY_REFUNDED') &&\n (data.fulfilments?.length ?? 0) > 0 && (\n <GlassCard treatment=\"plain\" className=\"space-y-4 p-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.orders.delivery', 'Delivery')}\n </p>\n {data.fulfilments?.map((fulfilment) => (\n <div\n key={fulfilment.brandId}\n className=\"space-y-2\"\n data-testid=\"order-fulfilment\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {fulfilment.brandName ?? tr('coolandlovely.orders.brand', 'Brand')}\n </span>\n <StatusBadge status={fulfilment.refunded ? 'REFUNDED' : fulfilment.status} />\n </div>\n {fulfilment.refunded ? (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'coolandlovely.orders.brandRefunded',\n 'The brand refunded these pieces, so they will not be shipped.'\n )}\n </p>\n ) : fulfilment.status === 'UNFULFILLED' ? (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'coolandlovely.orders.awaitingBrand',\n 'Waiting for the brand to confirm your pieces.'\n )}\n </p>\n ) : (\n <FulfilmentTimeline fulfilment={fulfilment} />\n )}\n </div>\n ))}\n </GlassCard>\n )}\n {data.items.map((item) => (\n <GlassCard key={item.id} treatment=\"plain\" className=\"flex items-center gap-4 p-4\">\n <Thumbnail\n icon={<Package className=\"h-5 w-5\" />}\n seed={item.styleItemId}\n fileId={item.image?.id}\n alt={item.name}\n className=\"h-14 w-14 shrink-0\"\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{item.name}</p>\n <p className=\"truncate text-xs text-text-secondary\">\n {[item.size, item.colour, `× ${item.quantity}`].filter(Boolean).join(' · ')}\n </p>\n {item.isCreatorAttributed && (\n <p className=\"mt-0.5 inline-flex items-center gap-1 text-xs text-accent-primary\">\n <Sparkles className=\"h-3 w-3\" />\n {tr('coolandlovely.orders.supportsCreator', 'Supports the creator of the look')}\n </p>\n )}\n </div>\n <span className=\"text-sm font-semibold tabular-nums text-text-primary\">\n {formatPrice(item.lineTotal, data.currency)}\n </span>\n </GlassCard>\n ))}\n </div>\n <GlassCard treatment=\"glass\" className=\"h-fit space-y-4 p-6\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr('coolandlovely.orders.status', 'Status')}\n </span>\n <span data-testid=\"order-status\">\n <StatusBadge status={data.status} />\n </span>\n </div>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">\n {tr('coolandlovely.checkout.subtotal', 'Subtotal')}\n </dt>\n <dd className=\"tabular-nums text-text-primary\">\n {formatPrice(data.subtotal, data.currency)}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">{tr('coolandlovely.checkout.tax', 'Tax')}</dt>\n <dd className=\"tabular-nums text-text-primary\">\n {formatPrice(data.taxAmount, data.currency)}\n </dd>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2 text-base font-semibold\">\n <dt className=\"text-text-primary\">{tr('coolandlovely.checkout.total', 'Total')}</dt>\n <dd className=\"tabular-nums text-text-primary\">\n {formatPrice(data.total, data.currency)}\n </dd>\n </div>\n {data.refundedAmount > 0 && (\n <div className=\"flex justify-between\" data-testid=\"order-refunded-amount\">\n <dt className=\"text-text-secondary\">\n {tr('coolandlovely.orders.refunded', 'Refunded')}\n </dt>\n <dd className=\"tabular-nums text-text-primary\">\n − {formatPrice(data.refundedAmount, data.currency)}\n </dd>\n </div>\n )}\n </dl>\n {data.shippingAddress && (\n <div className=\"border-t border-border-seam pt-3 text-sm\">\n <p className=\"mb-1 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.orders.shipTo', 'Ship to')}\n </p>\n <p className=\"text-text-primary\">{data.shippingName}</p>\n <p className=\"whitespace-pre-line text-text-secondary\">{data.shippingAddress}</p>\n </div>\n )}\n {data.paidAt && (\n <p className=\"text-xs text-text-secondary\">\n {tr('coolandlovely.orders.paidOn', 'Paid {{date}} via {{provider}}', {\n date: formatDate(data.paidAt),\n provider: data.paymentProvider ?? '—',\n })}\n </p>\n )}\n {actionError && <p className=\"text-sm text-status-error-text\">{actionError.message}</p>}\n {pending &&\n (session ? (\n <PayForOrder checkout={session} onSettle={settle} />\n ) : (\n <button\n type=\"button\"\n disabled={resume.isPending}\n onClick={() =>\n resume.mutate(data.id, { onSuccess: (result) => setSession(result) })\n }\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2.5 text-sm font-semibold text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {resume.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr('coolandlovely.orders.payNow', 'Pay now')}\n </button>\n ))}\n </GlassCard>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA2CA,IAAM,IAAoF;CACxF;EAAE,OAAO,KAAA;EAAW,KAAK;EAAkC,OAAO;EAAO;CACzE;EACE,OAAO;EACP,KAAK;EACL,OAAO;EACR;CACD;EAAE,OAAO;EAAQ,KAAK;EAAmC,OAAO;EAAQ;CACxE;EACE,OAAO;EACP,KAAK;EACL,OAAO;EACR;CACD;EAAE,OAAO;EAAY,KAAK;EAAuC,OAAO;EAAY;CACpF;EAAE,OAAO;EAAa,KAAK;EAAwC,OAAO;EAAa;CACxF,EAEK,IACJ;AAEF,SAAgB,IAAa;CAC3B,IAAM,IAAK,GAAO,EACZ,EAAE,kBAAe,GAAkB,EACnC,CAAC,GAAQ,KAAa,EAAqC,KAAA,EAAU,EACrE,IAAS,EAAY,EAAO;AAGlC,QACE,kBAAC,GAAD;EACS,OAJG,EAAG,8BAA8B,YAAY;EAKvD,aAAa,EAAG,oCAAoC,+BAA+B;YAFrF,CAIE,kBAAC,OAAD;GAAK,WAAU;GAA4B,MAAK;aAC7C,EAAQ,KAAK,MACZ,kBAAC,UAAD;IAEE,MAAK;IACL,MAAK;IACL,iBAAe,MAAW,EAAO;IACjC,eAAe,EAAU,EAAO,MAAM;IACtC,WAAW,EACT,uEACA,MAAW,EAAO,QACd,2EACA,0DACL;cAEA,EAAG,EAAO,KAAK,EAAO,MAAM;IACtB,EAbF,EAAO,IAaL,CACT;GACE,CAAA,EACL,EAAO,YACN,kBAAC,GAAD,EAAa,OAAO,EAAG,gCAAgC,kBAAkB,EAAI,CAAA,GAC3E,EAAO,WAAW,CAAC,EAAO,OAC5B,kBAAC,GAAD,EAAW,eAAe,KAAK,EAAO,SAAS,EAAI,CAAA,GACjD,EAAO,KAAK,MAAM,WAAW,IAC/B,kBAAC,GAAD;GACE,MAAM,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;GACrC,OAAO,EAAG,mCAAmC,gBAAgB;GAC7D,aAAa,EAAG,yCAAyC,gCAAgC;GACzF,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;GAAY,eAAY;aACpC,EAAO,KAAK,MAAM,KAAK,MACtB,kBAAC,UAAD;IAEE,MAAK;IACL,eAAe,EAAW,WAAW,EAAM,KAAK;IAChD,WAAU;cAJZ;KAME,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAM;OACL,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAW,EAAM,UAAU;QAAC;QAAG;QAC/B,EAAG,+BAA+B,oBAAoB,EACrD,OAAO,EAAM,WACd,CAAC;QACA;SACA;;KACN,kBAAC,GAAD,EAAa,QAAQ,EAAM,QAAU,CAAA;KACrC,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAY,EAAM,OAAO,EAAM,SAAS;MACpC,CAAA;KACP,kBAAC,GAAD,EAAc,WAAU,+BAAgC,CAAA;KACjD;MArBF,EAAM,GAqBJ,CACT;GACE,CAAA,CAEG;;;AAIjB,SAAgB,IAAkB;CAChC,IAAM,IAAK,GAAO,EACZ,EAAE,eAAY,GAAgC,EAC9C,EAAE,kBAAe,GAAkB,EACnC,IAAQ,EAAW,EAAQ,EAC3B,IAAS,GAAuB,EAChC,IAAO,GAAqB,EAC5B,IAAS,GAAgB,EACzB,CAAC,GAAS,KAAc,EAAkC,KAAK,EAC/D,IAAQ,EAAG,oCAAoC,QAAQ;AAE7D,KAAI,EAAM,UACR,QACE,kBAAC,GAAD;EAAmB;YACjB,kBAAC,GAAD,EAAe,CAAA;EACJ,CAAA;AAGjB,KAAI,EAAM,WAAW,CAAC,EAAM,KAC1B,QACE,kBAAC,GAAD;EAAmB;YACjB,kBAAC,GAAD;GACE,OAAO,EAAG,iCAAiC,kBAAkB;GAC7D,eAAe,KAAK,EAAM,SAAS;GACnC,CAAA;EACS,CAAA;CAIjB,IAAM,IAAO,EAAM,MACb,IAAU,EAAK,WAAW,mBAC1B,IAAc,EAAO,SAAS,EAAK,SAAS,EAAO;AAOzD,QACE,kBAAC,GAAD;EACE,OAAO,EAAK;EACZ,aAAa,EAAW,EAAK,UAAU;EACvC,SACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,UAAD;IAAQ,MAAK;IAAS,eAAe,EAAW,UAAU;IAAE,WAAW;cAAvE;KACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;;KAAE,EAAG,6BAA6B,OAAO;KACnE;OACR,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;IACE,MAAK;IACL,UAAU,EAAK;IACf,eAAe,EAAK,OAAO,EAAK,GAAG;IACnC,WAAW;cAJb,CAMG,EAAK,YACJ,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,GAE5C,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAElC,EAAG,qCAAqC,gBAAgB,CAClD;OACT,kBAAC,UAAD;IACE,MAAK;IACL,UAAU,EAAO;IACjB,eAAe,EAAO,OAAO,EAAK,GAAG;IACrC,WAAW,EACT,GACA,yDACD;cAPH;KASE,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;;KAAE,EAAG,+BAA+B,eAAe;KAC3E;MACR,EAAA,CAAA,CAED;;YAGR,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf;MACI,EAAK,SAAS,UAAU,KAAK,KAC7B,kBAAC,GAAD;MAAW,WAAU;MAAQ,WAAU;MAAgB,eAAY;gBAAnE,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAG,gCAAgC,UAAU;OAC5C,CAAA,EACH,EAAK,SAAS,KAAK,MAClB,kBAAC,OAAD;OAAqB,WAAU;OAAY,eAAY;iBAAvD;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAO,aAAa,EAAG,8BAA8B,QAAQ;UACzD,CAAA,EACP,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CACE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAY,EAAO,QAAQ,EAAO,SAAS;WACvC,CAAA,EACP,kBAAC,GAAD,EAAa,QAAQ,EAAO,QAAU,CAAA,CACjC;YACH;;QACN,kBAAC,KAAD;SAAG,WAAU;mBAA+B,EAAO;SAAW,CAAA;QAC7D,EAAO,WAAW,eACjB,kBAAC,KAAD;SAAG,WAAU;mBACV,EACC,yCACA,sDACA,EAAE,MAAM,EAAW,EAAO,cAAc,EAAO,UAAU,EAAE,CAC5D;SACC,CAAA;QAEF;SAtBI,EAAO,GAsBX,CACN,CACQ;;MAEZ,EAAK,WAAW,UAAU,EAAK,WAAW,0BACzC,EAAK,aAAa,UAAU,KAAK,KAChC,kBAAC,GAAD;MAAW,WAAU;MAAQ,WAAU;gBAAvC,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAG,iCAAiC,WAAW;OAC9C,CAAA,EACH,EAAK,aAAa,KAAK,MACtB,kBAAC,OAAD;OAEE,WAAU;OACV,eAAY;iBAHd,CAKE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAW,aAAa,EAAG,8BAA8B,QAAQ;SAC7D,CAAA,EACP,kBAAC,GAAD,EAAa,QAAQ,EAAW,WAAW,aAAa,EAAW,QAAU,CAAA,CACzE;WACL,EAAW,WACV,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,sCACA,gEACD;QACC,CAAA,GACF,EAAW,WAAW,gBACxB,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,sCACA,gDACD;QACC,CAAA,GAEJ,kBAAC,GAAD,EAAgC,eAAc,CAAA,CAE5C;SA3BC,EAAW,QA2BZ,CACN,CACQ;;KAEf,EAAK,MAAM,KAAK,MACf,kBAAC,GAAD;MAAyB,WAAU;MAAQ,WAAU;gBAArD;OACE,kBAAC,GAAD;QACE,MAAM,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;QACrC,MAAM,EAAK;QACX,QAAQ,EAAK,OAAO;QACpB,KAAK,EAAK;QACV,WAAU;QACV,CAAA;OACF,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,KAAD;UAAG,WAAU;oBAAkD,EAAK;UAAS,CAAA;SAC7E,kBAAC,KAAD;UAAG,WAAU;oBACV;WAAC,EAAK;WAAM,EAAK;WAAQ,KAAK,EAAK;WAAW,CAAC,OAAO,QAAQ,CAAC,KAAK,MAAM;UACzE,CAAA;SACH,EAAK,uBACJ,kBAAC,KAAD;UAAG,WAAU;oBAAb,CACE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAC/B,EAAG,wCAAwC,mCAAmC,CAC7E;;SAEF;;OACN,kBAAC,QAAD;QAAM,WAAU;kBACb,EAAY,EAAK,WAAW,EAAK,SAAS;QACtC,CAAA;OACG;QAvBI,EAAK,GAuBT,CACZ;KACE;OACN,kBAAC,GAAD;IAAW,WAAU;IAAQ,WAAU;cAAvC;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAG,+BAA+B,SAAS;OACvC,CAAA,EACP,kBAAC,QAAD;OAAM,eAAY;iBAChB,kBAAC,GAAD,EAAa,QAAQ,EAAK,QAAU,CAAA;OAC/B,CAAA,CACH;;KACN,kBAAC,MAAD;MAAI,WAAU;gBAAd;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAG,mCAAmC,WAAW;SAC/C,CAAA,EACL,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAY,EAAK,UAAU,EAAK,SAAS;SACvC,CAAA,CACD;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBAAuB,EAAG,8BAA8B,MAAM;SAAM,CAAA,EAClF,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAY,EAAK,WAAW,EAAK,SAAS;SACxC,CAAA,CACD;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBAAqB,EAAG,gCAAgC,QAAQ;SAAM,CAAA,EACpF,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAY,EAAK,OAAO,EAAK,SAAS;SACpC,CAAA,CACD;;OACL,EAAK,iBAAiB,KACrB,kBAAC,OAAD;QAAK,WAAU;QAAuB,eAAY;kBAAlD,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAG,iCAAiC,WAAW;SAC7C,CAAA,EACL,kBAAC,MAAD;SAAI,WAAU;mBAAd,CAA+C,MAC1C,EAAY,EAAK,gBAAgB,EAAK,SAAS,CAC/C;WACD;;OAEL;;KACJ,EAAK,mBACJ,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAG,+BAA+B,UAAU;QAC3C,CAAA;OACJ,kBAAC,KAAD;QAAG,WAAU;kBAAqB,EAAK;QAAiB,CAAA;OACxD,kBAAC,KAAD;QAAG,WAAU;kBAA2C,EAAK;QAAoB,CAAA;OAC7E;;KAEP,EAAK,UACJ,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAG,+BAA+B,kCAAkC;OACnE,MAAM,EAAW,EAAK,OAAO;OAC7B,UAAU,EAAK,mBAAmB;OACnC,CAAC;MACA,CAAA;KAEL,KAAe,kBAAC,KAAD;MAAG,WAAU;gBAAkC,EAAY;MAAY,CAAA;KACtF,MACE,IACC,kBAAC,GAAD;MAAa,UAAU;MAAS,UA9M7B,YAAY;AAEzB,OADA,MAAM,EAAK,YAAY,EAAK,GAAG,CAAC,YAAY,KAAA,EAAU,EACtD,EAAW,KAAK;;MA4M8C,CAAA,GAEpD,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,EAAO;MACjB,eACE,EAAO,OAAO,EAAK,IAAI,EAAE,YAAY,MAAW,EAAW,EAAO,EAAE,CAAC;MAEvE,WAAU;gBANZ,CAQG,EAAO,aAAa,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,EAChE,EAAG,+BAA+B,UAAU,CACtC;;KAEH;MACR;;EACK,CAAA"}
|
|
1
|
+
{"version":3,"file":"OrdersPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/commerce/OrdersPage.tsx"],"sourcesContent":["/**\n * My Orders + Order detail (BOFF-3370)\n * @module coolandlovely/pages/commerce\n *\n * The shopper's own orders (`cooMyOrders` / `cooMyOrder`). An unpaid order can be paid\n * (`cooResumeOrderPayment` re-uses its billing order), re-checked against billing\n * (`cooSyncOrderPayment`) or cancelled (`cooCancelOrder`). Brand refunds (BOFF-9702) show on\n * the order with their amount and reason. Inside the return window the shopper can ask a brand to\n * take back its pieces (`cooRequestReturn`, BOFF-9900) and sees the brand's decision.\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router';\nimport {\n ArrowLeft,\n ChevronRight,\n Loader2,\n Package,\n RefreshCw,\n Sparkles,\n XCircle,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\n\nimport { EmptyState } from '../../components/EmptyState';\nimport { FulfilmentTimeline } from '../../components/FulfilmentTimeline';\nimport { PageLayout } from '../../components/PageLayout';\nimport { PayForOrder } from '../../components/PayForOrder';\nimport { OrderReturns } from '../../components/ReturnRequests';\nimport { ErrorView, LoadingView } from '../../components/StateViews';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useTr } from '../../hooks';\nimport {\n useCancelOrder,\n useMyOrder,\n useMyOrders,\n useResumeOrderPayment,\n useSyncOrderPayment,\n} from '../../hooks/useCommerceApi';\nimport type { CooOrderCheckout, CooOrderStatus } from '../../types';\nimport { cn } from '../../utils/cn';\nimport { formatDate, formatPrice } from '../../utils/formatters';\n\nconst FILTERS: Array<{ value: CooOrderStatus | undefined; key: string; label: string }> = [\n { value: undefined, key: 'coolandlovely.orders.filterAll', label: 'All' },\n {\n value: 'PENDING_PAYMENT',\n key: 'coolandlovely.orders.filterPending',\n label: 'Awaiting payment',\n },\n { value: 'PAID', key: 'coolandlovely.orders.filterPaid', label: 'Paid' },\n {\n value: 'PARTIALLY_REFUNDED',\n key: 'coolandlovely.orders.filterPartiallyRefunded',\n label: 'Partly refunded',\n },\n { value: 'REFUNDED', key: 'coolandlovely.orders.filterRefunded', label: 'Refunded' },\n { value: 'CANCELLED', key: 'coolandlovely.orders.filterCancelled', label: 'Cancelled' },\n];\n\nconst secondaryButton =\n 'inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50';\n\nexport function OrdersPage() {\n const tr = useTr();\n const { navigateTo } = useCoolAndLovely();\n const [status, setStatus] = useState<CooOrderStatus | undefined>(undefined);\n const orders = useMyOrders(status);\n const title = tr('coolandlovely.orders.title', 'My orders');\n\n return (\n <PageLayout\n title={title}\n description={tr('coolandlovely.orders.description', 'Everything you have ordered.')}\n >\n <div className=\"mb-4 flex flex-wrap gap-2\" role=\"tablist\">\n {FILTERS.map((filter) => (\n <button\n key={filter.key}\n type=\"button\"\n role=\"tab\"\n aria-selected={status === filter.value}\n onClick={() => setStatus(filter.value)}\n className={cn(\n 'rounded-full border px-3 py-1 text-sm font-medium transition-colors',\n status === filter.value\n ? 'border-action-primary-bg bg-action-primary-bg text-action-primary-text'\n : 'border-border-seam text-text-primary hover:bg-bg-sunken'\n )}\n >\n {tr(filter.key, filter.label)}\n </button>\n ))}\n </div>\n {orders.isLoading ? (\n <LoadingView label={tr('coolandlovely.orders.loading', 'Loading orders…')} />\n ) : orders.isError || !orders.data ? (\n <ErrorView onRetry={() => void orders.refetch()} />\n ) : orders.data.items.length === 0 ? (\n <EmptyState\n icon={<Package className=\"h-8 w-8\" />}\n title={tr('coolandlovely.orders.emptyTitle', 'No orders yet')}\n description={tr('coolandlovely.orders.emptyDescription', 'Orders you place appear here.')}\n />\n ) : (\n <div className=\"space-y-3\" data-testid=\"orders-list\">\n {orders.data.items.map((order) => (\n <button\n key={order.id}\n type=\"button\"\n onClick={() => navigateTo(`/orders/${order.id}`)}\n className=\"flex w-full items-center gap-4 rounded-xl border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-mono text-sm font-medium text-text-primary\">\n {order.orderNumber}\n </p>\n <p className=\"truncate text-xs text-text-secondary\">\n {formatDate(order.createdAt)} ·{' '}\n {tr('coolandlovely.orders.pieces', '{{count}} pieces', {\n count: order.itemCount,\n })}\n </p>\n </div>\n <StatusBadge status={order.status} />\n <span className=\"w-28 text-right text-sm font-semibold tabular-nums text-text-primary\">\n {formatPrice(order.total, order.currency)}\n </span>\n <ChevronRight className=\"h-4 w-4 text-text-secondary\" />\n </button>\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n\nexport function OrderDetailPage() {\n const tr = useTr();\n const { orderId } = useParams<{ orderId: string }>();\n const { navigateTo } = useCoolAndLovely();\n const order = useMyOrder(orderId);\n const resume = useResumeOrderPayment();\n const sync = useSyncOrderPayment();\n const cancel = useCancelOrder();\n const [session, setSession] = useState<CooOrderCheckout | null>(null);\n const title = tr('coolandlovely.orders.detailTitle', 'Order');\n\n if (order.isLoading) {\n return (\n <PageLayout title={title}>\n <LoadingView />\n </PageLayout>\n );\n }\n if (order.isError || !order.data) {\n return (\n <PageLayout title={title}>\n <ErrorView\n title={tr('coolandlovely.orders.notFound', 'Order not found')}\n onRetry={() => void order.refetch()}\n />\n </PageLayout>\n );\n }\n\n const data = order.data;\n const pending = data.status === 'PENDING_PAYMENT';\n const actionError = resume.error ?? sync.error ?? cancel.error;\n\n const settle = async () => {\n await sync.mutateAsync(data.id).catch(() => undefined);\n setSession(null);\n };\n\n return (\n <PageLayout\n title={data.orderNumber}\n description={formatDate(data.createdAt)}\n actions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <button type=\"button\" onClick={() => navigateTo('/orders')} className={secondaryButton}>\n <ArrowLeft className=\"h-4 w-4\" /> {tr('coolandlovely.common.back', 'Back')}\n </button>\n {pending && (\n <>\n <button\n type=\"button\"\n disabled={sync.isPending}\n onClick={() => sync.mutate(data.id)}\n className={secondaryButton}\n >\n {sync.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <RefreshCw className=\"h-4 w-4\" />\n )}\n {tr('coolandlovely.orders.checkPayment', 'Check payment')}\n </button>\n <button\n type=\"button\"\n disabled={cancel.isPending}\n onClick={() => cancel.mutate(data.id)}\n className={cn(\n secondaryButton,\n 'text-status-error-text hover:bg-status-error-bg-subtle'\n )}\n >\n <XCircle className=\"h-4 w-4\" /> {tr('coolandlovely.orders.cancel', 'Cancel order')}\n </button>\n </>\n )}\n </div>\n }\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <div className=\"space-y-3 lg:col-span-2\">\n {(data.refunds?.length ?? 0) > 0 && (\n <GlassCard treatment=\"plain\" className=\"space-y-3 p-4\" data-testid=\"order-refunds\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.orders.refunds', 'Refunds')}\n </p>\n {data.refunds?.map((refund) => (\n <div key={refund.id} className=\"space-y-1\" data-testid=\"order-refund\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {refund.brandName ?? tr('coolandlovely.orders.brand', 'Brand')}\n </span>\n <span className=\"flex items-center gap-2\">\n <span className=\"text-sm font-semibold tabular-nums text-text-primary\">\n {formatPrice(refund.amount, refund.currency)}\n </span>\n <StatusBadge status={refund.status} />\n </span>\n </div>\n <p className=\"text-xs text-text-secondary\">{refund.reason}</p>\n {refund.status === 'COMPLETED' && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'coolandlovely.orders.refundedToMethod',\n 'Refunded {{date}} to your original payment method.',\n { date: formatDate(refund.refundedAt ?? refund.createdAt) }\n )}\n </p>\n )}\n </div>\n ))}\n </GlassCard>\n )}\n <OrderReturns order={data} />\n {(data.status === 'PAID' || data.status === 'PARTIALLY_REFUNDED') &&\n (data.fulfilments?.length ?? 0) > 0 && (\n <GlassCard treatment=\"plain\" className=\"space-y-4 p-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.orders.delivery', 'Delivery')}\n </p>\n {data.fulfilments?.map((fulfilment) => (\n <div\n key={fulfilment.brandId}\n className=\"space-y-2\"\n data-testid=\"order-fulfilment\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {fulfilment.brandName ?? tr('coolandlovely.orders.brand', 'Brand')}\n </span>\n <StatusBadge status={fulfilment.refunded ? 'REFUNDED' : fulfilment.status} />\n </div>\n {fulfilment.refunded ? (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'coolandlovely.orders.brandRefunded',\n 'The brand refunded these pieces, so they will not be shipped.'\n )}\n </p>\n ) : fulfilment.status === 'UNFULFILLED' ? (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'coolandlovely.orders.awaitingBrand',\n 'Waiting for the brand to confirm your pieces.'\n )}\n </p>\n ) : (\n <FulfilmentTimeline fulfilment={fulfilment} />\n )}\n </div>\n ))}\n </GlassCard>\n )}\n {data.items.map((item) => (\n <GlassCard key={item.id} treatment=\"plain\" className=\"flex items-center gap-4 p-4\">\n <Thumbnail\n icon={<Package className=\"h-5 w-5\" />}\n seed={item.styleItemId}\n fileId={item.image?.id}\n alt={item.name}\n className=\"h-14 w-14 shrink-0\"\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{item.name}</p>\n <p className=\"truncate text-xs text-text-secondary\">\n {[item.size, item.colour, `× ${item.quantity}`].filter(Boolean).join(' · ')}\n </p>\n {item.isCreatorAttributed && (\n <p className=\"mt-0.5 inline-flex items-center gap-1 text-xs text-accent-primary\">\n <Sparkles className=\"h-3 w-3\" />\n {tr('coolandlovely.orders.supportsCreator', 'Supports the creator of the look')}\n </p>\n )}\n </div>\n <span className=\"text-sm font-semibold tabular-nums text-text-primary\">\n {formatPrice(item.lineTotal, data.currency)}\n </span>\n </GlassCard>\n ))}\n </div>\n <GlassCard treatment=\"glass\" className=\"h-fit space-y-4 p-6\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr('coolandlovely.orders.status', 'Status')}\n </span>\n <span data-testid=\"order-status\">\n <StatusBadge status={data.status} />\n </span>\n </div>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">\n {tr('coolandlovely.checkout.subtotal', 'Subtotal')}\n </dt>\n <dd className=\"tabular-nums text-text-primary\">\n {formatPrice(data.subtotal, data.currency)}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">{tr('coolandlovely.checkout.tax', 'Tax')}</dt>\n <dd className=\"tabular-nums text-text-primary\">\n {formatPrice(data.taxAmount, data.currency)}\n </dd>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2 text-base font-semibold\">\n <dt className=\"text-text-primary\">{tr('coolandlovely.checkout.total', 'Total')}</dt>\n <dd className=\"tabular-nums text-text-primary\">\n {formatPrice(data.total, data.currency)}\n </dd>\n </div>\n {data.refundedAmount > 0 && (\n <div className=\"flex justify-between\" data-testid=\"order-refunded-amount\">\n <dt className=\"text-text-secondary\">\n {tr('coolandlovely.orders.refunded', 'Refunded')}\n </dt>\n <dd className=\"tabular-nums text-text-primary\">\n − {formatPrice(data.refundedAmount, data.currency)}\n </dd>\n </div>\n )}\n </dl>\n {data.shippingAddress && (\n <div className=\"border-t border-border-seam pt-3 text-sm\">\n <p className=\"mb-1 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.orders.shipTo', 'Ship to')}\n </p>\n <p className=\"text-text-primary\">{data.shippingName}</p>\n <p className=\"whitespace-pre-line text-text-secondary\">{data.shippingAddress}</p>\n </div>\n )}\n {data.paidAt && (\n <p className=\"text-xs text-text-secondary\">\n {tr('coolandlovely.orders.paidOn', 'Paid {{date}} via {{provider}}', {\n date: formatDate(data.paidAt),\n provider: data.paymentProvider ?? '—',\n })}\n </p>\n )}\n {actionError && <p className=\"text-sm text-status-error-text\">{actionError.message}</p>}\n {pending &&\n (session ? (\n <PayForOrder checkout={session} onSettle={settle} />\n ) : (\n <button\n type=\"button\"\n disabled={resume.isPending}\n onClick={() =>\n resume.mutate(data.id, { onSuccess: (result) => setSession(result) })\n }\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2.5 text-sm font-semibold text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {resume.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr('coolandlovely.orders.payNow', 'Pay now')}\n </button>\n ))}\n </GlassCard>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|