@burdenoff/microfe-coolandlovely 2026.1024.1 → 2026.1024.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/coolandlovely/CoolAndLovelyRoot.d.ts.map +1 -1
  2. package/dist/coolandlovely/CoolAndLovelyRoot.js +92 -68
  3. package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
  4. package/dist/coolandlovely/CoolAndLovelyRoutes.d.ts.map +1 -1
  5. package/dist/coolandlovely/CoolAndLovelyRoutes.js +25 -9
  6. package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
  7. package/dist/coolandlovely/components/AddToCartPanel.d.ts +10 -0
  8. package/dist/coolandlovely/components/AddToCartPanel.d.ts.map +1 -0
  9. package/dist/coolandlovely/components/AddToCartPanel.js +97 -0
  10. package/dist/coolandlovely/components/AddToCartPanel.js.map +1 -0
  11. package/dist/coolandlovely/components/PayForOrder.d.ts +11 -0
  12. package/dist/coolandlovely/components/PayForOrder.d.ts.map +1 -0
  13. package/dist/coolandlovely/components/PayForOrder.js +118 -0
  14. package/dist/coolandlovely/components/PayForOrder.js.map +1 -0
  15. package/dist/coolandlovely/components/StatusBadge.d.ts.map +1 -1
  16. package/dist/coolandlovely/components/StatusBadge.js +4 -0
  17. package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
  18. package/dist/coolandlovely/hooks/useCommerceApi.d.ts +27 -0
  19. package/dist/coolandlovely/hooks/useCommerceApi.d.ts.map +1 -0
  20. package/dist/coolandlovely/hooks/useCommerceApi.js +121 -0
  21. package/dist/coolandlovely/hooks/useCommerceApi.js.map +1 -0
  22. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts +1 -0
  23. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts.map +1 -1
  24. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +1 -1
  25. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
  26. package/dist/coolandlovely/pages/commerce/CartPage.d.ts +10 -0
  27. package/dist/coolandlovely/pages/commerce/CartPage.d.ts.map +1 -0
  28. package/dist/coolandlovely/pages/commerce/CartPage.js +283 -0
  29. package/dist/coolandlovely/pages/commerce/CartPage.js.map +1 -0
  30. package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.d.ts +11 -0
  31. package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.d.ts.map +1 -0
  32. package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.js +185 -0
  33. package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.js.map +1 -0
  34. package/dist/coolandlovely/pages/commerce/OrdersPage.d.ts +11 -0
  35. package/dist/coolandlovely/pages/commerce/OrdersPage.d.ts.map +1 -0
  36. package/dist/coolandlovely/pages/commerce/OrdersPage.js +280 -0
  37. package/dist/coolandlovely/pages/commerce/OrdersPage.js.map +1 -0
  38. package/dist/coolandlovely/pages/items/StyleItemDetailPage.d.ts.map +1 -1
  39. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +114 -106
  40. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -1
  41. package/dist/coolandlovely/pages/looks/LookDetailPage.js +1 -1
  42. package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -1
  43. package/dist/coolandlovely/types/commerce.d.ts +137 -0
  44. package/dist/coolandlovely/types/commerce.d.ts.map +1 -0
  45. package/dist/coolandlovely/types/index.d.ts +1 -0
  46. package/dist/coolandlovely/types/index.d.ts.map +1 -1
  47. package/dist/coolandlovely/utils/paymentProviders.d.ts +74 -0
  48. package/dist/coolandlovely/utils/paymentProviders.d.ts.map +1 -0
  49. package/dist/coolandlovely/utils/paymentProviders.js +42 -0
  50. package/dist/coolandlovely/utils/paymentProviders.js.map +1 -0
  51. package/package.json +1 -1
@@ -0,0 +1,280 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { useTr as r } from "../../hooks/useTr.js";
5
+ import "../../hooks/index.js";
6
+ import { StatusBadge as i } from "../../components/StatusBadge.js";
7
+ import { ErrorView as a, LoadingView as o } from "../../components/StateViews.js";
8
+ import { Thumbnail as s } from "../../components/Thumbnail.js";
9
+ import { formatDate as c, formatPrice as l } from "../../utils/formatters.js";
10
+ import { EmptyState as u } from "../../components/EmptyState.js";
11
+ import { PayForOrder as d } from "../../components/PayForOrder.js";
12
+ import { useCancelOrder as f, useMyOrder as p, useMyOrders as m, useResumeOrderPayment as h, useSyncOrderPayment as g } from "../../hooks/useCommerceApi.js";
13
+ import { useState as _ } from "react";
14
+ import { ArrowLeft as v, ChevronRight as y, Loader2 as b, Package as x, RefreshCw as S, Sparkles as C, XCircle as w } from "lucide-react";
15
+ import { useParams as T } from "react-router";
16
+ import { Fragment as E, jsx as D, jsxs as O } from "react/jsx-runtime";
17
+ import { GlassCard as k } from "@burdenoff/fe-libs/ui";
18
+ //#region src/coolandlovely/pages/commerce/OrdersPage.tsx
19
+ var A = [
20
+ {
21
+ value: void 0,
22
+ key: "coolandlovely.orders.filterAll",
23
+ label: "All"
24
+ },
25
+ {
26
+ value: "PENDING_PAYMENT",
27
+ key: "coolandlovely.orders.filterPending",
28
+ label: "Awaiting payment"
29
+ },
30
+ {
31
+ value: "PAID",
32
+ key: "coolandlovely.orders.filterPaid",
33
+ label: "Paid"
34
+ },
35
+ {
36
+ value: "CANCELLED",
37
+ key: "coolandlovely.orders.filterCancelled",
38
+ label: "Cancelled"
39
+ }
40
+ ], j = "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";
41
+ function M() {
42
+ let s = r(), { navigateTo: d } = e(), [f, p] = _(void 0), h = m(f);
43
+ return /* @__PURE__ */ O(n, {
44
+ title: s("coolandlovely.orders.title", "My orders"),
45
+ description: s("coolandlovely.orders.description", "Everything you have ordered."),
46
+ children: [/* @__PURE__ */ D("div", {
47
+ className: "mb-4 flex flex-wrap gap-2",
48
+ role: "tablist",
49
+ children: A.map((e) => /* @__PURE__ */ D("button", {
50
+ type: "button",
51
+ role: "tab",
52
+ "aria-selected": f === e.value,
53
+ onClick: () => p(e.value),
54
+ 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
+ children: s(e.key, e.label)
56
+ }, e.key))
57
+ }), h.isLoading ? /* @__PURE__ */ D(o, { label: s("coolandlovely.orders.loading", "Loading orders…") }) : h.isError || !h.data ? /* @__PURE__ */ D(a, { onRetry: () => void h.refetch() }) : h.data.items.length === 0 ? /* @__PURE__ */ D(u, {
58
+ icon: /* @__PURE__ */ D(x, { className: "h-8 w-8" }),
59
+ title: s("coolandlovely.orders.emptyTitle", "No orders yet"),
60
+ description: s("coolandlovely.orders.emptyDescription", "Orders you place appear here.")
61
+ }) : /* @__PURE__ */ D("div", {
62
+ className: "space-y-3",
63
+ "data-testid": "orders-list",
64
+ children: h.data.items.map((e) => /* @__PURE__ */ O("button", {
65
+ type: "button",
66
+ onClick: () => d(`/orders/${e.id}`),
67
+ 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
+ children: [
69
+ /* @__PURE__ */ O("div", {
70
+ className: "min-w-0 flex-1",
71
+ children: [/* @__PURE__ */ D("p", {
72
+ className: "font-mono text-sm font-medium text-text-primary",
73
+ children: e.orderNumber
74
+ }), /* @__PURE__ */ O("p", {
75
+ className: "truncate text-xs text-text-secondary",
76
+ children: [
77
+ c(e.createdAt),
78
+ " ·",
79
+ " ",
80
+ s("coolandlovely.orders.pieces", "{{count}} pieces", { count: e.itemCount })
81
+ ]
82
+ })]
83
+ }),
84
+ /* @__PURE__ */ D(i, { status: e.status }),
85
+ /* @__PURE__ */ D("span", {
86
+ className: "w-28 text-right text-sm font-semibold tabular-nums text-text-primary",
87
+ children: l(e.total, e.currency)
88
+ }),
89
+ /* @__PURE__ */ D(y, { className: "h-4 w-4 text-text-secondary" })
90
+ ]
91
+ }, e.id))
92
+ })]
93
+ });
94
+ }
95
+ function N() {
96
+ let u = r(), { orderId: m } = T(), { navigateTo: y } = e(), A = p(m), M = h(), N = g(), P = f(), [F, I] = _(null), L = u("coolandlovely.orders.detailTitle", "Order");
97
+ if (A.isLoading) return /* @__PURE__ */ D(n, {
98
+ title: L,
99
+ children: /* @__PURE__ */ D(o, {})
100
+ });
101
+ if (A.isError || !A.data) return /* @__PURE__ */ D(n, {
102
+ title: L,
103
+ children: /* @__PURE__ */ D(a, {
104
+ title: u("coolandlovely.orders.notFound", "Order not found"),
105
+ onRetry: () => void A.refetch()
106
+ })
107
+ });
108
+ let R = A.data, z = R.status === "PENDING_PAYMENT", B = M.error ?? N.error ?? P.error;
109
+ return /* @__PURE__ */ D(n, {
110
+ title: R.orderNumber,
111
+ description: c(R.createdAt),
112
+ actions: /* @__PURE__ */ O("div", {
113
+ className: "flex flex-wrap items-center gap-2",
114
+ children: [/* @__PURE__ */ O("button", {
115
+ type: "button",
116
+ onClick: () => y("/orders"),
117
+ className: j,
118
+ children: [
119
+ /* @__PURE__ */ D(v, { className: "h-4 w-4" }),
120
+ " ",
121
+ u("coolandlovely.common.back", "Back")
122
+ ]
123
+ }), z && /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ O("button", {
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", {
130
+ type: "button",
131
+ disabled: P.isPending,
132
+ onClick: () => P.mutate(R.id),
133
+ className: t(j, "text-status-error-text hover:bg-status-error-bg-subtle"),
134
+ children: [
135
+ /* @__PURE__ */ D(w, { className: "h-4 w-4" }),
136
+ " ",
137
+ u("coolandlovely.orders.cancel", "Cancel order")
138
+ ]
139
+ })] })]
140
+ }),
141
+ children: /* @__PURE__ */ O("div", {
142
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
143
+ children: [/* @__PURE__ */ D("div", {
144
+ className: "space-y-3 lg:col-span-2",
145
+ children: R.items.map((e) => /* @__PURE__ */ O(k, {
146
+ treatment: "plain",
147
+ className: "flex items-center gap-4 p-4",
148
+ children: [
149
+ /* @__PURE__ */ D(s, {
150
+ icon: /* @__PURE__ */ D(x, { className: "h-5 w-5" }),
151
+ seed: e.styleItemId,
152
+ fileId: e.image?.id,
153
+ alt: e.name,
154
+ className: "h-14 w-14 shrink-0"
155
+ }),
156
+ /* @__PURE__ */ O("div", {
157
+ className: "min-w-0 flex-1",
158
+ children: [
159
+ /* @__PURE__ */ D("p", {
160
+ className: "truncate text-sm font-medium text-text-primary",
161
+ children: e.name
162
+ }),
163
+ /* @__PURE__ */ D("p", {
164
+ className: "truncate text-xs text-text-secondary",
165
+ children: [
166
+ e.size,
167
+ e.colour,
168
+ `× ${e.quantity}`
169
+ ].filter(Boolean).join(" · ")
170
+ }),
171
+ e.isCreatorAttributed && /* @__PURE__ */ O("p", {
172
+ className: "mt-0.5 inline-flex items-center gap-1 text-xs text-accent-primary",
173
+ children: [/* @__PURE__ */ D(C, { className: "h-3 w-3" }), u("coolandlovely.orders.supportsCreator", "Supports the creator of the look")]
174
+ })
175
+ ]
176
+ }),
177
+ /* @__PURE__ */ D("span", {
178
+ className: "text-sm font-semibold tabular-nums text-text-primary",
179
+ children: l(e.lineTotal, R.currency)
180
+ })
181
+ ]
182
+ }, e.id))
183
+ }), /* @__PURE__ */ O(k, {
184
+ treatment: "glass",
185
+ className: "h-fit space-y-4 p-6",
186
+ children: [
187
+ /* @__PURE__ */ O("div", {
188
+ className: "flex items-center justify-between",
189
+ children: [/* @__PURE__ */ D("span", {
190
+ className: "text-sm text-text-secondary",
191
+ children: u("coolandlovely.orders.status", "Status")
192
+ }), /* @__PURE__ */ D("span", {
193
+ "data-testid": "order-status",
194
+ children: /* @__PURE__ */ D(i, { status: R.status })
195
+ })]
196
+ }),
197
+ /* @__PURE__ */ O("dl", {
198
+ className: "space-y-2 text-sm",
199
+ children: [
200
+ /* @__PURE__ */ O("div", {
201
+ className: "flex justify-between",
202
+ children: [/* @__PURE__ */ D("dt", {
203
+ className: "text-text-secondary",
204
+ children: u("coolandlovely.checkout.subtotal", "Subtotal")
205
+ }), /* @__PURE__ */ D("dd", {
206
+ className: "tabular-nums text-text-primary",
207
+ children: l(R.subtotal, R.currency)
208
+ })]
209
+ }),
210
+ /* @__PURE__ */ O("div", {
211
+ className: "flex justify-between",
212
+ children: [/* @__PURE__ */ D("dt", {
213
+ className: "text-text-secondary",
214
+ children: u("coolandlovely.checkout.tax", "Tax")
215
+ }), /* @__PURE__ */ D("dd", {
216
+ className: "tabular-nums text-text-primary",
217
+ children: l(R.taxAmount, R.currency)
218
+ })]
219
+ }),
220
+ /* @__PURE__ */ O("div", {
221
+ className: "flex justify-between border-t border-border-seam pt-2 text-base font-semibold",
222
+ children: [/* @__PURE__ */ D("dt", {
223
+ className: "text-text-primary",
224
+ children: u("coolandlovely.checkout.total", "Total")
225
+ }), /* @__PURE__ */ D("dd", {
226
+ className: "tabular-nums text-text-primary",
227
+ children: l(R.total, R.currency)
228
+ })]
229
+ })
230
+ ]
231
+ }),
232
+ R.shippingAddress && /* @__PURE__ */ O("div", {
233
+ className: "border-t border-border-seam pt-3 text-sm",
234
+ children: [
235
+ /* @__PURE__ */ D("p", {
236
+ className: "mb-1 text-xs font-medium uppercase tracking-wide text-text-secondary",
237
+ children: u("coolandlovely.orders.shipTo", "Ship to")
238
+ }),
239
+ /* @__PURE__ */ D("p", {
240
+ className: "text-text-primary",
241
+ children: R.shippingName
242
+ }),
243
+ /* @__PURE__ */ D("p", {
244
+ className: "whitespace-pre-line text-text-secondary",
245
+ children: R.shippingAddress
246
+ })
247
+ ]
248
+ }),
249
+ R.paidAt && /* @__PURE__ */ D("p", {
250
+ className: "text-xs text-text-secondary",
251
+ children: u("coolandlovely.orders.paidOn", "Paid {{date}} via {{provider}}", {
252
+ date: c(R.paidAt),
253
+ provider: R.paymentProvider ?? "—"
254
+ })
255
+ }),
256
+ B && /* @__PURE__ */ D("p", {
257
+ className: "text-sm text-status-error-text",
258
+ children: B.message
259
+ }),
260
+ z && (F ? /* @__PURE__ */ D(d, {
261
+ checkout: F,
262
+ onSettle: async () => {
263
+ await N.mutateAsync(R.id).catch(() => void 0), I(null);
264
+ }
265
+ }) : /* @__PURE__ */ O("button", {
266
+ type: "button",
267
+ disabled: M.isPending,
268
+ onClick: () => M.mutate(R.id, { onSuccess: (e) => I(e) }),
269
+ 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: [M.isPending && /* @__PURE__ */ D(b, { className: "h-4 w-4 animate-spin" }), u("coolandlovely.orders.payNow", "Pay now")]
271
+ }))
272
+ ]
273
+ })]
274
+ })
275
+ });
276
+ }
277
+ //#endregion
278
+ export { N as OrderDetailPage, M as OrdersPage };
279
+
280
+ //# sourceMappingURL=OrdersPage.js.map
@@ -0,0 +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 +1 @@
1
- {"version":3,"file":"StyleItemDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/items/StyleItemDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAuBH,wBAAgB,mBAAmB,gCA6PlC"}
1
+ {"version":3,"file":"StyleItemDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/items/StyleItemDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwBH,wBAAgB,mBAAmB,gCAoQlC"}