@burdenoff/microfe-store 2026.510.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +217 -0
  2. package/dist/StoreAdminRoot.d.ts +22 -0
  3. package/dist/StoreAdminRoot.js +23 -0
  4. package/dist/StoreAdminRoot.js.map +1 -0
  5. package/dist/StoreAdminRoutes.d.ts +9 -0
  6. package/dist/StoreAdminRoutes.js +69 -0
  7. package/dist/StoreAdminRoutes.js.map +1 -0
  8. package/dist/StoreRoot.d.ts +31 -0
  9. package/dist/StoreRoot.js +139 -0
  10. package/dist/StoreRoot.js.map +1 -0
  11. package/dist/StoreRoutes.d.ts +12 -0
  12. package/dist/StoreRoutes.js +285 -0
  13. package/dist/StoreRoutes.js.map +1 -0
  14. package/dist/components/InstallAppModal.d.ts +26 -0
  15. package/dist/components/InstallAppModal.js +287 -0
  16. package/dist/components/InstallAppModal.js.map +1 -0
  17. package/dist/components/RouteGuards.d.ts +17 -0
  18. package/dist/components/RouteGuards.js +26 -0
  19. package/dist/components/RouteGuards.js.map +1 -0
  20. package/dist/components/cart/CartDrawer.d.ts +35 -0
  21. package/dist/components/cart/CartDrawer.js +162 -0
  22. package/dist/components/cart/CartDrawer.js.map +1 -0
  23. package/dist/components/index.d.ts +9 -0
  24. package/dist/components/index.js +3 -0
  25. package/dist/components/marketplace/ProductCard.d.ts +18 -0
  26. package/dist/components/marketplace/ProductCard.js +2 -0
  27. package/dist/dev/main.d.ts +1 -0
  28. package/dist/generated/global-operations.d.ts +2012 -0
  29. package/dist/generated/global-operations.js +1444 -0
  30. package/dist/generated/global-operations.js.map +1 -0
  31. package/dist/generated/global-types.d.ts +20856 -0
  32. package/dist/generated/global-types.js +14 -0
  33. package/dist/generated/global-types.js.map +1 -0
  34. package/dist/generated/wspace-operations.d.ts +1 -0
  35. package/dist/generated/wspace-types.d.ts +53362 -0
  36. package/dist/hooks/index.d.ts +12 -0
  37. package/dist/hooks/useBackendCart.d.ts +73 -0
  38. package/dist/hooks/useBackendCart.js +171 -0
  39. package/dist/hooks/useBackendCart.js.map +1 -0
  40. package/dist/hooks/useCart.d.ts +62 -0
  41. package/dist/hooks/useCart.js +90 -0
  42. package/dist/hooks/useCart.js.map +1 -0
  43. package/dist/hooks/useInstallations.d.ts +43 -0
  44. package/dist/hooks/useInstallations.js +140 -0
  45. package/dist/hooks/useInstallations.js.map +1 -0
  46. package/dist/hooks/useOrders.d.ts +40 -0
  47. package/dist/hooks/useOrders.js +73 -0
  48. package/dist/hooks/useOrders.js.map +1 -0
  49. package/dist/hooks/useProductSearch.d.ts +22 -0
  50. package/dist/hooks/useProductSearch.js +59 -0
  51. package/dist/hooks/useProductSearch.js.map +1 -0
  52. package/dist/hooks/useStoreGraphQL.d.ts +475 -0
  53. package/dist/hooks/useStoreGraphQL.js +751 -0
  54. package/dist/hooks/useStoreGraphQL.js.map +1 -0
  55. package/dist/hooks/useStoreGraphQLWithContext.d.ts +48 -0
  56. package/dist/hooks/useStoreGraphQLWithContext.js +39 -0
  57. package/dist/hooks/useStoreGraphQLWithContext.js.map +1 -0
  58. package/dist/hooks/useStorePermissions.d.ts +63 -0
  59. package/dist/hooks/useStorePermissions.js +88 -0
  60. package/dist/hooks/useStorePermissions.js.map +1 -0
  61. package/dist/index.d.ts +44 -0
  62. package/dist/index.js +13 -0
  63. package/dist/pages/AdminDashboardPage.d.ts +3 -0
  64. package/dist/pages/AdminDashboardPage.js +491 -0
  65. package/dist/pages/AdminDashboardPage.js.map +1 -0
  66. package/dist/pages/AdminReviewModerationPage.d.ts +3 -0
  67. package/dist/pages/AdminReviewModerationPage.js +247 -0
  68. package/dist/pages/AdminReviewModerationPage.js.map +1 -0
  69. package/dist/pages/AdminStoresPage.d.ts +3 -0
  70. package/dist/pages/AdminStoresPage.js +442 -0
  71. package/dist/pages/AdminStoresPage.js.map +1 -0
  72. package/dist/pages/AdminSubmissionsQueuePage.d.ts +3 -0
  73. package/dist/pages/AdminSubmissionsQueuePage.js +387 -0
  74. package/dist/pages/AdminSubmissionsQueuePage.js.map +1 -0
  75. package/dist/pages/AppDetailPage.d.ts +3 -0
  76. package/dist/pages/AppDetailPage.js +166 -0
  77. package/dist/pages/AppDetailPage.js.map +1 -0
  78. package/dist/pages/AppSettingsPage.d.ts +3 -0
  79. package/dist/pages/AppSettingsPage.js +100 -0
  80. package/dist/pages/AppSettingsPage.js.map +1 -0
  81. package/dist/pages/CartPage.d.ts +8 -0
  82. package/dist/pages/CartPage.js +259 -0
  83. package/dist/pages/CartPage.js.map +1 -0
  84. package/dist/pages/InstalledAppsPage.d.ts +8 -0
  85. package/dist/pages/InstalledAppsPage.js +290 -0
  86. package/dist/pages/InstalledAppsPage.js.map +1 -0
  87. package/dist/pages/MarketplaceHomePage.d.ts +3 -0
  88. package/dist/pages/MarketplaceHomePage.js +1118 -0
  89. package/dist/pages/MarketplaceHomePage.js.map +1 -0
  90. package/dist/pages/MyLicensesPage.d.ts +3 -0
  91. package/dist/pages/MyLicensesPage.js +146 -0
  92. package/dist/pages/MyLicensesPage.js.map +1 -0
  93. package/dist/pages/OrderConfirmationPage.d.ts +3 -0
  94. package/dist/pages/OrderConfirmationPage.js +178 -0
  95. package/dist/pages/OrderConfirmationPage.js.map +1 -0
  96. package/dist/pages/OrdersPage.d.ts +8 -0
  97. package/dist/pages/OrdersPage.js +358 -0
  98. package/dist/pages/OrdersPage.js.map +1 -0
  99. package/dist/pages/ProductCategoryPage.d.ts +3 -0
  100. package/dist/pages/ProductCategoryPage.js +83 -0
  101. package/dist/pages/ProductCategoryPage.js.map +1 -0
  102. package/dist/pages/ProductDetailPage.d.ts +8 -0
  103. package/dist/pages/ProductDetailPage.js +1205 -0
  104. package/dist/pages/ProductDetailPage.js.map +1 -0
  105. package/dist/pages/ProductReviewsPage.d.ts +3 -0
  106. package/dist/pages/ProductReviewsPage.js +86 -0
  107. package/dist/pages/ProductReviewsPage.js.map +1 -0
  108. package/dist/pages/PublisherDashboardPage.d.ts +3 -0
  109. package/dist/pages/PublisherDashboardPage.js +154 -0
  110. package/dist/pages/PublisherDashboardPage.js.map +1 -0
  111. package/dist/pages/PublisherRevenuePage.d.ts +3 -0
  112. package/dist/pages/PublisherRevenuePage.js +138 -0
  113. package/dist/pages/PublisherRevenuePage.js.map +1 -0
  114. package/dist/pages/PublisherSubmissionsPage.d.ts +3 -0
  115. package/dist/pages/PublisherSubmissionsPage.js +174 -0
  116. package/dist/pages/PublisherSubmissionsPage.js.map +1 -0
  117. package/dist/pages/PublisherSubmitPage.d.ts +3 -0
  118. package/dist/pages/PublisherSubmitPage.js +224 -0
  119. package/dist/pages/PublisherSubmitPage.js.map +1 -0
  120. package/dist/pages/SearchResultsPage.d.ts +3 -0
  121. package/dist/pages/SearchResultsPage.js +125 -0
  122. package/dist/pages/SearchResultsPage.js.map +1 -0
  123. package/dist/pages/StoresPage.d.ts +3 -0
  124. package/dist/pages/StoresPage.js +154 -0
  125. package/dist/pages/StoresPage.js.map +1 -0
  126. package/dist/providers/StoreProvider.d.ts +38 -0
  127. package/dist/providers/StoreProvider.js +51 -0
  128. package/dist/providers/StoreProvider.js.map +1 -0
  129. package/dist/store/storeStore.d.ts +69 -0
  130. package/dist/store/storeStore.js +68 -0
  131. package/dist/store/storeStore.js.map +1 -0
  132. package/dist/translations/en.d.ts +518 -0
  133. package/dist/translations/en.js +514 -0
  134. package/dist/translations/en.js.map +1 -0
  135. package/dist/types/index.d.ts +575 -0
  136. package/dist/utils/index.d.ts +67 -0
  137. package/dist/utils/index.js +114 -0
  138. package/dist/utils/index.js.map +1 -0
  139. package/dist/utils/nativeBridge.d.ts +2 -0
  140. package/dist/utils/nativeBridge.js +2 -0
  141. package/package.json +105 -0
@@ -0,0 +1,100 @@
1
+ import { useStore as e } from "../providers/StoreProvider.js";
2
+ import { useInstallation as t } from "../hooks/useInstallations.js";
3
+ import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
4
+ import { ArrowLeft as r, Settings as i } from "lucide-react";
5
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
+ import { useNavigate as s, useParams as c } from "react-router-dom";
7
+ //#region src/pages/AppSettingsPage.tsx
8
+ var l = () => {
9
+ let l = s(), { basePath: u } = e(), { installationId: d } = c(), { installation: f, loading: p, error: m } = t(d), { t: h } = n();
10
+ return /* @__PURE__ */ o("div", {
11
+ className: "flex h-full flex-col",
12
+ children: [/* @__PURE__ */ a("header", {
13
+ className: "border-b border-border-default bg-bg-surface px-6 py-4",
14
+ children: /* @__PURE__ */ o("div", {
15
+ className: "mx-auto flex max-w-4xl items-center gap-3",
16
+ children: [/* @__PURE__ */ a("button", {
17
+ onClick: () => l(-1),
18
+ "aria-label": "Go back",
19
+ className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
20
+ children: /* @__PURE__ */ a(r, { className: "h-5 w-5" })
21
+ }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("h1", {
22
+ className: "text-2xl font-bold text-text-primary",
23
+ children: h("pages.appSettings.title", { defaultValue: "App Settings" })
24
+ }), /* @__PURE__ */ a("p", {
25
+ className: "text-sm text-text-muted",
26
+ children: h("pages.appSettings.subtitle", { defaultValue: "Review current installation configuration" })
27
+ })] })]
28
+ })
29
+ }), /* @__PURE__ */ a("main", {
30
+ className: "flex-1 overflow-y-auto p-6",
31
+ children: /* @__PURE__ */ a("div", {
32
+ className: "mx-auto max-w-4xl",
33
+ children: p ? /* @__PURE__ */ a("p", {
34
+ role: "status",
35
+ className: "text-sm text-text-muted",
36
+ children: "Loading settings..."
37
+ }) : m ? /* @__PURE__ */ a("p", {
38
+ role: "alert",
39
+ className: "text-sm text-status-error-text",
40
+ children: m.message
41
+ }) : f ? /* @__PURE__ */ o("div", {
42
+ className: "space-y-4 rounded-xl border border-border-default bg-bg-surface p-5",
43
+ children: [
44
+ /* @__PURE__ */ o("div", {
45
+ className: "flex items-center gap-2",
46
+ children: [/* @__PURE__ */ a(i, { className: "h-5 w-5 text-text-primary" }), /* @__PURE__ */ a("h2", {
47
+ className: "text-lg font-semibold text-text-primary",
48
+ children: h("pages.appSettings.configSnapshot", { defaultValue: "Configuration snapshot" })
49
+ })]
50
+ }),
51
+ /* @__PURE__ */ a("p", {
52
+ className: "text-sm text-text-muted",
53
+ children: h("pages.appSettings.configDescription", { defaultValue: "Store-level configuration for this installation is read-only here." })
54
+ }),
55
+ /* @__PURE__ */ o("div", {
56
+ className: "grid gap-4 lg:grid-cols-2",
57
+ children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
58
+ className: "mb-2 text-sm font-medium text-text-primary",
59
+ children: "Manifest"
60
+ }), /* @__PURE__ */ a("pre", {
61
+ className: "overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted",
62
+ children: JSON.stringify(f.manifest ?? {}, null, 2)
63
+ })] }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
64
+ className: "mb-2 text-sm font-medium text-text-primary",
65
+ children: "Metadata & Context"
66
+ }), /* @__PURE__ */ a("pre", {
67
+ className: "overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted",
68
+ children: JSON.stringify({
69
+ metadata: f.metadata ?? {},
70
+ context: f.context ?? {},
71
+ version: f.version,
72
+ status: f.status
73
+ }, null, 2)
74
+ })] })]
75
+ }),
76
+ /* @__PURE__ */ o("div", {
77
+ className: "flex flex-wrap gap-3",
78
+ children: [/* @__PURE__ */ a("button", {
79
+ onClick: () => l(`${u}/installed/${f.id}`),
80
+ className: "inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
81
+ children: h("pages.appSettings.viewInstallation", { defaultValue: "View Installation" })
82
+ }), /* @__PURE__ */ a("button", {
83
+ onClick: () => l(`${u}/marketplace/product/${f.productId}`),
84
+ className: "inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text hover:opacity-90",
85
+ children: h("pages.appDetail.viewProduct", { defaultValue: "View Product" })
86
+ })]
87
+ })
88
+ ]
89
+ }) : /* @__PURE__ */ a("p", {
90
+ className: "text-sm text-text-muted",
91
+ children: "Installation not found."
92
+ })
93
+ })
94
+ })]
95
+ });
96
+ };
97
+ //#endregion
98
+ export { l as AppSettingsPage };
99
+
100
+ //# sourceMappingURL=AppSettingsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppSettingsPage.js","names":[],"sources":["../../src/pages/AppSettingsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { ArrowLeft, Settings } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useInstallation } from '../hooks/useInstallations';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const AppSettingsPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { installationId } = useParams<{ installationId: string }>();\n const { installation, loading, error } = useInstallation(installationId);\n const { t } = useI18n();\n\n return (\n <div className=\"flex h-full flex-col\">\n <header className=\"border-b border-border-default bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto flex max-w-4xl items-center gap-3\">\n <button\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.appSettings.title', { defaultValue: 'App Settings' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.appSettings.subtitle', {\n defaultValue: 'Review current installation configuration',\n })}\n </p>\n </div>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-4xl\">\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading settings...\n </p>\n ) : error ? (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error.message}\n </p>\n ) : !installation ? (\n <p className=\"text-sm text-text-muted\">Installation not found.</p>\n ) : (\n <div className=\"space-y-4 rounded-xl border border-border-default bg-bg-surface p-5\">\n <div className=\"flex items-center gap-2\">\n <Settings className=\"h-5 w-5 text-text-primary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.appSettings.configSnapshot', {\n defaultValue: 'Configuration snapshot',\n })}\n </h2>\n </div>\n\n <p className=\"text-sm text-text-muted\">\n {t('pages.appSettings.configDescription', {\n defaultValue:\n 'Store-level configuration for this installation is read-only here.',\n })}\n </p>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">Manifest</p>\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted\">\n {JSON.stringify(installation.manifest ?? {}, null, 2)}\n </pre>\n </div>\n\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">Metadata & Context</p>\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted\">\n {JSON.stringify(\n {\n metadata: installation.metadata ?? {},\n context: installation.context ?? {},\n version: installation.version,\n status: installation.status,\n },\n null,\n 2\n )}\n </pre>\n </div>\n </div>\n\n <div className=\"flex flex-wrap gap-3\">\n <button\n onClick={() => navigate(`${basePath}/installed/${installation.id}`)}\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n {t('pages.appSettings.viewInstallation', { defaultValue: 'View Installation' })}\n </button>\n <button\n onClick={() =>\n navigate(`${basePath}/marketplace/product/${installation.productId}`)\n }\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text hover:opacity-90\"\n >\n {t('pages.appDetail.viewProduct', { defaultValue: 'View Product' })}\n </button>\n </div>\n </div>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":";;;;;;;AAOA,IAAa,UAA4B;CACvC,IAAM,IAAW,GAAa,EACxB,EAAE,gBAAa,GAAU,EACzB,EAAE,sBAAmB,GAAuC,EAC5D,EAAE,iBAAc,YAAS,aAAU,EAAgB,EAAe,EAClE,EAAE,SAAM,GAAS;AAEvB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GAAQ,WAAU;aAChB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,UAAD;KACE,eAAe,EAAS,GAAG;KAC3B,cAAW;KACX,WAAU;eAEV,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;KAC1B,CAAA,EACT,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAE,2BAA2B,EAAE,cAAc,gBAAgB,CAAC;KAC5D,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,8BAA8B,EAC/B,cAAc,6CACf,CAAC;KACA,CAAA,CACA,EAAA,CAAA,CACF;;GACC,CAAA,EAET,kBAAC,QAAD;GAAM,WAAU;aACd,kBAAC,OAAD;IAAK,WAAU;cACZ,IACC,kBAAC,KAAD;KAAG,MAAK;KAAS,WAAU;eAA0B;KAEjD,CAAA,GACF,IACF,kBAAC,KAAD;KAAG,MAAK;KAAQ,WAAU;eACvB,EAAM;KACL,CAAA,GACD,IAGH,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAU,WAAU,6BAA8B,CAAA,EAClD,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,oCAAoC,EACrC,cAAc,0BACf,CAAC;QACC,CAAA,CACD;;MAEN,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAE,uCAAuC,EACxC,cACE,sEACH,CAAC;OACA,CAAA;MAEJ,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA6C;QAAY,CAAA,EACtE,kBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK,UAAU,EAAa,YAAY,EAAE,EAAE,MAAM,EAAE;QACjD,CAAA,CACF,EAAA,CAAA,EAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA6C;QAAsB,CAAA,EAChF,kBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK,UACJ;SACE,UAAU,EAAa,YAAY,EAAE;SACrC,SAAS,EAAa,WAAW,EAAE;SACnC,SAAS,EAAa;SACtB,QAAQ,EAAa;SACtB,EACD,MACA,EACD;QACG,CAAA,CACF,EAAA,CAAA,CACF;;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,UAAD;QACE,eAAe,EAAS,GAAG,EAAS,aAAa,EAAa,KAAK;QACnE,WAAU;kBAET,EAAE,sCAAsC,EAAE,cAAc,qBAAqB,CAAC;QACxE,CAAA,EACT,kBAAC,UAAD;QACE,eACE,EAAS,GAAG,EAAS,uBAAuB,EAAa,YAAY;QAEvE,WAAU;kBAET,EAAE,+BAA+B,EAAE,cAAc,gBAAgB,CAAC;QAC5D,CAAA,CACL;;MACF;SA5DN,kBAAC,KAAD;KAAG,WAAU;eAA0B;KAA2B,CAAA;IA8DhE,CAAA;GACD,CAAA,CACH"}
@@ -0,0 +1,8 @@
1
+ import { FC } from 'react';
2
+
3
+ /**
4
+ * CartPage component
5
+ *
6
+ * Full page cart view with items, summary, and checkout
7
+ */
8
+ export declare const CartPage: FC;
@@ -0,0 +1,259 @@
1
+ import { useStore as e } from "../providers/StoreProvider.js";
2
+ import { useCart as t } from "../hooks/useCart.js";
3
+ import { formatPrice as n } from "../utils/index.js";
4
+ import { useState as r } from "react";
5
+ import { useI18n as i } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
+ import { ArrowLeft as a, Loader2 as o, Minus as s, Plus as c, ShoppingBag as l, ShoppingCart as u, Tag as d, Trash2 as f, Zap as p } from "lucide-react";
7
+ import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
8
+ import { useNavigate as _ } from "react-router-dom";
9
+ import { useQuotaErrorToast as v } from "@burdenoff/fe-libs/shared/hooks";
10
+ import { useEventBus as y } from "@burdenoff/fe-libs/shared/events";
11
+ import { isQuotaExhaustedError as b } from "@burdenoff/fe-libs/shared/utils";
12
+ //#region src/pages/CartPage.tsx
13
+ var x = () => {
14
+ let x = _(), { basePath: S } = e(), { cartItems: C, itemCount: w, total: T, updateQuantity: E, removeProduct: D, clearCart: O, createOrder: k } = t(), [A, j] = r(!1), [M, N] = r(null), { t: P } = i(), F = y(), { report: I } = v(), L = async () => {
15
+ try {
16
+ j(!0), N(null), F.emit("store.cart.checkout_started", {
17
+ cartId: "",
18
+ itemCount: w,
19
+ total: T
20
+ });
21
+ let e = await k({
22
+ total: T,
23
+ lineItems: C.map((e) => ({
24
+ productId: e.productId,
25
+ name: e.product?.displayName || "Product",
26
+ quantity: e.quantity,
27
+ unitPrice: e.unitPrice,
28
+ subtotal: e.totalPrice,
29
+ itemType: e.itemType.toLowerCase(),
30
+ variantId: e.variantId,
31
+ pricingModel: e.product?.pricingModel || "PAID_ONETIME"
32
+ })),
33
+ billingAccountId: ""
34
+ });
35
+ e?.id ? (F.emit("store.order.placed", {
36
+ orderId: e.id,
37
+ total: T,
38
+ itemCount: w
39
+ }), O().catch(() => {}), x(`/billing/checkout/store/${e.id}`)) : (N(P("pages.cart.failedToCreate", { defaultValue: "Failed to create order. Please try again." })), j(!1));
40
+ } catch (e) {
41
+ if (console.error("Checkout error:", e), b(e)) {
42
+ I(e), j(!1);
43
+ return;
44
+ }
45
+ N(e instanceof Error ? e.message : "An error occurred during checkout"), j(!1);
46
+ }
47
+ }, R = () => {
48
+ x(`${S}/marketplace`);
49
+ };
50
+ return /* @__PURE__ */ g("div", {
51
+ className: "h-full overflow-y-auto",
52
+ children: [/* @__PURE__ */ h("header", {
53
+ className: "sticky top-0 z-10 border-b border-border-default bg-bg-surface px-6 py-4",
54
+ children: /* @__PURE__ */ h("div", {
55
+ className: "mx-auto max-w-6xl",
56
+ children: /* @__PURE__ */ g("div", {
57
+ className: "flex items-center gap-4",
58
+ children: [/* @__PURE__ */ h("button", {
59
+ onClick: () => x(-1),
60
+ "aria-label": "Go back",
61
+ className: "cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary",
62
+ children: /* @__PURE__ */ h(a, { className: "h-5 w-5" })
63
+ }), /* @__PURE__ */ g("div", {
64
+ className: "flex items-center gap-3",
65
+ children: [
66
+ /* @__PURE__ */ h(u, { className: "h-6 w-6 text-text-primary" }),
67
+ /* @__PURE__ */ h("h1", {
68
+ className: "text-xl font-bold text-text-primary",
69
+ children: P("cart.title", { defaultValue: "Shopping Cart" })
70
+ }),
71
+ w > 0 && /* @__PURE__ */ g("span", {
72
+ className: "rounded-full bg-action-primary-bg px-2.5 py-0.5 text-sm font-medium text-action-primary-text",
73
+ children: [
74
+ w,
75
+ " ",
76
+ w === 1 ? P("pages.cart.item", {
77
+ defaultValue: `${w} item`,
78
+ count: w
79
+ }) : P("pages.cart.items", {
80
+ defaultValue: `${w} items`,
81
+ count: w
82
+ })
83
+ ]
84
+ })
85
+ ]
86
+ })]
87
+ })
88
+ })
89
+ }), /* @__PURE__ */ h("main", {
90
+ className: "mx-auto max-w-6xl px-6 py-6",
91
+ children: C.length === 0 ? /* @__PURE__ */ g("div", {
92
+ className: "flex flex-col items-center justify-center py-16 text-center",
93
+ children: [
94
+ /* @__PURE__ */ h("div", {
95
+ className: "mb-6 rounded-full bg-bg-sunken p-6",
96
+ children: /* @__PURE__ */ h(l, { className: "h-16 w-16 text-text-muted" })
97
+ }),
98
+ /* @__PURE__ */ h("h2", {
99
+ className: "mb-2 text-2xl font-bold text-text-primary",
100
+ children: P("cart.empty", { defaultValue: "Your cart is empty" })
101
+ }),
102
+ /* @__PURE__ */ h("p", {
103
+ className: "mb-6 max-w-md text-text-muted",
104
+ children: P("pages.cart.emptyDescription", { defaultValue: "Looks like you have not added any apps or products to your cart yet. Start exploring the marketplace to find something you will love!" })
105
+ }),
106
+ /* @__PURE__ */ g("button", {
107
+ onClick: R,
108
+ className: "cursor-pointer flex items-center gap-2 rounded-lg bg-action-primary-bg px-6 py-3 font-semibold text-action-primary-text transition-opacity hover:opacity-90",
109
+ children: [/* @__PURE__ */ h(l, { className: "h-5 w-5" }), P("pages.cart.browseMarketplace", { defaultValue: "Browse Marketplace" })]
110
+ })
111
+ ]
112
+ }) : /* @__PURE__ */ h("div", {
113
+ className: "mx-auto max-w-3xl",
114
+ children: /* @__PURE__ */ g("div", { children: [
115
+ /* @__PURE__ */ g("div", {
116
+ className: "mb-4 flex items-center justify-between",
117
+ children: [/* @__PURE__ */ h("h2", {
118
+ className: "text-lg font-semibold text-text-primary",
119
+ children: P("pages.cart.cartItems", {
120
+ defaultValue: `Cart Items (${w})`,
121
+ count: w
122
+ })
123
+ }), /* @__PURE__ */ g("button", {
124
+ onClick: O,
125
+ className: "cursor-pointer flex items-center gap-1 text-sm text-text-muted transition-colors hover:text-status-error-text",
126
+ children: [/* @__PURE__ */ h(f, { className: "h-4 w-4" }), P("cart.clearCart", { defaultValue: "Clear Cart" })]
127
+ })]
128
+ }),
129
+ /* @__PURE__ */ h("ul", {
130
+ className: "space-y-4",
131
+ children: C.map((e) => /* @__PURE__ */ g("li", {
132
+ className: "flex gap-4 rounded-xl border border-border-default bg-bg-surface p-4 transition-shadow hover:shadow-md",
133
+ children: [/* @__PURE__ */ h("div", {
134
+ className: "h-24 w-24 flex-shrink-0 overflow-hidden rounded-lg bg-bg-sunken",
135
+ children: e.product?.iconUrl ? /* @__PURE__ */ h("img", {
136
+ src: e.product.iconUrl,
137
+ alt: e.product.displayName,
138
+ className: "h-full w-full object-cover"
139
+ }) : /* @__PURE__ */ h("div", {
140
+ className: "flex h-full w-full items-center justify-center text-2xl font-bold text-text-muted",
141
+ children: e.product?.displayName?.charAt(0) || "P"
142
+ })
143
+ }), /* @__PURE__ */ g("div", {
144
+ className: "flex flex-1 flex-col",
145
+ children: [
146
+ /* @__PURE__ */ g("div", {
147
+ className: "flex items-start justify-between",
148
+ children: [/* @__PURE__ */ g("div", { children: [
149
+ /* @__PURE__ */ h("h3", {
150
+ className: "font-semibold text-text-primary",
151
+ children: e.product?.displayName || "Product"
152
+ }),
153
+ /* @__PURE__ */ h("p", {
154
+ className: "text-sm text-text-muted",
155
+ children: e.product?.publisher?.displayName || "Unknown Publisher"
156
+ }),
157
+ e.variant && /* @__PURE__ */ g("p", {
158
+ className: "mt-1 text-xs text-text-muted",
159
+ children: ["Version ", e.variant.version]
160
+ })
161
+ ] }), /* @__PURE__ */ h("button", {
162
+ onClick: () => D(e.id),
163
+ className: "cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-status-error-bg-subtle/10 hover:text-status-error-text",
164
+ "aria-label": `Remove ${e.product?.displayName ?? "item"} from cart`,
165
+ title: "Remove item",
166
+ children: /* @__PURE__ */ h(f, { className: "h-5 w-5" })
167
+ })]
168
+ }),
169
+ /* @__PURE__ */ g("div", {
170
+ className: "mt-2 flex items-center gap-2",
171
+ children: [/* @__PURE__ */ h("span", {
172
+ className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-muted",
173
+ children: e.itemType === "digital" ? /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(p, { className: "h-3 w-3" }), P("pages.cart.digital", { defaultValue: "Digital" })] }) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(d, { className: "h-3 w-3" }), P("pages.cart.physical", { defaultValue: "Physical" })] })
174
+ }), e.product?.pricingModel === "SUBSCRIPTION" && /* @__PURE__ */ h("span", {
175
+ className: "inline-flex items-center gap-1 rounded-full bg-bg-accent/10 px-2 py-0.5 text-xs font-medium text-text-link",
176
+ children: P("store.pricingModels.subscription", { defaultValue: "Subscription" })
177
+ })]
178
+ }),
179
+ /* @__PURE__ */ g("div", {
180
+ className: "mt-auto flex items-center justify-between pt-3",
181
+ children: [e.itemType === "physical" ? /* @__PURE__ */ g("div", {
182
+ className: "flex items-center gap-3",
183
+ children: [/* @__PURE__ */ h("span", {
184
+ className: "text-sm text-text-muted",
185
+ children: "Qty:"
186
+ }), /* @__PURE__ */ g("div", {
187
+ className: "flex items-center rounded-lg border border-border-default",
188
+ children: [
189
+ /* @__PURE__ */ h("button", {
190
+ onClick: () => E(e.id, e.quantity - 1),
191
+ className: "cursor-pointer rounded-l-lg p-2 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50",
192
+ disabled: e.quantity <= 1,
193
+ children: /* @__PURE__ */ h(s, { className: "h-4 w-4" })
194
+ }),
195
+ /* @__PURE__ */ h("span", {
196
+ className: "min-w-[3rem] text-center font-medium",
197
+ children: e.quantity
198
+ }),
199
+ /* @__PURE__ */ h("button", {
200
+ onClick: () => E(e.id, e.quantity + 1),
201
+ className: "cursor-pointer rounded-r-lg p-2 transition-colors hover:bg-bg-sunken",
202
+ children: /* @__PURE__ */ h(c, { className: "h-4 w-4" })
203
+ })
204
+ ]
205
+ })]
206
+ }) : /* @__PURE__ */ h("div", {
207
+ className: "text-sm text-text-muted",
208
+ children: P("pages.cart.singleLicense", { defaultValue: "Single license" })
209
+ }), /* @__PURE__ */ g("div", {
210
+ className: "text-right",
211
+ children: [/* @__PURE__ */ h("p", {
212
+ className: "text-lg font-bold text-text-primary",
213
+ children: n(e.totalPrice)
214
+ }), e.quantity > 1 && e.itemType === "physical" && /* @__PURE__ */ g("p", {
215
+ className: "text-xs text-text-muted",
216
+ children: [n(e.unitPrice), " each"]
217
+ })]
218
+ })]
219
+ })
220
+ ]
221
+ })]
222
+ }, e.id))
223
+ }),
224
+ /* @__PURE__ */ g("div", {
225
+ className: "mt-8 rounded-xl border border-border-default bg-bg-surface p-5",
226
+ children: [M && /* @__PURE__ */ h("div", {
227
+ role: "alert",
228
+ className: "mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
229
+ children: M
230
+ }), /* @__PURE__ */ g("div", {
231
+ className: "flex items-center justify-between",
232
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("p", {
233
+ className: "text-sm text-text-muted",
234
+ children: "Total"
235
+ }), /* @__PURE__ */ h("p", {
236
+ className: "text-2xl font-bold text-text-primary",
237
+ children: n(T)
238
+ })] }), /* @__PURE__ */ h("button", {
239
+ onClick: L,
240
+ disabled: A,
241
+ className: "flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-6 py-3 font-semibold text-action-primary-text transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-70",
242
+ children: A ? /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(o, { className: "h-4 w-4 animate-spin" }), P("pages.cart.processing", { defaultValue: "Processing..." })] }) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(p, { className: "h-4 w-4" }), P("pages.cart.proceedToCheckout", { defaultValue: "Proceed to Checkout" })] })
243
+ })]
244
+ })]
245
+ }),
246
+ /* @__PURE__ */ g("button", {
247
+ onClick: R,
248
+ className: "cursor-pointer mt-4 flex items-center gap-2 text-sm font-medium text-text-link hover:underline",
249
+ children: [/* @__PURE__ */ h(a, { className: "h-4 w-4" }), P("cart.continueShopping", { defaultValue: "Continue Shopping" })]
250
+ })
251
+ ] })
252
+ })
253
+ })]
254
+ });
255
+ };
256
+ //#endregion
257
+ export { x as CartPage };
258
+
259
+ //# sourceMappingURL=CartPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CartPage.js","names":[],"sources":["../../src/pages/CartPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { useQuotaErrorToast } from '@burdenoff/fe-libs/shared/hooks';\nimport { isQuotaExhaustedError } from '@burdenoff/fe-libs/shared/utils';\nimport {\n ShoppingCart,\n Trash2,\n Plus,\n Minus,\n ArrowLeft,\n ShoppingBag,\n Zap,\n Tag,\n Loader2,\n} from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useCart } from '../hooks/useCart';\nimport { formatPrice } from '../utils';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\n/**\n * CartPage component\n *\n * Full page cart view with items, summary, and checkout\n */\nexport const CartPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { cartItems, itemCount, total, updateQuantity, removeProduct, clearCart, createOrder } =\n useCart();\n const [isCheckingOut, setIsCheckingOut] = useState(false);\n const [checkoutError, setCheckoutError] = useState<string | null>(null);\n const { t } = useI18n();\n const bus = useEventBus();\n // Surface QUOTA_EXHAUSTED gateway errors as a toast (e.g. when the\n // workspace has hit its store-purchases-per-month limit). The hook also\n // listens for the global `burdenoff:quota-exhausted` event so any other\n // mutation in the page that triggers it will toast as well.\n const { report: reportQuotaError } = useQuotaErrorToast();\n\n const handleCheckout = async () => {\n try {\n setIsCheckingOut(true);\n setCheckoutError(null);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n bus.emit('store.cart.checkout_started' as any, {\n cartId: '',\n itemCount,\n total,\n });\n\n // Build line items from cart\n const lineItems = cartItems.map((item) => ({\n productId: item.productId,\n name: item.product?.displayName || 'Product',\n quantity: item.quantity,\n unitPrice: item.unitPrice,\n subtotal: item.totalPrice,\n itemType: item.itemType.toLowerCase(),\n variantId: item.variantId,\n pricingModel: item.product?.pricingModel || 'PAID_ONETIME',\n }));\n\n // Create order input\n const orderInput = {\n total,\n lineItems,\n billingAccountId: '', // Will be set on billing page\n };\n\n // Call createStoreOrder mutation to create PENDING order\n const order = await createOrder(orderInput);\n\n if (order?.id) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n bus.emit('store.order.placed' as any, {\n orderId: order.id,\n total,\n itemCount,\n });\n // Clear cart now that the order is created — non-blocking so a\n // clear failure never prevents the user from reaching billing.\n clearCart().catch(() => {});\n // Navigate to billing page with the order ID\n navigate(`/billing/checkout/store/${order.id}`);\n } else {\n setCheckoutError(\n t('pages.cart.failedToCreate', {\n defaultValue: 'Failed to create order. Please try again.',\n })\n );\n setIsCheckingOut(false);\n }\n } catch (error) {\n console.error('Checkout error:', error);\n // Quota-exhausted errors surface a global toast via the shell's\n // GlobalUiProvider; suppress the inline checkout error so we don't\n // stack two error UIs on top of each other.\n if (isQuotaExhaustedError(error)) {\n reportQuotaError(error);\n setIsCheckingOut(false);\n return;\n }\n setCheckoutError(\n error instanceof Error ? error.message : 'An error occurred during checkout'\n );\n setIsCheckingOut(false);\n }\n };\n\n const handleContinueShopping = () => {\n navigate(`${basePath}/marketplace`);\n };\n\n return (\n <div className=\"h-full overflow-y-auto\">\n {/* Header */}\n <header className=\"sticky top-0 z-10 border-b border-border-default bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto max-w-6xl\">\n <div className=\"flex items-center gap-4\">\n <button\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n <div className=\"flex items-center gap-3\">\n <ShoppingCart className=\"h-6 w-6 text-text-primary\" />\n <h1 className=\"text-xl font-bold text-text-primary\">\n {t('cart.title', { defaultValue: 'Shopping Cart' })}\n </h1>\n {itemCount > 0 && (\n <span className=\"rounded-full bg-action-primary-bg px-2.5 py-0.5 text-sm font-medium text-action-primary-text\">\n {itemCount}{' '}\n {itemCount === 1\n ? t('pages.cart.item', { defaultValue: `${itemCount} item`, count: itemCount })\n : t('pages.cart.items', {\n defaultValue: `${itemCount} items`,\n count: itemCount,\n })}\n </span>\n )}\n </div>\n </div>\n </div>\n </header>\n\n <main className=\"mx-auto max-w-6xl px-6 py-6\">\n {cartItems.length === 0 ? (\n // Empty Cart State\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <div className=\"mb-6 rounded-full bg-bg-sunken p-6\">\n <ShoppingBag className=\"h-16 w-16 text-text-muted\" />\n </div>\n <h2 className=\"mb-2 text-2xl font-bold text-text-primary\">\n {t('cart.empty', { defaultValue: 'Your cart is empty' })}\n </h2>\n <p className=\"mb-6 max-w-md text-text-muted\">\n {t('pages.cart.emptyDescription', {\n defaultValue:\n 'Looks like you have not added any apps or products to your cart yet. Start exploring the marketplace to find something you will love!',\n })}\n </p>\n <button\n onClick={handleContinueShopping}\n className=\"cursor-pointer flex items-center gap-2 rounded-lg bg-action-primary-bg px-6 py-3 font-semibold text-action-primary-text transition-opacity hover:opacity-90\"\n >\n <ShoppingBag className=\"h-5 w-5\" />\n {t('pages.cart.browseMarketplace', { defaultValue: 'Browse Marketplace' })}\n </button>\n </div>\n ) : (\n // Cart with Items\n <div className=\"mx-auto max-w-3xl\">\n {/* Cart Items */}\n <div>\n {/* Cart Actions */}\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.cart.cartItems', {\n defaultValue: `Cart Items (${itemCount})`,\n count: itemCount,\n })}\n </h2>\n <button\n onClick={clearCart}\n className=\"cursor-pointer flex items-center gap-1 text-sm text-text-muted transition-colors hover:text-status-error-text\"\n >\n <Trash2 className=\"h-4 w-4\" />\n {t('cart.clearCart', { defaultValue: 'Clear Cart' })}\n </button>\n </div>\n\n {/* Items List */}\n <ul className=\"space-y-4\">\n {cartItems.map((item) => (\n <li\n key={item.id}\n className=\"flex gap-4 rounded-xl border border-border-default bg-bg-surface p-4 transition-shadow hover:shadow-md\"\n >\n {/* Product Image */}\n <div className=\"h-24 w-24 flex-shrink-0 overflow-hidden rounded-lg bg-bg-sunken\">\n {item.product?.iconUrl ? (\n <img\n src={item.product.iconUrl}\n alt={item.product.displayName}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center text-2xl font-bold text-text-muted\">\n {item.product?.displayName?.charAt(0) || 'P'}\n </div>\n )}\n </div>\n\n {/* Product Info */}\n <div className=\"flex flex-1 flex-col\">\n <div className=\"flex items-start justify-between\">\n <div>\n <h3 className=\"font-semibold text-text-primary\">\n {item.product?.displayName || 'Product'}\n </h3>\n <p className=\"text-sm text-text-muted\">\n {item.product?.publisher?.displayName || 'Unknown Publisher'}\n </p>\n {item.variant && (\n <p className=\"mt-1 text-xs text-text-muted\">\n Version {item.variant.version}\n </p>\n )}\n </div>\n <button\n onClick={() => removeProduct(item.id)}\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-status-error-bg-subtle/10 hover:text-status-error-text\"\n aria-label={`Remove ${item.product?.displayName ?? 'item'} from cart`}\n title=\"Remove item\"\n >\n <Trash2 className=\"h-5 w-5\" />\n </button>\n </div>\n\n {/* Item Type Badge */}\n <div className=\"mt-2 flex items-center gap-2\">\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-muted\">\n {item.itemType === 'digital' ? (\n <>\n <Zap className=\"h-3 w-3\" />\n {t('pages.cart.digital', { defaultValue: 'Digital' })}\n </>\n ) : (\n <>\n <Tag className=\"h-3 w-3\" />\n {t('pages.cart.physical', { defaultValue: 'Physical' })}\n </>\n )}\n </span>\n {item.product?.pricingModel === 'SUBSCRIPTION' && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-accent/10 px-2 py-0.5 text-xs font-medium text-text-link\">\n {t('store.pricingModels.subscription', {\n defaultValue: 'Subscription',\n })}\n </span>\n )}\n </div>\n\n {/* Quantity and Price Row */}\n <div className=\"mt-auto flex items-center justify-between pt-3\">\n {/* Quantity Controls - Only show for physical items */}\n {item.itemType === 'physical' ? (\n <div className=\"flex items-center gap-3\">\n <span className=\"text-sm text-text-muted\">Qty:</span>\n <div className=\"flex items-center rounded-lg border border-border-default\">\n <button\n onClick={() => updateQuantity(item.id, item.quantity - 1)}\n className=\"cursor-pointer rounded-l-lg p-2 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50\"\n disabled={item.quantity <= 1}\n >\n <Minus className=\"h-4 w-4\" />\n </button>\n <span className=\"min-w-[3rem] text-center font-medium\">\n {item.quantity}\n </span>\n <button\n onClick={() => updateQuantity(item.id, item.quantity + 1)}\n className=\"cursor-pointer rounded-r-lg p-2 transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ) : (\n <div className=\"text-sm text-text-muted\">\n {t('pages.cart.singleLicense', { defaultValue: 'Single license' })}\n </div>\n )}\n\n {/* Price */}\n <div className=\"text-right\">\n <p className=\"text-lg font-bold text-text-primary\">\n {formatPrice(item.totalPrice)}\n </p>\n {item.quantity > 1 && item.itemType === 'physical' && (\n <p className=\"text-xs text-text-muted\">\n {formatPrice(item.unitPrice)} each\n </p>\n )}\n </div>\n </div>\n </div>\n </li>\n ))}\n </ul>\n\n {/* Checkout Footer */}\n <div className=\"mt-8 rounded-xl border border-border-default bg-bg-surface p-5\">\n {checkoutError && (\n <div\n role=\"alert\"\n className=\"mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {checkoutError}\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm text-text-muted\">Total</p>\n <p className=\"text-2xl font-bold text-text-primary\">{formatPrice(total)}</p>\n </div>\n <button\n onClick={handleCheckout}\n disabled={isCheckingOut}\n className=\"flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-6 py-3 font-semibold text-action-primary-text transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-70\"\n >\n {isCheckingOut ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n {t('pages.cart.processing', { defaultValue: 'Processing...' })}\n </>\n ) : (\n <>\n <Zap className=\"h-4 w-4\" />\n {t('pages.cart.proceedToCheckout', { defaultValue: 'Proceed to Checkout' })}\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Continue Shopping */}\n <button\n onClick={handleContinueShopping}\n className=\"cursor-pointer mt-4 flex items-center gap-2 text-sm font-medium text-text-link hover:underline\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n {t('cart.continueShopping', { defaultValue: 'Continue Shopping' })}\n </button>\n </div>\n </div>\n )}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { FC } from 'react';
2
+
3
+ /**
4
+ * InstalledAppsPage component
5
+ *
6
+ * Displays installed applications for the current actor
7
+ */
8
+ export declare const InstalledAppsPage: FC;