@burdenoff/microfe-store 2026.915.1 → 2026.916.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/StoreAdminRoutes.js +17 -7
- package/dist/StoreAdminRoutes.js.map +1 -1
- package/dist/components/cart/CartDrawer.d.ts +2 -0
- package/dist/components/cart/CartDrawer.js +24 -24
- package/dist/components/cart/CartDrawer.js.map +1 -1
- package/dist/pages/AdminFulfillmentLogsPage.d.ts +9 -0
- package/dist/pages/AdminFulfillmentLogsPage.js +278 -0
- package/dist/pages/AdminFulfillmentLogsPage.js.map +1 -0
- package/dist/pages/AdminOrdersPage.js +134 -124
- package/dist/pages/AdminOrdersPage.js.map +1 -1
- package/dist/pages/CartPage.js +57 -57
- package/dist/pages/CartPage.js.map +1 -1
- package/dist/pages/MarketplaceHomePage.js +135 -134
- package/dist/pages/MarketplaceHomePage.js.map +1 -1
- package/package.json +1 -1
package/dist/StoreAdminRoutes.js
CHANGED
|
@@ -5,8 +5,8 @@ import { Suspense as i, lazy as a } from "react";
|
|
|
5
5
|
import { Navigate as o, Route as s, Routes as c } from "react-router";
|
|
6
6
|
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
7
7
|
//#region src/StoreAdminRoutes.tsx
|
|
8
|
-
var d = a(() => import("./pages/AdminDashboardPage.js").then((e) => ({ default: e.AdminDashboardPage }))), f = a(() => import("./pages/AdminSubmissionsQueuePage.js").then((e) => ({ default: e.AdminSubmissionsQueuePage }))), p = a(() => import("./pages/AdminStoresPage.js").then((e) => ({ default: e.AdminStoresPage }))), m = a(() => import("./pages/AdminReviewModerationPage.js").then((e) => ({ default: e.AdminReviewModerationPage }))), h = a(() => import("./pages/AdminOrdersPage.js").then((e) => ({ default: e.AdminOrdersPage }))), g = () => {
|
|
9
|
-
let { hasPermission: a } = t(),
|
|
8
|
+
var d = a(() => import("./pages/AdminDashboardPage.js").then((e) => ({ default: e.AdminDashboardPage }))), f = a(() => import("./pages/AdminSubmissionsQueuePage.js").then((e) => ({ default: e.AdminSubmissionsQueuePage }))), p = a(() => import("./pages/AdminStoresPage.js").then((e) => ({ default: e.AdminStoresPage }))), m = a(() => import("./pages/AdminReviewModerationPage.js").then((e) => ({ default: e.AdminReviewModerationPage }))), h = a(() => import("./pages/AdminOrdersPage.js").then((e) => ({ default: e.AdminOrdersPage }))), g = a(() => import("./pages/AdminFulfillmentLogsPage.js").then((e) => ({ default: e.AdminFulfillmentLogsPage }))), _ = () => {
|
|
9
|
+
let { hasPermission: a } = t(), _ = a(e.REVIEW_ADMIN) || a(e.PRODUCT_ADMIN);
|
|
10
10
|
return /* @__PURE__ */ u(c, { children: [
|
|
11
11
|
/* @__PURE__ */ l(s, {
|
|
12
12
|
index: !0,
|
|
@@ -18,7 +18,7 @@ var d = a(() => import("./pages/AdminDashboardPage.js").then((e) => ({ default:
|
|
|
18
18
|
/* @__PURE__ */ l(s, {
|
|
19
19
|
path: "dashboard",
|
|
20
20
|
element: /* @__PURE__ */ l(n, {
|
|
21
|
-
allowed:
|
|
21
|
+
allowed: _,
|
|
22
22
|
children: /* @__PURE__ */ l(i, {
|
|
23
23
|
fallback: /* @__PURE__ */ l(r, {}),
|
|
24
24
|
children: /* @__PURE__ */ l(d, {})
|
|
@@ -28,7 +28,7 @@ var d = a(() => import("./pages/AdminDashboardPage.js").then((e) => ({ default:
|
|
|
28
28
|
/* @__PURE__ */ l(s, {
|
|
29
29
|
path: "submissions",
|
|
30
30
|
element: /* @__PURE__ */ l(n, {
|
|
31
|
-
allowed:
|
|
31
|
+
allowed: _,
|
|
32
32
|
children: /* @__PURE__ */ l(i, {
|
|
33
33
|
fallback: /* @__PURE__ */ l(r, {}),
|
|
34
34
|
children: /* @__PURE__ */ l(f, {})
|
|
@@ -38,7 +38,7 @@ var d = a(() => import("./pages/AdminDashboardPage.js").then((e) => ({ default:
|
|
|
38
38
|
/* @__PURE__ */ l(s, {
|
|
39
39
|
path: "stores",
|
|
40
40
|
element: /* @__PURE__ */ l(n, {
|
|
41
|
-
allowed:
|
|
41
|
+
allowed: _,
|
|
42
42
|
children: /* @__PURE__ */ l(i, {
|
|
43
43
|
fallback: /* @__PURE__ */ l(r, {}),
|
|
44
44
|
children: /* @__PURE__ */ l(p, {})
|
|
@@ -48,13 +48,23 @@ var d = a(() => import("./pages/AdminDashboardPage.js").then((e) => ({ default:
|
|
|
48
48
|
/* @__PURE__ */ l(s, {
|
|
49
49
|
path: "orders",
|
|
50
50
|
element: /* @__PURE__ */ l(n, {
|
|
51
|
-
allowed:
|
|
51
|
+
allowed: _,
|
|
52
52
|
children: /* @__PURE__ */ l(i, {
|
|
53
53
|
fallback: /* @__PURE__ */ l(r, {}),
|
|
54
54
|
children: /* @__PURE__ */ l(h, {})
|
|
55
55
|
})
|
|
56
56
|
})
|
|
57
57
|
}),
|
|
58
|
+
/* @__PURE__ */ l(s, {
|
|
59
|
+
path: "fulfillment-logs",
|
|
60
|
+
element: /* @__PURE__ */ l(n, {
|
|
61
|
+
allowed: _,
|
|
62
|
+
children: /* @__PURE__ */ l(i, {
|
|
63
|
+
fallback: /* @__PURE__ */ l(r, {}),
|
|
64
|
+
children: /* @__PURE__ */ l(g, {})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
}),
|
|
58
68
|
/* @__PURE__ */ l(s, {
|
|
59
69
|
path: "reviews",
|
|
60
70
|
element: /* @__PURE__ */ l(n, {
|
|
@@ -75,6 +85,6 @@ var d = a(() => import("./pages/AdminDashboardPage.js").then((e) => ({ default:
|
|
|
75
85
|
] });
|
|
76
86
|
};
|
|
77
87
|
//#endregion
|
|
78
|
-
export {
|
|
88
|
+
export { _ as StoreAdminRoutes };
|
|
79
89
|
|
|
80
90
|
//# sourceMappingURL=StoreAdminRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoreAdminRoutes.js","names":[],"sources":["../src/StoreAdminRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, type FC } from 'react';\nimport { Routes, Route, Navigate } from 'react-router';\nimport { useStorePermissions, STORE_PERMISSIONS } from './hooks/useStorePermissions';\nimport { PageLoadingFallback, PermissionGuard } from './components/RouteGuards';\n\nconst AdminDashboardPage = lazy(() =>\n import('./pages/AdminDashboardPage').then((m) => ({\n default: m.AdminDashboardPage,\n }))\n);\n\nconst AdminSubmissionsQueuePage = lazy(() =>\n import('./pages/AdminSubmissionsQueuePage').then((m) => ({\n default: m.AdminSubmissionsQueuePage,\n }))\n);\n\nconst AdminStoresPage = lazy(() =>\n import('./pages/AdminStoresPage').then((m) => ({\n default: m.AdminStoresPage,\n }))\n);\n\nconst AdminReviewModerationPage = lazy(() =>\n import('./pages/AdminReviewModerationPage').then((m) => ({\n default: m.AdminReviewModerationPage,\n }))\n);\n\nconst AdminOrdersPage = lazy(() =>\n import('./pages/AdminOrdersPage').then((m) => ({\n default: m.AdminOrdersPage,\n }))\n);\n\n/**\n * StoreAdminRoutes component\n *\n * Admin-only routing for the Store microfrontend.\n * Mounted by the admin app shell via StoreAdminRoot.\n */\nexport const StoreAdminRoutes: FC = () => {\n const { hasPermission } = useStorePermissions();\n const isAdmin =\n hasPermission(STORE_PERMISSIONS.REVIEW_ADMIN) || hasPermission(STORE_PERMISSIONS.PRODUCT_ADMIN);\n\n return (\n <Routes>\n {/* Default redirect to dashboard */}\n <Route index element={<Navigate to=\"dashboard\" replace />} />\n\n <Route\n path=\"dashboard\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminDashboardPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"submissions\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminSubmissionsQueuePage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"stores\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminStoresPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"orders\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminOrdersPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"reviews\"\n element={\n <PermissionGuard allowed={hasPermission(STORE_PERMISSIONS.REVIEW_ADMIN)}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminReviewModerationPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n {/* Catch-all redirect */}\n <Route path=\"*\" element={<Navigate to=\"dashboard\" replace />} />\n </Routes>\n );\n};\n"],"mappings":";;;;;;;AAKA,IAAM,IAAqB,QACzB,OAAO,iCAA8B,MAAM,OAAO,EAChD,SAAS,EAAE,oBACZ,EAAE,CACJ,EAEK,IAA4B,QAChC,OAAO,wCAAqC,MAAM,OAAO,EACvD,SAAS,EAAE,2BACZ,EAAE,CACJ,EAEK,IAAkB,QACtB,OAAO,8BAA2B,MAAM,OAAO,EAC7C,SAAS,EAAE,iBACZ,EAAE,CACJ,EAEK,IAA4B,QAChC,OAAO,wCAAqC,MAAM,OAAO,EACvD,SAAS,EAAE,2BACZ,EAAE,CACJ,EAEK,IAAkB,QACtB,OAAO,8BAA2B,MAAM,OAAO,EAC7C,SAAS,EAAE,iBACZ,EAAE,CACJ,EAQY,UAA6B;CACxC,IAAM,EAAE,qBAAkB,GAAqB,EACzC,IACJ,EAAc,EAAkB,aAAa,IAAI,EAAc,EAAkB,cAAc;AAEjG,QACE,kBAAC,GAAD,EAAA,UAAA;EAEE,kBAAC,GAAD;GAAO,OAAA;GAAM,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAY,SAAA;IAAU,CAAA;GAAI,CAAA;EAE7D,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAAsB,CAAA;KACb,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAA6B,CAAA;KACpB,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAAmB,CAAA;KACV,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAAmB,CAAA;KACV,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS,EAAc,EAAkB,aAAa;cACrE,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAA6B,CAAA;KACpB,CAAA;IACK,CAAA;GAEpB,CAAA;EAGF,kBAAC,GAAD;GAAO,MAAK;GAAI,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAY,SAAA;IAAU,CAAA;GAAI,CAAA;EACzD,EAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"StoreAdminRoutes.js","names":[],"sources":["../src/StoreAdminRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, type FC } from 'react';\nimport { Routes, Route, Navigate } from 'react-router';\nimport { useStorePermissions, STORE_PERMISSIONS } from './hooks/useStorePermissions';\nimport { PageLoadingFallback, PermissionGuard } from './components/RouteGuards';\n\nconst AdminDashboardPage = lazy(() =>\n import('./pages/AdminDashboardPage').then((m) => ({\n default: m.AdminDashboardPage,\n }))\n);\n\nconst AdminSubmissionsQueuePage = lazy(() =>\n import('./pages/AdminSubmissionsQueuePage').then((m) => ({\n default: m.AdminSubmissionsQueuePage,\n }))\n);\n\nconst AdminStoresPage = lazy(() =>\n import('./pages/AdminStoresPage').then((m) => ({\n default: m.AdminStoresPage,\n }))\n);\n\nconst AdminReviewModerationPage = lazy(() =>\n import('./pages/AdminReviewModerationPage').then((m) => ({\n default: m.AdminReviewModerationPage,\n }))\n);\n\nconst AdminOrdersPage = lazy(() =>\n import('./pages/AdminOrdersPage').then((m) => ({\n default: m.AdminOrdersPage,\n }))\n);\n\nconst AdminFulfillmentLogsPage = lazy(() =>\n import('./pages/AdminFulfillmentLogsPage').then((m) => ({\n default: m.AdminFulfillmentLogsPage,\n }))\n);\n\n/**\n * StoreAdminRoutes component\n *\n * Admin-only routing for the Store microfrontend.\n * Mounted by the admin app shell via StoreAdminRoot.\n */\nexport const StoreAdminRoutes: FC = () => {\n const { hasPermission } = useStorePermissions();\n const isAdmin =\n hasPermission(STORE_PERMISSIONS.REVIEW_ADMIN) || hasPermission(STORE_PERMISSIONS.PRODUCT_ADMIN);\n\n return (\n <Routes>\n {/* Default redirect to dashboard */}\n <Route index element={<Navigate to=\"dashboard\" replace />} />\n\n <Route\n path=\"dashboard\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminDashboardPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"submissions\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminSubmissionsQueuePage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"stores\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminStoresPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"orders\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminOrdersPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"fulfillment-logs\"\n element={\n <PermissionGuard allowed={isAdmin}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminFulfillmentLogsPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n <Route\n path=\"reviews\"\n element={\n <PermissionGuard allowed={hasPermission(STORE_PERMISSIONS.REVIEW_ADMIN)}>\n <Suspense fallback={<PageLoadingFallback />}>\n <AdminReviewModerationPage />\n </Suspense>\n </PermissionGuard>\n }\n />\n\n {/* Catch-all redirect */}\n <Route path=\"*\" element={<Navigate to=\"dashboard\" replace />} />\n </Routes>\n );\n};\n"],"mappings":";;;;;;;AAKA,IAAM,IAAqB,QACzB,OAAO,iCAA8B,MAAM,OAAO,EAChD,SAAS,EAAE,oBACZ,EAAE,CACJ,EAEK,IAA4B,QAChC,OAAO,wCAAqC,MAAM,OAAO,EACvD,SAAS,EAAE,2BACZ,EAAE,CACJ,EAEK,IAAkB,QACtB,OAAO,8BAA2B,MAAM,OAAO,EAC7C,SAAS,EAAE,iBACZ,EAAE,CACJ,EAEK,IAA4B,QAChC,OAAO,wCAAqC,MAAM,OAAO,EACvD,SAAS,EAAE,2BACZ,EAAE,CACJ,EAEK,IAAkB,QACtB,OAAO,8BAA2B,MAAM,OAAO,EAC7C,SAAS,EAAE,iBACZ,EAAE,CACJ,EAEK,IAA2B,QAC/B,OAAO,uCAAoC,MAAM,OAAO,EACtD,SAAS,EAAE,0BACZ,EAAE,CACJ,EAQY,UAA6B;CACxC,IAAM,EAAE,qBAAkB,GAAqB,EACzC,IACJ,EAAc,EAAkB,aAAa,IAAI,EAAc,EAAkB,cAAc;AAEjG,QACE,kBAAC,GAAD,EAAA,UAAA;EAEE,kBAAC,GAAD;GAAO,OAAA;GAAM,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAY,SAAA;IAAU,CAAA;GAAI,CAAA;EAE7D,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAAsB,CAAA;KACb,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAA6B,CAAA;KACpB,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAAmB,CAAA;KACV,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAAmB,CAAA;KACV,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS;cACxB,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAA4B,CAAA;KACnB,CAAA;IACK,CAAA;GAEpB,CAAA;EAEF,kBAAC,GAAD;GACE,MAAK;GACL,SACE,kBAAC,GAAD;IAAiB,SAAS,EAAc,EAAkB,aAAa;cACrE,kBAAC,GAAD;KAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;eACzC,kBAAC,GAAD,EAA6B,CAAA;KACpB,CAAA;IACK,CAAA;GAEpB,CAAA;EAGF,kBAAC,GAAD;GAAO,MAAK;GAAI,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAY,SAAA;IAAU,CAAA;GAAI,CAAA;EACzD,EAAA,CAAA"}
|
|
@@ -3,11 +3,11 @@ import { useTr as t } from "../../shared/hooks/useTr.js";
|
|
|
3
3
|
import { Minus as n, Plus as r, ShoppingCart as i, Trash2 as a, X as o } from "lucide-react";
|
|
4
4
|
import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/cart/CartDrawer.tsx
|
|
6
|
-
var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m,
|
|
7
|
-
let
|
|
6
|
+
var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, currency: h, subtotal: g, tax: _, total: v, updateQuantity: y, removeProduct: b }) => {
|
|
7
|
+
let x = t();
|
|
8
8
|
return u ? /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("button", {
|
|
9
9
|
type: "button",
|
|
10
|
-
"aria-label":
|
|
10
|
+
"aria-label": x("cart.closeCart", "Close cart"),
|
|
11
11
|
className: "fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity",
|
|
12
12
|
onClick: d
|
|
13
13
|
}), /* @__PURE__ */ c("div", {
|
|
@@ -23,7 +23,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
23
23
|
/* @__PURE__ */ c(i, { className: "size-5 text-text-primary" }),
|
|
24
24
|
/* @__PURE__ */ c("h2", {
|
|
25
25
|
className: "text-lg font-semibold text-text-primary",
|
|
26
|
-
children:
|
|
26
|
+
children: x("cart.title", "Shopping Cart")
|
|
27
27
|
}),
|
|
28
28
|
m > 0 && /* @__PURE__ */ c("span", {
|
|
29
29
|
className: "rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link",
|
|
@@ -33,7 +33,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
33
33
|
}), /* @__PURE__ */ c("button", {
|
|
34
34
|
type: "button",
|
|
35
35
|
onClick: d,
|
|
36
|
-
"aria-label":
|
|
36
|
+
"aria-label": x("cart.closeCart", "Close cart"),
|
|
37
37
|
className: "cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary",
|
|
38
38
|
children: /* @__PURE__ */ c(o, { className: "size-5" })
|
|
39
39
|
})]
|
|
@@ -41,7 +41,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
41
41
|
/* @__PURE__ */ c("div", {
|
|
42
42
|
className: "flex-1 overflow-y-auto px-4 sm:px-6 py-4",
|
|
43
43
|
children: p.length === 0 ? /* @__PURE__ */ l("output", {
|
|
44
|
-
"aria-label":
|
|
44
|
+
"aria-label": x("cart.empty", "Your cart is empty"),
|
|
45
45
|
className: "flex h-full flex-col items-center justify-center text-center",
|
|
46
46
|
children: [
|
|
47
47
|
/* @__PURE__ */ c(i, {
|
|
@@ -50,11 +50,11 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
50
50
|
}),
|
|
51
51
|
/* @__PURE__ */ c("h3", {
|
|
52
52
|
className: "mb-2 text-lg font-semibold text-text-primary",
|
|
53
|
-
children:
|
|
53
|
+
children: x("cart.empty", "Your cart is empty")
|
|
54
54
|
}),
|
|
55
55
|
/* @__PURE__ */ c("p", {
|
|
56
56
|
className: "text-sm text-text-muted",
|
|
57
|
-
children:
|
|
57
|
+
children: x("cart.emptyHint", "Start shopping to add items to your cart")
|
|
58
58
|
})
|
|
59
59
|
]
|
|
60
60
|
}) : /* @__PURE__ */ c("div", {
|
|
@@ -76,7 +76,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
76
76
|
children: [
|
|
77
77
|
/* @__PURE__ */ c("h4", {
|
|
78
78
|
className: "mb-1 font-semibold text-text-primary",
|
|
79
|
-
children: t.productName || t.product?.name ||
|
|
79
|
+
children: t.productName || t.product?.name || x("common.product", "Product")
|
|
80
80
|
}),
|
|
81
81
|
t.variantName && /* @__PURE__ */ c("p", {
|
|
82
82
|
className: "mb-2 text-xs text-text-muted",
|
|
@@ -89,8 +89,8 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
89
89
|
children: [
|
|
90
90
|
/* @__PURE__ */ c("button", {
|
|
91
91
|
type: "button",
|
|
92
|
-
onClick: () =>
|
|
93
|
-
"aria-label":
|
|
92
|
+
onClick: () => y(t.id, t.quantity - 1),
|
|
93
|
+
"aria-label": x("cart.decreaseQuantity", "Decrease quantity of {{name}}", { name: t.productName || t.product?.name || x("common.item", "item") }),
|
|
94
94
|
className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50",
|
|
95
95
|
disabled: t.quantity <= 1,
|
|
96
96
|
children: /* @__PURE__ */ c(n, {
|
|
@@ -100,13 +100,13 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
100
100
|
}),
|
|
101
101
|
/* @__PURE__ */ c("span", {
|
|
102
102
|
className: "min-w-[2rem] text-center text-sm font-medium",
|
|
103
|
-
"aria-label":
|
|
103
|
+
"aria-label": x("cart.quantity", "Quantity: {{quantity}}", { quantity: t.quantity }),
|
|
104
104
|
children: t.quantity
|
|
105
105
|
}),
|
|
106
106
|
/* @__PURE__ */ c("button", {
|
|
107
107
|
type: "button",
|
|
108
|
-
onClick: () =>
|
|
109
|
-
"aria-label":
|
|
108
|
+
onClick: () => y(t.id, t.quantity + 1),
|
|
109
|
+
"aria-label": x("cart.increaseQuantity", "Increase quantity of {{name}}", { name: t.productName || t.product?.name || x("common.item", "item") }),
|
|
110
110
|
className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken",
|
|
111
111
|
children: /* @__PURE__ */ c(r, {
|
|
112
112
|
className: "size-4",
|
|
@@ -116,8 +116,8 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
116
116
|
]
|
|
117
117
|
}), /* @__PURE__ */ c("button", {
|
|
118
118
|
type: "button",
|
|
119
|
-
onClick: () =>
|
|
120
|
-
"aria-label":
|
|
119
|
+
onClick: () => b(t.id),
|
|
120
|
+
"aria-label": x("cart.removeItem", "Remove {{name}} from cart", { name: t.productName || t.product?.name || x("common.item", "item") }),
|
|
121
121
|
className: "cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis",
|
|
122
122
|
children: /* @__PURE__ */ c(a, {
|
|
123
123
|
className: "size-4",
|
|
@@ -129,7 +129,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
129
129
|
className: "mt-2 text-right",
|
|
130
130
|
children: /* @__PURE__ */ c("span", {
|
|
131
131
|
className: "font-semibold tabular-nums text-text-primary",
|
|
132
|
-
children: e(t.subtotal)
|
|
132
|
+
children: e(t.subtotal, h)
|
|
133
133
|
})
|
|
134
134
|
})
|
|
135
135
|
]
|
|
@@ -146,30 +146,30 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
146
146
|
className: "flex justify-between text-sm",
|
|
147
147
|
children: [/* @__PURE__ */ c("span", {
|
|
148
148
|
className: "text-text-muted",
|
|
149
|
-
children:
|
|
149
|
+
children: x("cart.subtotal", "Subtotal")
|
|
150
150
|
}), /* @__PURE__ */ c("span", {
|
|
151
151
|
className: "font-medium tabular-nums text-text-primary",
|
|
152
|
-
children: e(h)
|
|
152
|
+
children: e(g, h)
|
|
153
153
|
})]
|
|
154
154
|
}),
|
|
155
155
|
/* @__PURE__ */ l("div", {
|
|
156
156
|
className: "flex justify-between text-sm",
|
|
157
157
|
children: [/* @__PURE__ */ c("span", {
|
|
158
158
|
className: "text-text-muted",
|
|
159
|
-
children:
|
|
159
|
+
children: x("cart.tax", "Tax")
|
|
160
160
|
}), /* @__PURE__ */ c("span", {
|
|
161
161
|
className: "font-medium tabular-nums text-text-primary",
|
|
162
|
-
children: e(
|
|
162
|
+
children: e(_, h)
|
|
163
163
|
})]
|
|
164
164
|
}),
|
|
165
165
|
/* @__PURE__ */ l("div", {
|
|
166
166
|
className: "flex justify-between border-t border-border-seam pt-2",
|
|
167
167
|
children: [/* @__PURE__ */ c("span", {
|
|
168
168
|
className: "font-semibold text-text-primary",
|
|
169
|
-
children:
|
|
169
|
+
children: x("cart.total", "Total")
|
|
170
170
|
}), /* @__PURE__ */ c("span", {
|
|
171
171
|
className: "text-lg font-bold tabular-nums text-text-primary",
|
|
172
|
-
children: e(
|
|
172
|
+
children: e(v, h)
|
|
173
173
|
})]
|
|
174
174
|
})
|
|
175
175
|
]
|
|
@@ -177,7 +177,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
|
|
|
177
177
|
type: "button",
|
|
178
178
|
onClick: f,
|
|
179
179
|
className: "cursor-pointer mt-4 w-full rounded-lg bg-action-primary-bg py-3 font-bold text-action-primary-text shadow-elevation-1 transition-[opacity,box-shadow] hover:opacity-90 hover:shadow-[var(--shadow-pop)]",
|
|
180
|
-
children:
|
|
180
|
+
children: x("cart.checkout", "Proceed to Checkout")
|
|
181
181
|
})]
|
|
182
182
|
})
|
|
183
183
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CartDrawer.js","names":[],"sources":["../../../src/components/cart/CartDrawer.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { X, ShoppingCart, Trash2, Plus, Minus } from 'lucide-react';\nimport { formatPrice } from '../../utils';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/**\n * Props for CartDrawer\n */\ninterface CartDrawerProps {\n isOpen: boolean;\n onClose: () => void;\n onCheckout: () => void;\n cartItems: Array<{\n id: string;\n quantity: number;\n subtotal: number;\n productName?: string;\n productIcon?: string;\n variantName?: string;\n product?: { icon?: string; name?: string };\n }>;\n itemCount: number;\n subtotal: number;\n tax: number;\n total: number;\n updateQuantity: (cartItemId: string, quantity: number) => Promise<void>;\n removeProduct: (cartItemId: string) => Promise<void>;\n}\n\n/**\n * CartDrawer component\n *\n * Sliding drawer for cart management\n */\nexport const CartDrawer: FC<CartDrawerProps> = ({\n isOpen,\n onClose,\n onCheckout,\n cartItems,\n itemCount,\n subtotal,\n tax,\n total,\n updateQuantity,\n removeProduct,\n}) => {\n const tr = useTr();\n if (!isOpen) return null;\n\n return (\n <>\n {/* Backdrop */}\n <button\n type=\"button\"\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity\"\n onClick={onClose}\n />\n\n {/* Drawer */}\n <div className=\"fixed right-0 top-0 z-50 size-full sm:max-w-md bg-bg-surface shadow-xl\">\n <div className=\"flex h-full flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-border-seam px-4 sm:px-6 py-4\">\n <div className=\"flex items-center gap-2\">\n <ShoppingCart className=\"size-5 text-text-primary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('cart.title', 'Shopping Cart')}\n </h2>\n {itemCount > 0 && (\n <span className=\"rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link\">\n {itemCount}\n </span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Cart Items */}\n <div className=\"flex-1 overflow-y-auto px-4 sm:px-6 py-4\">\n {cartItems.length === 0 ? (\n <output\n aria-label={tr('cart.empty', 'Your cart is empty')}\n className=\"flex h-full flex-col items-center justify-center text-center\"\n >\n <ShoppingCart className=\"mb-4 size-16 text-text-muted\" aria-hidden=\"true\" />\n <h3 className=\"mb-2 text-lg font-semibold text-text-primary\">\n {tr('cart.empty', 'Your cart is empty')}\n </h3>\n <p className=\"text-sm text-text-muted\">\n {tr('cart.emptyHint', 'Start shopping to add items to your cart')}\n </p>\n </output>\n ) : (\n <div className=\"space-y-4\">\n {cartItems.map((item) => (\n <div\n key={item.id}\n className=\"flex gap-4 rounded-lg border border-border-seam bg-bg-surface p-4 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n {/* Product Image */}\n <div className=\"size-20 flex-shrink-0 overflow-hidden rounded bg-bg-sunken\">\n {item.productIcon || item.product?.icon ? (\n <img\n src={item.productIcon || item.product?.icon}\n alt={item.productName || item.product?.name}\n className=\"size-full object-cover\"\n />\n ) : (\n <div className=\"flex size-full items-center justify-center\">\n <ShoppingCart className=\"size-8 text-text-muted\" />\n </div>\n )}\n </div>\n\n {/* Product Info */}\n <div className=\"flex flex-1 flex-col\">\n <h4 className=\"mb-1 font-semibold text-text-primary\">\n {item.productName || item.product?.name || tr('common.product', 'Product')}\n </h4>\n {item.variantName && (\n <p className=\"mb-2 text-xs text-text-muted\">{item.variantName}</p>\n )}\n\n {/* Quantity Controls */}\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center rounded border border-border-default\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity - 1)}\n aria-label={tr(\n 'cart.decreaseQuantity',\n 'Decrease quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50\"\n disabled={item.quantity <= 1}\n >\n <Minus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n <span\n className=\"min-w-[2rem] text-center text-sm font-medium\"\n aria-label={tr('cart.quantity', 'Quantity: {{quantity}}', {\n quantity: item.quantity,\n })}\n >\n {item.quantity}\n </span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity + 1)}\n aria-label={tr(\n 'cart.increaseQuantity',\n 'Increase quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n <button\n type=\"button\"\n onClick={() => removeProduct(item.id)}\n aria-label={tr('cart.removeItem', 'Remove {{name}} from cart', {\n name:\n item.productName || item.product?.name || tr('common.item', 'item'),\n })}\n className=\"cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis\"\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n {/* Price */}\n <div className=\"mt-2 text-right\">\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {formatPrice(item.subtotal)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer with Summary */}\n {cartItems.length > 0 && (\n <div className=\"border-t border-border-seam bg-accent-wash px-4 sm:px-6 py-4\">\n <div className=\"space-y-2\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.subtotal', 'Subtotal')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(subtotal)}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.tax', 'Tax')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(tax)}\n </span>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2\">\n <span className=\"font-semibold text-text-primary\">\n {tr('cart.total', 'Total')}\n </span>\n <span className=\"text-lg font-bold tabular-nums text-text-primary\">\n {formatPrice(total)}\n </span>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={onCheckout}\n className=\"cursor-pointer mt-4 w-full rounded-lg bg-action-primary-bg py-3 font-bold text-action-primary-text shadow-elevation-1 transition-[opacity,box-shadow] hover:opacity-90 hover:shadow-[var(--shadow-pop)]\"\n >\n {tr('cart.checkout', 'Proceed to Checkout')}\n </button>\n </div>\n )}\n </div>\n </div>\n </>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CartDrawer.js","names":[],"sources":["../../../src/components/cart/CartDrawer.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { X, ShoppingCart, Trash2, Plus, Minus } from 'lucide-react';\nimport { formatPrice } from '../../utils';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/**\n * Props for CartDrawer\n */\ninterface CartDrawerProps {\n isOpen: boolean;\n onClose: () => void;\n onCheckout: () => void;\n cartItems: Array<{\n id: string;\n quantity: number;\n subtotal: number;\n productName?: string;\n productIcon?: string;\n variantName?: string;\n product?: { icon?: string; name?: string };\n }>;\n itemCount: number;\n /** Cart-wide currency — see useBackendCart.ts's Cart type (one currency per cart). */\n currency: string;\n subtotal: number;\n tax: number;\n total: number;\n updateQuantity: (cartItemId: string, quantity: number) => Promise<void>;\n removeProduct: (cartItemId: string) => Promise<void>;\n}\n\n/**\n * CartDrawer component\n *\n * Sliding drawer for cart management\n */\nexport const CartDrawer: FC<CartDrawerProps> = ({\n isOpen,\n onClose,\n onCheckout,\n cartItems,\n itemCount,\n currency,\n subtotal,\n tax,\n total,\n updateQuantity,\n removeProduct,\n}) => {\n const tr = useTr();\n if (!isOpen) return null;\n\n return (\n <>\n {/* Backdrop */}\n <button\n type=\"button\"\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity\"\n onClick={onClose}\n />\n\n {/* Drawer */}\n <div className=\"fixed right-0 top-0 z-50 size-full sm:max-w-md bg-bg-surface shadow-xl\">\n <div className=\"flex h-full flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-border-seam px-4 sm:px-6 py-4\">\n <div className=\"flex items-center gap-2\">\n <ShoppingCart className=\"size-5 text-text-primary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('cart.title', 'Shopping Cart')}\n </h2>\n {itemCount > 0 && (\n <span className=\"rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link\">\n {itemCount}\n </span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Cart Items */}\n <div className=\"flex-1 overflow-y-auto px-4 sm:px-6 py-4\">\n {cartItems.length === 0 ? (\n <output\n aria-label={tr('cart.empty', 'Your cart is empty')}\n className=\"flex h-full flex-col items-center justify-center text-center\"\n >\n <ShoppingCart className=\"mb-4 size-16 text-text-muted\" aria-hidden=\"true\" />\n <h3 className=\"mb-2 text-lg font-semibold text-text-primary\">\n {tr('cart.empty', 'Your cart is empty')}\n </h3>\n <p className=\"text-sm text-text-muted\">\n {tr('cart.emptyHint', 'Start shopping to add items to your cart')}\n </p>\n </output>\n ) : (\n <div className=\"space-y-4\">\n {cartItems.map((item) => (\n <div\n key={item.id}\n className=\"flex gap-4 rounded-lg border border-border-seam bg-bg-surface p-4 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n {/* Product Image */}\n <div className=\"size-20 flex-shrink-0 overflow-hidden rounded bg-bg-sunken\">\n {item.productIcon || item.product?.icon ? (\n <img\n src={item.productIcon || item.product?.icon}\n alt={item.productName || item.product?.name}\n className=\"size-full object-cover\"\n />\n ) : (\n <div className=\"flex size-full items-center justify-center\">\n <ShoppingCart className=\"size-8 text-text-muted\" />\n </div>\n )}\n </div>\n\n {/* Product Info */}\n <div className=\"flex flex-1 flex-col\">\n <h4 className=\"mb-1 font-semibold text-text-primary\">\n {item.productName || item.product?.name || tr('common.product', 'Product')}\n </h4>\n {item.variantName && (\n <p className=\"mb-2 text-xs text-text-muted\">{item.variantName}</p>\n )}\n\n {/* Quantity Controls */}\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center rounded border border-border-default\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity - 1)}\n aria-label={tr(\n 'cart.decreaseQuantity',\n 'Decrease quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50\"\n disabled={item.quantity <= 1}\n >\n <Minus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n <span\n className=\"min-w-[2rem] text-center text-sm font-medium\"\n aria-label={tr('cart.quantity', 'Quantity: {{quantity}}', {\n quantity: item.quantity,\n })}\n >\n {item.quantity}\n </span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity + 1)}\n aria-label={tr(\n 'cart.increaseQuantity',\n 'Increase quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n <button\n type=\"button\"\n onClick={() => removeProduct(item.id)}\n aria-label={tr('cart.removeItem', 'Remove {{name}} from cart', {\n name:\n item.productName || item.product?.name || tr('common.item', 'item'),\n })}\n className=\"cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis\"\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n {/* Price */}\n <div className=\"mt-2 text-right\">\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {formatPrice(item.subtotal, currency)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer with Summary */}\n {cartItems.length > 0 && (\n <div className=\"border-t border-border-seam bg-accent-wash px-4 sm:px-6 py-4\">\n <div className=\"space-y-2\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.subtotal', 'Subtotal')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(subtotal, currency)}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.tax', 'Tax')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(tax, currency)}\n </span>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2\">\n <span className=\"font-semibold text-text-primary\">\n {tr('cart.total', 'Total')}\n </span>\n <span className=\"text-lg font-bold tabular-nums text-text-primary\">\n {formatPrice(total, currency)}\n </span>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={onCheckout}\n className=\"cursor-pointer mt-4 w-full rounded-lg bg-action-primary-bg py-3 font-bold text-action-primary-text shadow-elevation-1 transition-[opacity,box-shadow] hover:opacity-90 hover:shadow-[var(--shadow-pop)]\"\n >\n {tr('cart.checkout', 'Proceed to Checkout')}\n </button>\n </div>\n )}\n </div>\n </div>\n </>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Admin-only log of every carrier shipment-creation attempt (every Temporal
|
|
5
|
+
* retry, not just the last failure) — the "why did this order's shipment
|
|
6
|
+
* fail" debugging surface that OrderFulfillment.failureReason alone can't
|
|
7
|
+
* answer, since it only ever holds the last attempt's message.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AdminFulfillmentLogsPage: FC;
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { useStore as e } from "../providers/StoreProvider.js";
|
|
2
|
+
import { useCallback as t, useEffect as n, useState as r } from "react";
|
|
3
|
+
import { useNavigate as i, useSearchParams as a } from "react-router";
|
|
4
|
+
import { ArrowLeft as o, CheckCircle2 as s, RefreshCw as c, Truck as l, XCircle as u } from "lucide-react";
|
|
5
|
+
import { graphqlFetch as d } from "@burdenoff/fe-libs/shared/graphql";
|
|
6
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
7
|
+
import { IllustratedEmptyState as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
//#region src/pages/AdminFulfillmentLogsPage.tsx
|
|
9
|
+
var _ = [
|
|
10
|
+
{
|
|
11
|
+
value: "",
|
|
12
|
+
label: "All results"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
value: "false",
|
|
16
|
+
label: "Failed only"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
value: "true",
|
|
20
|
+
label: "Succeeded only"
|
|
21
|
+
}
|
|
22
|
+
], v = "\n query AdminOrderFulfillmentAttempts(\n $limit: Int!\n $offset: Int!\n $orderId: ID\n $carrier: String\n $succeeded: Boolean\n ) {\n orderFulfillmentAttempts(\n limit: $limit\n offset: $offset\n orderId: $orderId\n carrier: $carrier\n succeeded: $succeeded\n ) {\n totalCount\n attempts {\n id\n attemptNumber\n carrier\n succeeded\n errorMessage\n errorStatusCode\n durationMs\n occurredAt\n }\n }\n }\n", y = 25;
|
|
23
|
+
function b(e) {
|
|
24
|
+
return new Date(e).toLocaleString("en-US", {
|
|
25
|
+
year: "numeric",
|
|
26
|
+
month: "short",
|
|
27
|
+
day: "numeric",
|
|
28
|
+
hour: "2-digit",
|
|
29
|
+
minute: "2-digit",
|
|
30
|
+
second: "2-digit"
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
var x = () => {
|
|
34
|
+
let x = i(), { authToken: S, basePath: C } = e(), [w] = a(), [T, E] = r([]), [D, O] = r(0), [k, A] = r(!1), [j, M] = r(null), [N, P] = r(0), [F, I] = r(""), [L, R] = r(""), [z, B] = r(w.get("orderId") ?? ""), V = t(async () => {
|
|
35
|
+
A(!0), M(null);
|
|
36
|
+
try {
|
|
37
|
+
let e = await d({
|
|
38
|
+
gateway: "global",
|
|
39
|
+
query: v,
|
|
40
|
+
variables: {
|
|
41
|
+
limit: y,
|
|
42
|
+
offset: N * y,
|
|
43
|
+
orderId: z.trim() || void 0,
|
|
44
|
+
carrier: L.trim() || void 0,
|
|
45
|
+
succeeded: F === "" ? void 0 : F === "true"
|
|
46
|
+
},
|
|
47
|
+
authToken: S || void 0
|
|
48
|
+
});
|
|
49
|
+
if (e.errors?.length) throw Error(e.errors[0]?.message ?? "Failed to load fulfillment logs");
|
|
50
|
+
O(e.data?.orderFulfillmentAttempts.totalCount ?? 0), E(e.data?.orderFulfillmentAttempts.attempts ?? []);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
M(e instanceof Error ? e.message : "Failed to load fulfillment logs");
|
|
53
|
+
} finally {
|
|
54
|
+
A(!1);
|
|
55
|
+
}
|
|
56
|
+
}, [
|
|
57
|
+
S,
|
|
58
|
+
N,
|
|
59
|
+
z,
|
|
60
|
+
L,
|
|
61
|
+
F
|
|
62
|
+
]);
|
|
63
|
+
return n(() => {
|
|
64
|
+
V();
|
|
65
|
+
}, [V]), /* @__PURE__ */ m("div", {
|
|
66
|
+
className: "min-h-screen bg-surface-default",
|
|
67
|
+
children: [/* @__PURE__ */ p("header", {
|
|
68
|
+
className: "border-b border-border-seam bg-surface-raised",
|
|
69
|
+
children: /* @__PURE__ */ p("div", {
|
|
70
|
+
className: "mx-auto max-w-7xl px-6 py-4",
|
|
71
|
+
children: /* @__PURE__ */ m("div", {
|
|
72
|
+
className: "flex items-center justify-between",
|
|
73
|
+
children: [/* @__PURE__ */ m("div", {
|
|
74
|
+
className: "flex items-center gap-3",
|
|
75
|
+
children: [/* @__PURE__ */ m("button", {
|
|
76
|
+
type: "button",
|
|
77
|
+
onClick: () => x(`${C}/dashboard`),
|
|
78
|
+
className: "inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm text-text-secondary hover:bg-surface-hover hover:text-text-primary",
|
|
79
|
+
children: [/* @__PURE__ */ p(o, { className: "size-4" }), "Back"]
|
|
80
|
+
}), /* @__PURE__ */ m("div", {
|
|
81
|
+
className: "flex items-center gap-2",
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ p(l, { className: "size-5 text-text-primary" }),
|
|
84
|
+
/* @__PURE__ */ p("h1", {
|
|
85
|
+
className: "text-xl font-semibold text-text-primary",
|
|
86
|
+
children: "Fulfillment logs"
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ p("span", {
|
|
89
|
+
className: "rounded-full bg-surface-accent-muted px-2 py-0.5 text-xs font-medium text-text-accent",
|
|
90
|
+
children: D
|
|
91
|
+
})
|
|
92
|
+
]
|
|
93
|
+
})]
|
|
94
|
+
}), /* @__PURE__ */ m("button", {
|
|
95
|
+
type: "button",
|
|
96
|
+
onClick: () => void V(),
|
|
97
|
+
className: "inline-flex items-center gap-2 rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-sm text-text-primary hover:bg-surface-hover",
|
|
98
|
+
disabled: k,
|
|
99
|
+
children: [/* @__PURE__ */ p(c, { className: `size-4 ${k ? "animate-spin" : ""}` }), "Refresh"]
|
|
100
|
+
})]
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
}), /* @__PURE__ */ m("main", {
|
|
104
|
+
className: "mx-auto max-w-7xl p-6",
|
|
105
|
+
children: [
|
|
106
|
+
/* @__PURE__ */ p(g, {
|
|
107
|
+
className: "mb-4",
|
|
108
|
+
children: "Every carrier shipment-creation attempt for every physical order — including retries Temporal made after a failure — so you can see what happened, why, and whether it eventually succeeded. OrderFulfillment.failureReason only ever shows the last attempt; this is the full history."
|
|
109
|
+
}),
|
|
110
|
+
/* @__PURE__ */ m("div", {
|
|
111
|
+
className: "mb-4 flex flex-col gap-3 sm:flex-row sm:items-center",
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ p("select", {
|
|
114
|
+
"aria-label": "Filter by result",
|
|
115
|
+
value: F,
|
|
116
|
+
onChange: (e) => {
|
|
117
|
+
I(e.target.value), P(0);
|
|
118
|
+
},
|
|
119
|
+
className: "rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-sm text-text-primary",
|
|
120
|
+
children: _.map((e) => /* @__PURE__ */ p("option", {
|
|
121
|
+
value: e.value,
|
|
122
|
+
children: e.label
|
|
123
|
+
}, e.value))
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ p("input", {
|
|
126
|
+
type: "text",
|
|
127
|
+
"aria-label": "Filter by carrier",
|
|
128
|
+
placeholder: "Carrier (e.g. shiprocket)…",
|
|
129
|
+
value: L,
|
|
130
|
+
onChange: (e) => {
|
|
131
|
+
R(e.target.value), P(0);
|
|
132
|
+
},
|
|
133
|
+
className: "rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-sm text-text-primary sm:w-48"
|
|
134
|
+
}),
|
|
135
|
+
/* @__PURE__ */ p("input", {
|
|
136
|
+
type: "search",
|
|
137
|
+
"aria-label": "Filter by order ID",
|
|
138
|
+
placeholder: "Order ID…",
|
|
139
|
+
value: z,
|
|
140
|
+
onChange: (e) => {
|
|
141
|
+
B(e.target.value), P(0);
|
|
142
|
+
},
|
|
143
|
+
className: "flex-1 rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-sm text-text-primary"
|
|
144
|
+
})
|
|
145
|
+
]
|
|
146
|
+
}),
|
|
147
|
+
j && /* @__PURE__ */ p("div", {
|
|
148
|
+
role: "alert",
|
|
149
|
+
className: "mb-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
|
|
150
|
+
children: j
|
|
151
|
+
}),
|
|
152
|
+
k && T.length === 0 ? /* @__PURE__ */ p("output", {
|
|
153
|
+
className: "block py-16 text-center text-text-secondary",
|
|
154
|
+
children: "Loading fulfillment logs…"
|
|
155
|
+
}) : T.length === 0 ? /* @__PURE__ */ p(h, {
|
|
156
|
+
illustration: "empty-generic",
|
|
157
|
+
title: "No fulfillment attempts",
|
|
158
|
+
description: "Carrier shipment-creation attempts will show up here as physical orders are placed."
|
|
159
|
+
}) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("div", {
|
|
160
|
+
className: "overflow-hidden rounded-lg border border-border-seam",
|
|
161
|
+
children: /* @__PURE__ */ m("table", {
|
|
162
|
+
className: "w-full text-sm",
|
|
163
|
+
children: [/* @__PURE__ */ p("thead", {
|
|
164
|
+
className: "bg-surface-muted text-left text-xs uppercase tracking-wide text-text-secondary",
|
|
165
|
+
children: /* @__PURE__ */ m("tr", { children: [
|
|
166
|
+
/* @__PURE__ */ p("th", {
|
|
167
|
+
className: "px-4 py-2",
|
|
168
|
+
children: "Attempt #"
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ p("th", {
|
|
171
|
+
className: "px-4 py-2",
|
|
172
|
+
children: "Carrier"
|
|
173
|
+
}),
|
|
174
|
+
/* @__PURE__ */ p("th", {
|
|
175
|
+
className: "px-4 py-2",
|
|
176
|
+
children: "Result"
|
|
177
|
+
}),
|
|
178
|
+
/* @__PURE__ */ p("th", {
|
|
179
|
+
className: "px-4 py-2",
|
|
180
|
+
children: "Error"
|
|
181
|
+
}),
|
|
182
|
+
/* @__PURE__ */ p("th", {
|
|
183
|
+
className: "px-4 py-2 text-right",
|
|
184
|
+
children: "Duration"
|
|
185
|
+
}),
|
|
186
|
+
/* @__PURE__ */ p("th", {
|
|
187
|
+
className: "px-4 py-2",
|
|
188
|
+
children: "Occurred"
|
|
189
|
+
})
|
|
190
|
+
] })
|
|
191
|
+
}), /* @__PURE__ */ p("tbody", {
|
|
192
|
+
className: "divide-y divide-border-seam bg-surface-raised",
|
|
193
|
+
children: T.map((e) => /* @__PURE__ */ m("tr", {
|
|
194
|
+
className: "text-text-primary align-top",
|
|
195
|
+
children: [
|
|
196
|
+
/* @__PURE__ */ p("td", {
|
|
197
|
+
className: "px-4 py-2 font-mono text-xs",
|
|
198
|
+
children: e.attemptNumber
|
|
199
|
+
}),
|
|
200
|
+
/* @__PURE__ */ p("td", {
|
|
201
|
+
className: "px-4 py-2 text-xs",
|
|
202
|
+
children: e.carrier
|
|
203
|
+
}),
|
|
204
|
+
/* @__PURE__ */ p("td", {
|
|
205
|
+
className: "px-4 py-2",
|
|
206
|
+
children: e.succeeded ? /* @__PURE__ */ m("span", {
|
|
207
|
+
className: "inline-flex items-center gap-1 rounded-full bg-surface-success-muted px-2 py-0.5 text-xs font-medium text-text-success",
|
|
208
|
+
children: [/* @__PURE__ */ p(s, { className: "size-3" }), "Succeeded"]
|
|
209
|
+
}) : /* @__PURE__ */ m("span", {
|
|
210
|
+
className: "inline-flex items-center gap-1 rounded-full bg-surface-danger-muted px-2 py-0.5 text-xs font-medium text-text-danger",
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ p(u, { className: "size-3" }),
|
|
213
|
+
"Failed",
|
|
214
|
+
e.errorStatusCode ? ` (${e.errorStatusCode})` : ""
|
|
215
|
+
]
|
|
216
|
+
})
|
|
217
|
+
}),
|
|
218
|
+
/* @__PURE__ */ p("td", {
|
|
219
|
+
className: "max-w-md px-4 py-2 text-xs text-text-secondary",
|
|
220
|
+
children: e.errorMessage ? /* @__PURE__ */ p("span", {
|
|
221
|
+
title: e.errorMessage,
|
|
222
|
+
className: "line-clamp-2",
|
|
223
|
+
children: e.errorMessage
|
|
224
|
+
}) : /* @__PURE__ */ p("span", {
|
|
225
|
+
className: "text-text-muted",
|
|
226
|
+
children: "—"
|
|
227
|
+
})
|
|
228
|
+
}),
|
|
229
|
+
/* @__PURE__ */ p("td", {
|
|
230
|
+
className: "px-4 py-2 text-right tabular-nums text-xs text-text-secondary",
|
|
231
|
+
children: e.durationMs === null ? "—" : `${e.durationMs}ms`
|
|
232
|
+
}),
|
|
233
|
+
/* @__PURE__ */ p("td", {
|
|
234
|
+
className: "px-4 py-2 text-xs text-text-secondary whitespace-nowrap",
|
|
235
|
+
children: b(e.occurredAt)
|
|
236
|
+
})
|
|
237
|
+
]
|
|
238
|
+
}, e.id))
|
|
239
|
+
})]
|
|
240
|
+
})
|
|
241
|
+
}), D > y && /* @__PURE__ */ m("div", {
|
|
242
|
+
className: "mt-4 flex items-center justify-between text-sm",
|
|
243
|
+
children: [/* @__PURE__ */ m("span", {
|
|
244
|
+
className: "text-text-secondary",
|
|
245
|
+
children: [
|
|
246
|
+
"Showing ",
|
|
247
|
+
N * y + 1,
|
|
248
|
+
"–",
|
|
249
|
+
Math.min((N + 1) * y, D),
|
|
250
|
+
" of",
|
|
251
|
+
" ",
|
|
252
|
+
D
|
|
253
|
+
]
|
|
254
|
+
}), /* @__PURE__ */ m("div", {
|
|
255
|
+
className: "flex items-center gap-2",
|
|
256
|
+
children: [/* @__PURE__ */ p("button", {
|
|
257
|
+
type: "button",
|
|
258
|
+
disabled: N === 0,
|
|
259
|
+
onClick: () => P((e) => e - 1),
|
|
260
|
+
className: "rounded-md border border-border-default px-3 py-1.5 text-xs font-medium text-text-secondary hover:bg-surface-hover disabled:opacity-40",
|
|
261
|
+
children: "Previous"
|
|
262
|
+
}), /* @__PURE__ */ p("button", {
|
|
263
|
+
type: "button",
|
|
264
|
+
disabled: (N + 1) * y >= D,
|
|
265
|
+
onClick: () => P((e) => e + 1),
|
|
266
|
+
className: "rounded-md border border-border-default px-3 py-1.5 text-xs font-medium text-text-secondary hover:bg-surface-hover disabled:opacity-40",
|
|
267
|
+
children: "Next"
|
|
268
|
+
})]
|
|
269
|
+
})]
|
|
270
|
+
})] })
|
|
271
|
+
]
|
|
272
|
+
})]
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
//#endregion
|
|
276
|
+
export { x as AdminFulfillmentLogsPage };
|
|
277
|
+
|
|
278
|
+
//# sourceMappingURL=AdminFulfillmentLogsPage.js.map
|