@burdenoff/microfe-coolandlovely 2026.1031.1 → 2026.1101.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coolandlovely/CoolAndLovelyRoot.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoot.js +16 -4
- package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.js +46 -38
- package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
- package/dist/coolandlovely/components/ActivityTrail.js +1 -1
- package/dist/coolandlovely/components/ActivityTrail.js.map +1 -1
- package/dist/coolandlovely/components/ActorName.js.map +1 -1
- package/dist/coolandlovely/components/AddToCartPanel.js.map +1 -1
- package/dist/coolandlovely/components/AddToLookbookButton.js.map +1 -1
- package/dist/coolandlovely/components/BrandCard.js.map +1 -1
- package/dist/coolandlovely/components/BrandCover.js.map +1 -1
- package/dist/coolandlovely/components/BrandCreatorAvatars.js.map +1 -1
- package/dist/coolandlovely/components/CollaborationFeeCard.js.map +1 -1
- package/dist/coolandlovely/components/CollectionCard.js.map +1 -1
- package/dist/coolandlovely/components/ColourSwatchRow.js.map +1 -1
- package/dist/coolandlovely/components/Comments.js.map +1 -1
- package/dist/coolandlovely/components/EmptyState.js.map +1 -1
- package/dist/coolandlovely/components/FeedbackWidget.js.map +1 -1
- package/dist/coolandlovely/components/Field.d.ts +3 -1
- package/dist/coolandlovely/components/Field.d.ts.map +1 -1
- package/dist/coolandlovely/components/Field.js +5 -4
- package/dist/coolandlovely/components/Field.js.map +1 -1
- package/dist/coolandlovely/components/FileImage.js.map +1 -1
- package/dist/coolandlovely/components/FollowButton.js.map +1 -1
- package/dist/coolandlovely/components/FulfilmentTimeline.js.map +1 -1
- package/dist/coolandlovely/components/ImageUploadField.js +3 -1
- package/dist/coolandlovely/components/ImageUploadField.js.map +1 -1
- package/dist/coolandlovely/components/LookCard.js.map +1 -1
- package/dist/coolandlovely/components/LookbookCard.js.map +1 -1
- package/dist/coolandlovely/components/MetricsCard.js.map +1 -1
- package/dist/coolandlovely/components/PageLayout.js.map +1 -1
- package/dist/coolandlovely/components/PayForOrder.js.map +1 -1
- package/dist/coolandlovely/components/RefundPanel.js +1 -1
- package/dist/coolandlovely/components/RefundPanel.js.map +1 -1
- package/dist/coolandlovely/components/ReturnRequests.js +1 -1
- package/dist/coolandlovely/components/ReturnRequests.js.map +1 -1
- package/dist/coolandlovely/components/ShopItemCard.js.map +1 -1
- package/dist/coolandlovely/components/StateViews.js.map +1 -1
- package/dist/coolandlovely/components/StatusBadge.js +1 -1
- package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
- package/dist/coolandlovely/components/StepTracker.js.map +1 -1
- package/dist/coolandlovely/components/StockEditor.js.map +1 -1
- package/dist/coolandlovely/components/StoreListingCard.js.map +1 -1
- package/dist/coolandlovely/components/TagList.js.map +1 -1
- package/dist/coolandlovely/components/Thumbnail.js +1 -1
- package/dist/coolandlovely/components/Thumbnail.js.map +1 -1
- package/dist/coolandlovely/components/VisibilityChip.js.map +1 -1
- package/dist/coolandlovely/components/WardrobeItemCard.js.map +1 -1
- package/dist/coolandlovely/components/index.js +2 -1
- package/dist/coolandlovely/context/CoolAndLovelyContext.js +2 -1
- package/dist/coolandlovely/context/CoolAndLovelyContext.js.map +1 -1
- package/dist/coolandlovely/context/index.js +2 -1
- package/dist/coolandlovely/hooks/index.js +4 -3
- package/dist/coolandlovely/hooks/useActivity.d.ts +1 -1
- package/dist/coolandlovely/hooks/useActivity.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useActivity.js.map +1 -1
- package/dist/coolandlovely/hooks/useAssistantEntity.js.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts +4 -4
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCatalogImport.d.ts +25 -0
- package/dist/coolandlovely/hooks/useCatalogImport.d.ts.map +1 -0
- package/dist/coolandlovely/hooks/useCatalogImport.js +113 -0
- package/dist/coolandlovely/hooks/useCatalogImport.js.map +1 -0
- package/dist/coolandlovely/hooks/useComments.d.ts +1 -1
- package/dist/coolandlovely/hooks/useComments.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useComments.js.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts +7 -7
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts +24 -24
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useEditorialApi.d.ts +95 -0
- package/dist/coolandlovely/hooks/useEditorialApi.d.ts.map +1 -0
- package/dist/coolandlovely/hooks/useEditorialApi.js +107 -0
- package/dist/coolandlovely/hooks/useEditorialApi.js.map +1 -0
- package/dist/coolandlovely/hooks/useFiles.js +6 -3
- package/dist/coolandlovely/hooks/useFiles.js.map +1 -1
- package/dist/coolandlovely/hooks/useInventoryApi.d.ts +1 -1
- package/dist/coolandlovely/hooks/useInventoryApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useInventoryApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useTr.js.map +1 -1
- package/dist/coolandlovely/index.js +6 -5
- package/dist/coolandlovely/pages/HomePage.js.map +1 -1
- package/dist/coolandlovely/pages/admin/AdminBrandsPage.js.map +1 -1
- package/dist/coolandlovely/pages/admin/AdminCollaborationsPage.js.map +1 -1
- package/dist/coolandlovely/pages/admin/AdminFeaturedItemsPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandsListPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandsListPage.js +72 -60
- package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/ImportCatalogPage.d.ts +17 -0
- package/dist/coolandlovely/pages/brands/ImportCatalogPage.d.ts.map +1 -0
- package/dist/coolandlovely/pages/brands/ImportCatalogPage.js +417 -0
- package/dist/coolandlovely/pages/brands/ImportCatalogPage.js.map +1 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/CartPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.js.map +1 -1
- package/dist/coolandlovely/pages/discover/DiscoverPage.js +1 -1
- package/dist/coolandlovely/pages/discover/DiscoverPage.js.map +1 -1
- package/dist/coolandlovely/pages/editorial/EditorialPage.d.ts +2 -0
- package/dist/coolandlovely/pages/editorial/EditorialPage.d.ts.map +1 -0
- package/dist/coolandlovely/pages/editorial/EditorialPage.js +486 -0
- package/dist/coolandlovely/pages/editorial/EditorialPage.js.map +1 -0
- package/dist/coolandlovely/pages/items/StoreListedPieceView.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -1
- package/dist/coolandlovely/pages/trends/TrendsPage.js.map +1 -1
- package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -1
- package/dist/coolandlovely/store/coolandlovelyStore.js.map +1 -1
- package/dist/coolandlovely/store/index.js +2 -1
- package/dist/coolandlovely/types/commerce.d.ts.map +1 -1
- package/dist/coolandlovely/types/index.d.ts +80 -0
- package/dist/coolandlovely/types/index.d.ts.map +1 -1
- package/dist/coolandlovely/utils/cn.js +1 -1
- package/dist/coolandlovely/utils/cn.js.map +1 -1
- package/dist/coolandlovely/utils/formatters.js.map +1 -1
- package/dist/coolandlovely/utils/icons.js.map +1 -1
- package/dist/coolandlovely/utils/index.js +2 -1
- package/dist/coolandlovely/utils/navigation.js.map +1 -1
- package/dist/coolandlovely/utils/paymentProviders.js +22 -22
- package/dist/coolandlovely/utils/paymentProviders.js.map +1 -1
- package/dist/coolandlovely/utils/sparkline.js +13 -15
- package/dist/coolandlovely/utils/sparkline.js.map +1 -1
- package/dist/node_modules/clsx/dist/clsx.js +1 -1
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -1
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +225 -146
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -1
- package/dist/services/createSandboxAssistantTransport.js.map +1 -1
- package/dist/stories/DiscoverPage.stories.d.ts.map +1 -1
- package/dist/utils/pageContext.js +1 -1
- package/dist/utils/pageContext.js.map +1 -1
- package/package.json +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoolAndLovelyRoot.d.ts","sourceRoot":"","sources":["../../src/coolandlovely/CoolAndLovelyRoot.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA0BhC,OAAO,KAAK,EAAE,sBAAsB,EAAW,MAAM,SAAS,CAAC;AAY/D,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"CoolAndLovelyRoot.d.ts","sourceRoot":"","sources":["../../src/coolandlovely/CoolAndLovelyRoot.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA0BhC,OAAO,KAAK,EAAE,sBAAsB,EAAW,MAAM,SAAS,CAAC;AAY/D,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CAgOxD,CAAC"}
|
|
@@ -19,7 +19,8 @@ var D = new a({ defaultOptions: { queries: {
|
|
|
19
19
|
return n === e ? t : n;
|
|
20
20
|
}, [j]), N = E("coolandlovely.admin.curation", !1), P = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
|
|
21
21
|
return i(() => {
|
|
22
|
-
if (O) return
|
|
22
|
+
if (!O) return;
|
|
23
|
+
let e = [
|
|
23
24
|
{
|
|
24
25
|
id: "coolandlovely-overview",
|
|
25
26
|
label: M("coolandlovely.nav.overview", "Overview"),
|
|
@@ -132,6 +133,14 @@ var D = new a({ defaultOptions: { queries: {
|
|
|
132
133
|
order: 41,
|
|
133
134
|
group: "signals"
|
|
134
135
|
},
|
|
136
|
+
{
|
|
137
|
+
id: "coolandlovely-journal",
|
|
138
|
+
label: M("coolandlovely.nav.journal", "Journal"),
|
|
139
|
+
path: P(A, "journal"),
|
|
140
|
+
icon: /* @__PURE__ */ C(b, { size: 20 }),
|
|
141
|
+
order: 42,
|
|
142
|
+
group: "signals"
|
|
143
|
+
},
|
|
135
144
|
...N ? [
|
|
136
145
|
{
|
|
137
146
|
id: "coolandlovely-admin",
|
|
@@ -166,20 +175,23 @@ var D = new a({ defaultOptions: { queries: {
|
|
|
166
175
|
group: "admin"
|
|
167
176
|
}
|
|
168
177
|
] : []
|
|
169
|
-
]
|
|
178
|
+
];
|
|
179
|
+
return O(e);
|
|
170
180
|
}, [
|
|
171
181
|
O,
|
|
172
182
|
A,
|
|
173
183
|
M,
|
|
174
184
|
N
|
|
175
185
|
]), i(() => {
|
|
176
|
-
if (k) return
|
|
186
|
+
if (!k) return;
|
|
187
|
+
let e = [{
|
|
177
188
|
id: "coolandlovely-status",
|
|
178
189
|
label: M("coolandlovely.footer.ready", "CoolAndLovely"),
|
|
179
190
|
type: "status",
|
|
180
191
|
order: 10,
|
|
181
192
|
section: "left"
|
|
182
|
-
}]
|
|
193
|
+
}];
|
|
194
|
+
return k(e);
|
|
183
195
|
}, [k, M]), /* @__PURE__ */ C(o, {
|
|
184
196
|
client: D,
|
|
185
197
|
children: /* @__PURE__ */ C(T, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoolAndLovelyRoot.js","names":[],"sources":["../../src/coolandlovely/CoolAndLovelyRoot.tsx"],"sourcesContent":["/**\n * CoolAndLovely Root Component\n * @module coolandlovely\n *\n * Single Root export consumed by host application shells. The export name and\n * prop contract (basePath / navigate / currentUser / apiGatewayUrl /\n * registerNavItems / registerFooterItems / workspace context) are stable — the\n * host imports `CoolAndLovelyRoot` the same way regardless of the internal UI.\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Home,\n Store,\n Shapes,\n Shirt,\n Sparkles,\n Handshake,\n Heart,\n BookHeart,\n UserCircle,\n Compass,\n TrendingUp,\n Shield,\n ShoppingBag,\n Package,\n Wallet,\n} from 'lucide-react';\nimport { CoolAndLovelyProvider } from './context/CoolAndLovelyContext';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags/useFeatureFlag';\nimport { CoolAndLovelyRoutes } from './CoolAndLovelyRoutes';\nimport { FeedbackWidget } from './components';\nimport type { CoolAndLovelyRootProps, NavItem } from './types';\n\n// Create a query client for this microfrontend\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n },\n },\n});\n\nexport const CoolAndLovelyRoot: FC<CoolAndLovelyRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/' } = props;\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n const showAdmin = useFeatureFlag('coolandlovely.admin.curation', false);\n\n // Helper to join paths correctly\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with the shell on mount.\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'coolandlovely-overview',\n label: t('coolandlovely.nav.overview', 'Overview'),\n path: joinPath(basePath, ''),\n icon: <Home size={20} />,\n order: 1,\n group: 'main',\n },\n // Catalog\n {\n id: 'coolandlovely-brands',\n label: t('coolandlovely.nav.brands', 'Brands'),\n path: joinPath(basePath, 'brands'),\n icon: <Store size={20} />,\n order: 10,\n group: 'catalog',\n },\n {\n id: 'coolandlovely-collections',\n label: t('coolandlovely.nav.collections', 'Collections'),\n path: joinPath(basePath, 'collections'),\n icon: <Shapes size={20} />,\n order: 11,\n group: 'catalog',\n },\n {\n id: 'coolandlovely-items',\n label: t('coolandlovely.nav.items', 'Style Items'),\n path: joinPath(basePath, 'items'),\n icon: <Shirt size={20} />,\n order: 12,\n group: 'catalog',\n },\n // Social\n {\n id: 'coolandlovely-looks',\n label: t('coolandlovely.nav.looks', 'Looks'),\n path: joinPath(basePath, 'looks'),\n icon: <Sparkles size={20} />,\n order: 20,\n group: 'social',\n },\n {\n id: 'coolandlovely-collaborations',\n label: t('coolandlovely.nav.collaborations', 'Collaborations'),\n path: joinPath(basePath, 'collaborations'),\n icon: <Handshake size={20} />,\n order: 21,\n group: 'social',\n },\n // My style\n {\n id: 'coolandlovely-wardrobe',\n label: t('coolandlovely.nav.wardrobe', 'My Wardrobe'),\n path: joinPath(basePath, 'wardrobe'),\n icon: <Heart size={20} />,\n order: 30,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-lookbooks',\n label: t('coolandlovely.nav.lookbooks', 'Lookbooks'),\n path: joinPath(basePath, 'lookbooks'),\n icon: <BookHeart size={20} />,\n order: 31,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-profile',\n label: t('coolandlovely.nav.profile', 'Style Profile'),\n path: joinPath(basePath, 'profile'),\n icon: <UserCircle size={20} />,\n order: 32,\n group: 'my-style',\n },\n // Shopping (BOFF-3370)\n {\n id: 'coolandlovely-cart',\n label: t('coolandlovely.nav.cart', 'Cart'),\n path: joinPath(basePath, 'cart'),\n icon: <ShoppingBag size={20} />,\n order: 33,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-orders',\n label: t('coolandlovely.nav.orders', 'My Orders'),\n path: joinPath(basePath, 'orders'),\n icon: <Package size={20} />,\n order: 34,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-earnings',\n label: t('coolandlovely.nav.earnings', 'Creator Earnings'),\n path: joinPath(basePath, 'earnings'),\n icon: <Wallet size={20} />,\n order: 35,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-discover',\n label: t('coolandlovely.nav.discover', 'Discover'),\n path: joinPath(basePath, 'discover'),\n icon: <Compass size={20} />,\n order: 40,\n group: 'signals',\n },\n {\n id: 'coolandlovely-trends',\n label: t('coolandlovely.nav.trends', 'Trends'),\n path: joinPath(basePath, 'trends'),\n icon: <TrendingUp size={20} />,\n order: 41,\n group: 'signals',\n },\n // Admin curation (feature-flagged)\n ...(showAdmin\n ? [\n {\n id: 'coolandlovely-admin',\n label: t('coolandlovely.nav.admin', 'Admin'),\n path: joinPath(basePath, 'admin/brands'),\n icon: <Shield size={20} />,\n order: 50,\n group: 'admin',\n },\n {\n id: 'coolandlovely-admin-brands',\n label: t('coolandlovely.nav.adminBrands', 'Brands'),\n path: joinPath(basePath, 'admin/brands'),\n icon: <Store size={20} />,\n order: 51,\n group: 'admin',\n },\n {\n id: 'coolandlovely-admin-collaborations',\n label: t('coolandlovely.nav.adminCollaborations', 'Collaborations'),\n path: joinPath(basePath, 'admin/collaborations'),\n icon: <Handshake size={20} />,\n order: 52,\n group: 'admin',\n },\n {\n id: 'coolandlovely-admin-featured-items',\n label: t('coolandlovely.nav.adminFeaturedItems', 'Featured Items'),\n path: joinPath(basePath, 'admin/featured-items'),\n icon: <Shirt size={20} />,\n order: 53,\n group: 'admin',\n },\n ]\n : []),\n ];\n\n const cleanup = registerNavItems(navItems);\n return cleanup;\n }, [registerNavItems, basePath, t, showAdmin]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'coolandlovely-status',\n label: t('coolandlovely.footer.ready', 'CoolAndLovely'),\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, t]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider\n workspaceId={props.workspaceId ?? null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n <CoolAndLovelyProvider {...props}>\n <CoolAndLovelyRoutes />\n <FeedbackWidget />\n </CoolAndLovelyProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CoolAndLovelyRoot.js","names":[],"sources":["../../src/coolandlovely/CoolAndLovelyRoot.tsx"],"sourcesContent":["/**\n * CoolAndLovely Root Component\n * @module coolandlovely\n *\n * Single Root export consumed by host application shells. The export name and\n * prop contract (basePath / navigate / currentUser / apiGatewayUrl /\n * registerNavItems / registerFooterItems / workspace context) are stable — the\n * host imports `CoolAndLovelyRoot` the same way regardless of the internal UI.\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Home,\n Store,\n Shapes,\n Shirt,\n Sparkles,\n Handshake,\n Heart,\n BookHeart,\n UserCircle,\n Compass,\n TrendingUp,\n Shield,\n ShoppingBag,\n Package,\n Wallet,\n} from 'lucide-react';\nimport { CoolAndLovelyProvider } from './context/CoolAndLovelyContext';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags/useFeatureFlag';\nimport { CoolAndLovelyRoutes } from './CoolAndLovelyRoutes';\nimport { FeedbackWidget } from './components';\nimport type { CoolAndLovelyRootProps, NavItem } from './types';\n\n// Create a query client for this microfrontend\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n },\n },\n});\n\nexport const CoolAndLovelyRoot: FC<CoolAndLovelyRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/' } = props;\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n const showAdmin = useFeatureFlag('coolandlovely.admin.curation', false);\n\n // Helper to join paths correctly\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with the shell on mount.\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'coolandlovely-overview',\n label: t('coolandlovely.nav.overview', 'Overview'),\n path: joinPath(basePath, ''),\n icon: <Home size={20} />,\n order: 1,\n group: 'main',\n },\n // Catalog\n {\n id: 'coolandlovely-brands',\n label: t('coolandlovely.nav.brands', 'Brands'),\n path: joinPath(basePath, 'brands'),\n icon: <Store size={20} />,\n order: 10,\n group: 'catalog',\n },\n {\n id: 'coolandlovely-collections',\n label: t('coolandlovely.nav.collections', 'Collections'),\n path: joinPath(basePath, 'collections'),\n icon: <Shapes size={20} />,\n order: 11,\n group: 'catalog',\n },\n {\n id: 'coolandlovely-items',\n label: t('coolandlovely.nav.items', 'Style Items'),\n path: joinPath(basePath, 'items'),\n icon: <Shirt size={20} />,\n order: 12,\n group: 'catalog',\n },\n // Social\n {\n id: 'coolandlovely-looks',\n label: t('coolandlovely.nav.looks', 'Looks'),\n path: joinPath(basePath, 'looks'),\n icon: <Sparkles size={20} />,\n order: 20,\n group: 'social',\n },\n {\n id: 'coolandlovely-collaborations',\n label: t('coolandlovely.nav.collaborations', 'Collaborations'),\n path: joinPath(basePath, 'collaborations'),\n icon: <Handshake size={20} />,\n order: 21,\n group: 'social',\n },\n // My style\n {\n id: 'coolandlovely-wardrobe',\n label: t('coolandlovely.nav.wardrobe', 'My Wardrobe'),\n path: joinPath(basePath, 'wardrobe'),\n icon: <Heart size={20} />,\n order: 30,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-lookbooks',\n label: t('coolandlovely.nav.lookbooks', 'Lookbooks'),\n path: joinPath(basePath, 'lookbooks'),\n icon: <BookHeart size={20} />,\n order: 31,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-profile',\n label: t('coolandlovely.nav.profile', 'Style Profile'),\n path: joinPath(basePath, 'profile'),\n icon: <UserCircle size={20} />,\n order: 32,\n group: 'my-style',\n },\n // Shopping (BOFF-3370)\n {\n id: 'coolandlovely-cart',\n label: t('coolandlovely.nav.cart', 'Cart'),\n path: joinPath(basePath, 'cart'),\n icon: <ShoppingBag size={20} />,\n order: 33,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-orders',\n label: t('coolandlovely.nav.orders', 'My Orders'),\n path: joinPath(basePath, 'orders'),\n icon: <Package size={20} />,\n order: 34,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-earnings',\n label: t('coolandlovely.nav.earnings', 'Creator Earnings'),\n path: joinPath(basePath, 'earnings'),\n icon: <Wallet size={20} />,\n order: 35,\n group: 'my-style',\n },\n {\n id: 'coolandlovely-discover',\n label: t('coolandlovely.nav.discover', 'Discover'),\n path: joinPath(basePath, 'discover'),\n icon: <Compass size={20} />,\n order: 40,\n group: 'signals',\n },\n {\n id: 'coolandlovely-trends',\n label: t('coolandlovely.nav.trends', 'Trends'),\n path: joinPath(basePath, 'trends'),\n icon: <TrendingUp size={20} />,\n order: 41,\n group: 'signals',\n },\n // Admin curation (feature-flagged)\n {\n id: 'coolandlovely-journal',\n label: t('coolandlovely.nav.journal', 'Journal'),\n path: joinPath(basePath, 'journal'),\n icon: <TrendingUp size={20} />,\n order: 42,\n group: 'signals',\n },\n // Admin curation (feature-flagged)\n ...(showAdmin\n ? [\n {\n id: 'coolandlovely-admin',\n label: t('coolandlovely.nav.admin', 'Admin'),\n path: joinPath(basePath, 'admin/brands'),\n icon: <Shield size={20} />,\n order: 50,\n group: 'admin',\n },\n {\n id: 'coolandlovely-admin-brands',\n label: t('coolandlovely.nav.adminBrands', 'Brands'),\n path: joinPath(basePath, 'admin/brands'),\n icon: <Store size={20} />,\n order: 51,\n group: 'admin',\n },\n {\n id: 'coolandlovely-admin-collaborations',\n label: t('coolandlovely.nav.adminCollaborations', 'Collaborations'),\n path: joinPath(basePath, 'admin/collaborations'),\n icon: <Handshake size={20} />,\n order: 52,\n group: 'admin',\n },\n {\n id: 'coolandlovely-admin-featured-items',\n label: t('coolandlovely.nav.adminFeaturedItems', 'Featured Items'),\n path: joinPath(basePath, 'admin/featured-items'),\n icon: <Shirt size={20} />,\n order: 53,\n group: 'admin',\n },\n ]\n : []),\n ];\n\n const cleanup = registerNavItems(navItems);\n return cleanup;\n }, [registerNavItems, basePath, t, showAdmin]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'coolandlovely-status',\n label: t('coolandlovely.footer.ready', 'CoolAndLovely'),\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, t]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider\n workspaceId={props.workspaceId ?? null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n <CoolAndLovelyProvider {...props}>\n <CoolAndLovelyRoutes />\n <FeedbackWidget />\n </CoolAndLovelyProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoolAndLovelyRoutes.d.ts","sourceRoot":"","sources":["../../src/coolandlovely/CoolAndLovelyRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAkB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"CoolAndLovelyRoutes.d.ts","sourceRoot":"","sources":["../../src/coolandlovely/CoolAndLovelyRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAkB,MAAM,OAAO,CAAC;AAoJhD,eAAO,MAAM,mBAAmB,EAAE,EA+FjC,CAAC"}
|
|
@@ -4,15 +4,15 @@ import { Suspense as n, lazy as r } from "react";
|
|
|
4
4
|
import { Navigate as i, Route as a, Routes as o, useLocation as s } from "react-router";
|
|
5
5
|
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
6
|
//#region src/coolandlovely/CoolAndLovelyRoutes.tsx
|
|
7
|
-
var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ default: e.BrandsListPage }))), d = r(() => import("./pages/brands/BrandDetailPage.js").then((e) => ({ default: e.BrandDetailPage }))), f = r(() => import("./pages/brands/BrandFormPage.js").then((e) => ({ default: e.BrandFormPage }))), p = r(() => import("./pages/collections/CollectionsListPage.js").then((e) => ({ default: e.CollectionsListPage }))),
|
|
7
|
+
var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ default: e.BrandsListPage }))), d = r(() => import("./pages/brands/BrandDetailPage.js").then((e) => ({ default: e.BrandDetailPage }))), f = r(() => import("./pages/brands/BrandFormPage.js").then((e) => ({ default: e.BrandFormPage }))), p = r(() => import("./pages/brands/ImportCatalogPage.js").then((e) => ({ default: e.ImportCatalogPage }))), m = r(() => import("./pages/collections/CollectionsListPage.js").then((e) => ({ default: e.CollectionsListPage }))), h = r(() => import("./pages/collections/CollectionDetailPage.js").then((e) => ({ default: e.CollectionDetailPage }))), g = r(() => import("./pages/collections/CollectionFormPage.js").then((e) => ({ default: e.CollectionFormPage }))), _ = r(() => import("./pages/items/StyleItemsListPage.js").then((e) => ({ default: e.StyleItemsListPage }))), v = r(() => import("./pages/items/StyleItemDetailPage.js").then((e) => ({ default: e.StyleItemDetailPage }))), y = r(() => import("./pages/items/StyleItemFormPage.js").then((e) => ({ default: e.StyleItemFormPage }))), b = r(() => import("./pages/looks/LooksListPage.js").then((e) => ({ default: e.LooksListPage }))), x = r(() => import("./pages/looks/LookDetailPage.js").then((e) => ({ default: e.LookDetailPage }))), S = r(() => import("./pages/looks/LookFormPage.js").then((e) => ({ default: e.LookFormPage }))), C = r(() => import("./pages/collaborations/CollaborationsListPage.js").then((e) => ({ default: e.CollaborationsListPage }))), w = r(() => import("./pages/collaborations/CollaborationDetailPage.js").then((e) => ({ default: e.CollaborationDetailPage }))), T = r(() => import("./pages/collaborations/CollaborationFormPage.js").then((e) => ({ default: e.CollaborationFormPage }))), E = r(() => import("./pages/wardrobe/WardrobeListPage.js").then((e) => ({ default: e.WardrobeListPage }))), D = r(() => import("./pages/wardrobe/WardrobeFormPage.js").then((e) => ({ default: e.WardrobeFormPage }))), O = r(() => import("./pages/lookbooks/LookbooksListPage.js").then((e) => ({ default: e.LookbooksListPage }))), k = r(() => import("./pages/lookbooks/LookbookDetailPage.js").then((e) => ({ default: e.LookbookDetailPage }))), A = r(() => import("./pages/profile/StyleProfilePage.js").then((e) => ({ default: e.StyleProfilePage }))), j = r(() => import("./pages/discover/DiscoverPage.js").then((e) => ({ default: e.DiscoverPage }))), M = r(() => import("./pages/trends/TrendsPage.js").then((e) => ({ default: e.TrendsPage }))), N = r(() => import("./pages/editorial/EditorialPage.js").then((e) => ({ default: e.EditorialPage }))), P = r(() => import("./pages/commerce/CartPage.js").then((e) => ({ default: e.CartPage }))), F = r(() => import("./pages/commerce/BrandOrdersPage.js").then((e) => ({ default: e.BrandOrdersPage }))), I = r(() => import("./pages/commerce/BrandOrdersPage.js").then((e) => ({ default: e.BrandOrderDetailPage }))), L = r(() => import("./pages/commerce/OrdersPage.js").then((e) => ({ default: e.OrdersPage }))), R = r(() => import("./pages/commerce/OrdersPage.js").then((e) => ({ default: e.OrderDetailPage }))), z = r(() => import("./pages/commerce/CreatorEarningsPage.js").then((e) => ({ default: e.CreatorEarningsPage }))), B = r(() => import("./pages/admin/AdminBrandsPage.js").then((e) => ({ default: e.AdminBrandsPage }))), V = r(() => import("./pages/admin/AdminCollaborationsPage.js").then((e) => ({ default: e.AdminCollaborationsPage }))), H = r(() => import("./pages/admin/AdminFeaturedItemsPage.js").then((e) => ({ default: e.AdminFeaturedItemsPage }))), U = () => /* @__PURE__ */ c("div", {
|
|
8
8
|
className: "flex min-h-[400px] items-center justify-center",
|
|
9
9
|
children: /* @__PURE__ */ c("div", { className: "h-8 w-8 animate-spin rounded-full border-b-2 border-primary" })
|
|
10
|
-
}),
|
|
11
|
-
let { basePath: r, isStandalone:
|
|
12
|
-
return
|
|
10
|
+
}), W = () => {
|
|
11
|
+
let { basePath: r, isStandalone: W, workspaceId: G, currentUser: K } = e(), q = s(), J = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
|
|
12
|
+
return J && !W && !(q.pathname === J || q.pathname.startsWith(J + "/")) ? null : /* @__PURE__ */ c("div", {
|
|
13
13
|
className: "flex min-h-full flex-col",
|
|
14
14
|
children: /* @__PURE__ */ c(n, {
|
|
15
|
-
fallback: /* @__PURE__ */ c(
|
|
15
|
+
fallback: /* @__PURE__ */ c(U, {}),
|
|
16
16
|
children: /* @__PURE__ */ l(o, { children: [
|
|
17
17
|
/* @__PURE__ */ c(a, {
|
|
18
18
|
index: !0,
|
|
@@ -26,6 +26,10 @@ var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ defaul
|
|
|
26
26
|
path: "brands/new",
|
|
27
27
|
element: /* @__PURE__ */ c(f, {})
|
|
28
28
|
}),
|
|
29
|
+
/* @__PURE__ */ c(a, {
|
|
30
|
+
path: "brands/import",
|
|
31
|
+
element: /* @__PURE__ */ c(p, {})
|
|
32
|
+
}),
|
|
29
33
|
/* @__PURE__ */ c(a, {
|
|
30
34
|
path: "brands/:brandId",
|
|
31
35
|
element: /* @__PURE__ */ c(d, {})
|
|
@@ -36,119 +40,123 @@ var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ defaul
|
|
|
36
40
|
}),
|
|
37
41
|
/* @__PURE__ */ c(a, {
|
|
38
42
|
path: "collections",
|
|
39
|
-
element: /* @__PURE__ */ c(
|
|
43
|
+
element: /* @__PURE__ */ c(m, {})
|
|
40
44
|
}),
|
|
41
45
|
/* @__PURE__ */ c(a, {
|
|
42
46
|
path: "collections/new",
|
|
43
|
-
element: /* @__PURE__ */ c(
|
|
47
|
+
element: /* @__PURE__ */ c(g, {})
|
|
44
48
|
}),
|
|
45
49
|
/* @__PURE__ */ c(a, {
|
|
46
50
|
path: "collections/:collectionId",
|
|
47
|
-
element: /* @__PURE__ */ c(
|
|
51
|
+
element: /* @__PURE__ */ c(h, {})
|
|
48
52
|
}),
|
|
49
53
|
/* @__PURE__ */ c(a, {
|
|
50
54
|
path: "collections/:collectionId/edit",
|
|
51
|
-
element: /* @__PURE__ */ c(
|
|
55
|
+
element: /* @__PURE__ */ c(g, {})
|
|
52
56
|
}),
|
|
53
57
|
/* @__PURE__ */ c(a, {
|
|
54
58
|
path: "items",
|
|
55
|
-
element: /* @__PURE__ */ c(
|
|
59
|
+
element: /* @__PURE__ */ c(_, {})
|
|
56
60
|
}),
|
|
57
61
|
/* @__PURE__ */ c(a, {
|
|
58
62
|
path: "items/new",
|
|
59
|
-
element: /* @__PURE__ */ c(
|
|
63
|
+
element: /* @__PURE__ */ c(y, {})
|
|
60
64
|
}),
|
|
61
65
|
/* @__PURE__ */ c(a, {
|
|
62
66
|
path: "items/:itemId",
|
|
63
|
-
element: /* @__PURE__ */ c(
|
|
67
|
+
element: /* @__PURE__ */ c(v, {})
|
|
64
68
|
}),
|
|
65
69
|
/* @__PURE__ */ c(a, {
|
|
66
70
|
path: "items/:itemId/edit",
|
|
67
|
-
element: /* @__PURE__ */ c(
|
|
71
|
+
element: /* @__PURE__ */ c(y, {})
|
|
68
72
|
}),
|
|
69
73
|
/* @__PURE__ */ c(a, {
|
|
70
74
|
path: "looks",
|
|
71
|
-
element: /* @__PURE__ */ c(
|
|
75
|
+
element: /* @__PURE__ */ c(b, {})
|
|
72
76
|
}),
|
|
73
77
|
/* @__PURE__ */ c(a, {
|
|
74
78
|
path: "looks/new",
|
|
75
|
-
element: /* @__PURE__ */ c(
|
|
79
|
+
element: /* @__PURE__ */ c(S, {})
|
|
76
80
|
}),
|
|
77
81
|
/* @__PURE__ */ c(a, {
|
|
78
82
|
path: "looks/:lookId",
|
|
79
|
-
element: /* @__PURE__ */ c(
|
|
83
|
+
element: /* @__PURE__ */ c(x, {})
|
|
80
84
|
}),
|
|
81
85
|
/* @__PURE__ */ c(a, {
|
|
82
86
|
path: "collaborations",
|
|
83
|
-
element: /* @__PURE__ */ c(
|
|
87
|
+
element: /* @__PURE__ */ c(C, {})
|
|
84
88
|
}),
|
|
85
89
|
/* @__PURE__ */ c(a, {
|
|
86
90
|
path: "collaborations/new",
|
|
87
|
-
element: /* @__PURE__ */ c(
|
|
91
|
+
element: /* @__PURE__ */ c(T, {})
|
|
88
92
|
}),
|
|
89
93
|
/* @__PURE__ */ c(a, {
|
|
90
94
|
path: "collaborations/:collaborationId",
|
|
91
|
-
element: /* @__PURE__ */ c(
|
|
95
|
+
element: /* @__PURE__ */ c(w, {})
|
|
92
96
|
}),
|
|
93
97
|
/* @__PURE__ */ c(a, {
|
|
94
98
|
path: "collaborations/:collaborationId/edit",
|
|
95
|
-
element: /* @__PURE__ */ c(
|
|
99
|
+
element: /* @__PURE__ */ c(T, {})
|
|
96
100
|
}),
|
|
97
101
|
/* @__PURE__ */ c(a, {
|
|
98
102
|
path: "wardrobe",
|
|
99
|
-
element: /* @__PURE__ */ c(
|
|
103
|
+
element: /* @__PURE__ */ c(E, {})
|
|
100
104
|
}),
|
|
101
105
|
/* @__PURE__ */ c(a, {
|
|
102
106
|
path: "wardrobe/new",
|
|
103
|
-
element: /* @__PURE__ */ c(
|
|
107
|
+
element: /* @__PURE__ */ c(D, {})
|
|
104
108
|
}),
|
|
105
109
|
/* @__PURE__ */ c(a, {
|
|
106
110
|
path: "lookbooks",
|
|
107
|
-
element: /* @__PURE__ */ c(
|
|
111
|
+
element: /* @__PURE__ */ c(O, {})
|
|
108
112
|
}),
|
|
109
113
|
/* @__PURE__ */ c(a, {
|
|
110
114
|
path: "lookbooks/:lookbookId",
|
|
111
|
-
element: /* @__PURE__ */ c(
|
|
115
|
+
element: /* @__PURE__ */ c(k, {})
|
|
112
116
|
}),
|
|
113
117
|
/* @__PURE__ */ c(a, {
|
|
114
118
|
path: "profile",
|
|
115
|
-
element: /* @__PURE__ */ c(
|
|
119
|
+
element: /* @__PURE__ */ c(A, {})
|
|
116
120
|
}),
|
|
117
121
|
/* @__PURE__ */ c(a, {
|
|
118
122
|
path: "profile/:userId",
|
|
119
|
-
element: /* @__PURE__ */ c(
|
|
123
|
+
element: /* @__PURE__ */ c(A, {})
|
|
120
124
|
}),
|
|
121
125
|
/* @__PURE__ */ c(a, {
|
|
122
126
|
path: "discover",
|
|
123
|
-
element: /* @__PURE__ */ c(
|
|
127
|
+
element: /* @__PURE__ */ c(j, {})
|
|
124
128
|
}),
|
|
125
129
|
/* @__PURE__ */ c(a, {
|
|
126
130
|
path: "trends",
|
|
127
|
-
element: /* @__PURE__ */ c(
|
|
131
|
+
element: /* @__PURE__ */ c(M, {})
|
|
132
|
+
}),
|
|
133
|
+
/* @__PURE__ */ c(a, {
|
|
134
|
+
path: "journal",
|
|
135
|
+
element: /* @__PURE__ */ c(N, {}, `${G ?? ""}:${K?.id ?? ""}`)
|
|
128
136
|
}),
|
|
129
137
|
/* @__PURE__ */ c(a, {
|
|
130
138
|
path: "cart",
|
|
131
|
-
element: /* @__PURE__ */ c(
|
|
139
|
+
element: /* @__PURE__ */ c(P, {})
|
|
132
140
|
}),
|
|
133
141
|
/* @__PURE__ */ c(a, {
|
|
134
142
|
path: "orders",
|
|
135
|
-
element: /* @__PURE__ */ c(
|
|
143
|
+
element: /* @__PURE__ */ c(L, {})
|
|
136
144
|
}),
|
|
137
145
|
/* @__PURE__ */ c(a, {
|
|
138
146
|
path: "orders/:orderId",
|
|
139
|
-
element: /* @__PURE__ */ c(
|
|
147
|
+
element: /* @__PURE__ */ c(R, {})
|
|
140
148
|
}),
|
|
141
149
|
/* @__PURE__ */ c(a, {
|
|
142
150
|
path: "earnings",
|
|
143
|
-
element: /* @__PURE__ */ c(
|
|
151
|
+
element: /* @__PURE__ */ c(z, {})
|
|
144
152
|
}),
|
|
145
153
|
/* @__PURE__ */ c(a, {
|
|
146
154
|
path: "brand-orders",
|
|
147
|
-
element: /* @__PURE__ */ c(
|
|
155
|
+
element: /* @__PURE__ */ c(F, {})
|
|
148
156
|
}),
|
|
149
157
|
/* @__PURE__ */ c(a, {
|
|
150
158
|
path: "brand-orders/:brandId/:orderId",
|
|
151
|
-
element: /* @__PURE__ */ c(
|
|
159
|
+
element: /* @__PURE__ */ c(I, {})
|
|
152
160
|
}),
|
|
153
161
|
/* @__PURE__ */ c(a, {
|
|
154
162
|
path: "admin",
|
|
@@ -159,15 +167,15 @@ var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ defaul
|
|
|
159
167
|
}),
|
|
160
168
|
/* @__PURE__ */ c(a, {
|
|
161
169
|
path: "admin/brands",
|
|
162
|
-
element: /* @__PURE__ */ c(
|
|
170
|
+
element: /* @__PURE__ */ c(B, {})
|
|
163
171
|
}),
|
|
164
172
|
/* @__PURE__ */ c(a, {
|
|
165
173
|
path: "admin/collaborations",
|
|
166
|
-
element: /* @__PURE__ */ c(
|
|
174
|
+
element: /* @__PURE__ */ c(V, {})
|
|
167
175
|
}),
|
|
168
176
|
/* @__PURE__ */ c(a, {
|
|
169
177
|
path: "admin/featured-items",
|
|
170
|
-
element: /* @__PURE__ */ c(
|
|
178
|
+
element: /* @__PURE__ */ c(H, {})
|
|
171
179
|
}),
|
|
172
180
|
/* @__PURE__ */ c(a, {
|
|
173
181
|
path: "*",
|
|
@@ -181,6 +189,6 @@ var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ defaul
|
|
|
181
189
|
});
|
|
182
190
|
};
|
|
183
191
|
//#endregion
|
|
184
|
-
export {
|
|
192
|
+
export { W as CoolAndLovelyRoutes };
|
|
185
193
|
|
|
186
194
|
//# sourceMappingURL=CoolAndLovelyRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoolAndLovelyRoutes.js","names":[],"sources":["../../src/coolandlovely/CoolAndLovelyRoutes.tsx"],"sourcesContent":["/**\n * CoolAndLovely Routes\n * @module coolandlovely\n *\n * Real fashion-domain routes wired to the live `wspace-coolandlovely-svc`\n * GraphQL contract: overview, brands, collections, style items, looks,\n * collaborations, wardrobe, lookbooks and the shopper's style profile.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { useCoolAndLovely } from './context/CoolAndLovelyContext';\n\n// Eager-loaded overview (primary landing page)\nimport { HomePage } from './pages/HomePage';\n\n// Brands\nconst BrandsListPage = lazy(() =>\n import('./pages/brands/BrandsListPage').then((m) => ({ default: m.BrandsListPage }))\n);\nconst BrandDetailPage = lazy(() =>\n import('./pages/brands/BrandDetailPage').then((m) => ({ default: m.BrandDetailPage }))\n);\nconst BrandFormPage = lazy(() =>\n import('./pages/brands/BrandFormPage').then((m) => ({ default: m.BrandFormPage }))\n);\n\n// Collections\nconst CollectionsListPage = lazy(() =>\n import('./pages/collections/CollectionsListPage').then((m) => ({\n default: m.CollectionsListPage,\n }))\n);\nconst CollectionDetailPage = lazy(() =>\n import('./pages/collections/CollectionDetailPage').then((m) => ({\n default: m.CollectionDetailPage,\n }))\n);\nconst CollectionFormPage = lazy(() =>\n import('./pages/collections/CollectionFormPage').then((m) => ({ default: m.CollectionFormPage }))\n);\n\n// Style items\nconst StyleItemsListPage = lazy(() =>\n import('./pages/items/StyleItemsListPage').then((m) => ({ default: m.StyleItemsListPage }))\n);\nconst StyleItemDetailPage = lazy(() =>\n import('./pages/items/StyleItemDetailPage').then((m) => ({ default: m.StyleItemDetailPage }))\n);\nconst StyleItemFormPage = lazy(() =>\n import('./pages/items/StyleItemFormPage').then((m) => ({ default: m.StyleItemFormPage }))\n);\n\n// Looks\nconst LooksListPage = lazy(() =>\n import('./pages/looks/LooksListPage').then((m) => ({ default: m.LooksListPage }))\n);\nconst LookDetailPage = lazy(() =>\n import('./pages/looks/LookDetailPage').then((m) => ({ default: m.LookDetailPage }))\n);\nconst LookFormPage = lazy(() =>\n import('./pages/looks/LookFormPage').then((m) => ({ default: m.LookFormPage }))\n);\n\n// Collaborations\nconst CollaborationsListPage = lazy(() =>\n import('./pages/collaborations/CollaborationsListPage').then((m) => ({\n default: m.CollaborationsListPage,\n }))\n);\nconst CollaborationDetailPage = lazy(() =>\n import('./pages/collaborations/CollaborationDetailPage').then((m) => ({\n default: m.CollaborationDetailPage,\n }))\n);\nconst CollaborationFormPage = lazy(() =>\n import('./pages/collaborations/CollaborationFormPage').then((m) => ({\n default: m.CollaborationFormPage,\n }))\n);\n\n// Wardrobe (self-scoped)\nconst WardrobeListPage = lazy(() =>\n import('./pages/wardrobe/WardrobeListPage').then((m) => ({ default: m.WardrobeListPage }))\n);\nconst WardrobeFormPage = lazy(() =>\n import('./pages/wardrobe/WardrobeFormPage').then((m) => ({ default: m.WardrobeFormPage }))\n);\n\n// Lookbooks\nconst LookbooksListPage = lazy(() =>\n import('./pages/lookbooks/LookbooksListPage').then((m) => ({ default: m.LookbooksListPage }))\n);\nconst LookbookDetailPage = lazy(() =>\n import('./pages/lookbooks/LookbookDetailPage').then((m) => ({ default: m.LookbookDetailPage }))\n);\n\n// Style profile (self-scoped)\nconst StyleProfilePage = lazy(() =>\n import('./pages/profile/StyleProfilePage').then((m) => ({ default: m.StyleProfilePage }))\n);\n\n// Discovery + trends (client-side analytics over the real catalogue/social lists)\nconst DiscoverPage = lazy(() =>\n import('./pages/discover/DiscoverPage').then((m) => ({ default: m.DiscoverPage }))\n);\nconst TrendsPage = lazy(() =>\n import('./pages/trends/TrendsPage').then((m) => ({ default: m.TrendsPage }))\n);\n\n// Commerce (BOFF-3370): cart, orders, creator earnings\nconst CartPage = lazy(() =>\n import('./pages/commerce/CartPage').then((m) => ({ default: m.CartPage }))\n);\nconst BrandOrdersPage = lazy(() =>\n import('./pages/commerce/BrandOrdersPage').then((m) => ({ default: m.BrandOrdersPage }))\n);\nconst BrandOrderDetailPage = lazy(() =>\n import('./pages/commerce/BrandOrdersPage').then((m) => ({ default: m.BrandOrderDetailPage }))\n);\nconst OrdersPage = lazy(() =>\n import('./pages/commerce/OrdersPage').then((m) => ({ default: m.OrdersPage }))\n);\nconst OrderDetailPage = lazy(() =>\n import('./pages/commerce/OrdersPage').then((m) => ({ default: m.OrderDetailPage }))\n);\nconst CreatorEarningsPage = lazy(() =>\n import('./pages/commerce/CreatorEarningsPage').then((m) => ({ default: m.CreatorEarningsPage }))\n);\n\n// Admin curation (gated by the `coolandlovely.admin.curation` feature flag)\nconst AdminBrandsPage = lazy(() =>\n import('./pages/admin/AdminBrandsPage').then((m) => ({ default: m.AdminBrandsPage }))\n);\nconst AdminCollaborationsPage = lazy(() =>\n import('./pages/admin/AdminCollaborationsPage').then((m) => ({\n default: m.AdminCollaborationsPage,\n }))\n);\nconst AdminFeaturedItemsPage = lazy(() =>\n import('./pages/admin/AdminFeaturedItemsPage').then((m) => ({\n default: m.AdminFeaturedItemsPage,\n }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-b-2 border-primary\" />\n </div>\n);\n\nexport const CoolAndLovelyRoutes: FC = () => {\n const { basePath, isStandalone } = useCoolAndLovely();\n const location = useLocation();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the path matches the basePath (when integrated).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Overview */}\n <Route index element={<HomePage />} />\n\n {/* Brands */}\n <Route path=\"brands\" element={<BrandsListPage />} />\n <Route path=\"brands/new\" element={<BrandFormPage />} />\n <Route path=\"brands/:brandId\" element={<BrandDetailPage />} />\n <Route path=\"brands/:brandId/edit\" element={<BrandFormPage />} />\n\n {/* Collections */}\n <Route path=\"collections\" element={<CollectionsListPage />} />\n <Route path=\"collections/new\" element={<CollectionFormPage />} />\n <Route path=\"collections/:collectionId\" element={<CollectionDetailPage />} />\n <Route path=\"collections/:collectionId/edit\" element={<CollectionFormPage />} />\n\n {/* Style items */}\n <Route path=\"items\" element={<StyleItemsListPage />} />\n <Route path=\"items/new\" element={<StyleItemFormPage />} />\n <Route path=\"items/:itemId\" element={<StyleItemDetailPage />} />\n <Route path=\"items/:itemId/edit\" element={<StyleItemFormPage />} />\n\n {/* Looks */}\n <Route path=\"looks\" element={<LooksListPage />} />\n <Route path=\"looks/new\" element={<LookFormPage />} />\n <Route path=\"looks/:lookId\" element={<LookDetailPage />} />\n\n {/* Collaborations */}\n <Route path=\"collaborations\" element={<CollaborationsListPage />} />\n <Route path=\"collaborations/new\" element={<CollaborationFormPage />} />\n <Route path=\"collaborations/:collaborationId\" element={<CollaborationDetailPage />} />\n <Route path=\"collaborations/:collaborationId/edit\" element={<CollaborationFormPage />} />\n\n {/* Wardrobe (self-scoped) */}\n <Route path=\"wardrobe\" element={<WardrobeListPage />} />\n <Route path=\"wardrobe/new\" element={<WardrobeFormPage />} />\n\n {/* Lookbooks */}\n <Route path=\"lookbooks\" element={<LookbooksListPage />} />\n <Route path=\"lookbooks/:lookbookId\" element={<LookbookDetailPage />} />\n\n {/* Style profile (self-scoped) + public profiles */}\n <Route path=\"profile\" element={<StyleProfilePage />} />\n <Route path=\"profile/:userId\" element={<StyleProfilePage />} />\n\n {/* Discovery + trends */}\n <Route path=\"discover\" element={<DiscoverPage />} />\n <Route path=\"trends\" element={<TrendsPage />} />\n\n {/* Commerce */}\n <Route path=\"cart\" element={<CartPage />} />\n <Route path=\"orders\" element={<OrdersPage />} />\n <Route path=\"orders/:orderId\" element={<OrderDetailPage />} />\n <Route path=\"earnings\" element={<CreatorEarningsPage />} />\n\n {/* Brand-side orders and fulfilment (BOFF-9636) */}\n <Route path=\"brand-orders\" element={<BrandOrdersPage />} />\n <Route path=\"brand-orders/:brandId/:orderId\" element={<BrandOrderDetailPage />} />\n\n {/* Admin curation */}\n <Route path=\"admin\" element={<Navigate to=\"admin/brands\" replace />} />\n <Route path=\"admin/brands\" element={<AdminBrandsPage />} />\n <Route path=\"admin/collaborations\" element={<AdminCollaborationsPage />} />\n <Route path=\"admin/featured-items\" element={<AdminFeaturedItemsPage />} />\n\n {/* Fallback */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CoolAndLovelyRoutes.js","names":[],"sources":["../../src/coolandlovely/CoolAndLovelyRoutes.tsx"],"sourcesContent":["/**\n * CoolAndLovely Routes\n * @module coolandlovely\n *\n * Real fashion-domain routes wired to the live `wspace-coolandlovely-svc`\n * GraphQL contract: overview, brands, collections, style items, looks,\n * collaborations, wardrobe, lookbooks and the shopper's style profile.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { useCoolAndLovely } from './context/CoolAndLovelyContext';\n\n// Eager-loaded overview (primary landing page)\nimport { HomePage } from './pages/HomePage';\n\n// Brands\nconst BrandsListPage = lazy(() =>\n import('./pages/brands/BrandsListPage').then((m) => ({ default: m.BrandsListPage }))\n);\nconst BrandDetailPage = lazy(() =>\n import('./pages/brands/BrandDetailPage').then((m) => ({ default: m.BrandDetailPage }))\n);\nconst BrandFormPage = lazy(() =>\n import('./pages/brands/BrandFormPage').then((m) => ({ default: m.BrandFormPage }))\n);\nconst ImportCatalogPage = lazy(() =>\n import('./pages/brands/ImportCatalogPage').then((m) => ({ default: m.ImportCatalogPage }))\n);\n\n// Collections\nconst CollectionsListPage = lazy(() =>\n import('./pages/collections/CollectionsListPage').then((m) => ({\n default: m.CollectionsListPage,\n }))\n);\nconst CollectionDetailPage = lazy(() =>\n import('./pages/collections/CollectionDetailPage').then((m) => ({\n default: m.CollectionDetailPage,\n }))\n);\nconst CollectionFormPage = lazy(() =>\n import('./pages/collections/CollectionFormPage').then((m) => ({ default: m.CollectionFormPage }))\n);\n\n// Style items\nconst StyleItemsListPage = lazy(() =>\n import('./pages/items/StyleItemsListPage').then((m) => ({ default: m.StyleItemsListPage }))\n);\nconst StyleItemDetailPage = lazy(() =>\n import('./pages/items/StyleItemDetailPage').then((m) => ({ default: m.StyleItemDetailPage }))\n);\nconst StyleItemFormPage = lazy(() =>\n import('./pages/items/StyleItemFormPage').then((m) => ({ default: m.StyleItemFormPage }))\n);\n\n// Looks\nconst LooksListPage = lazy(() =>\n import('./pages/looks/LooksListPage').then((m) => ({ default: m.LooksListPage }))\n);\nconst LookDetailPage = lazy(() =>\n import('./pages/looks/LookDetailPage').then((m) => ({ default: m.LookDetailPage }))\n);\nconst LookFormPage = lazy(() =>\n import('./pages/looks/LookFormPage').then((m) => ({ default: m.LookFormPage }))\n);\n\n// Collaborations\nconst CollaborationsListPage = lazy(() =>\n import('./pages/collaborations/CollaborationsListPage').then((m) => ({\n default: m.CollaborationsListPage,\n }))\n);\nconst CollaborationDetailPage = lazy(() =>\n import('./pages/collaborations/CollaborationDetailPage').then((m) => ({\n default: m.CollaborationDetailPage,\n }))\n);\nconst CollaborationFormPage = lazy(() =>\n import('./pages/collaborations/CollaborationFormPage').then((m) => ({\n default: m.CollaborationFormPage,\n }))\n);\n\n// Wardrobe (self-scoped)\nconst WardrobeListPage = lazy(() =>\n import('./pages/wardrobe/WardrobeListPage').then((m) => ({ default: m.WardrobeListPage }))\n);\nconst WardrobeFormPage = lazy(() =>\n import('./pages/wardrobe/WardrobeFormPage').then((m) => ({ default: m.WardrobeFormPage }))\n);\n\n// Lookbooks\nconst LookbooksListPage = lazy(() =>\n import('./pages/lookbooks/LookbooksListPage').then((m) => ({ default: m.LookbooksListPage }))\n);\nconst LookbookDetailPage = lazy(() =>\n import('./pages/lookbooks/LookbookDetailPage').then((m) => ({ default: m.LookbookDetailPage }))\n);\n\n// Style profile (self-scoped)\nconst StyleProfilePage = lazy(() =>\n import('./pages/profile/StyleProfilePage').then((m) => ({ default: m.StyleProfilePage }))\n);\n\n// Discovery + trends (client-side analytics over the real catalogue/social lists)\nconst DiscoverPage = lazy(() =>\n import('./pages/discover/DiscoverPage').then((m) => ({ default: m.DiscoverPage }))\n);\nconst TrendsPage = lazy(() =>\n import('./pages/trends/TrendsPage').then((m) => ({ default: m.TrendsPage }))\n);\nconst EditorialPage = lazy(() =>\n import('./pages/editorial/EditorialPage').then((module) => ({ default: module.EditorialPage }))\n);\n\n// Commerce (BOFF-3370): cart, orders, creator earnings\nconst CartPage = lazy(() =>\n import('./pages/commerce/CartPage').then((m) => ({ default: m.CartPage }))\n);\nconst BrandOrdersPage = lazy(() =>\n import('./pages/commerce/BrandOrdersPage').then((m) => ({ default: m.BrandOrdersPage }))\n);\nconst BrandOrderDetailPage = lazy(() =>\n import('./pages/commerce/BrandOrdersPage').then((m) => ({ default: m.BrandOrderDetailPage }))\n);\nconst OrdersPage = lazy(() =>\n import('./pages/commerce/OrdersPage').then((m) => ({ default: m.OrdersPage }))\n);\nconst OrderDetailPage = lazy(() =>\n import('./pages/commerce/OrdersPage').then((m) => ({ default: m.OrderDetailPage }))\n);\nconst CreatorEarningsPage = lazy(() =>\n import('./pages/commerce/CreatorEarningsPage').then((m) => ({ default: m.CreatorEarningsPage }))\n);\n\n// Admin curation (gated by the `coolandlovely.admin.curation` feature flag)\nconst AdminBrandsPage = lazy(() =>\n import('./pages/admin/AdminBrandsPage').then((m) => ({ default: m.AdminBrandsPage }))\n);\nconst AdminCollaborationsPage = lazy(() =>\n import('./pages/admin/AdminCollaborationsPage').then((m) => ({\n default: m.AdminCollaborationsPage,\n }))\n);\nconst AdminFeaturedItemsPage = lazy(() =>\n import('./pages/admin/AdminFeaturedItemsPage').then((m) => ({\n default: m.AdminFeaturedItemsPage,\n }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-b-2 border-primary\" />\n </div>\n);\n\nexport const CoolAndLovelyRoutes: FC = () => {\n const { basePath, isStandalone, workspaceId, currentUser } = useCoolAndLovely();\n const location = useLocation();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the path matches the basePath (when integrated).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Overview */}\n <Route index element={<HomePage />} />\n\n {/* Brands */}\n <Route path=\"brands\" element={<BrandsListPage />} />\n <Route path=\"brands/new\" element={<BrandFormPage />} />\n <Route path=\"brands/import\" element={<ImportCatalogPage />} />\n <Route path=\"brands/:brandId\" element={<BrandDetailPage />} />\n <Route path=\"brands/:brandId/edit\" element={<BrandFormPage />} />\n\n {/* Collections */}\n <Route path=\"collections\" element={<CollectionsListPage />} />\n <Route path=\"collections/new\" element={<CollectionFormPage />} />\n <Route path=\"collections/:collectionId\" element={<CollectionDetailPage />} />\n <Route path=\"collections/:collectionId/edit\" element={<CollectionFormPage />} />\n\n {/* Style items */}\n <Route path=\"items\" element={<StyleItemsListPage />} />\n <Route path=\"items/new\" element={<StyleItemFormPage />} />\n <Route path=\"items/:itemId\" element={<StyleItemDetailPage />} />\n <Route path=\"items/:itemId/edit\" element={<StyleItemFormPage />} />\n\n {/* Looks */}\n <Route path=\"looks\" element={<LooksListPage />} />\n <Route path=\"looks/new\" element={<LookFormPage />} />\n <Route path=\"looks/:lookId\" element={<LookDetailPage />} />\n\n {/* Collaborations */}\n <Route path=\"collaborations\" element={<CollaborationsListPage />} />\n <Route path=\"collaborations/new\" element={<CollaborationFormPage />} />\n <Route path=\"collaborations/:collaborationId\" element={<CollaborationDetailPage />} />\n <Route path=\"collaborations/:collaborationId/edit\" element={<CollaborationFormPage />} />\n\n {/* Wardrobe (self-scoped) */}\n <Route path=\"wardrobe\" element={<WardrobeListPage />} />\n <Route path=\"wardrobe/new\" element={<WardrobeFormPage />} />\n\n {/* Lookbooks */}\n <Route path=\"lookbooks\" element={<LookbooksListPage />} />\n <Route path=\"lookbooks/:lookbookId\" element={<LookbookDetailPage />} />\n\n {/* Style profile (self-scoped) + public profiles */}\n <Route path=\"profile\" element={<StyleProfilePage />} />\n <Route path=\"profile/:userId\" element={<StyleProfilePage />} />\n\n {/* Discovery + trends */}\n <Route path=\"discover\" element={<DiscoverPage />} />\n <Route path=\"trends\" element={<TrendsPage />} />\n <Route\n path=\"journal\"\n element={<EditorialPage key={`${workspaceId ?? ''}:${currentUser?.id ?? ''}`} />}\n />\n\n {/* Commerce */}\n <Route path=\"cart\" element={<CartPage />} />\n <Route path=\"orders\" element={<OrdersPage />} />\n <Route path=\"orders/:orderId\" element={<OrderDetailPage />} />\n <Route path=\"earnings\" element={<CreatorEarningsPage />} />\n\n {/* Brand-side orders and fulfilment (BOFF-9636) */}\n <Route path=\"brand-orders\" element={<BrandOrdersPage />} />\n <Route path=\"brand-orders/:brandId/:orderId\" element={<BrandOrderDetailPage />} />\n\n {/* Admin curation */}\n <Route path=\"admin\" element={<Navigate to=\"admin/brands\" replace />} />\n <Route path=\"admin/brands\" element={<AdminBrandsPage />} />\n <Route path=\"admin/collaborations\" element={<AdminCollaborationsPage />} />\n <Route path=\"admin/featured-items\" element={<AdminFeaturedItemsPage />} />\n\n {/* Fallback */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActivityTrail.js","names":[],"sources":["../../../src/coolandlovely/components/ActivityTrail.tsx"],"sourcesContent":["/**\n * ActivityTrail — resource-scoped audit trail for a CoolAndLovely record.\n * @module coolandlovely/components\n *\n * Reads the platform `ActivityLog` rows that the svc's mutation-audit plugin\n * already writes for every `coo*` mutation (see `hooks/useActivity.ts`). Who\n * changed what, when — resolved to a real display name via `ActorName`.\n *\n * No fabricated history: a record with no rows shows an empty state, and a\n * caller without the workspace `activity-log:read` permission sees the error\n * instead of a convincing-looking blank timeline.\n */\n\nimport type { FC } from 'react';\nimport { History, Loader2, RotateCw } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { ActorName } from './ActorName';\nimport { useEntityActivity } from '../hooks/useActivity';\nimport { formatDate, formatRelativeTime, titleCase } from '../utils/formatters';\nimport { cn } from '../utils/cn';\n\ninterface ActivityTrailProps {\n /** ActivityLog.resourceType written by the svc, e.g. \"coolandlovely-brand\". */\n resourceType: string;\n /** The record id (the panel stays idle until it is present). */\n resourceId?: string;\n /** Section heading (default \"Audit trail\"). */\n title?: string;\n /** Max entries to request (default 20). */\n limit?: number;\n className?: string;\n}\n\n/**\n * `coolandlovely.brand_transitioned` → \"Brand transitioned\".\n *\n * Only reshapes the snake_case event names the audit plugin emits; anything\n * else (the generic `graphql_mutation` fallback, which carries the raw field\n * name) is shown verbatim rather than mangled by a lowercase pass.\n */\nexport function formatActivityAction(action: string): string {\n const tail = action.includes('.') ? action.slice(action.lastIndexOf('.') + 1) : action;\n if (!/^[a-z0-9_]+$/.test(tail)) return action;\n const label = titleCase(tail);\n return label.charAt(0) + label.slice(1).toLowerCase();\n}\n\nexport const ActivityTrail: FC<ActivityTrailProps> = ({\n resourceType,\n resourceId,\n title = 'Audit trail',\n limit = 20,\n className,\n}) => {\n const query = useEntityActivity(resourceType, resourceId, limit);\n const entries = query.data ?? [];\n\n return (\n <GlassCard treatment=\"plain\" className={cn('p-5', className)}>\n <h3 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <History className=\"h-4 w-4\" /> {title}\n </h3>\n\n {query.isError ? (\n <div className=\"space-y-2\">\n <p className=\"text-sm text-text-secondary\">\n Activity could not be loaded for this record.\n </p>\n <button\n type=\"button\"\n onClick={() => void query.refetch()}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <RotateCw className=\"h-3.5 w-3.5\" /> Retry\n </button>\n </div>\n ) : !query.isFetched ? (\n // Deliberately NOT `isLoading`: a query held back (no record id, no\n // workspace) has never run, and \"no changes recorded\" would be a claim\n // about data we never asked for.\n <p className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"h-4 w-4 animate-spin\" /> Loading activity…\n </p>\n ) : entries.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n No changes recorded yet. Edits, lifecycle transitions and archival are logged here as they\n happen.\n </p>\n ) : (\n <ul className=\"divide-y divide-border-seam\">\n {entries.map((entry) => (\n <li key={entry.id} className=\"flex items-start justify-between gap-3 py-2.5 first:pt-0\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {formatActivityAction(entry.action)}\n </p>\n <p className=\"mt-0.5 truncate text-xs text-text-secondary\">\n <ActorName id={entry.userId} />\n </p>\n </div>\n <time\n dateTime={entry.timestamp}\n title={formatDate(entry.timestamp)}\n className=\"shrink-0 whitespace-nowrap text-xs text-text-secondary\"\n >\n {formatRelativeTime(entry.timestamp)}\n </time>\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n );\n};\n"],"mappings":";;;;;;;;AAwCA,SAAgB,EAAqB,GAAwB;CAC3D,IAAM,IAAO,EAAO,SAAS,IAAI,
|
|
1
|
+
{"version":3,"file":"ActivityTrail.js","names":[],"sources":["../../../src/coolandlovely/components/ActivityTrail.tsx"],"sourcesContent":["/**\n * ActivityTrail — resource-scoped audit trail for a CoolAndLovely record.\n * @module coolandlovely/components\n *\n * Reads the platform `ActivityLog` rows that the svc's mutation-audit plugin\n * already writes for every `coo*` mutation (see `hooks/useActivity.ts`). Who\n * changed what, when — resolved to a real display name via `ActorName`.\n *\n * No fabricated history: a record with no rows shows an empty state, and a\n * caller without the workspace `activity-log:read` permission sees the error\n * instead of a convincing-looking blank timeline.\n */\n\nimport type { FC } from 'react';\nimport { History, Loader2, RotateCw } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { ActorName } from './ActorName';\nimport { useEntityActivity } from '../hooks/useActivity';\nimport { formatDate, formatRelativeTime, titleCase } from '../utils/formatters';\nimport { cn } from '../utils/cn';\n\ninterface ActivityTrailProps {\n /** ActivityLog.resourceType written by the svc, e.g. \"coolandlovely-brand\". */\n resourceType: string;\n /** The record id (the panel stays idle until it is present). */\n resourceId?: string;\n /** Section heading (default \"Audit trail\"). */\n title?: string;\n /** Max entries to request (default 20). */\n limit?: number;\n className?: string;\n}\n\n/**\n * `coolandlovely.brand_transitioned` → \"Brand transitioned\".\n *\n * Only reshapes the snake_case event names the audit plugin emits; anything\n * else (the generic `graphql_mutation` fallback, which carries the raw field\n * name) is shown verbatim rather than mangled by a lowercase pass.\n */\nexport function formatActivityAction(action: string): string {\n const tail = action.includes('.') ? action.slice(action.lastIndexOf('.') + 1) : action;\n if (!/^[a-z0-9_]+$/.test(tail)) return action;\n const label = titleCase(tail);\n return label.charAt(0) + label.slice(1).toLowerCase();\n}\n\nexport const ActivityTrail: FC<ActivityTrailProps> = ({\n resourceType,\n resourceId,\n title = 'Audit trail',\n limit = 20,\n className,\n}) => {\n const query = useEntityActivity(resourceType, resourceId, limit);\n const entries = query.data ?? [];\n\n return (\n <GlassCard treatment=\"plain\" className={cn('p-5', className)}>\n <h3 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <History className=\"h-4 w-4\" /> {title}\n </h3>\n\n {query.isError ? (\n <div className=\"space-y-2\">\n <p className=\"text-sm text-text-secondary\">\n Activity could not be loaded for this record.\n </p>\n <button\n type=\"button\"\n onClick={() => void query.refetch()}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <RotateCw className=\"h-3.5 w-3.5\" /> Retry\n </button>\n </div>\n ) : !query.isFetched ? (\n // Deliberately NOT `isLoading`: a query held back (no record id, no\n // workspace) has never run, and \"no changes recorded\" would be a claim\n // about data we never asked for.\n <p className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"h-4 w-4 animate-spin\" /> Loading activity…\n </p>\n ) : entries.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n No changes recorded yet. Edits, lifecycle transitions and archival are logged here as they\n happen.\n </p>\n ) : (\n <ul className=\"divide-y divide-border-seam\">\n {entries.map((entry) => (\n <li key={entry.id} className=\"flex items-start justify-between gap-3 py-2.5 first:pt-0\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {formatActivityAction(entry.action)}\n </p>\n <p className=\"mt-0.5 truncate text-xs text-text-secondary\">\n <ActorName id={entry.userId} />\n </p>\n </div>\n <time\n dateTime={entry.timestamp}\n title={formatDate(entry.timestamp)}\n className=\"shrink-0 whitespace-nowrap text-xs text-text-secondary\"\n >\n {formatRelativeTime(entry.timestamp)}\n </time>\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n );\n};\n"],"mappings":";;;;;;;;AAwCA,SAAgB,EAAqB,GAAwB;CAC3D,IAAM,IAAO,EAAO,SAAS,GAAG,IAAI,EAAO,MAAM,EAAO,YAAY,GAAG,IAAI,CAAC,IAAI;CAChF,IAAI,CAAC,eAAe,KAAK,CAAI,GAAG,OAAO;CACvC,IAAM,IAAQ,EAAU,CAAI;CAC5B,OAAO,EAAM,OAAO,CAAC,IAAI,EAAM,MAAM,CAAC,CAAC,CAAC,YAAY;AACtD;AAEA,IAAa,KAAyC,EACpD,iBACA,eACA,WAAQ,eACR,WAAQ,IACR,mBACI;CACJ,IAAM,IAAQ,EAAkB,GAAc,GAAY,CAAK,GACzD,IAAU,EAAM,QAAQ,CAAC;CAE/B,OACE,kBAAC,GAAD;EAAW,WAAU;EAAQ,WAAW,EAAG,OAAO,CAAS;YAA3D,CACE,kBAAC,MAAD;GAAI,WAAU;aAAd;IACE,kBAAC,GAAD,EAAS,WAAU,UAAW,CAAA;IAAC;IAAE;GAC/B;MAEH,EAAM,UACL,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAA8B;GAExC,CAAA,GACH,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,KAAK,EAAM,QAAQ;IAClC,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAU,WAAU,cAAe,CAAA,GAAC,QAC9B;KACL;OACF,EAAM,YAOP,EAAQ,WAAW,IACrB,kBAAC,KAAD;GAAG,WAAU;aAA8B;EAGxC,CAAA,IAEH,kBAAC,MAAD;GAAI,WAAU;aACX,EAAQ,KAAK,MACZ,kBAAC,MAAD;IAAmB,WAAU;cAA7B,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAqB,EAAM,MAAM;KACjC,CAAA,GACH,kBAAC,KAAD;MAAG,WAAU;gBACX,kBAAC,GAAD,EAAW,IAAI,EAAM,OAAS,CAAA;KAC7B,CAAA,CACA;QACL,kBAAC,QAAD;KACE,UAAU,EAAM;KAChB,OAAO,EAAW,EAAM,SAAS;KACjC,WAAU;eAET,EAAmB,EAAM,SAAS;IAC/B,CAAA,CACJ;MAhBK,EAAM,EAgBX,CACL;EACC,CAAA,IA7BJ,kBAAC,KAAD;GAAG,WAAU;aAAb,CACE,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,GAAC,oBAC3C;IA6BI;;AAEf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActorName.js","names":[],"sources":["../../../src/coolandlovely/components/ActorName.tsx"],"sourcesContent":["/**\n * ActorName — render an actor UUID as a human-readable display name.\n * @module coolandlovely/components\n *\n * Wraps fe-libs `useActorProfiles`, which resolves identities via the GLOBAL\n * gateway (workspace-member → org-member → admin lookup → local fallback) with\n * an internal 5-minute cache. NEVER select firstName/name on a federated\n * wspace `User` — resolve names here instead. The MFE is handed a *workspace*\n * `apiGatewayUrl`; `useActorProfiles` detects that and only uses it for the\n * workspace-scoped tier, resolving the global gateway from the hostname itself,\n * so forwarding our workspace URL is safe. Failures degrade to a short-id\n * fallback, never an error.\n */\n\nimport type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useActorProfiles, type ActorInput } from '@burdenoff/fe-libs/shared';\nimport { useCoolAndLovely } from '../context/CoolAndLovelyContext';\n\ninterface ActorNameProps {\n /** Actor id (usually a user UUID). */\n id?: string | null;\n /** Actor type — 'user' (default), 'app', 'service', 'super_admin'. */\n actorType?: string;\n className?: string;\n /** Shown when `id` is absent/empty (default \"—\"). */\n fallback?: string;\n}\n\nexport const ActorName: FC<ActorNameProps> = ({\n id,\n actorType = 'user',\n className,\n fallback = '—',\n}) => {\n const { apiGatewayUrl, authToken, workspaceId } = useCoolAndLovely();\n\n const actors = useMemo<ActorInput[]>(\n () => (id ? [{ actorId: id, actorType }] : []),\n [id, actorType]\n );\n const profiles = useActorProfiles(actors, { apiGatewayUrl, authToken, workspaceId });\n\n if (!id) return <span className={className}>{fallback}</span>;\n\n const profile = profiles[id];\n const displayName = profile?.displayName ?? id;\n\n return (\n <span className={className} title={profile?.email ?? id}>\n {displayName}\n </span>\n );\n};\n"],"mappings":";;;;;AA6BA,IAAa,KAAiC,EAC5C,OACA,eAAY,QACZ,cACA,cAAW,UACP;CACJ,IAAM,EAAE,kBAAe,cAAW,mBAAgB,
|
|
1
|
+
{"version":3,"file":"ActorName.js","names":[],"sources":["../../../src/coolandlovely/components/ActorName.tsx"],"sourcesContent":["/**\n * ActorName — render an actor UUID as a human-readable display name.\n * @module coolandlovely/components\n *\n * Wraps fe-libs `useActorProfiles`, which resolves identities via the GLOBAL\n * gateway (workspace-member → org-member → admin lookup → local fallback) with\n * an internal 5-minute cache. NEVER select firstName/name on a federated\n * wspace `User` — resolve names here instead. The MFE is handed a *workspace*\n * `apiGatewayUrl`; `useActorProfiles` detects that and only uses it for the\n * workspace-scoped tier, resolving the global gateway from the hostname itself,\n * so forwarding our workspace URL is safe. Failures degrade to a short-id\n * fallback, never an error.\n */\n\nimport type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useActorProfiles, type ActorInput } from '@burdenoff/fe-libs/shared';\nimport { useCoolAndLovely } from '../context/CoolAndLovelyContext';\n\ninterface ActorNameProps {\n /** Actor id (usually a user UUID). */\n id?: string | null;\n /** Actor type — 'user' (default), 'app', 'service', 'super_admin'. */\n actorType?: string;\n className?: string;\n /** Shown when `id` is absent/empty (default \"—\"). */\n fallback?: string;\n}\n\nexport const ActorName: FC<ActorNameProps> = ({\n id,\n actorType = 'user',\n className,\n fallback = '—',\n}) => {\n const { apiGatewayUrl, authToken, workspaceId } = useCoolAndLovely();\n\n const actors = useMemo<ActorInput[]>(\n () => (id ? [{ actorId: id, actorType }] : []),\n [id, actorType]\n );\n const profiles = useActorProfiles(actors, { apiGatewayUrl, authToken, workspaceId });\n\n if (!id) return <span className={className}>{fallback}</span>;\n\n const profile = profiles[id];\n const displayName = profile?.displayName ?? id;\n\n return (\n <span className={className} title={profile?.email ?? id}>\n {displayName}\n </span>\n );\n};\n"],"mappings":";;;;;AA6BA,IAAa,KAAiC,EAC5C,OACA,eAAY,QACZ,cACA,cAAW,UACP;CACJ,IAAM,EAAE,kBAAe,cAAW,mBAAgB,EAAiB,GAM7D,IAAW,EAJF,QACN,IAAK,CAAC;EAAE,SAAS;EAAI;CAAU,CAAC,IAAI,CAAC,GAC5C,CAAC,GAAI,CAAS,CAEkB,GAAQ;EAAE;EAAe;EAAW;CAAY,CAAC;CAEnF,IAAI,CAAC,GAAI,OAAO,kBAAC,QAAD;EAAiB;YAAY;CAAe,CAAA;CAE5D,IAAM,IAAU,EAAS,IACnB,IAAc,GAAS,eAAe;CAE5C,OACE,kBAAC,QAAD;EAAiB;EAAW,OAAO,GAAS,SAAS;YAClD;CACG,CAAA;AAEV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddToCartPanel.js","names":[],"sources":["../../../src/coolandlovely/components/AddToCartPanel.tsx"],"sourcesContent":["/**\n * AddToCartPanel — size / colour / quantity picker + \"Add to cart\" for a catalogue piece.\n * @module coolandlovely/components\n *\n * When the shopper arrived from a look (\"shop the look\"), the look id rides along so the look's\n * creator earns the commission once the order is paid (BOFF-3370).\n *\n * When the brand tracks stock for the piece (BOFF-9637), sold-out sizes and colours are disabled,\n * the quantity is capped at what is left, and a low stock count is shown. The service checks the\n * stock again when the piece is added and when the order is placed.\n */\n\nimport { type FC, useState } from 'react';\nimport { Check, Loader2, ShoppingBag, Sparkles } from 'lucide-react';\n\nimport { useCoolAndLovely } from '../context/CoolAndLovelyContext';\nimport { useTr } from '../hooks';\nimport { useAddToCart } from '../hooks/useCommerceApi';\nimport { useStyleItemInventory } from '../hooks/useInventoryApi';\nimport type { CooStyleItem, CooStyleItemInventory } from '../types';\nimport { cn } from '../utils/cn';\n\ninterface AddToCartPanelProps {\n item: Pick<CooStyleItem, 'id' | 'status' | 'price' | 'sizes' | 'colours'>;\n lookId?: string | null;\n}\n\nconst MAX_QUANTITY = 10;\n/** Stock at or below this is shown to the shopper as \"Only N left\". */\nconst LOW_STOCK = 5;\n\n/**\n * Units left of a size/colour choice while the piece tracks stock; null when it does not (or the\n * stock could not be read — the service still enforces it). A partial choice (size picked, colour\n * not yet) sums every variant that matches it.\n */\nfunction unitsLeft(\n inventory: CooStyleItemInventory | null | undefined,\n size: string | null,\n colour: string | null\n): number | null {\n if (!inventory?.trackInventory) return null;\n return inventory.variants\n .filter(\n (variant) =>\n (size === null || (variant.size ?? '') === size) &&\n (colour === null || (variant.colour ?? '') === colour)\n )\n .reduce((sum, variant) => sum + variant.stockQuantity, 0);\n}\n\nconst chip = (selected: boolean) =>\n cn(\n 'inline-flex min-w-9 items-center justify-center rounded-full border px-3 py-1 text-sm font-medium transition-colors',\n selected\n ? 'border-action-primary-bg bg-action-primary-bg text-action-primary-text'\n : 'border-border-seam text-text-primary hover:bg-bg-sunken'\n );\n\nexport const AddToCartPanel: FC<AddToCartPanelProps> = ({ item, lookId }) => {\n const tr = useTr();\n const { navigateTo } = useCoolAndLovely();\n const addToCart = useAddToCart();\n const inventory = useStyleItemInventory(item.id);\n const [size, setSize] = useState<string | null>(\n item.sizes.length === 1 ? (item.sizes[0] ?? null) : null\n );\n const [colour, setColour] = useState<string | null>(\n item.colours.length === 1 ? (item.colours[0] ?? null) : null\n );\n const [quantity, setQuantity] = useState(1);\n\n const purchasable = item.status === 'ACTIVE' && item.price > 0;\n const needsSize = item.sizes.length > 0 && !size;\n const needsColour = item.colours.length > 0 && !colour;\n const stock = inventory.data;\n const left = needsSize || needsColour ? null : unitsLeft(stock, size ?? '', colour ?? '');\n const soldOut = left !== null && left <= 0;\n const maxQuantity = left === null ? MAX_QUANTITY : Math.max(1, Math.min(MAX_QUANTITY, left));\n\n if (!purchasable) {\n return (\n <p className=\"rounded-lg border border-border-seam bg-bg-sunken p-3 text-sm text-text-secondary\">\n {tr('coolandlovely.cart.notForSale', 'This piece is not available to buy right now.')}\n </p>\n );\n }\n\n return (\n <div className=\"space-y-4\" data-testid=\"add-to-cart-panel\">\n {lookId && (\n <p className=\"inline-flex items-center gap-1.5 text-xs font-medium text-accent-primary\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n {tr(\n 'coolandlovely.cart.shoppingLook',\n 'Shopping from a look — your purchase supports its creator'\n )}\n </p>\n )}\n {item.sizes.length > 0 && (\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.cart.chooseSize', 'Choose a size')}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {item.sizes.map((option) => (\n <button\n key={option}\n type=\"button\"\n aria-pressed={size === option}\n disabled={unitsLeft(stock, option, colour) === 0}\n onClick={() => {\n setSize(option);\n setQuantity(1);\n }}\n className={cn(chip(size === option), 'disabled:opacity-40 disabled:line-through')}\n >\n {option}\n </button>\n ))}\n </div>\n </div>\n )}\n {item.colours.length > 0 && (\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.cart.chooseColour', 'Choose a colour')}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {item.colours.map((option) => (\n <button\n key={option}\n type=\"button\"\n aria-pressed={colour === option}\n disabled={unitsLeft(stock, size, option) === 0}\n onClick={() => {\n setColour(option);\n setQuantity(1);\n }}\n className={cn(chip(colour === option), 'disabled:opacity-40 disabled:line-through')}\n >\n {option}\n </button>\n ))}\n </div>\n </div>\n )}\n <div className=\"flex items-center gap-3\">\n <label htmlFor=\"coo-add-quantity\" className=\"text-sm text-text-secondary\">\n {tr('coolandlovely.cart.quantity', 'Quantity')}\n </label>\n <select\n id=\"coo-add-quantity\"\n value={quantity}\n onChange={(event) => setQuantity(Number(event.target.value))}\n className=\"rounded-lg border border-border-seam bg-bg-surface px-2 py-1.5 text-sm text-text-primary\"\n >\n {Array.from({ length: maxQuantity }, (_, index) => index + 1).map((value) => (\n <option key={value} value={value}>\n {value}\n </option>\n ))}\n </select>\n </div>\n {left !== null && (\n <p\n data-testid=\"stock-left\"\n className={cn(\n 'text-sm font-medium',\n soldOut || left <= LOW_STOCK ? 'text-status-warning-text' : 'text-text-secondary'\n )}\n >\n {soldOut\n ? tr('coolandlovely.cart.soldOut', 'Sold out in this size and colour')\n : left <= LOW_STOCK\n ? tr('coolandlovely.cart.onlyLeft', 'Only {{count}} left', { count: left })\n : tr('coolandlovely.cart.inStock', 'In stock')}\n </p>\n )}\n {addToCart.error && (\n <p className=\"text-sm text-status-error-text\">{addToCart.error.message}</p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n disabled={needsSize || needsColour || soldOut || addToCart.isPending}\n onClick={() =>\n addToCart.mutate({\n input: { styleItemId: item.id, quantity, size, colour, lookId: lookId ?? null },\n })\n }\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2.5 text-sm font-semibold text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {addToCart.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : addToCart.isSuccess ? (\n <Check className=\"h-4 w-4\" />\n ) : (\n <ShoppingBag className=\"h-4 w-4\" />\n )}\n {addToCart.isSuccess\n ? tr('coolandlovely.cart.added', 'Added to cart')\n : tr('coolandlovely.cart.add', 'Add to cart')}\n </button>\n {addToCart.isSuccess && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/cart')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-4 py-2.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n {tr('coolandlovely.cart.viewCart', 'View cart')}\n </button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AddToCartPanel.js","names":[],"sources":["../../../src/coolandlovely/components/AddToCartPanel.tsx"],"sourcesContent":["/**\n * AddToCartPanel — size / colour / quantity picker + \"Add to cart\" for a catalogue piece.\n * @module coolandlovely/components\n *\n * When the shopper arrived from a look (\"shop the look\"), the look id rides along so the look's\n * creator earns the commission once the order is paid (BOFF-3370).\n *\n * When the brand tracks stock for the piece (BOFF-9637), sold-out sizes and colours are disabled,\n * the quantity is capped at what is left, and a low stock count is shown. The service checks the\n * stock again when the piece is added and when the order is placed.\n */\n\nimport { type FC, useState } from 'react';\nimport { Check, Loader2, ShoppingBag, Sparkles } from 'lucide-react';\n\nimport { useCoolAndLovely } from '../context/CoolAndLovelyContext';\nimport { useTr } from '../hooks';\nimport { useAddToCart } from '../hooks/useCommerceApi';\nimport { useStyleItemInventory } from '../hooks/useInventoryApi';\nimport type { CooStyleItem, CooStyleItemInventory } from '../types';\nimport { cn } from '../utils/cn';\n\ninterface AddToCartPanelProps {\n item: Pick<CooStyleItem, 'id' | 'status' | 'price' | 'sizes' | 'colours'>;\n lookId?: string | null;\n}\n\nconst MAX_QUANTITY = 10;\n/** Stock at or below this is shown to the shopper as \"Only N left\". */\nconst LOW_STOCK = 5;\n\n/**\n * Units left of a size/colour choice while the piece tracks stock; null when it does not (or the\n * stock could not be read — the service still enforces it). A partial choice (size picked, colour\n * not yet) sums every variant that matches it.\n */\nfunction unitsLeft(\n inventory: CooStyleItemInventory | null | undefined,\n size: string | null,\n colour: string | null\n): number | null {\n if (!inventory?.trackInventory) return null;\n return inventory.variants\n .filter(\n (variant) =>\n (size === null || (variant.size ?? '') === size) &&\n (colour === null || (variant.colour ?? '') === colour)\n )\n .reduce((sum, variant) => sum + variant.stockQuantity, 0);\n}\n\nconst chip = (selected: boolean) =>\n cn(\n 'inline-flex min-w-9 items-center justify-center rounded-full border px-3 py-1 text-sm font-medium transition-colors',\n selected\n ? 'border-action-primary-bg bg-action-primary-bg text-action-primary-text'\n : 'border-border-seam text-text-primary hover:bg-bg-sunken'\n );\n\nexport const AddToCartPanel: FC<AddToCartPanelProps> = ({ item, lookId }) => {\n const tr = useTr();\n const { navigateTo } = useCoolAndLovely();\n const addToCart = useAddToCart();\n const inventory = useStyleItemInventory(item.id);\n const [size, setSize] = useState<string | null>(\n item.sizes.length === 1 ? (item.sizes[0] ?? null) : null\n );\n const [colour, setColour] = useState<string | null>(\n item.colours.length === 1 ? (item.colours[0] ?? null) : null\n );\n const [quantity, setQuantity] = useState(1);\n\n const purchasable = item.status === 'ACTIVE' && item.price > 0;\n const needsSize = item.sizes.length > 0 && !size;\n const needsColour = item.colours.length > 0 && !colour;\n const stock = inventory.data;\n const left = needsSize || needsColour ? null : unitsLeft(stock, size ?? '', colour ?? '');\n const soldOut = left !== null && left <= 0;\n const maxQuantity = left === null ? MAX_QUANTITY : Math.max(1, Math.min(MAX_QUANTITY, left));\n\n if (!purchasable) {\n return (\n <p className=\"rounded-lg border border-border-seam bg-bg-sunken p-3 text-sm text-text-secondary\">\n {tr('coolandlovely.cart.notForSale', 'This piece is not available to buy right now.')}\n </p>\n );\n }\n\n return (\n <div className=\"space-y-4\" data-testid=\"add-to-cart-panel\">\n {lookId && (\n <p className=\"inline-flex items-center gap-1.5 text-xs font-medium text-accent-primary\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n {tr(\n 'coolandlovely.cart.shoppingLook',\n 'Shopping from a look — your purchase supports its creator'\n )}\n </p>\n )}\n {item.sizes.length > 0 && (\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.cart.chooseSize', 'Choose a size')}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {item.sizes.map((option) => (\n <button\n key={option}\n type=\"button\"\n aria-pressed={size === option}\n disabled={unitsLeft(stock, option, colour) === 0}\n onClick={() => {\n setSize(option);\n setQuantity(1);\n }}\n className={cn(chip(size === option), 'disabled:opacity-40 disabled:line-through')}\n >\n {option}\n </button>\n ))}\n </div>\n </div>\n )}\n {item.colours.length > 0 && (\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.cart.chooseColour', 'Choose a colour')}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {item.colours.map((option) => (\n <button\n key={option}\n type=\"button\"\n aria-pressed={colour === option}\n disabled={unitsLeft(stock, size, option) === 0}\n onClick={() => {\n setColour(option);\n setQuantity(1);\n }}\n className={cn(chip(colour === option), 'disabled:opacity-40 disabled:line-through')}\n >\n {option}\n </button>\n ))}\n </div>\n </div>\n )}\n <div className=\"flex items-center gap-3\">\n <label htmlFor=\"coo-add-quantity\" className=\"text-sm text-text-secondary\">\n {tr('coolandlovely.cart.quantity', 'Quantity')}\n </label>\n <select\n id=\"coo-add-quantity\"\n value={quantity}\n onChange={(event) => setQuantity(Number(event.target.value))}\n className=\"rounded-lg border border-border-seam bg-bg-surface px-2 py-1.5 text-sm text-text-primary\"\n >\n {Array.from({ length: maxQuantity }, (_, index) => index + 1).map((value) => (\n <option key={value} value={value}>\n {value}\n </option>\n ))}\n </select>\n </div>\n {left !== null && (\n <p\n data-testid=\"stock-left\"\n className={cn(\n 'text-sm font-medium',\n soldOut || left <= LOW_STOCK ? 'text-status-warning-text' : 'text-text-secondary'\n )}\n >\n {soldOut\n ? tr('coolandlovely.cart.soldOut', 'Sold out in this size and colour')\n : left <= LOW_STOCK\n ? tr('coolandlovely.cart.onlyLeft', 'Only {{count}} left', { count: left })\n : tr('coolandlovely.cart.inStock', 'In stock')}\n </p>\n )}\n {addToCart.error && (\n <p className=\"text-sm text-status-error-text\">{addToCart.error.message}</p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n disabled={needsSize || needsColour || soldOut || addToCart.isPending}\n onClick={() =>\n addToCart.mutate({\n input: { styleItemId: item.id, quantity, size, colour, lookId: lookId ?? null },\n })\n }\n className=\"inline-flex flex-1 items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2.5 text-sm font-semibold text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {addToCart.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : addToCart.isSuccess ? (\n <Check className=\"h-4 w-4\" />\n ) : (\n <ShoppingBag className=\"h-4 w-4\" />\n )}\n {addToCart.isSuccess\n ? tr('coolandlovely.cart.added', 'Added to cart')\n : tr('coolandlovely.cart.add', 'Add to cart')}\n </button>\n {addToCart.isSuccess && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/cart')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-4 py-2.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n {tr('coolandlovely.cart.viewCart', 'View cart')}\n </button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|