@burdenoff/microfe-store 2026.830.1 → 2026.831.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/components/InstallAppModal.js +145 -150
- package/dist/components/InstallAppModal.js.map +1 -1
- package/dist/components/MarkdownEditor.js +71 -70
- package/dist/components/MarkdownEditor.js.map +1 -1
- package/dist/components/cart/CartDrawer.js +179 -175
- package/dist/components/cart/CartDrawer.js.map +1 -1
- package/dist/pages/AppDetailPage.js +110 -119
- package/dist/pages/AppDetailPage.js.map +1 -1
- package/dist/pages/AppSettingsPage.js +60 -59
- package/dist/pages/AppSettingsPage.js.map +1 -1
- package/dist/pages/CartPage.js +122 -121
- package/dist/pages/CartPage.js.map +1 -1
- package/dist/pages/InstalledAppsPage.js +188 -197
- package/dist/pages/InstalledAppsPage.js.map +1 -1
- package/dist/pages/MarketplaceHomePage.js +380 -376
- package/dist/pages/MarketplaceHomePage.js.map +1 -1
- package/dist/pages/MyLicensesPage.js +68 -67
- package/dist/pages/MyLicensesPage.js.map +1 -1
- package/dist/pages/OrderConfirmationPage.js +117 -129
- package/dist/pages/OrderConfirmationPage.js.map +1 -1
- package/dist/pages/OrdersPage.js +87 -90
- package/dist/pages/OrdersPage.js.map +1 -1
- package/dist/pages/ProductDetailPage.js +600 -606
- package/dist/pages/ProductDetailPage.js.map +1 -1
- package/dist/shared/hooks/useTr.d.ts +16 -0
- package/dist/shared/hooks/useTr.js +14 -0
- package/dist/shared/hooks/useTr.js.map +1 -0
- package/dist/translations/en.d.ts +327 -10
- package/dist/translations/en.js +343 -26
- package/dist/translations/en.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,269 +1,257 @@
|
|
|
1
1
|
import { useStore as e } from "../providers/StoreProvider.js";
|
|
2
2
|
import { formatPrice as t } from "../utils/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
3
|
+
import { useTr as n } from "../shared/hooks/useTr.js";
|
|
4
|
+
import { nativeCopyText as r, nativeImpact as i, nativeNotify as a } from "../utils/nativeBridge.js";
|
|
5
|
+
import { useEffect as o, useState as s } from "react";
|
|
6
|
+
import { useNavigate as c, useParams as l } from "react-router";
|
|
7
|
+
import { ArrowRight as u, CheckCircle2 as d, Copy as f, Download as p, KeyRound as m, Package as h, Receipt as g, Truck as _ } from "lucide-react";
|
|
8
|
+
import { graphqlFetch as v } from "@burdenoff/fe-libs/shared/graphql";
|
|
9
|
+
import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
10
|
+
import { EmphasisPanel as S, NextSteps as C } from "@burdenoff/fe-libs/ui";
|
|
10
11
|
//#region src/pages/OrderConfirmationPage.tsx
|
|
11
|
-
var
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
if (!
|
|
12
|
+
var w = "\n query OrderConfirmation($id: ID!) {\n getStoreOrder(id: $id) {\n id\n status\n total\n currency\n purchasedAt\n lineItems\n context\n fulfillment {\n status\n trackingNumber\n trackingUrl\n carrier\n estimatedDeliveryDate\n }\n }\n myEntitlements {\n id\n productId\n licenseKey\n expiresAt\n features\n product {\n id\n name\n slug\n icon\n manifest\n }\n }\n }\n", T = () => {
|
|
13
|
+
let T = c(), { basePath: E, authToken: D } = e(), { orderId: O } = l(), k = n(), [A, j] = s(null), [M, N] = s([]), [P, F] = s(!0), [I, L] = s(null), [R, z] = s(null);
|
|
14
|
+
o(() => {
|
|
15
|
+
if (!O) return;
|
|
15
16
|
let e = !1;
|
|
16
17
|
return (async () => {
|
|
17
|
-
|
|
18
|
+
F(!0), L(null);
|
|
18
19
|
try {
|
|
19
|
-
let t = await
|
|
20
|
+
let t = await v({
|
|
20
21
|
gateway: "global",
|
|
21
|
-
query:
|
|
22
|
-
variables: { id:
|
|
23
|
-
authToken:
|
|
22
|
+
query: w,
|
|
23
|
+
variables: { id: O },
|
|
24
|
+
authToken: D || void 0
|
|
24
25
|
});
|
|
25
26
|
if (e) return;
|
|
26
27
|
if (t.errors?.length) throw Error(t.errors[0]?.message ?? "Failed to load order");
|
|
27
|
-
|
|
28
|
+
j(t.data?.getStoreOrder ?? null);
|
|
28
29
|
let n = new Set((t.data?.getStoreOrder?.lineItems ?? []).map((e) => e.productId));
|
|
29
|
-
|
|
30
|
+
N((t.data?.myEntitlements ?? []).filter((e) => n.has(e.productId)));
|
|
30
31
|
} catch (t) {
|
|
31
32
|
if (e) return;
|
|
32
|
-
|
|
33
|
+
L(t instanceof Error ? t.message : "Failed to load order");
|
|
33
34
|
} finally {
|
|
34
|
-
e ||
|
|
35
|
+
e || F(!1);
|
|
35
36
|
}
|
|
36
37
|
})(), () => {
|
|
37
38
|
e = !0;
|
|
38
39
|
};
|
|
39
|
-
}, [
|
|
40
|
-
let
|
|
41
|
-
|
|
40
|
+
}, [O, D]);
|
|
41
|
+
let B = async (e) => {
|
|
42
|
+
i("light");
|
|
42
43
|
try {
|
|
43
|
-
await
|
|
44
|
+
await r(e) ? (z(e), a("success"), setTimeout(() => z(null), 1500)) : a("error");
|
|
44
45
|
} catch {
|
|
45
|
-
|
|
46
|
+
a("error");
|
|
46
47
|
}
|
|
47
|
-
},
|
|
48
|
+
}, V = (e, t) => {
|
|
48
49
|
let n = new URLSearchParams();
|
|
49
50
|
n.set("install", e), t && n.set("licenseKey", t), window.location.href = `/vibecontrols/agents?${n.toString()}`;
|
|
50
|
-
},
|
|
51
|
-
return /* @__PURE__ */
|
|
51
|
+
}, H = (e, n) => t(e, n || "USD"), U = A?.lineItems ?? [], W = U.some((e) => String(e.itemType ?? "").toLowerCase() === "physical"), G = U.some((e) => String(e.itemType ?? "").toLowerCase() !== "physical");
|
|
52
|
+
return /* @__PURE__ */ x("main", {
|
|
52
53
|
className: "mx-auto max-w-3xl p-6",
|
|
53
54
|
children: [
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ x(S, {
|
|
55
56
|
className: "rounded-2xl p-6 text-center",
|
|
56
57
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
-
/* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ b(d, { className: "mx-auto size-12 text-status-success-text" }),
|
|
59
|
+
/* @__PURE__ */ b("h1", {
|
|
59
60
|
className: "mt-3 text-2xl font-bold text-text-primary",
|
|
60
|
-
children: "Order placed successfully"
|
|
61
|
+
children: k("pages.orderConfirmation.title", "Order placed successfully")
|
|
61
62
|
}),
|
|
62
|
-
|
|
63
|
+
A && /* @__PURE__ */ x("p", {
|
|
63
64
|
className: "mt-1 text-sm tabular-nums text-text-secondary",
|
|
64
|
-
children: [
|
|
65
|
-
"Total: ",
|
|
66
|
-
B(O.total, O.currency),
|
|
67
|
-
O.purchasedAt && ` • ${new Date(O.purchasedAt).toLocaleString()}`
|
|
68
|
-
]
|
|
65
|
+
children: [k("pages.orderConfirmation.totalAt", "Total: {{total}}", { total: H(A.total, A.currency) }), A.purchasedAt && ` • ${new Date(A.purchasedAt).toLocaleString()}`]
|
|
69
66
|
}),
|
|
70
|
-
|
|
67
|
+
O && /* @__PURE__ */ x("div", {
|
|
71
68
|
className: "mx-auto mt-4 max-w-sm rounded-lg border border-border-seam bg-surface-default px-4 py-2 text-left",
|
|
72
|
-
children: [/* @__PURE__ */
|
|
69
|
+
children: [/* @__PURE__ */ b("p", {
|
|
73
70
|
className: "text-xs uppercase tracking-wide text-text-tertiary",
|
|
74
|
-
children: "Order ID"
|
|
75
|
-
}), /* @__PURE__ */
|
|
71
|
+
children: k("pages.orderConfirmation.orderId", "Order ID")
|
|
72
|
+
}), /* @__PURE__ */ b("p", {
|
|
76
73
|
className: "mt-0.5 break-all font-mono text-xs text-text-primary",
|
|
77
|
-
children:
|
|
74
|
+
children: O
|
|
78
75
|
})]
|
|
79
76
|
})
|
|
80
77
|
]
|
|
81
78
|
}),
|
|
82
|
-
/* @__PURE__ */
|
|
79
|
+
/* @__PURE__ */ b("p", {
|
|
83
80
|
className: "mt-3 text-center text-xs text-text-tertiary",
|
|
84
|
-
children:
|
|
81
|
+
children: W ? k("pages.orderConfirmation.physicalNotice", "You'll receive shipping and tracking updates as your order is prepared and dispatched.") : k("pages.orderConfirmation.digitalNotice", "This purchase is final and non-refundable. Digital app orders cannot be cancelled once completed.")
|
|
85
82
|
}),
|
|
86
|
-
|
|
83
|
+
I && /* @__PURE__ */ b("div", {
|
|
87
84
|
role: "alert",
|
|
88
85
|
className: "mt-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
|
|
89
|
-
children:
|
|
86
|
+
children: I
|
|
90
87
|
}),
|
|
91
|
-
|
|
88
|
+
P ? /* @__PURE__ */ b("output", {
|
|
92
89
|
className: "mt-6 block py-12 text-center text-text-secondary",
|
|
93
|
-
children: "Loading your order…"
|
|
94
|
-
}) : /* @__PURE__ */
|
|
90
|
+
children: k("pages.orderConfirmation.loading", "Loading your order…")
|
|
91
|
+
}) : /* @__PURE__ */ x(y, { children: [W && /* @__PURE__ */ x("section", {
|
|
95
92
|
className: "mt-6",
|
|
96
|
-
children: [/* @__PURE__ */
|
|
93
|
+
children: [/* @__PURE__ */ x("h2", {
|
|
97
94
|
className: "mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary",
|
|
98
|
-
children: [/* @__PURE__ */
|
|
99
|
-
}), /* @__PURE__ */
|
|
95
|
+
children: [/* @__PURE__ */ b(_, { className: "size-4" }), k("pages.orderConfirmation.shipping", "Shipping")]
|
|
96
|
+
}), /* @__PURE__ */ x("div", {
|
|
100
97
|
className: "rounded-lg border border-border-seam bg-surface-raised p-4",
|
|
101
98
|
children: [
|
|
102
|
-
/* @__PURE__ */
|
|
99
|
+
/* @__PURE__ */ b("p", {
|
|
103
100
|
className: "text-sm text-text-secondary",
|
|
104
|
-
children:
|
|
101
|
+
children: A?.fulfillment?.status && A.fulfillment.status !== "PENDING" ? k("pages.orderConfirmation.status", "Status: {{status}}", { status: ((e) => e.replace(/_/g, " ").toLowerCase().replace(/^./, (e) => e.toUpperCase()))(A.fulfillment.status) }) : k("pages.orderConfirmation.preparingShipment", "Your order is being prepared for shipment. We'll share tracking details once it ships.")
|
|
105
102
|
}),
|
|
106
|
-
|
|
103
|
+
A?.fulfillment?.estimatedDeliveryDate && /* @__PURE__ */ b("p", {
|
|
107
104
|
className: "mt-1 text-xs text-text-tertiary",
|
|
108
|
-
children:
|
|
109
|
-
"Estimated delivery:",
|
|
110
|
-
" ",
|
|
111
|
-
new Date(O.fulfillment.estimatedDeliveryDate).toLocaleDateString()
|
|
112
|
-
]
|
|
105
|
+
children: k("pages.orderConfirmation.estimatedDelivery", "Estimated delivery: {{date}}", { date: new Date(A.fulfillment.estimatedDeliveryDate).toLocaleDateString() })
|
|
113
106
|
}),
|
|
114
|
-
|
|
115
|
-
href:
|
|
107
|
+
A?.fulfillment?.trackingUrl && /* @__PURE__ */ x("a", {
|
|
108
|
+
href: A.fulfillment.trackingUrl,
|
|
116
109
|
target: "_blank",
|
|
117
110
|
rel: "noreferrer",
|
|
118
111
|
className: "mt-3 inline-flex items-center gap-1.5 rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-xs font-semibold text-text-primary hover:bg-surface-hover",
|
|
119
112
|
children: [
|
|
120
|
-
/* @__PURE__ */
|
|
121
|
-
"Track package",
|
|
122
|
-
|
|
113
|
+
/* @__PURE__ */ b(h, { className: "size-3.5" }),
|
|
114
|
+
k("pages.orderConfirmation.trackPackage", "Track package"),
|
|
115
|
+
A.fulfillment.trackingNumber ? ` (${A.fulfillment.trackingNumber})` : ""
|
|
123
116
|
]
|
|
124
117
|
}),
|
|
125
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ b("ul", {
|
|
126
119
|
className: "mt-4 space-y-2 border-t border-border-seam pt-3",
|
|
127
|
-
children:
|
|
120
|
+
children: U.filter((e) => String(e.itemType ?? "").toLowerCase() === "physical").map((e, t) => /* @__PURE__ */ x("li", {
|
|
128
121
|
className: "flex items-center justify-between gap-3 text-sm",
|
|
129
|
-
children: [/* @__PURE__ */
|
|
122
|
+
children: [/* @__PURE__ */ x("span", {
|
|
130
123
|
className: "min-w-0 truncate text-text-primary",
|
|
131
124
|
children: [
|
|
132
125
|
e.name,
|
|
133
126
|
" × ",
|
|
134
127
|
e.quantity
|
|
135
128
|
]
|
|
136
|
-
}), /* @__PURE__ */
|
|
129
|
+
}), /* @__PURE__ */ b("span", {
|
|
137
130
|
className: "tabular-nums text-text-secondary",
|
|
138
|
-
children:
|
|
131
|
+
children: H(e.subtotal, A?.currency ?? "USD")
|
|
139
132
|
})]
|
|
140
133
|
}, e.productId ?? t))
|
|
141
134
|
})
|
|
142
135
|
]
|
|
143
136
|
})]
|
|
144
|
-
}),
|
|
137
|
+
}), M.length > 0 && /* @__PURE__ */ x("div", {
|
|
145
138
|
className: "mt-6",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
139
|
+
children: [/* @__PURE__ */ x("h2", {
|
|
147
140
|
className: "mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary",
|
|
148
|
-
children: [
|
|
149
|
-
|
|
150
|
-
"Your licenses (",
|
|
151
|
-
A.length,
|
|
152
|
-
")"
|
|
153
|
-
]
|
|
154
|
-
}), /* @__PURE__ */ y("ul", {
|
|
141
|
+
children: [/* @__PURE__ */ b(m, { className: "size-4" }), k("pages.orderConfirmation.licenses", "Your licenses ({{count}})", { count: M.length })]
|
|
142
|
+
}), /* @__PURE__ */ b("ul", {
|
|
155
143
|
className: "space-y-3",
|
|
156
|
-
children:
|
|
144
|
+
children: M.map((e) => /* @__PURE__ */ b("li", {
|
|
157
145
|
className: "rounded-lg border border-border-seam bg-surface-raised p-4 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]",
|
|
158
|
-
children: /* @__PURE__ */
|
|
146
|
+
children: /* @__PURE__ */ x("div", {
|
|
159
147
|
className: "flex items-start gap-3",
|
|
160
148
|
children: [
|
|
161
|
-
e.product?.icon ? /* @__PURE__ */
|
|
149
|
+
e.product?.icon ? /* @__PURE__ */ b("img", {
|
|
162
150
|
src: e.product.icon,
|
|
163
151
|
alt: "",
|
|
164
152
|
className: "size-12 flex-shrink-0 rounded-md object-cover"
|
|
165
|
-
}) : /* @__PURE__ */
|
|
153
|
+
}) : /* @__PURE__ */ b("div", {
|
|
166
154
|
className: "flex size-12 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-xs text-text-secondary",
|
|
167
155
|
children: e.product?.name.slice(0, 2).toUpperCase() ?? "?"
|
|
168
156
|
}),
|
|
169
|
-
/* @__PURE__ */
|
|
157
|
+
/* @__PURE__ */ x("div", {
|
|
170
158
|
className: "min-w-0 flex-1",
|
|
171
159
|
children: [
|
|
172
|
-
/* @__PURE__ */
|
|
160
|
+
/* @__PURE__ */ b("h3", {
|
|
173
161
|
className: "text-base font-semibold text-text-primary",
|
|
174
|
-
children: e.product?.name ?? "Unknown product"
|
|
162
|
+
children: e.product?.name ?? k("common.unknownProduct", "Unknown product")
|
|
175
163
|
}),
|
|
176
164
|
e.expiresAt && /* @__PURE__ */ b("p", {
|
|
177
165
|
className: "text-xs text-text-secondary",
|
|
178
|
-
children:
|
|
166
|
+
children: k("pages.orderConfirmation.expires", "Expires: {{date}}", { date: new Date(e.expiresAt).toLocaleDateString() })
|
|
179
167
|
}),
|
|
180
|
-
e.licenseKey && /* @__PURE__ */
|
|
168
|
+
e.licenseKey && /* @__PURE__ */ x("div", {
|
|
181
169
|
className: "mt-2 flex items-center gap-2",
|
|
182
|
-
children: [/* @__PURE__ */
|
|
170
|
+
children: [/* @__PURE__ */ b("code", {
|
|
183
171
|
className: "flex-1 truncate rounded bg-surface-muted px-2 py-1 font-mono text-[11px] text-text-primary",
|
|
184
172
|
children: e.licenseKey
|
|
185
|
-
}), /* @__PURE__ */
|
|
173
|
+
}), /* @__PURE__ */ b("button", {
|
|
186
174
|
type: "button",
|
|
187
|
-
onClick: () => void
|
|
175
|
+
onClick: () => void B(e.licenseKey),
|
|
188
176
|
className: "rounded-md border border-border-default bg-surface-default p-1 text-text-primary hover:bg-surface-hover",
|
|
189
|
-
title: "Copy license key",
|
|
190
|
-
children: /* @__PURE__ */
|
|
177
|
+
title: k("pages.orderConfirmation.copyLicenseKey", "Copy license key"),
|
|
178
|
+
children: /* @__PURE__ */ b(f, { className: "size-3.5" })
|
|
191
179
|
})]
|
|
192
180
|
}),
|
|
193
|
-
|
|
181
|
+
R === e.licenseKey && /* @__PURE__ */ b("p", {
|
|
194
182
|
className: "mt-1 text-xs text-status-success-text",
|
|
195
|
-
children: "Copied to clipboard"
|
|
183
|
+
children: k("pages.orderConfirmation.copied", "Copied to clipboard")
|
|
196
184
|
})
|
|
197
185
|
]
|
|
198
186
|
}),
|
|
199
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ x("button", {
|
|
200
188
|
type: "button",
|
|
201
|
-
onClick: () =>
|
|
189
|
+
onClick: () => V(e.productId, e.licenseKey),
|
|
202
190
|
className: "inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text hover:opacity-90",
|
|
203
|
-
children: [/* @__PURE__ */
|
|
191
|
+
children: [/* @__PURE__ */ b(p, { className: "size-3.5" }), k("pages.orderConfirmation.installToWorkspace", "Install to workspace")]
|
|
204
192
|
})
|
|
205
193
|
]
|
|
206
194
|
})
|
|
207
195
|
}, e.id))
|
|
208
196
|
})]
|
|
209
197
|
})] }),
|
|
210
|
-
!
|
|
198
|
+
!P && /* @__PURE__ */ b(C, {
|
|
211
199
|
className: "mt-6",
|
|
212
200
|
storageKey: "store-order-confirmation",
|
|
213
|
-
title: "What's next?",
|
|
201
|
+
title: k("pages.orderConfirmation.whatsNext", "What's next?"),
|
|
214
202
|
steps: [
|
|
215
|
-
...
|
|
203
|
+
...G || M.length > 0 ? [{
|
|
216
204
|
id: "install",
|
|
217
|
-
label: "Install what you bought",
|
|
218
|
-
description: "Add each purchased app to a workspace using its license.",
|
|
219
|
-
icon: /* @__PURE__ */
|
|
205
|
+
label: k("pages.orderConfirmation.nextInstall", "Install what you bought"),
|
|
206
|
+
description: k("pages.orderConfirmation.nextInstallDescription", "Add each purchased app to a workspace using its license."),
|
|
207
|
+
icon: /* @__PURE__ */ b(p, { className: "size-4" }),
|
|
220
208
|
onClick: () => {
|
|
221
|
-
let e =
|
|
222
|
-
e &&
|
|
209
|
+
let e = M[0];
|
|
210
|
+
e && V(e.productId, e.licenseKey);
|
|
223
211
|
},
|
|
224
|
-
done:
|
|
212
|
+
done: M.length === 0
|
|
225
213
|
}] : [],
|
|
226
|
-
...
|
|
214
|
+
...W ? [{
|
|
227
215
|
id: "track",
|
|
228
|
-
label: "Track your order",
|
|
229
|
-
description: "Follow delivery status under My Orders.",
|
|
230
|
-
icon: /* @__PURE__ */
|
|
231
|
-
onClick: () =>
|
|
216
|
+
label: k("pages.orderConfirmation.nextTrack", "Track your order"),
|
|
217
|
+
description: k("pages.orderConfirmation.nextTrackDescription", "Follow delivery status under My Orders."),
|
|
218
|
+
icon: /* @__PURE__ */ b(_, { className: "size-4" }),
|
|
219
|
+
onClick: () => T(`${E}/orders`)
|
|
232
220
|
}] : [],
|
|
233
221
|
{
|
|
234
222
|
id: "orders",
|
|
235
|
-
label: "Keep this receipt",
|
|
236
|
-
description: "Find this order any time under My Orders.",
|
|
237
|
-
icon: /* @__PURE__ */
|
|
238
|
-
onClick: () =>
|
|
223
|
+
label: k("pages.orderConfirmation.nextReceipt", "Keep this receipt"),
|
|
224
|
+
description: k("pages.orderConfirmation.nextReceiptDescription", "Find this order any time under My Orders."),
|
|
225
|
+
icon: /* @__PURE__ */ b(g, { className: "size-4" }),
|
|
226
|
+
onClick: () => T(`${E}/orders`)
|
|
239
227
|
},
|
|
240
228
|
{
|
|
241
229
|
id: "shop",
|
|
242
|
-
label: "Discover more",
|
|
243
|
-
description: "Browse the marketplace for more apps and tools.",
|
|
244
|
-
icon: /* @__PURE__ */
|
|
245
|
-
onClick: () =>
|
|
230
|
+
label: k("pages.orderConfirmation.nextDiscover", "Discover more"),
|
|
231
|
+
description: k("pages.orderConfirmation.nextDiscoverDescription", "Browse the marketplace for more apps and tools."),
|
|
232
|
+
icon: /* @__PURE__ */ b(u, { className: "size-4" }),
|
|
233
|
+
onClick: () => T(`${E}/marketplace`)
|
|
246
234
|
}
|
|
247
235
|
]
|
|
248
236
|
}),
|
|
249
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ x("div", {
|
|
250
238
|
className: "mt-6 flex flex-col gap-2 sm:flex-row sm:justify-center",
|
|
251
|
-
children: [/* @__PURE__ */
|
|
239
|
+
children: [/* @__PURE__ */ x("button", {
|
|
252
240
|
type: "button",
|
|
253
|
-
onClick: () =>
|
|
241
|
+
onClick: () => T(`${E}/orders`),
|
|
254
242
|
className: "cursor-pointer inline-flex items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text",
|
|
255
|
-
children: [/* @__PURE__ */
|
|
256
|
-
}), /* @__PURE__ */
|
|
243
|
+
children: [/* @__PURE__ */ b(g, { className: "size-4" }), k("pages.orderConfirmation.viewOrders", "View My Orders")]
|
|
244
|
+
}), /* @__PURE__ */ x("button", {
|
|
257
245
|
type: "button",
|
|
258
|
-
onClick: () =>
|
|
246
|
+
onClick: () => T(`${E}/marketplace`),
|
|
259
247
|
className: "cursor-pointer inline-flex items-center justify-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-semibold text-text-primary hover:bg-surface-hover",
|
|
260
|
-
children: ["Continue Shopping", /* @__PURE__ */
|
|
248
|
+
children: [k("pages.orderConfirmation.continueShopping", "Continue Shopping"), /* @__PURE__ */ b(u, { className: "size-4" })]
|
|
261
249
|
})]
|
|
262
250
|
})
|
|
263
251
|
]
|
|
264
252
|
});
|
|
265
253
|
};
|
|
266
254
|
//#endregion
|
|
267
|
-
export {
|
|
255
|
+
export { T as OrderConfirmationPage };
|
|
268
256
|
|
|
269
257
|
//# sourceMappingURL=OrderConfirmationPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrderConfirmationPage.js","names":[],"sources":["../../src/pages/OrderConfirmationPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport {\n CheckCircle2,\n Receipt,\n ArrowRight,\n Copy,\n Download,\n KeyRound,\n Truck,\n Package,\n} from 'lucide-react';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { EmphasisPanel, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { useStore } from '../providers/StoreProvider';\nimport { nativeCopyText, nativeImpact, nativeNotify } from '../utils/nativeBridge';\nimport { formatPrice as formatCurrency } from '../utils';\n\ntype LineItem = {\n productId: string;\n name: string;\n quantity: number;\n unitPrice: number;\n subtotal: number;\n itemType?: string;\n};\n\ntype OrderFulfillment = {\n status: string;\n trackingNumber: string | null;\n trackingUrl: string | null;\n carrier: string | null;\n estimatedDeliveryDate: string | null;\n};\n\ntype OrderDetails = {\n id: string;\n status: string;\n total: number;\n currency: string;\n purchasedAt?: string | null;\n lineItems: LineItem[];\n context?: Record<string, unknown> | null;\n fulfillment?: OrderFulfillment | null;\n};\n\ntype Entitlement = {\n id: string;\n productId: string;\n licenseKey: string | null;\n expiresAt: string | null;\n features: string[];\n product: {\n id: string;\n name: string;\n slug: string;\n icon: string | null;\n manifest: Record<string, unknown> | null;\n } | null;\n};\n\nconst ORDER_QUERY = /* GraphQL */ `\n query OrderConfirmation($id: ID!) {\n getStoreOrder(id: $id) {\n id\n status\n total\n currency\n purchasedAt\n lineItems\n context\n fulfillment {\n status\n trackingNumber\n trackingUrl\n carrier\n estimatedDeliveryDate\n }\n }\n myEntitlements {\n id\n productId\n licenseKey\n expiresAt\n features\n product {\n id\n name\n slug\n icon\n manifest\n }\n }\n }\n`;\n\nexport const OrderConfirmationPage: FC = () => {\n const navigate = useNavigate();\n const { basePath, authToken } = useStore();\n const { orderId } = useParams<{ orderId: string }>();\n const [order, setOrder] = useState<OrderDetails | null>(null);\n const [entitlements, setEntitlements] = useState<Entitlement[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [copiedKey, setCopiedKey] = useState<string | null>(null);\n\n useEffect(() => {\n if (!orderId) return;\n let cancelled = false;\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{\n getStoreOrder: OrderDetails | null;\n myEntitlements: Entitlement[];\n }>({\n gateway: 'global',\n query: ORDER_QUERY,\n variables: { id: orderId },\n authToken: authToken || undefined,\n });\n if (cancelled) return;\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to load order');\n }\n setOrder(result.data?.getStoreOrder ?? null);\n // Filter entitlements to only those matching products in this order\n const productIds = new Set(\n (result.data?.getStoreOrder?.lineItems ?? []).map((item) => item.productId)\n );\n const orderEntitlements = (result.data?.myEntitlements ?? []).filter((e) =>\n productIds.has(e.productId)\n );\n setEntitlements(orderEntitlements);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err.message : 'Failed to load order');\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n void load();\n return () => {\n cancelled = true;\n };\n }, [orderId, authToken]);\n\n const copyKey = async (key: string) => {\n void nativeImpact('light');\n try {\n const ok = await nativeCopyText(key);\n if (ok) {\n setCopiedKey(key);\n void nativeNotify('success');\n setTimeout(() => setCopiedKey(null), 1500);\n } else {\n void nativeNotify('error');\n }\n } catch {\n void nativeNotify('error');\n }\n };\n\n const installInWorkspace = (productId: string, licenseKey: string | null) => {\n const params = new URLSearchParams();\n params.set('install', productId);\n if (licenseKey) params.set('licenseKey', licenseKey);\n // Navigate to the vibecontrols plugin install page via the top-level router.\n // Uses a plain anchor to avoid cross-MFE router imports.\n window.location.href = `/vibecontrols/agents?${params.toString()}`;\n };\n\n const formatPrice = (amount: number, currency: string) =>\n formatCurrency(amount, currency || 'USD');\n\n const lineItems = order?.lineItems ?? [];\n const hasPhysical = lineItems.some(\n (li) => String(li.itemType ?? '').toLowerCase() === 'physical'\n );\n const hasDigital = lineItems.some((li) => String(li.itemType ?? '').toLowerCase() !== 'physical');\n const formatFulfillmentStatus = (s: string) =>\n s\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/^./, (c) => c.toUpperCase());\n\n return (\n <main className=\"mx-auto max-w-3xl p-6\">\n <EmphasisPanel className=\"rounded-2xl p-6 text-center\">\n <CheckCircle2 className=\"mx-auto size-12 text-status-success-text\" />\n <h1 className=\"mt-3 text-2xl font-bold text-text-primary\">Order placed successfully</h1>\n {order && (\n <p className=\"mt-1 text-sm tabular-nums text-text-secondary\">\n Total: {formatPrice(order.total, order.currency)}\n {order.purchasedAt && ` • ${new Date(order.purchasedAt).toLocaleString()}`}\n </p>\n )}\n {orderId && (\n <div className=\"mx-auto mt-4 max-w-sm rounded-lg border border-border-seam bg-surface-default px-4 py-2 text-left\">\n <p className=\"text-xs uppercase tracking-wide text-text-tertiary\">Order ID</p>\n <p className=\"mt-0.5 break-all font-mono text-xs text-text-primary\">{orderId}</p>\n </div>\n )}\n </EmphasisPanel>\n\n <p className=\"mt-3 text-center text-xs text-text-tertiary\">\n {hasPhysical\n ? \"You'll receive shipping and tracking updates as your order is prepared and dispatched.\"\n : 'This purchase is final and non-refundable. Digital app orders cannot be cancelled once completed.'}\n </p>\n\n {error && (\n <div\n role=\"alert\"\n className=\"mt-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {error}\n </div>\n )}\n\n {loading ? (\n <output className=\"mt-6 block py-12 text-center text-text-secondary\">\n Loading your order…\n </output>\n ) : (\n <>\n {hasPhysical && (\n <section className=\"mt-6\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Truck className=\"size-4\" />\n Shipping\n </h2>\n <div className=\"rounded-lg border border-border-seam bg-surface-raised p-4\">\n <p className=\"text-sm text-text-secondary\">\n {order?.fulfillment?.status && order.fulfillment.status !== 'PENDING'\n ? `Status: ${formatFulfillmentStatus(order.fulfillment.status)}`\n : \"Your order is being prepared for shipment. We'll share tracking details once it ships.\"}\n </p>\n {order?.fulfillment?.estimatedDeliveryDate && (\n <p className=\"mt-1 text-xs text-text-tertiary\">\n Estimated delivery:{' '}\n {new Date(order.fulfillment.estimatedDeliveryDate).toLocaleDateString()}\n </p>\n )}\n {order?.fulfillment?.trackingUrl && (\n <a\n href={order.fulfillment.trackingUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"mt-3 inline-flex items-center gap-1.5 rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-xs font-semibold text-text-primary hover:bg-surface-hover\"\n >\n <Package className=\"size-3.5\" />\n Track package\n {order.fulfillment.trackingNumber\n ? ` (${order.fulfillment.trackingNumber})`\n : ''}\n </a>\n )}\n <ul className=\"mt-4 space-y-2 border-t border-border-seam pt-3\">\n {lineItems\n .filter((li) => String(li.itemType ?? '').toLowerCase() === 'physical')\n .map((li, idx) => (\n <li\n key={li.productId ?? idx}\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"min-w-0 truncate text-text-primary\">\n {li.name} × {li.quantity}\n </span>\n <span className=\"tabular-nums text-text-secondary\">\n {formatPrice(li.subtotal, order?.currency ?? 'USD')}\n </span>\n </li>\n ))}\n </ul>\n </div>\n </section>\n )}\n {entitlements.length > 0 && (\n <div className=\"mt-6\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <KeyRound className=\"size-4\" />\n Your licenses ({entitlements.length})\n </h2>\n <ul className=\"space-y-3\">\n {entitlements.map((ent) => (\n <li\n key={ent.id}\n className=\"rounded-lg border border-border-seam bg-surface-raised p-4 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start gap-3\">\n {ent.product?.icon ? (\n <img\n src={ent.product.icon}\n alt=\"\"\n className=\"size-12 flex-shrink-0 rounded-md object-cover\"\n />\n ) : (\n <div className=\"flex size-12 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-xs text-text-secondary\">\n {ent.product?.name.slice(0, 2).toUpperCase() ?? '?'}\n </div>\n )}\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {ent.product?.name ?? 'Unknown product'}\n </h3>\n {ent.expiresAt && (\n <p className=\"text-xs text-text-secondary\">\n Expires: {new Date(ent.expiresAt).toLocaleDateString()}\n </p>\n )}\n {ent.licenseKey && (\n <div className=\"mt-2 flex items-center gap-2\">\n <code className=\"flex-1 truncate rounded bg-surface-muted px-2 py-1 font-mono text-[11px] text-text-primary\">\n {ent.licenseKey}\n </code>\n <button\n type=\"button\"\n onClick={() => void copyKey(ent.licenseKey!)}\n className=\"rounded-md border border-border-default bg-surface-default p-1 text-text-primary hover:bg-surface-hover\"\n title=\"Copy license key\"\n >\n <Copy className=\"size-3.5\" />\n </button>\n </div>\n )}\n {copiedKey === ent.licenseKey && (\n <p className=\"mt-1 text-xs text-status-success-text\">\n Copied to clipboard\n </p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => installInWorkspace(ent.productId, ent.licenseKey)}\n className=\"inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text hover:opacity-90\"\n >\n <Download className=\"size-3.5\" />\n Install to workspace\n </button>\n </div>\n </li>\n ))}\n </ul>\n </div>\n )}\n </>\n )}\n\n {!loading && (\n <NextSteps\n className=\"mt-6\"\n storageKey=\"store-order-confirmation\"\n title=\"What's next?\"\n steps={[\n ...(hasDigital || entitlements.length > 0\n ? [\n {\n id: 'install',\n label: 'Install what you bought',\n description: 'Add each purchased app to a workspace using its license.',\n icon: <Download className=\"size-4\" />,\n onClick: () => {\n const first = entitlements[0];\n if (first) installInWorkspace(first.productId, first.licenseKey);\n },\n done: entitlements.length === 0,\n },\n ]\n : []),\n ...(hasPhysical\n ? [\n {\n id: 'track',\n label: 'Track your order',\n description: 'Follow delivery status under My Orders.',\n icon: <Truck className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/orders`),\n },\n ]\n : []),\n {\n id: 'orders',\n label: 'Keep this receipt',\n description: 'Find this order any time under My Orders.',\n icon: <Receipt className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/orders`),\n },\n {\n id: 'shop',\n label: 'Discover more',\n description: 'Browse the marketplace for more apps and tools.',\n icon: <ArrowRight className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/marketplace`),\n },\n ]}\n />\n )}\n\n <div className=\"mt-6 flex flex-col gap-2 sm:flex-row sm:justify-center\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/orders`)}\n className=\"cursor-pointer inline-flex items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text\"\n >\n <Receipt className=\"size-4\" />\n View My Orders\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/marketplace`)}\n className=\"cursor-pointer inline-flex items-center justify-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-semibold text-text-primary hover:bg-surface-hover\"\n >\n Continue Shopping\n <ArrowRight className=\"size-4\" />\n </button>\n </div>\n </main>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrderConfirmationPage.js","names":[],"sources":["../../src/pages/OrderConfirmationPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport {\n CheckCircle2,\n Receipt,\n ArrowRight,\n Copy,\n Download,\n KeyRound,\n Truck,\n Package,\n} from 'lucide-react';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { EmphasisPanel, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { useStore } from '../providers/StoreProvider';\nimport { nativeCopyText, nativeImpact, nativeNotify } from '../utils/nativeBridge';\nimport { formatPrice as formatCurrency } from '../utils';\nimport { useTr } from '../shared/hooks/useTr';\n\ntype LineItem = {\n productId: string;\n name: string;\n quantity: number;\n unitPrice: number;\n subtotal: number;\n itemType?: string;\n};\n\ntype OrderFulfillment = {\n status: string;\n trackingNumber: string | null;\n trackingUrl: string | null;\n carrier: string | null;\n estimatedDeliveryDate: string | null;\n};\n\ntype OrderDetails = {\n id: string;\n status: string;\n total: number;\n currency: string;\n purchasedAt?: string | null;\n lineItems: LineItem[];\n context?: Record<string, unknown> | null;\n fulfillment?: OrderFulfillment | null;\n};\n\ntype Entitlement = {\n id: string;\n productId: string;\n licenseKey: string | null;\n expiresAt: string | null;\n features: string[];\n product: {\n id: string;\n name: string;\n slug: string;\n icon: string | null;\n manifest: Record<string, unknown> | null;\n } | null;\n};\n\nconst ORDER_QUERY = /* GraphQL */ `\n query OrderConfirmation($id: ID!) {\n getStoreOrder(id: $id) {\n id\n status\n total\n currency\n purchasedAt\n lineItems\n context\n fulfillment {\n status\n trackingNumber\n trackingUrl\n carrier\n estimatedDeliveryDate\n }\n }\n myEntitlements {\n id\n productId\n licenseKey\n expiresAt\n features\n product {\n id\n name\n slug\n icon\n manifest\n }\n }\n }\n`;\n\nexport const OrderConfirmationPage: FC = () => {\n const navigate = useNavigate();\n const { basePath, authToken } = useStore();\n const { orderId } = useParams<{ orderId: string }>();\n const tr = useTr();\n const [order, setOrder] = useState<OrderDetails | null>(null);\n const [entitlements, setEntitlements] = useState<Entitlement[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [copiedKey, setCopiedKey] = useState<string | null>(null);\n\n useEffect(() => {\n if (!orderId) return;\n let cancelled = false;\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{\n getStoreOrder: OrderDetails | null;\n myEntitlements: Entitlement[];\n }>({\n gateway: 'global',\n query: ORDER_QUERY,\n variables: { id: orderId },\n authToken: authToken || undefined,\n });\n if (cancelled) return;\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to load order');\n }\n setOrder(result.data?.getStoreOrder ?? null);\n // Filter entitlements to only those matching products in this order\n const productIds = new Set(\n (result.data?.getStoreOrder?.lineItems ?? []).map((item) => item.productId)\n );\n const orderEntitlements = (result.data?.myEntitlements ?? []).filter((e) =>\n productIds.has(e.productId)\n );\n setEntitlements(orderEntitlements);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err.message : 'Failed to load order');\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n void load();\n return () => {\n cancelled = true;\n };\n }, [orderId, authToken]);\n\n const copyKey = async (key: string) => {\n void nativeImpact('light');\n try {\n const ok = await nativeCopyText(key);\n if (ok) {\n setCopiedKey(key);\n void nativeNotify('success');\n setTimeout(() => setCopiedKey(null), 1500);\n } else {\n void nativeNotify('error');\n }\n } catch {\n void nativeNotify('error');\n }\n };\n\n const installInWorkspace = (productId: string, licenseKey: string | null) => {\n const params = new URLSearchParams();\n params.set('install', productId);\n if (licenseKey) params.set('licenseKey', licenseKey);\n // Navigate to the vibecontrols plugin install page via the top-level router.\n // Uses a plain anchor to avoid cross-MFE router imports.\n window.location.href = `/vibecontrols/agents?${params.toString()}`;\n };\n\n const formatPrice = (amount: number, currency: string) =>\n formatCurrency(amount, currency || 'USD');\n\n const lineItems = order?.lineItems ?? [];\n const hasPhysical = lineItems.some(\n (li) => String(li.itemType ?? '').toLowerCase() === 'physical'\n );\n const hasDigital = lineItems.some((li) => String(li.itemType ?? '').toLowerCase() !== 'physical');\n const formatFulfillmentStatus = (s: string) =>\n s\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/^./, (c) => c.toUpperCase());\n\n return (\n <main className=\"mx-auto max-w-3xl p-6\">\n <EmphasisPanel className=\"rounded-2xl p-6 text-center\">\n <CheckCircle2 className=\"mx-auto size-12 text-status-success-text\" />\n <h1 className=\"mt-3 text-2xl font-bold text-text-primary\">\n {tr('pages.orderConfirmation.title', 'Order placed successfully')}\n </h1>\n {order && (\n <p className=\"mt-1 text-sm tabular-nums text-text-secondary\">\n {tr('pages.orderConfirmation.totalAt', 'Total: {{total}}', {\n total: formatPrice(order.total, order.currency),\n })}\n {order.purchasedAt && ` • ${new Date(order.purchasedAt).toLocaleString()}`}\n </p>\n )}\n {orderId && (\n <div className=\"mx-auto mt-4 max-w-sm rounded-lg border border-border-seam bg-surface-default px-4 py-2 text-left\">\n <p className=\"text-xs uppercase tracking-wide text-text-tertiary\">\n {tr('pages.orderConfirmation.orderId', 'Order ID')}\n </p>\n <p className=\"mt-0.5 break-all font-mono text-xs text-text-primary\">{orderId}</p>\n </div>\n )}\n </EmphasisPanel>\n\n <p className=\"mt-3 text-center text-xs text-text-tertiary\">\n {hasPhysical\n ? tr(\n 'pages.orderConfirmation.physicalNotice',\n \"You'll receive shipping and tracking updates as your order is prepared and dispatched.\"\n )\n : tr(\n 'pages.orderConfirmation.digitalNotice',\n 'This purchase is final and non-refundable. Digital app orders cannot be cancelled once completed.'\n )}\n </p>\n\n {error && (\n <div\n role=\"alert\"\n className=\"mt-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {error}\n </div>\n )}\n\n {loading ? (\n <output className=\"mt-6 block py-12 text-center text-text-secondary\">\n {tr('pages.orderConfirmation.loading', 'Loading your order…')}\n </output>\n ) : (\n <>\n {hasPhysical && (\n <section className=\"mt-6\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Truck className=\"size-4\" />\n {tr('pages.orderConfirmation.shipping', 'Shipping')}\n </h2>\n <div className=\"rounded-lg border border-border-seam bg-surface-raised p-4\">\n <p className=\"text-sm text-text-secondary\">\n {order?.fulfillment?.status && order.fulfillment.status !== 'PENDING'\n ? tr('pages.orderConfirmation.status', 'Status: {{status}}', {\n status: formatFulfillmentStatus(order.fulfillment.status),\n })\n : tr(\n 'pages.orderConfirmation.preparingShipment',\n \"Your order is being prepared for shipment. We'll share tracking details once it ships.\"\n )}\n </p>\n {order?.fulfillment?.estimatedDeliveryDate && (\n <p className=\"mt-1 text-xs text-text-tertiary\">\n {tr(\n 'pages.orderConfirmation.estimatedDelivery',\n 'Estimated delivery: {{date}}',\n {\n date: new Date(\n order.fulfillment.estimatedDeliveryDate\n ).toLocaleDateString(),\n }\n )}\n </p>\n )}\n {order?.fulfillment?.trackingUrl && (\n <a\n href={order.fulfillment.trackingUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"mt-3 inline-flex items-center gap-1.5 rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-xs font-semibold text-text-primary hover:bg-surface-hover\"\n >\n <Package className=\"size-3.5\" />\n {tr('pages.orderConfirmation.trackPackage', 'Track package')}\n {order.fulfillment.trackingNumber\n ? ` (${order.fulfillment.trackingNumber})`\n : ''}\n </a>\n )}\n <ul className=\"mt-4 space-y-2 border-t border-border-seam pt-3\">\n {lineItems\n .filter((li) => String(li.itemType ?? '').toLowerCase() === 'physical')\n .map((li, idx) => (\n <li\n key={li.productId ?? idx}\n className=\"flex items-center justify-between gap-3 text-sm\"\n >\n <span className=\"min-w-0 truncate text-text-primary\">\n {li.name} × {li.quantity}\n </span>\n <span className=\"tabular-nums text-text-secondary\">\n {formatPrice(li.subtotal, order?.currency ?? 'USD')}\n </span>\n </li>\n ))}\n </ul>\n </div>\n </section>\n )}\n {entitlements.length > 0 && (\n <div className=\"mt-6\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <KeyRound className=\"size-4\" />\n {tr('pages.orderConfirmation.licenses', 'Your licenses ({{count}})', {\n count: entitlements.length,\n })}\n </h2>\n <ul className=\"space-y-3\">\n {entitlements.map((ent) => (\n <li\n key={ent.id}\n className=\"rounded-lg border border-border-seam bg-surface-raised p-4 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start gap-3\">\n {ent.product?.icon ? (\n <img\n src={ent.product.icon}\n alt=\"\"\n className=\"size-12 flex-shrink-0 rounded-md object-cover\"\n />\n ) : (\n <div className=\"flex size-12 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-xs text-text-secondary\">\n {ent.product?.name.slice(0, 2).toUpperCase() ?? '?'}\n </div>\n )}\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {ent.product?.name ?? tr('common.unknownProduct', 'Unknown product')}\n </h3>\n {ent.expiresAt && (\n <p className=\"text-xs text-text-secondary\">\n {tr('pages.orderConfirmation.expires', 'Expires: {{date}}', {\n date: new Date(ent.expiresAt).toLocaleDateString(),\n })}\n </p>\n )}\n {ent.licenseKey && (\n <div className=\"mt-2 flex items-center gap-2\">\n <code className=\"flex-1 truncate rounded bg-surface-muted px-2 py-1 font-mono text-[11px] text-text-primary\">\n {ent.licenseKey}\n </code>\n <button\n type=\"button\"\n onClick={() => void copyKey(ent.licenseKey!)}\n className=\"rounded-md border border-border-default bg-surface-default p-1 text-text-primary hover:bg-surface-hover\"\n title={tr(\n 'pages.orderConfirmation.copyLicenseKey',\n 'Copy license key'\n )}\n >\n <Copy className=\"size-3.5\" />\n </button>\n </div>\n )}\n {copiedKey === ent.licenseKey && (\n <p className=\"mt-1 text-xs text-status-success-text\">\n {tr('pages.orderConfirmation.copied', 'Copied to clipboard')}\n </p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => installInWorkspace(ent.productId, ent.licenseKey)}\n className=\"inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text hover:opacity-90\"\n >\n <Download className=\"size-3.5\" />\n {tr('pages.orderConfirmation.installToWorkspace', 'Install to workspace')}\n </button>\n </div>\n </li>\n ))}\n </ul>\n </div>\n )}\n </>\n )}\n\n {!loading && (\n <NextSteps\n className=\"mt-6\"\n storageKey=\"store-order-confirmation\"\n title={tr('pages.orderConfirmation.whatsNext', \"What's next?\")}\n steps={[\n ...(hasDigital || entitlements.length > 0\n ? [\n {\n id: 'install',\n label: tr('pages.orderConfirmation.nextInstall', 'Install what you bought'),\n description: tr(\n 'pages.orderConfirmation.nextInstallDescription',\n 'Add each purchased app to a workspace using its license.'\n ),\n icon: <Download className=\"size-4\" />,\n onClick: () => {\n const first = entitlements[0];\n if (first) installInWorkspace(first.productId, first.licenseKey);\n },\n done: entitlements.length === 0,\n },\n ]\n : []),\n ...(hasPhysical\n ? [\n {\n id: 'track',\n label: tr('pages.orderConfirmation.nextTrack', 'Track your order'),\n description: tr(\n 'pages.orderConfirmation.nextTrackDescription',\n 'Follow delivery status under My Orders.'\n ),\n icon: <Truck className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/orders`),\n },\n ]\n : []),\n {\n id: 'orders',\n label: tr('pages.orderConfirmation.nextReceipt', 'Keep this receipt'),\n description: tr(\n 'pages.orderConfirmation.nextReceiptDescription',\n 'Find this order any time under My Orders.'\n ),\n icon: <Receipt className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/orders`),\n },\n {\n id: 'shop',\n label: tr('pages.orderConfirmation.nextDiscover', 'Discover more'),\n description: tr(\n 'pages.orderConfirmation.nextDiscoverDescription',\n 'Browse the marketplace for more apps and tools.'\n ),\n icon: <ArrowRight className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/marketplace`),\n },\n ]}\n />\n )}\n\n <div className=\"mt-6 flex flex-col gap-2 sm:flex-row sm:justify-center\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/orders`)}\n className=\"cursor-pointer inline-flex items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text\"\n >\n <Receipt className=\"size-4\" />\n {tr('pages.orderConfirmation.viewOrders', 'View My Orders')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/marketplace`)}\n className=\"cursor-pointer inline-flex items-center justify-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-semibold text-text-primary hover:bg-surface-hover\"\n >\n {tr('pages.orderConfirmation.continueShopping', 'Continue Shopping')}\n <ArrowRight className=\"size-4\" />\n </button>\n </div>\n </main>\n );\n};\n"],"mappings":"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"}
|