@burdenoff/microfe-coolandlovely 2026.1024.4 → 2026.1026.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coolandlovely/CoolAndLovelyRoutes.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.js +20 -12
- package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
- package/dist/coolandlovely/components/FulfilmentTimeline.d.ts +7 -0
- package/dist/coolandlovely/components/FulfilmentTimeline.d.ts.map +1 -0
- package/dist/coolandlovely/components/FulfilmentTimeline.js +77 -0
- package/dist/coolandlovely/components/FulfilmentTimeline.js.map +1 -0
- package/dist/coolandlovely/components/StatusBadge.d.ts.map +1 -1
- package/dist/coolandlovely/components/StatusBadge.js +9 -1
- package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts +7 -0
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts.map +1 -0
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js +92 -0
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js.map +1 -0
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts +2 -0
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.js +26 -22
- package/dist/coolandlovely/hooks/useCommerceApi.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js +157 -148
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.d.ts +13 -0
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.d.ts.map +1 -0
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js +360 -0
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js.map +1 -0
- package/dist/coolandlovely/pages/commerce/CartPage.js +4 -4
- package/dist/coolandlovely/pages/commerce/OrdersPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.js +122 -101
- package/dist/coolandlovely/pages/commerce/OrdersPage.js.map +1 -1
- package/dist/coolandlovely/types/commerce.d.ts +61 -0
- package/dist/coolandlovely/types/commerce.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -8,15 +8,16 @@ import { ErrorView as a, LoadingView as o } from "../../components/StateViews.js
|
|
|
8
8
|
import { Thumbnail as s } from "../../components/Thumbnail.js";
|
|
9
9
|
import { formatDate as c, formatPrice as l } from "../../utils/formatters.js";
|
|
10
10
|
import { EmptyState as u } from "../../components/EmptyState.js";
|
|
11
|
-
import {
|
|
11
|
+
import { FulfilmentTimeline as d } from "../../components/FulfilmentTimeline.js";
|
|
12
12
|
import { useCancelOrder as f, useMyOrder as p, useMyOrders as m, useResumeOrderPayment as h, useSyncOrderPayment as g } from "../../hooks/useCommerceApi.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
13
|
+
import { PayForOrder as _ } from "../../components/PayForOrder.js";
|
|
14
|
+
import { useState as v } from "react";
|
|
15
|
+
import { ArrowLeft as y, ChevronRight as b, Loader2 as x, Package as S, RefreshCw as C, Sparkles as w, XCircle as T } from "lucide-react";
|
|
16
|
+
import { useParams as E } from "react-router";
|
|
17
|
+
import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
|
|
18
|
+
import { GlassCard as A } from "@burdenoff/fe-libs/ui";
|
|
18
19
|
//#region src/coolandlovely/pages/commerce/OrdersPage.tsx
|
|
19
|
-
var
|
|
20
|
+
var j = [
|
|
20
21
|
{
|
|
21
22
|
value: void 0,
|
|
22
23
|
key: "coolandlovely.orders.filterAll",
|
|
@@ -37,16 +38,16 @@ var A = [
|
|
|
37
38
|
key: "coolandlovely.orders.filterCancelled",
|
|
38
39
|
label: "Cancelled"
|
|
39
40
|
}
|
|
40
|
-
],
|
|
41
|
-
function
|
|
42
|
-
let s = r(), { navigateTo: d } = e(), [f, p] =
|
|
43
|
-
return /* @__PURE__ */
|
|
41
|
+
], M = "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";
|
|
42
|
+
function N() {
|
|
43
|
+
let s = r(), { navigateTo: d } = e(), [f, p] = v(void 0), h = m(f);
|
|
44
|
+
return /* @__PURE__ */ k(n, {
|
|
44
45
|
title: s("coolandlovely.orders.title", "My orders"),
|
|
45
46
|
description: s("coolandlovely.orders.description", "Everything you have ordered."),
|
|
46
|
-
children: [/* @__PURE__ */
|
|
47
|
+
children: [/* @__PURE__ */ O("div", {
|
|
47
48
|
className: "mb-4 flex flex-wrap gap-2",
|
|
48
49
|
role: "tablist",
|
|
49
|
-
children:
|
|
50
|
+
children: j.map((e) => /* @__PURE__ */ O("button", {
|
|
50
51
|
type: "button",
|
|
51
52
|
role: "tab",
|
|
52
53
|
"aria-selected": f === e.value,
|
|
@@ -54,24 +55,24 @@ function M() {
|
|
|
54
55
|
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"),
|
|
55
56
|
children: s(e.key, e.label)
|
|
56
57
|
}, e.key))
|
|
57
|
-
}), h.isLoading ? /* @__PURE__ */
|
|
58
|
-
icon: /* @__PURE__ */
|
|
58
|
+
}), h.isLoading ? /* @__PURE__ */ O(o, { label: s("coolandlovely.orders.loading", "Loading orders…") }) : h.isError || !h.data ? /* @__PURE__ */ O(a, { onRetry: () => void h.refetch() }) : h.data.items.length === 0 ? /* @__PURE__ */ O(u, {
|
|
59
|
+
icon: /* @__PURE__ */ O(S, { className: "h-8 w-8" }),
|
|
59
60
|
title: s("coolandlovely.orders.emptyTitle", "No orders yet"),
|
|
60
61
|
description: s("coolandlovely.orders.emptyDescription", "Orders you place appear here.")
|
|
61
|
-
}) : /* @__PURE__ */
|
|
62
|
+
}) : /* @__PURE__ */ O("div", {
|
|
62
63
|
className: "space-y-3",
|
|
63
64
|
"data-testid": "orders-list",
|
|
64
|
-
children: h.data.items.map((e) => /* @__PURE__ */
|
|
65
|
+
children: h.data.items.map((e) => /* @__PURE__ */ k("button", {
|
|
65
66
|
type: "button",
|
|
66
67
|
onClick: () => d(`/orders/${e.id}`),
|
|
67
68
|
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",
|
|
68
69
|
children: [
|
|
69
|
-
/* @__PURE__ */
|
|
70
|
+
/* @__PURE__ */ k("div", {
|
|
70
71
|
className: "min-w-0 flex-1",
|
|
71
|
-
children: [/* @__PURE__ */
|
|
72
|
+
children: [/* @__PURE__ */ O("p", {
|
|
72
73
|
className: "font-mono text-sm font-medium text-text-primary",
|
|
73
74
|
children: e.orderNumber
|
|
74
|
-
}), /* @__PURE__ */
|
|
75
|
+
}), /* @__PURE__ */ k("p", {
|
|
75
76
|
className: "truncate text-xs text-text-secondary",
|
|
76
77
|
children: [
|
|
77
78
|
c(e.createdAt),
|
|
@@ -81,86 +82,106 @@ function M() {
|
|
|
81
82
|
]
|
|
82
83
|
})]
|
|
83
84
|
}),
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
/* @__PURE__ */
|
|
85
|
+
/* @__PURE__ */ O(i, { status: e.status }),
|
|
86
|
+
/* @__PURE__ */ O("span", {
|
|
86
87
|
className: "w-28 text-right text-sm font-semibold tabular-nums text-text-primary",
|
|
87
88
|
children: l(e.total, e.currency)
|
|
88
89
|
}),
|
|
89
|
-
/* @__PURE__ */
|
|
90
|
+
/* @__PURE__ */ O(b, { className: "h-4 w-4 text-text-secondary" })
|
|
90
91
|
]
|
|
91
92
|
}, e.id))
|
|
92
93
|
})]
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
|
-
function
|
|
96
|
-
let u = r(), { orderId: m } =
|
|
97
|
-
if (
|
|
98
|
-
title:
|
|
99
|
-
children: /* @__PURE__ */
|
|
96
|
+
function P() {
|
|
97
|
+
let u = r(), { orderId: m } = E(), { navigateTo: b } = e(), j = p(m), N = h(), P = g(), F = f(), [I, L] = v(null), R = u("coolandlovely.orders.detailTitle", "Order");
|
|
98
|
+
if (j.isLoading) return /* @__PURE__ */ O(n, {
|
|
99
|
+
title: R,
|
|
100
|
+
children: /* @__PURE__ */ O(o, {})
|
|
100
101
|
});
|
|
101
|
-
if (
|
|
102
|
-
title:
|
|
103
|
-
children: /* @__PURE__ */
|
|
102
|
+
if (j.isError || !j.data) return /* @__PURE__ */ O(n, {
|
|
103
|
+
title: R,
|
|
104
|
+
children: /* @__PURE__ */ O(a, {
|
|
104
105
|
title: u("coolandlovely.orders.notFound", "Order not found"),
|
|
105
|
-
onRetry: () => void
|
|
106
|
+
onRetry: () => void j.refetch()
|
|
106
107
|
})
|
|
107
108
|
});
|
|
108
|
-
let
|
|
109
|
-
return /* @__PURE__ */
|
|
110
|
-
title:
|
|
111
|
-
description: c(
|
|
112
|
-
actions: /* @__PURE__ */
|
|
109
|
+
let z = j.data, B = z.status === "PENDING_PAYMENT", V = N.error ?? P.error ?? F.error;
|
|
110
|
+
return /* @__PURE__ */ O(n, {
|
|
111
|
+
title: z.orderNumber,
|
|
112
|
+
description: c(z.createdAt),
|
|
113
|
+
actions: /* @__PURE__ */ k("div", {
|
|
113
114
|
className: "flex flex-wrap items-center gap-2",
|
|
114
|
-
children: [/* @__PURE__ */
|
|
115
|
+
children: [/* @__PURE__ */ k("button", {
|
|
115
116
|
type: "button",
|
|
116
|
-
onClick: () =>
|
|
117
|
-
className:
|
|
117
|
+
onClick: () => b("/orders"),
|
|
118
|
+
className: M,
|
|
118
119
|
children: [
|
|
119
|
-
/* @__PURE__ */
|
|
120
|
+
/* @__PURE__ */ O(y, { className: "h-4 w-4" }),
|
|
120
121
|
" ",
|
|
121
122
|
u("coolandlovely.common.back", "Back")
|
|
122
123
|
]
|
|
123
|
-
}),
|
|
124
|
-
type: "button",
|
|
125
|
-
disabled: N.isPending,
|
|
126
|
-
onClick: () => N.mutate(R.id),
|
|
127
|
-
className: j,
|
|
128
|
-
children: [N.isPending ? /* @__PURE__ */ D(b, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ D(S, { className: "h-4 w-4" }), u("coolandlovely.orders.checkPayment", "Check payment")]
|
|
129
|
-
}), /* @__PURE__ */ O("button", {
|
|
124
|
+
}), B && /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ k("button", {
|
|
130
125
|
type: "button",
|
|
131
126
|
disabled: P.isPending,
|
|
132
|
-
onClick: () => P.mutate(
|
|
133
|
-
className:
|
|
127
|
+
onClick: () => P.mutate(z.id),
|
|
128
|
+
className: M,
|
|
129
|
+
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")]
|
|
130
|
+
}), /* @__PURE__ */ k("button", {
|
|
131
|
+
type: "button",
|
|
132
|
+
disabled: F.isPending,
|
|
133
|
+
onClick: () => F.mutate(z.id),
|
|
134
|
+
className: t(M, "text-status-error-text hover:bg-status-error-bg-subtle"),
|
|
134
135
|
children: [
|
|
135
|
-
/* @__PURE__ */
|
|
136
|
+
/* @__PURE__ */ O(T, { className: "h-4 w-4" }),
|
|
136
137
|
" ",
|
|
137
138
|
u("coolandlovely.orders.cancel", "Cancel order")
|
|
138
139
|
]
|
|
139
140
|
})] })]
|
|
140
141
|
}),
|
|
141
|
-
children: /* @__PURE__ */
|
|
142
|
+
children: /* @__PURE__ */ k("div", {
|
|
142
143
|
className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
|
|
143
|
-
children: [/* @__PURE__ */
|
|
144
|
+
children: [/* @__PURE__ */ k("div", {
|
|
144
145
|
className: "space-y-3 lg:col-span-2",
|
|
145
|
-
children:
|
|
146
|
+
children: [z.status === "PAID" && (z.fulfilments?.length ?? 0) > 0 && /* @__PURE__ */ k(A, {
|
|
147
|
+
treatment: "plain",
|
|
148
|
+
className: "space-y-4 p-4",
|
|
149
|
+
children: [/* @__PURE__ */ O("p", {
|
|
150
|
+
className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
|
|
151
|
+
children: u("coolandlovely.orders.delivery", "Delivery")
|
|
152
|
+
}), z.fulfilments?.map((e) => /* @__PURE__ */ k("div", {
|
|
153
|
+
className: "space-y-2",
|
|
154
|
+
"data-testid": "order-fulfilment",
|
|
155
|
+
children: [/* @__PURE__ */ k("div", {
|
|
156
|
+
className: "flex items-center justify-between gap-2",
|
|
157
|
+
children: [/* @__PURE__ */ O("span", {
|
|
158
|
+
className: "text-sm font-medium text-text-primary",
|
|
159
|
+
children: e.brandName ?? u("coolandlovely.orders.brand", "Brand")
|
|
160
|
+
}), /* @__PURE__ */ O(i, { status: e.status })]
|
|
161
|
+
}), e.status === "UNFULFILLED" ? /* @__PURE__ */ O("p", {
|
|
162
|
+
className: "text-xs text-text-secondary",
|
|
163
|
+
children: u("coolandlovely.orders.awaitingBrand", "Waiting for the brand to confirm your pieces.")
|
|
164
|
+
}) : /* @__PURE__ */ O(d, { fulfilment: e })]
|
|
165
|
+
}, e.brandId))]
|
|
166
|
+
}), z.items.map((e) => /* @__PURE__ */ k(A, {
|
|
146
167
|
treatment: "plain",
|
|
147
168
|
className: "flex items-center gap-4 p-4",
|
|
148
169
|
children: [
|
|
149
|
-
/* @__PURE__ */
|
|
150
|
-
icon: /* @__PURE__ */
|
|
170
|
+
/* @__PURE__ */ O(s, {
|
|
171
|
+
icon: /* @__PURE__ */ O(S, { className: "h-5 w-5" }),
|
|
151
172
|
seed: e.styleItemId,
|
|
152
173
|
fileId: e.image?.id,
|
|
153
174
|
alt: e.name,
|
|
154
175
|
className: "h-14 w-14 shrink-0"
|
|
155
176
|
}),
|
|
156
|
-
/* @__PURE__ */
|
|
177
|
+
/* @__PURE__ */ k("div", {
|
|
157
178
|
className: "min-w-0 flex-1",
|
|
158
179
|
children: [
|
|
159
|
-
/* @__PURE__ */
|
|
180
|
+
/* @__PURE__ */ O("p", {
|
|
160
181
|
className: "truncate text-sm font-medium text-text-primary",
|
|
161
182
|
children: e.name
|
|
162
183
|
}),
|
|
163
|
-
/* @__PURE__ */
|
|
184
|
+
/* @__PURE__ */ O("p", {
|
|
164
185
|
className: "truncate text-xs text-text-secondary",
|
|
165
186
|
children: [
|
|
166
187
|
e.size,
|
|
@@ -168,106 +189,106 @@ function N() {
|
|
|
168
189
|
`× ${e.quantity}`
|
|
169
190
|
].filter(Boolean).join(" · ")
|
|
170
191
|
}),
|
|
171
|
-
e.isCreatorAttributed && /* @__PURE__ */
|
|
192
|
+
e.isCreatorAttributed && /* @__PURE__ */ k("p", {
|
|
172
193
|
className: "mt-0.5 inline-flex items-center gap-1 text-xs text-accent-primary",
|
|
173
|
-
children: [/* @__PURE__ */
|
|
194
|
+
children: [/* @__PURE__ */ O(w, { className: "h-3 w-3" }), u("coolandlovely.orders.supportsCreator", "Supports the creator of the look")]
|
|
174
195
|
})
|
|
175
196
|
]
|
|
176
197
|
}),
|
|
177
|
-
/* @__PURE__ */
|
|
198
|
+
/* @__PURE__ */ O("span", {
|
|
178
199
|
className: "text-sm font-semibold tabular-nums text-text-primary",
|
|
179
|
-
children: l(e.lineTotal,
|
|
200
|
+
children: l(e.lineTotal, z.currency)
|
|
180
201
|
})
|
|
181
202
|
]
|
|
182
|
-
}, e.id))
|
|
183
|
-
}), /* @__PURE__ */
|
|
203
|
+
}, e.id))]
|
|
204
|
+
}), /* @__PURE__ */ k(A, {
|
|
184
205
|
treatment: "glass",
|
|
185
206
|
className: "h-fit space-y-4 p-6",
|
|
186
207
|
children: [
|
|
187
|
-
/* @__PURE__ */
|
|
208
|
+
/* @__PURE__ */ k("div", {
|
|
188
209
|
className: "flex items-center justify-between",
|
|
189
|
-
children: [/* @__PURE__ */
|
|
210
|
+
children: [/* @__PURE__ */ O("span", {
|
|
190
211
|
className: "text-sm text-text-secondary",
|
|
191
212
|
children: u("coolandlovely.orders.status", "Status")
|
|
192
|
-
}), /* @__PURE__ */
|
|
213
|
+
}), /* @__PURE__ */ O("span", {
|
|
193
214
|
"data-testid": "order-status",
|
|
194
|
-
children: /* @__PURE__ */
|
|
215
|
+
children: /* @__PURE__ */ O(i, { status: z.status })
|
|
195
216
|
})]
|
|
196
217
|
}),
|
|
197
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ k("dl", {
|
|
198
219
|
className: "space-y-2 text-sm",
|
|
199
220
|
children: [
|
|
200
|
-
/* @__PURE__ */
|
|
221
|
+
/* @__PURE__ */ k("div", {
|
|
201
222
|
className: "flex justify-between",
|
|
202
|
-
children: [/* @__PURE__ */
|
|
223
|
+
children: [/* @__PURE__ */ O("dt", {
|
|
203
224
|
className: "text-text-secondary",
|
|
204
225
|
children: u("coolandlovely.checkout.subtotal", "Subtotal")
|
|
205
|
-
}), /* @__PURE__ */
|
|
226
|
+
}), /* @__PURE__ */ O("dd", {
|
|
206
227
|
className: "tabular-nums text-text-primary",
|
|
207
|
-
children: l(
|
|
228
|
+
children: l(z.subtotal, z.currency)
|
|
208
229
|
})]
|
|
209
230
|
}),
|
|
210
|
-
/* @__PURE__ */
|
|
231
|
+
/* @__PURE__ */ k("div", {
|
|
211
232
|
className: "flex justify-between",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
233
|
+
children: [/* @__PURE__ */ O("dt", {
|
|
213
234
|
className: "text-text-secondary",
|
|
214
235
|
children: u("coolandlovely.checkout.tax", "Tax")
|
|
215
|
-
}), /* @__PURE__ */
|
|
236
|
+
}), /* @__PURE__ */ O("dd", {
|
|
216
237
|
className: "tabular-nums text-text-primary",
|
|
217
|
-
children: l(
|
|
238
|
+
children: l(z.taxAmount, z.currency)
|
|
218
239
|
})]
|
|
219
240
|
}),
|
|
220
|
-
/* @__PURE__ */
|
|
241
|
+
/* @__PURE__ */ k("div", {
|
|
221
242
|
className: "flex justify-between border-t border-border-seam pt-2 text-base font-semibold",
|
|
222
|
-
children: [/* @__PURE__ */
|
|
243
|
+
children: [/* @__PURE__ */ O("dt", {
|
|
223
244
|
className: "text-text-primary",
|
|
224
245
|
children: u("coolandlovely.checkout.total", "Total")
|
|
225
|
-
}), /* @__PURE__ */
|
|
246
|
+
}), /* @__PURE__ */ O("dd", {
|
|
226
247
|
className: "tabular-nums text-text-primary",
|
|
227
|
-
children: l(
|
|
248
|
+
children: l(z.total, z.currency)
|
|
228
249
|
})]
|
|
229
250
|
})
|
|
230
251
|
]
|
|
231
252
|
}),
|
|
232
|
-
|
|
253
|
+
z.shippingAddress && /* @__PURE__ */ k("div", {
|
|
233
254
|
className: "border-t border-border-seam pt-3 text-sm",
|
|
234
255
|
children: [
|
|
235
|
-
/* @__PURE__ */
|
|
256
|
+
/* @__PURE__ */ O("p", {
|
|
236
257
|
className: "mb-1 text-xs font-medium uppercase tracking-wide text-text-secondary",
|
|
237
258
|
children: u("coolandlovely.orders.shipTo", "Ship to")
|
|
238
259
|
}),
|
|
239
|
-
/* @__PURE__ */
|
|
260
|
+
/* @__PURE__ */ O("p", {
|
|
240
261
|
className: "text-text-primary",
|
|
241
|
-
children:
|
|
262
|
+
children: z.shippingName
|
|
242
263
|
}),
|
|
243
|
-
/* @__PURE__ */
|
|
264
|
+
/* @__PURE__ */ O("p", {
|
|
244
265
|
className: "whitespace-pre-line text-text-secondary",
|
|
245
|
-
children:
|
|
266
|
+
children: z.shippingAddress
|
|
246
267
|
})
|
|
247
268
|
]
|
|
248
269
|
}),
|
|
249
|
-
|
|
270
|
+
z.paidAt && /* @__PURE__ */ O("p", {
|
|
250
271
|
className: "text-xs text-text-secondary",
|
|
251
272
|
children: u("coolandlovely.orders.paidOn", "Paid {{date}} via {{provider}}", {
|
|
252
|
-
date: c(
|
|
253
|
-
provider:
|
|
273
|
+
date: c(z.paidAt),
|
|
274
|
+
provider: z.paymentProvider ?? "—"
|
|
254
275
|
})
|
|
255
276
|
}),
|
|
256
|
-
|
|
277
|
+
V && /* @__PURE__ */ O("p", {
|
|
257
278
|
className: "text-sm text-status-error-text",
|
|
258
|
-
children:
|
|
279
|
+
children: V.message
|
|
259
280
|
}),
|
|
260
|
-
|
|
261
|
-
checkout:
|
|
281
|
+
B && (I ? /* @__PURE__ */ O(_, {
|
|
282
|
+
checkout: I,
|
|
262
283
|
onSettle: async () => {
|
|
263
|
-
await
|
|
284
|
+
await P.mutateAsync(z.id).catch(() => void 0), L(null);
|
|
264
285
|
}
|
|
265
|
-
}) : /* @__PURE__ */
|
|
286
|
+
}) : /* @__PURE__ */ k("button", {
|
|
266
287
|
type: "button",
|
|
267
|
-
disabled:
|
|
268
|
-
onClick: () =>
|
|
288
|
+
disabled: N.isPending,
|
|
289
|
+
onClick: () => N.mutate(z.id, { onSuccess: (e) => L(e) }),
|
|
269
290
|
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",
|
|
270
|
-
children: [
|
|
291
|
+
children: [N.isPending && /* @__PURE__ */ O(x, { className: "h-4 w-4 animate-spin" }), u("coolandlovely.orders.payNow", "Pay now")]
|
|
271
292
|
}))
|
|
272
293
|
]
|
|
273
294
|
})]
|
|
@@ -275,6 +296,6 @@ function N() {
|
|
|
275
296
|
});
|
|
276
297
|
}
|
|
277
298
|
//#endregion
|
|
278
|
-
export {
|
|
299
|
+
export { P as OrderDetailPage, N as OrdersPage };
|
|
279
300
|
|
|
280
301
|
//# 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`).\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 { 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 { 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.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 </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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"}
|
|
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`).\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 { 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.status === 'PAID' && (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 key={fulfilment.brandId} className=\"space-y-2\" data-testid=\"order-fulfilment\">\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.status} />\n </div>\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 </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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"}
|
|
@@ -2,6 +2,23 @@ import { CooFileRef, CooStyleItem } from './index';
|
|
|
2
2
|
|
|
3
3
|
export type CooOrderStatus = 'PENDING_PAYMENT' | 'PAID' | 'CANCELLED';
|
|
4
4
|
export type CooEarningSyncStatus = 'PENDING' | 'SYNCED' | 'FAILED';
|
|
5
|
+
/** Brand-side fulfilment (BOFF-9636): forward-only, one per brand in an order. */
|
|
6
|
+
export type CooFulfilmentStatus = 'UNFULFILLED' | 'CONFIRMED' | 'SHIPPED' | 'DELIVERED';
|
|
7
|
+
export interface CooOrderFulfilment {
|
|
8
|
+
id: string | null;
|
|
9
|
+
orderId: string;
|
|
10
|
+
brandId: string;
|
|
11
|
+
brandName: string | null;
|
|
12
|
+
status: CooFulfilmentStatus;
|
|
13
|
+
carrier: string | null;
|
|
14
|
+
trackingNumber: string | null;
|
|
15
|
+
trackingUrl: string | null;
|
|
16
|
+
note: string | null;
|
|
17
|
+
confirmedAt: string | null;
|
|
18
|
+
shippedAt: string | null;
|
|
19
|
+
deliveredAt: string | null;
|
|
20
|
+
updatedAt: string | null;
|
|
21
|
+
}
|
|
5
22
|
export interface CooCartItem {
|
|
6
23
|
id: string;
|
|
7
24
|
styleItemId: string;
|
|
@@ -61,6 +78,50 @@ export interface CooOrder {
|
|
|
61
78
|
createdAt: string;
|
|
62
79
|
updatedAt: string;
|
|
63
80
|
items: CooOrderItem[];
|
|
81
|
+
/** Present on the order detail query only. */
|
|
82
|
+
fulfilments?: CooOrderFulfilment[];
|
|
83
|
+
fulfilmentStatus?: CooFulfilmentStatus;
|
|
84
|
+
}
|
|
85
|
+
/** A paid order as one brand sees it: only that brand's lines and fulfilment. */
|
|
86
|
+
export interface CooBrandOrder {
|
|
87
|
+
id: string;
|
|
88
|
+
orderNumber: string;
|
|
89
|
+
status: CooOrderStatus;
|
|
90
|
+
brandId: string;
|
|
91
|
+
currency: string;
|
|
92
|
+
brandSubtotal: number;
|
|
93
|
+
itemCount: number;
|
|
94
|
+
shippingName: string | null;
|
|
95
|
+
shippingAddress: string | null;
|
|
96
|
+
buyerNote: string | null;
|
|
97
|
+
paidAt: string | null;
|
|
98
|
+
createdAt: string;
|
|
99
|
+
items: CooOrderItem[];
|
|
100
|
+
fulfilment: CooOrderFulfilment;
|
|
101
|
+
}
|
|
102
|
+
export interface CooBrandOrderConnection {
|
|
103
|
+
items: CooBrandOrder[];
|
|
104
|
+
pageInfo: {
|
|
105
|
+
cursor: string | null;
|
|
106
|
+
hasMore: boolean;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export interface CooBrandOrderSummary {
|
|
110
|
+
brandId: string;
|
|
111
|
+
unfulfilled: number;
|
|
112
|
+
confirmed: number;
|
|
113
|
+
shipped: number;
|
|
114
|
+
delivered: number;
|
|
115
|
+
total: number;
|
|
116
|
+
}
|
|
117
|
+
export interface CooUpdateOrderFulfilmentInput {
|
|
118
|
+
brandId: string;
|
|
119
|
+
orderId: string;
|
|
120
|
+
status: Exclude<CooFulfilmentStatus, 'UNFULFILLED'>;
|
|
121
|
+
carrier?: string | null;
|
|
122
|
+
trackingNumber?: string | null;
|
|
123
|
+
trackingUrl?: string | null;
|
|
124
|
+
note?: string | null;
|
|
64
125
|
}
|
|
65
126
|
export interface CooOrderConnection {
|
|
66
127
|
items: CooOrder[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/types/commerce.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,MAAM,GAAG,WAAW,CAAC;AACtE,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/types/commerce.ts"],"names":[],"mappings":"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"}
|