@burdenoff/microfe-coolandlovely 2026.1101.8 → 2026.1102.2
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/README.md +15 -0
- package/dist/coolandlovely/CoolAndLovelyRoot.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoot.js +8 -0
- package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.js +20 -16
- package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
- package/dist/coolandlovely/components/WardrobeItemCard.d.ts +2 -1
- package/dist/coolandlovely/components/WardrobeItemCard.d.ts.map +1 -1
- package/dist/coolandlovely/components/WardrobeItemCard.js +4 -3
- package/dist/coolandlovely/components/WardrobeItemCard.js.map +1 -1
- package/dist/coolandlovely/components/prices/BestPriceBadge.d.ts +7 -0
- package/dist/coolandlovely/components/prices/BestPriceBadge.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/BestPriceBadge.js +22 -0
- package/dist/coolandlovely/components/prices/BestPriceBadge.js.map +1 -0
- package/dist/coolandlovely/components/prices/LookbookPriceBoard.d.ts +10 -0
- package/dist/coolandlovely/components/prices/LookbookPriceBoard.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/LookbookPriceBoard.js +120 -0
- package/dist/coolandlovely/components/prices/LookbookPriceBoard.js.map +1 -0
- package/dist/coolandlovely/components/prices/PriceComparison.d.ts +5 -0
- package/dist/coolandlovely/components/prices/PriceComparison.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/PriceComparison.js +95 -0
- package/dist/coolandlovely/components/prices/PriceComparison.js.map +1 -0
- package/dist/coolandlovely/components/prices/PriceCurrencySelect.d.ts +6 -0
- package/dist/coolandlovely/components/prices/PriceCurrencySelect.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/PriceCurrencySelect.js +38 -0
- package/dist/coolandlovely/components/prices/PriceCurrencySelect.js.map +1 -0
- package/dist/coolandlovely/components/prices/PricePanel.d.ts +6 -0
- package/dist/coolandlovely/components/prices/PricePanel.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/PricePanel.js +105 -0
- package/dist/coolandlovely/components/prices/PricePanel.js.map +1 -0
- package/dist/coolandlovely/components/prices/PriceWatchDisclosure.d.ts +2 -0
- package/dist/coolandlovely/components/prices/PriceWatchDisclosure.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/PriceWatchDisclosure.js +28 -0
- package/dist/coolandlovely/components/prices/PriceWatchDisclosure.js.map +1 -0
- package/dist/coolandlovely/components/prices/PriceWatchForm.d.ts +5 -0
- package/dist/coolandlovely/components/prices/PriceWatchForm.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/PriceWatchForm.js +89 -0
- package/dist/coolandlovely/components/prices/PriceWatchForm.js.map +1 -0
- package/dist/coolandlovely/components/prices/PriceWatches.d.ts +3 -0
- package/dist/coolandlovely/components/prices/PriceWatches.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/PriceWatches.js +189 -0
- package/dist/coolandlovely/components/prices/PriceWatches.js.map +1 -0
- package/dist/coolandlovely/components/prices/RetailerOfferLink.d.ts +6 -0
- package/dist/coolandlovely/components/prices/RetailerOfferLink.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/RetailerOfferLink.js +28 -0
- package/dist/coolandlovely/components/prices/RetailerOfferLink.js.map +1 -0
- package/dist/coolandlovely/components/prices/money.d.ts +6 -0
- package/dist/coolandlovely/components/prices/money.d.ts.map +1 -0
- package/dist/coolandlovely/components/prices/money.js +42 -0
- package/dist/coolandlovely/components/prices/money.js.map +1 -0
- package/dist/coolandlovely/hooks/useContextNavigation.d.ts +3 -0
- package/dist/coolandlovely/hooks/useContextNavigation.d.ts.map +1 -0
- package/dist/coolandlovely/hooks/useContextNavigation.js +31 -0
- package/dist/coolandlovely/hooks/useContextNavigation.js.map +1 -0
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCreatorMarketplace.d.ts +118 -0
- package/dist/coolandlovely/hooks/useCreatorMarketplace.d.ts.map +1 -0
- package/dist/coolandlovely/hooks/useCreatorMarketplace.js +120 -0
- package/dist/coolandlovely/hooks/useCreatorMarketplace.js.map +1 -0
- package/dist/coolandlovely/hooks/usePriceApi.d.ts +57 -0
- package/dist/coolandlovely/hooks/usePriceApi.d.ts.map +1 -0
- package/dist/coolandlovely/hooks/usePriceApi.js +111 -0
- package/dist/coolandlovely/hooks/usePriceApi.js.map +1 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js +139 -121
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +140 -137
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js +104 -95
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.js +49 -40
- package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StoreListedPieceView.d.ts.map +1 -1
- package/dist/coolandlovely/pages/items/StoreListedPieceView.js +130 -123
- package/dist/coolandlovely/pages/items/StoreListedPieceView.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +241 -230
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +64 -119
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/marketplace/CreatorMarketplacePage.d.ts +2 -0
- package/dist/coolandlovely/pages/marketplace/CreatorMarketplacePage.d.ts.map +1 -0
- package/dist/coolandlovely/pages/marketplace/CreatorMarketplacePage.js +714 -0
- package/dist/coolandlovely/pages/marketplace/CreatorMarketplacePage.js.map +1 -0
- package/dist/coolandlovely/pages/profile/StyleProfilePage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js +214 -209
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -1
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js +83 -49
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -1
- package/dist/coolandlovely/types/index.d.ts +5 -0
- package/dist/coolandlovely/types/index.d.ts.map +1 -1
- package/dist/generated/wspace-operations.d.ts +931 -2
- package/dist/generated/wspace-operations.d.ts.map +1 -1
- package/dist/generated/wspace-operations.js +221 -1
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.d.ts +539 -1
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/generated/wspace-types.js +14 -0
- package/dist/generated/wspace-types.js.map +1 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -7,6 +7,21 @@ Part of the [Burdenoff](https://burdenoff.com) platform by
|
|
|
7
7
|
|
|
8
8
|
See `AGENTS.md` for development commands and architecture details.
|
|
9
9
|
|
|
10
|
+
## Creator marketplace
|
|
11
|
+
|
|
12
|
+
The creator marketplace route lets creators manage private or published service offers and lets brand owners send proposals using the exact offer revision they reviewed. Offers are scoped to the workspace and owner. Existing quotes retain their fee, currency, role, deliverables and delivery window after later edits or withdrawal. The unified personal inbox includes legacy collaboration invitations and later lifecycle history. Accepting a proposal does not initiate payment or make a balance withdrawable.
|
|
13
|
+
|
|
14
|
+
The UI uses generated operation documents, the canonical shared GraphQL transport and a QueryClient scoped to the API endpoint, tenant, organization, workspace and actor. Capability checks gate publishing and decisions; the backend remains authoritative. Internal marketplace/collaboration links preserve the host context. A stale-offer error requires an explicit reload before the buyer reviews replacement terms; background list refreshes never replace an open quote silently. Quota exhaustion closes the creation dialog before showing the billing action.
|
|
15
|
+
|
|
16
|
+
Refresh the workspace schema through the canonical Hive CDN helper before generating types:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
bash ~/products/dev/scripts/utils/schema-pull.sh --mode cdn --layer wspace
|
|
20
|
+
bun run sanity
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Backend acceptance lives in `coolandlovely-doctor` (`test-creator-marketplace.py`), with explicitly owned designated QA fixtures and exact cleanup. Browser acceptance uses Playwright CLI against the actual host release and is recorded in the audit repository. Configurable milestone payouts, referral programs, advertising economics and complete paid-currency policy are separate remaining monetization work.
|
|
24
|
+
|
|
10
25
|
## License
|
|
11
26
|
|
|
12
27
|
Proprietary — Copyright Burdenoff Consultancy Services Pvt. Ltd.
|
|
@@ -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;AA2BhC,OAAO,KAAK,EAAE,sBAAsB,EAAW,MAAM,SAAS,CAAC;AAE/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;AA2BhC,OAAO,KAAK,EAAE,sBAAsB,EAAW,MAAM,SAAS,CAAC;AAE/D,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CAwOxD,CAAC"}
|
|
@@ -115,6 +115,14 @@ var D = (D) => {
|
|
|
115
115
|
order: 35,
|
|
116
116
|
group: "my-style"
|
|
117
117
|
},
|
|
118
|
+
{
|
|
119
|
+
id: "coolandlovely-marketplace",
|
|
120
|
+
label: M("coolandlovely.nav.marketplace", "Creator marketplace"),
|
|
121
|
+
path: P(A, "creator-marketplace"),
|
|
122
|
+
icon: /* @__PURE__ */ C(u, { size: 20 }),
|
|
123
|
+
order: 36,
|
|
124
|
+
group: "my-style"
|
|
125
|
+
},
|
|
118
126
|
{
|
|
119
127
|
id: "coolandlovely-discover",
|
|
120
128
|
label: M("coolandlovely.nav.discover", "Discover"),
|
|
@@ -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 { 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 { CoolAndLovelyQueryScope } from './context/QueryScope';\nimport { coolAndLovelyScopeKey } from './context/queryScopeKey';\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\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 <CoolAndLovelyQueryScope key={coolAndLovelyScopeKey(props)}>\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 </CoolAndLovelyQueryScope>\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 { 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 { CoolAndLovelyQueryScope } from './context/QueryScope';\nimport { coolAndLovelyScopeKey } from './context/queryScopeKey';\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\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-marketplace',\n label: t('coolandlovely.nav.marketplace', 'Creator marketplace'),\n path: joinPath(basePath, 'creator-marketplace'),\n icon: <Handshake size={20} />,\n order: 36,\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 <CoolAndLovelyQueryScope key={coolAndLovelyScopeKey(props)}>\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 </CoolAndLovelyQueryScope>\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;AA0JhD,eAAO,MAAM,mBAAmB,EAAE,EAgGjC,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/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 }))),
|
|
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/marketplace/CreatorMarketplacePage.js").then((e) => ({ default: e.CreatorMarketplacePage }))), F = r(() => import("./pages/commerce/CartPage.js").then((e) => ({ default: e.CartPage }))), I = r(() => import("./pages/commerce/BrandOrdersPage.js").then((e) => ({ default: e.BrandOrdersPage }))), L = r(() => import("./pages/commerce/BrandOrdersPage.js").then((e) => ({ default: e.BrandOrderDetailPage }))), R = r(() => import("./pages/commerce/OrdersPage.js").then((e) => ({ default: e.OrdersPage }))), z = r(() => import("./pages/commerce/OrdersPage.js").then((e) => ({ default: e.OrderDetailPage }))), B = r(() => import("./pages/commerce/CreatorEarningsPage.js").then((e) => ({ default: e.CreatorEarningsPage }))), V = r(() => import("./pages/admin/AdminBrandsPage.js").then((e) => ({ default: e.AdminBrandsPage }))), H = r(() => import("./pages/admin/AdminCollaborationsPage.js").then((e) => ({ default: e.AdminCollaborationsPage }))), U = r(() => import("./pages/admin/AdminFeaturedItemsPage.js").then((e) => ({ default: e.AdminFeaturedItemsPage }))), W = () => /* @__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
|
+
}), G = () => {
|
|
11
|
+
let { basePath: r, isStandalone: G, workspaceId: K, currentUser: q } = e(), J = s(), Y = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
|
|
12
|
+
return Y && !G && !(J.pathname === Y || J.pathname.startsWith(Y + "/")) ? 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(W, {}),
|
|
16
16
|
children: /* @__PURE__ */ l(o, { children: [
|
|
17
17
|
/* @__PURE__ */ c(a, {
|
|
18
18
|
index: !0,
|
|
@@ -132,31 +132,35 @@ var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ defaul
|
|
|
132
132
|
}),
|
|
133
133
|
/* @__PURE__ */ c(a, {
|
|
134
134
|
path: "journal",
|
|
135
|
-
element: /* @__PURE__ */ c(N, {}, `${
|
|
135
|
+
element: /* @__PURE__ */ c(N, {}, `${K ?? ""}:${q?.id ?? ""}`)
|
|
136
136
|
}),
|
|
137
137
|
/* @__PURE__ */ c(a, {
|
|
138
138
|
path: "cart",
|
|
139
|
-
element: /* @__PURE__ */ c(
|
|
139
|
+
element: /* @__PURE__ */ c(F, {})
|
|
140
140
|
}),
|
|
141
141
|
/* @__PURE__ */ c(a, {
|
|
142
142
|
path: "orders",
|
|
143
|
-
element: /* @__PURE__ */ c(
|
|
143
|
+
element: /* @__PURE__ */ c(R, {})
|
|
144
144
|
}),
|
|
145
145
|
/* @__PURE__ */ c(a, {
|
|
146
146
|
path: "orders/:orderId",
|
|
147
|
-
element: /* @__PURE__ */ c(
|
|
147
|
+
element: /* @__PURE__ */ c(z, {})
|
|
148
148
|
}),
|
|
149
149
|
/* @__PURE__ */ c(a, {
|
|
150
150
|
path: "earnings",
|
|
151
|
-
element: /* @__PURE__ */ c(
|
|
151
|
+
element: /* @__PURE__ */ c(B, {})
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ c(a, {
|
|
154
|
+
path: "creator-marketplace",
|
|
155
|
+
element: /* @__PURE__ */ c(P, {})
|
|
152
156
|
}),
|
|
153
157
|
/* @__PURE__ */ c(a, {
|
|
154
158
|
path: "brand-orders",
|
|
155
|
-
element: /* @__PURE__ */ c(
|
|
159
|
+
element: /* @__PURE__ */ c(I, {})
|
|
156
160
|
}),
|
|
157
161
|
/* @__PURE__ */ c(a, {
|
|
158
162
|
path: "brand-orders/:brandId/:orderId",
|
|
159
|
-
element: /* @__PURE__ */ c(
|
|
163
|
+
element: /* @__PURE__ */ c(L, {})
|
|
160
164
|
}),
|
|
161
165
|
/* @__PURE__ */ c(a, {
|
|
162
166
|
path: "admin",
|
|
@@ -167,15 +171,15 @@ var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ defaul
|
|
|
167
171
|
}),
|
|
168
172
|
/* @__PURE__ */ c(a, {
|
|
169
173
|
path: "admin/brands",
|
|
170
|
-
element: /* @__PURE__ */ c(
|
|
174
|
+
element: /* @__PURE__ */ c(V, {})
|
|
171
175
|
}),
|
|
172
176
|
/* @__PURE__ */ c(a, {
|
|
173
177
|
path: "admin/collaborations",
|
|
174
|
-
element: /* @__PURE__ */ c(
|
|
178
|
+
element: /* @__PURE__ */ c(H, {})
|
|
175
179
|
}),
|
|
176
180
|
/* @__PURE__ */ c(a, {
|
|
177
181
|
path: "admin/featured-items",
|
|
178
|
-
element: /* @__PURE__ */ c(
|
|
182
|
+
element: /* @__PURE__ */ c(U, {})
|
|
179
183
|
}),
|
|
180
184
|
/* @__PURE__ */ c(a, {
|
|
181
185
|
path: "*",
|
|
@@ -189,6 +193,6 @@ var u = r(() => import("./pages/brands/BrandsListPage.js").then((e) => ({ defaul
|
|
|
189
193
|
});
|
|
190
194
|
};
|
|
191
195
|
//#endregion
|
|
192
|
-
export {
|
|
196
|
+
export { G as CoolAndLovelyRoutes };
|
|
193
197
|
|
|
194
198
|
//# 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);\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
|
+
{"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\nconst CreatorMarketplacePage = lazy(() =>\n import('./pages/marketplace/CreatorMarketplacePage').then((m) => ({\n default: m.CreatorMarketplacePage,\n }))\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 <Route path=\"creator-marketplace\" element={<CreatorMarketplacePage />} />\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,4 +1,4 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
2
|
import { CooWardrobeItem } from '../types';
|
|
3
3
|
|
|
4
4
|
interface WardrobeItemCardProps {
|
|
@@ -8,6 +8,7 @@ interface WardrobeItemCardProps {
|
|
|
8
8
|
isLoggingWear?: boolean;
|
|
9
9
|
isRemoving?: boolean;
|
|
10
10
|
className?: string;
|
|
11
|
+
retailerPrice?: ReactNode;
|
|
11
12
|
}
|
|
12
13
|
export declare const WardrobeItemCard: FC<WardrobeItemCardProps>;
|
|
13
14
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WardrobeItemCard.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/components/WardrobeItemCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"WardrobeItemCard.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/components/WardrobeItemCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAO3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,UAAU,qBAAqB;IAC7B,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CA0GtD,CAAC"}
|
|
@@ -6,8 +6,8 @@ import { categoryIcon as o } from "../utils/icons.js";
|
|
|
6
6
|
import { CheckCircle2 as s, Loader2 as c, Trash2 as l } from "lucide-react";
|
|
7
7
|
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
8
8
|
//#region src/coolandlovely/components/WardrobeItemCard.tsx
|
|
9
|
-
var f = ({ item: f, onLogWear: p, onRemove: m, isLoggingWear: h, isRemoving: g, className: _ }) => {
|
|
10
|
-
let
|
|
9
|
+
var f = ({ item: f, onLogWear: p, onRemove: m, isLoggingWear: h, isRemoving: g, className: _, retailerPrice: v }) => {
|
|
10
|
+
let y = f.brandName || f.colour || a(f.category);
|
|
11
11
|
return /* @__PURE__ */ d("div", {
|
|
12
12
|
className: e("group flex flex-col overflow-hidden rounded-xl border border-border-seam bg-bg-surface shadow-sm transition-shadow hover:shadow-lg", _),
|
|
13
13
|
children: [/* @__PURE__ */ d("div", {
|
|
@@ -58,7 +58,7 @@ var f = ({ item: f, onLogWear: p, onRemove: m, isLoggingWear: h, isRemoving: g,
|
|
|
58
58
|
}),
|
|
59
59
|
/* @__PURE__ */ u("p", {
|
|
60
60
|
className: "truncate text-xs text-text-secondary",
|
|
61
|
-
children:
|
|
61
|
+
children: y
|
|
62
62
|
}),
|
|
63
63
|
/* @__PURE__ */ d("div", {
|
|
64
64
|
className: "mt-2 flex flex-wrap items-center gap-1.5",
|
|
@@ -67,6 +67,7 @@ var f = ({ item: f, onLogWear: p, onRemove: m, isLoggingWear: h, isRemoving: g,
|
|
|
67
67
|
children: f.size
|
|
68
68
|
})]
|
|
69
69
|
}),
|
|
70
|
+
v,
|
|
70
71
|
f.notes && /* @__PURE__ */ u("p", {
|
|
71
72
|
className: "mt-2 line-clamp-2 text-xs text-text-secondary",
|
|
72
73
|
children: f.notes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WardrobeItemCard.js","names":[],"sources":["../../../src/coolandlovely/components/WardrobeItemCard.tsx"],"sourcesContent":["/**\n * WardrobeItemCard — a digital wardrobe piece card for list/grids.\n * @module coolandlovely/components\n *\n * Image-forward card with a worn-count badge, hover action bar (log wear / remove),\n * details, size, source and cost-per-wear. Extracted from WardrobeListPage for\n * isolated rendering/tests.\n */\n\nimport type { FC } from 'react';\nimport { CheckCircle2, Loader2, Trash2 } from 'lucide-react';\nimport { Thumbnail } from './Thumbnail';\nimport { StatusBadge } from './StatusBadge';\nimport { categoryIcon } from '../utils/icons';\nimport { titleCase, formatRelativeTime, formatPrice } from '../utils/formatters';\nimport { cn } from '../utils/cn';\nimport type { CooWardrobeItem } from '../types';\n\ninterface WardrobeItemCardProps {\n item: CooWardrobeItem;\n onLogWear?: () => void;\n onRemove?: () => void;\n isLoggingWear?: boolean;\n isRemoving?: boolean;\n className?: string;\n}\n\nexport const WardrobeItemCard: FC<WardrobeItemCardProps> = ({\n item,\n onLogWear,\n onRemove,\n isLoggingWear,\n isRemoving,\n className,\n}) => {\n const subtitle = item.brandName || item.colour || titleCase(item.category);\n\n return (\n <div\n className={cn(\n 'group flex flex-col overflow-hidden rounded-xl border border-border-seam bg-bg-surface shadow-sm transition-shadow hover:shadow-lg',\n className\n )}\n >\n {/* Image-forward hero */}\n <div className=\"relative\">\n <Thumbnail\n icon={categoryIcon(item.category, 40)}\n seed={item.id}\n fileId={item.image?.id}\n alt={item.name}\n className=\"aspect-[4/5] w-full rounded-none\"\n />\n\n {/* Worn-count badge */}\n <div className=\"absolute right-2.5 top-2.5 flex h-12 w-12 flex-col items-center justify-center rounded-full bg-bg-surface/90 text-center leading-none shadow-sm ring-1 ring-[var(--color-accent-soft)] backdrop-blur\">\n <span className=\"text-[9px] font-medium uppercase tracking-wide text-text-secondary\">\n worn\n </span>\n <span className=\"text-sm font-bold tabular-nums text-text-primary\">\n {item.timesWorn}×\n </span>\n </div>\n\n {/* Hover action bar */}\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-1.5 bg-gradient-to-t from-bg-canvas/90 to-transparent p-2.5 pt-8 opacity-100 transition-opacity duration-200 sm:opacity-0 sm:focus-within:opacity-100 sm:group-hover:opacity-100\">\n <button\n type=\"button\"\n disabled={isLoggingWear}\n onClick={onLogWear}\n aria-label={`Log a wear for ${item.name}`}\n className=\"inline-flex items-center gap-1 rounded-lg bg-bg-surface/90 px-2.5 py-1 text-xs font-medium text-status-success-text shadow-sm backdrop-blur transition-colors hover:bg-bg-surface disabled:opacity-50\"\n >\n {isLoggingWear ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n )}\n Wore it\n </button>\n <button\n type=\"button\"\n disabled={isRemoving}\n onClick={onRemove}\n aria-label={`Remove ${item.name}`}\n className=\"ml-auto inline-flex h-7 w-7 items-center justify-center rounded-lg bg-bg-surface/90 text-text-secondary shadow-sm backdrop-blur transition-colors hover:text-status-error-text disabled:opacity-50\"\n >\n {isRemoving ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Trash2 className=\"h-3.5 w-3.5\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Details */}\n <div className=\"flex flex-1 flex-col p-4\">\n <p className=\"truncate text-sm font-semibold text-text-primary\">{item.name}</p>\n <p className=\"truncate text-xs text-text-secondary\">{subtitle}</p>\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={item.source} />\n {item.size && (\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\">\n {item.size}\n </span>\n )}\n </div>\n {item.notes && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{item.notes}</p>\n )}\n <div className=\"mt-3 flex items-center justify-between gap-2 border-t border-border-seam pt-2 text-xs text-text-secondary\">\n <span>\n {item.lastWornAt ? `Last worn ${formatRelativeTime(item.lastWornAt)}` : 'Not worn yet'}\n </span>\n {item.costPerWear != null ? (\n <span\n title={`${formatPrice(item.purchasePrice ?? 0, item.currency ?? 'USD')} ÷ ${item.timesWorn} wears`}\n className=\"shrink-0 font-medium text-text-primary\"\n >\n {formatPrice(item.costPerWear, item.currency ?? 'USD')}/wear\n </span>\n ) : item.purchasePrice != null ? (\n <span className=\"shrink-0 text-text-secondary\">\n {formatPrice(item.purchasePrice, item.currency ?? 'USD')} paid\n </span>\n ) : null}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"WardrobeItemCard.js","names":[],"sources":["../../../src/coolandlovely/components/WardrobeItemCard.tsx"],"sourcesContent":["/**\n * WardrobeItemCard — a digital wardrobe piece card for list/grids.\n * @module coolandlovely/components\n *\n * Image-forward card with a worn-count badge, hover action bar (log wear / remove),\n * details, size, source and cost-per-wear. Extracted from WardrobeListPage for\n * isolated rendering/tests.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { CheckCircle2, Loader2, Trash2 } from 'lucide-react';\nimport { Thumbnail } from './Thumbnail';\nimport { StatusBadge } from './StatusBadge';\nimport { categoryIcon } from '../utils/icons';\nimport { titleCase, formatRelativeTime, formatPrice } from '../utils/formatters';\nimport { cn } from '../utils/cn';\nimport type { CooWardrobeItem } from '../types';\n\ninterface WardrobeItemCardProps {\n item: CooWardrobeItem;\n onLogWear?: () => void;\n onRemove?: () => void;\n isLoggingWear?: boolean;\n isRemoving?: boolean;\n className?: string;\n retailerPrice?: ReactNode;\n}\n\nexport const WardrobeItemCard: FC<WardrobeItemCardProps> = ({\n item,\n onLogWear,\n onRemove,\n isLoggingWear,\n isRemoving,\n className,\n retailerPrice,\n}) => {\n const subtitle = item.brandName || item.colour || titleCase(item.category);\n\n return (\n <div\n className={cn(\n 'group flex flex-col overflow-hidden rounded-xl border border-border-seam bg-bg-surface shadow-sm transition-shadow hover:shadow-lg',\n className\n )}\n >\n {/* Image-forward hero */}\n <div className=\"relative\">\n <Thumbnail\n icon={categoryIcon(item.category, 40)}\n seed={item.id}\n fileId={item.image?.id}\n alt={item.name}\n className=\"aspect-[4/5] w-full rounded-none\"\n />\n\n {/* Worn-count badge */}\n <div className=\"absolute right-2.5 top-2.5 flex h-12 w-12 flex-col items-center justify-center rounded-full bg-bg-surface/90 text-center leading-none shadow-sm ring-1 ring-[var(--color-accent-soft)] backdrop-blur\">\n <span className=\"text-[9px] font-medium uppercase tracking-wide text-text-secondary\">\n worn\n </span>\n <span className=\"text-sm font-bold tabular-nums text-text-primary\">\n {item.timesWorn}×\n </span>\n </div>\n\n {/* Hover action bar */}\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-1.5 bg-gradient-to-t from-bg-canvas/90 to-transparent p-2.5 pt-8 opacity-100 transition-opacity duration-200 sm:opacity-0 sm:focus-within:opacity-100 sm:group-hover:opacity-100\">\n <button\n type=\"button\"\n disabled={isLoggingWear}\n onClick={onLogWear}\n aria-label={`Log a wear for ${item.name}`}\n className=\"inline-flex items-center gap-1 rounded-lg bg-bg-surface/90 px-2.5 py-1 text-xs font-medium text-status-success-text shadow-sm backdrop-blur transition-colors hover:bg-bg-surface disabled:opacity-50\"\n >\n {isLoggingWear ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n )}\n Wore it\n </button>\n <button\n type=\"button\"\n disabled={isRemoving}\n onClick={onRemove}\n aria-label={`Remove ${item.name}`}\n className=\"ml-auto inline-flex h-7 w-7 items-center justify-center rounded-lg bg-bg-surface/90 text-text-secondary shadow-sm backdrop-blur transition-colors hover:text-status-error-text disabled:opacity-50\"\n >\n {isRemoving ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Trash2 className=\"h-3.5 w-3.5\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Details */}\n <div className=\"flex flex-1 flex-col p-4\">\n <p className=\"truncate text-sm font-semibold text-text-primary\">{item.name}</p>\n <p className=\"truncate text-xs text-text-secondary\">{subtitle}</p>\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={item.source} />\n {item.size && (\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\">\n {item.size}\n </span>\n )}\n </div>\n {retailerPrice}\n {item.notes && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{item.notes}</p>\n )}\n <div className=\"mt-3 flex items-center justify-between gap-2 border-t border-border-seam pt-2 text-xs text-text-secondary\">\n <span>\n {item.lastWornAt ? `Last worn ${formatRelativeTime(item.lastWornAt)}` : 'Not worn yet'}\n </span>\n {item.costPerWear != null ? (\n <span\n title={`${formatPrice(item.purchasePrice ?? 0, item.currency ?? 'USD')} ÷ ${item.timesWorn} wears`}\n className=\"shrink-0 font-medium text-text-primary\"\n >\n {formatPrice(item.costPerWear, item.currency ?? 'USD')}/wear\n </span>\n ) : item.purchasePrice != null ? (\n <span className=\"shrink-0 text-text-secondary\">\n {formatPrice(item.purchasePrice, item.currency ?? 'USD')} paid\n </span>\n ) : null}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;AA4BA,IAAa,KAA+C,EAC1D,SACA,cACA,aACA,kBACA,eACA,cACA,uBACI;CACJ,IAAM,IAAW,EAAK,aAAa,EAAK,UAAU,EAAU,EAAK,QAAQ;CAEzE,OACE,kBAAC,OAAD;EACE,WAAW,EACT,sIACA,CACF;YAJF,CAOE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,MAAM,EAAa,EAAK,UAAU,EAAE;KACpC,MAAM,EAAK;KACX,QAAQ,EAAK,OAAO;KACpB,KAAK,EAAK;KACV,WAAU;IACX,CAAA;IAGD,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAqE;KAE/E,CAAA,GACN,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CACG,EAAK,WAAU,GACZ;OACH;;IAGL,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,UAAU;MACV,SAAS;MACT,cAAY,kBAAkB,EAAK;MACnC,WAAU;gBALZ,CAOG,IACC,kBAAC,GAAD,EAAS,WAAU,2BAA4B,CAAA,IAE/C,kBAAC,GAAD,EAAc,WAAU,cAAe,CAAA,GACvC,SAEI;SACR,kBAAC,UAAD;MACE,MAAK;MACL,UAAU;MACV,SAAS;MACT,cAAY,UAAU,EAAK;MAC3B,WAAU;gBAET,IACC,kBAAC,GAAD,EAAS,WAAU,2BAA4B,CAAA,IAE/C,kBAAC,GAAD,EAAQ,WAAU,cAAe,CAAA;KAE7B,CAAA,CACL;;GACF;MAGL,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,KAAD;KAAG,WAAU;eAAoD,EAAK;IAAQ,CAAA;IAC9E,kBAAC,KAAD;KAAG,WAAU;eAAwC;IAAY,CAAA;IACjE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAa,QAAQ,EAAK,OAAS,CAAA,GAClC,EAAK,QACJ,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAK;KACF,CAAA,CAEL;;IACJ;IACA,EAAK,SACJ,kBAAC,KAAD;KAAG,WAAU;eAAiD,EAAK;IAAS,CAAA;IAE9E,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,QAAD,EAAA,UACG,EAAK,aAAa,aAAa,EAAmB,EAAK,UAAU,MAAM,eACpE,CAAA,GACL,EAAK,eAAe,OAOjB,EAAK,iBAAiB,OAItB,OAHF,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CACG,EAAY,EAAK,eAAe,EAAK,YAAY,KAAK,GAAE,OACrD;UATN,kBAAC,QAAD;MACE,OAAO,GAAG,EAAY,EAAK,iBAAiB,GAAG,EAAK,YAAY,KAAK,EAAE,KAAK,EAAK,UAAU;MAC3F,WAAU;gBAFZ,CAIG,EAAY,EAAK,aAAa,EAAK,YAAY,KAAK,GAAE,OACnD;OAML;;GACF;IACF;;AAET"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CooBestPricesQuery } from '../../../generated/wspace-operations';
|
|
2
|
+
|
|
3
|
+
export declare function BestPriceBadge({ summary, onOpen, }: {
|
|
4
|
+
summary: CooBestPricesQuery['cooBestPrices'][number] | undefined;
|
|
5
|
+
onOpen: () => void;
|
|
6
|
+
}): import("react").JSX.Element | null;
|
|
7
|
+
//# sourceMappingURL=BestPriceBadge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BestPriceBadge.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/components/prices/BestPriceBadge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,MAAM,GACP,EAAE;IACD,OAAO,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IACjE,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,sCAYA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { formatRetailerPrice as e } from "./money.js";
|
|
2
|
+
import { jsxs as t } from "react/jsx-runtime";
|
|
3
|
+
//#region src/coolandlovely/components/prices/BestPriceBadge.tsx
|
|
4
|
+
function n({ summary: n, onOpen: r }) {
|
|
5
|
+
return n?.lowestPriceMinor == null ? null : /* @__PURE__ */ t("button", {
|
|
6
|
+
type: "button",
|
|
7
|
+
className: "mt-2 text-left text-xs font-medium text-action-primary-bg underline",
|
|
8
|
+
onClick: r,
|
|
9
|
+
children: [
|
|
10
|
+
"Retailers from ",
|
|
11
|
+
e(n.lowestPriceMinor, n.currency),
|
|
12
|
+
" ·",
|
|
13
|
+
" ",
|
|
14
|
+
n.offerCount,
|
|
15
|
+
" offers"
|
|
16
|
+
]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { n as BestPriceBadge };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=BestPriceBadge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BestPriceBadge.js","names":[],"sources":["../../../../src/coolandlovely/components/prices/BestPriceBadge.tsx"],"sourcesContent":["import type { CooBestPricesQuery } from '../../../generated/wspace-operations';\nimport { formatRetailerPrice } from './money';\n\nexport function BestPriceBadge({\n summary,\n onOpen,\n}: {\n summary: CooBestPricesQuery['cooBestPrices'][number] | undefined;\n onOpen: () => void;\n}) {\n if (summary?.lowestPriceMinor == null) return null;\n return (\n <button\n type=\"button\"\n className=\"mt-2 text-left text-xs font-medium text-action-primary-bg underline\"\n onClick={onOpen}\n >\n Retailers from {formatRetailerPrice(summary.lowestPriceMinor, summary.currency)} ·{' '}\n {summary.offerCount} offers\n </button>\n );\n}\n"],"mappings":";;;AAGA,SAAgB,EAAe,EAC7B,YACA,aAIC;CAED,OADI,GAAS,oBAAoB,OAAa,OAE5C,kBAAC,UAAD;EACE,MAAK;EACL,WAAU;EACV,SAAS;YAHX;GAIC;GACiB,EAAoB,EAAQ,kBAAkB,EAAQ,QAAQ;GAAE;GAAG;GAClF,EAAQ;GAAW;EACd;;AAEZ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CooLook, CooLookbookEntry, CooStyleItem } from '../../types';
|
|
2
|
+
|
|
3
|
+
export declare function LookbookPriceBoard({ entries, looks, items, removingEntryId, onRemove, }: {
|
|
4
|
+
entries: CooLookbookEntry[];
|
|
5
|
+
looks: CooLook[];
|
|
6
|
+
items: CooStyleItem[];
|
|
7
|
+
removingEntryId?: string;
|
|
8
|
+
onRemove: (id: string) => void;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=LookbookPriceBoard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LookbookPriceBoard.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/components/prices/LookbookPriceBoard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3E,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,KAAK,EACL,KAAK,EACL,eAAe,EACf,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC,+BA6GA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
2
|
+
import "../../context/index.js";
|
|
3
|
+
import { Thumbnail as t } from "../Thumbnail.js";
|
|
4
|
+
import { useBestPrices as n } from "../../hooks/usePriceApi.js";
|
|
5
|
+
import { BestPriceBadge as r } from "./BestPriceBadge.js";
|
|
6
|
+
import { PriceCurrencySelect as i } from "./PriceCurrencySelect.js";
|
|
7
|
+
import { useMemo as a, useState as o } from "react";
|
|
8
|
+
import { Loader2 as s, Sparkles as c, Tag as l, X as u } from "lucide-react";
|
|
9
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
10
|
+
//#region src/coolandlovely/components/prices/LookbookPriceBoard.tsx
|
|
11
|
+
var p = [
|
|
12
|
+
"aspect-[3/4]",
|
|
13
|
+
"aspect-square",
|
|
14
|
+
"aspect-[4/5]"
|
|
15
|
+
];
|
|
16
|
+
function m({ entries: m, looks: h, items: g, removingEntryId: _, onRemove: v }) {
|
|
17
|
+
let { navigateTo: y } = e(), [b, x] = o("USD"), S = a(() => new Map(h.map((e) => [e.id, e])), [h]), C = a(() => new Map(g.map((e) => [e.id, e])), [g]), w = a(() => [...new Set(m.map((e) => e.styleItemId).filter((e) => !!e))], [m]), T = n(w.slice(0, 100), b), E = a(() => new Map(T.data?.map((e) => [e.styleItemId, e])), [T.data]);
|
|
18
|
+
return /* @__PURE__ */ f("section", {
|
|
19
|
+
className: "mt-6",
|
|
20
|
+
children: [
|
|
21
|
+
/* @__PURE__ */ d(i, {
|
|
22
|
+
value: b,
|
|
23
|
+
onChange: x,
|
|
24
|
+
currencies: g.map((e) => e.currency)
|
|
25
|
+
}),
|
|
26
|
+
/* @__PURE__ */ f("p", {
|
|
27
|
+
className: "mb-3 text-xs text-text-secondary",
|
|
28
|
+
children: [
|
|
29
|
+
"Retailer quotes for clipped catalog pieces use ",
|
|
30
|
+
b,
|
|
31
|
+
" without currency conversion.",
|
|
32
|
+
w.length > 100 ? " Pricing covers the first 100 linked pieces." : ""
|
|
33
|
+
]
|
|
34
|
+
}),
|
|
35
|
+
T.isError && /* @__PURE__ */ f("p", {
|
|
36
|
+
role: "alert",
|
|
37
|
+
className: "mb-3 text-sm text-status-error-text",
|
|
38
|
+
children: [
|
|
39
|
+
"Retailer prices could not be loaded.",
|
|
40
|
+
" ",
|
|
41
|
+
/* @__PURE__ */ d("button", {
|
|
42
|
+
type: "button",
|
|
43
|
+
className: "underline",
|
|
44
|
+
onClick: () => void T.refetch(),
|
|
45
|
+
children: "Retry prices"
|
|
46
|
+
})
|
|
47
|
+
]
|
|
48
|
+
}),
|
|
49
|
+
/* @__PURE__ */ f("h3", {
|
|
50
|
+
className: "mb-3 text-lg font-semibold text-text-primary",
|
|
51
|
+
children: [
|
|
52
|
+
"Board (",
|
|
53
|
+
m.length,
|
|
54
|
+
")"
|
|
55
|
+
]
|
|
56
|
+
}),
|
|
57
|
+
m.length === 0 ? /* @__PURE__ */ d("p", {
|
|
58
|
+
className: "rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary",
|
|
59
|
+
children: "This lookbook has no entries yet. Clip a catalogue piece or save a look to add one."
|
|
60
|
+
}) : /* @__PURE__ */ d("div", {
|
|
61
|
+
className: "columns-2 gap-4 md:columns-3",
|
|
62
|
+
children: m.map((e, n) => {
|
|
63
|
+
let i = !!e.lookId, a = e.lookId ? S.get(e.lookId) : void 0, o = e.styleItemId ? C.get(e.styleItemId) : void 0, m = i ? a?.title ?? "Saved look" : o?.name ?? "Clipped piece", h = i ? a?.image?.id : o?.image?.id, g = _ === e.id, b = () => {
|
|
64
|
+
i && e.lookId ? y(`/looks/${e.lookId}`) : e.styleItemId && y(`/items/${e.styleItemId}`);
|
|
65
|
+
};
|
|
66
|
+
return /* @__PURE__ */ f("div", {
|
|
67
|
+
className: "group relative mb-4 break-inside-avoid overflow-hidden rounded-xl border border-border-seam bg-bg-surface shadow-sm transition-shadow hover:shadow-lg",
|
|
68
|
+
children: [
|
|
69
|
+
/* @__PURE__ */ d("button", {
|
|
70
|
+
type: "button",
|
|
71
|
+
onClick: b,
|
|
72
|
+
"aria-label": `Open ${m}`,
|
|
73
|
+
className: "block w-full text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--color-focus-ring)]",
|
|
74
|
+
children: /* @__PURE__ */ d(t, {
|
|
75
|
+
icon: d(i ? c : l, { className: "h-8 w-8" }),
|
|
76
|
+
seed: e.id,
|
|
77
|
+
fileId: h,
|
|
78
|
+
alt: m,
|
|
79
|
+
className: `w-full rounded-none ${p[n % p.length]}`,
|
|
80
|
+
overlay: /* @__PURE__ */ f("div", {
|
|
81
|
+
className: "pointer-events-none absolute inset-x-0 bottom-0 flex flex-col gap-1.5 bg-gradient-to-t from-bg-canvas/90 via-bg-canvas/40 to-transparent p-3 pt-10",
|
|
82
|
+
children: [e.note && /* @__PURE__ */ d("span", {
|
|
83
|
+
className: "inline-flex w-fit max-w-full items-center rounded-md bg-bg-canvas/80 px-2 py-0.5 text-[11px] font-medium text-text-primary backdrop-blur",
|
|
84
|
+
children: /* @__PURE__ */ d("span", {
|
|
85
|
+
className: "truncate",
|
|
86
|
+
children: e.note
|
|
87
|
+
})
|
|
88
|
+
}), /* @__PURE__ */ d("p", {
|
|
89
|
+
className: "truncate text-sm font-semibold text-text-primary",
|
|
90
|
+
children: m
|
|
91
|
+
})]
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
}),
|
|
95
|
+
e.styleItemId && /* @__PURE__ */ d("div", {
|
|
96
|
+
className: "px-3 pb-3",
|
|
97
|
+
children: /* @__PURE__ */ d(r, {
|
|
98
|
+
summary: E.get(e.styleItemId),
|
|
99
|
+
onOpen: b
|
|
100
|
+
})
|
|
101
|
+
}),
|
|
102
|
+
/* @__PURE__ */ d("button", {
|
|
103
|
+
type: "button",
|
|
104
|
+
disabled: !!_,
|
|
105
|
+
onClick: () => v(e.id),
|
|
106
|
+
"aria-label": `Remove ${m}`,
|
|
107
|
+
className: "absolute right-2 top-2 z-10 inline-flex h-7 w-7 items-center justify-center rounded-full bg-bg-surface/90 text-text-secondary opacity-100 shadow-sm backdrop-blur transition-opacity hover:text-status-error-text sm:opacity-0 sm:focus-visible:opacity-100 sm:group-hover:opacity-100 disabled:opacity-60",
|
|
108
|
+
children: g ? /* @__PURE__ */ d(s, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ d(u, { className: "h-3.5 w-3.5" })
|
|
109
|
+
})
|
|
110
|
+
]
|
|
111
|
+
}, e.id);
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { m as LookbookPriceBoard };
|
|
119
|
+
|
|
120
|
+
//# sourceMappingURL=LookbookPriceBoard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LookbookPriceBoard.js","names":[],"sources":["../../../../src/coolandlovely/components/prices/LookbookPriceBoard.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { Loader2, Sparkles, Tag, X } from 'lucide-react';\nimport { useCoolAndLovely } from '../../context';\nimport { useBestPrices } from '../../hooks/usePriceApi';\nimport type { CooLook, CooLookbookEntry, CooStyleItem } from '../../types';\nimport { Thumbnail } from '../Thumbnail';\nimport { BestPriceBadge } from './BestPriceBadge';\nimport { PriceCurrencySelect } from './PriceCurrencySelect';\n\n/** Alternating aspect ratios preserve the existing board rhythm. */\nconst TILE_ASPECTS = ['aspect-[3/4]', 'aspect-square', 'aspect-[4/5]'];\n\nexport function LookbookPriceBoard({\n entries,\n looks,\n items,\n removingEntryId,\n onRemove,\n}: {\n entries: CooLookbookEntry[];\n looks: CooLook[];\n items: CooStyleItem[];\n removingEntryId?: string;\n onRemove: (id: string) => void;\n}) {\n const { navigateTo } = useCoolAndLovely();\n const [priceCurrency, setPriceCurrency] = useState('USD');\n const lookById = useMemo(() => new Map(looks.map((look) => [look.id, look])), [looks]);\n const itemById = useMemo(() => new Map(items.map((item) => [item.id, item])), [items]);\n const priceIds = useMemo(\n () => [\n ...new Set(\n entries.map((entry) => entry.styleItemId).filter((id): id is string => Boolean(id))\n ),\n ],\n [entries]\n );\n const bestPrices = useBestPrices(priceIds.slice(0, 100), priceCurrency);\n const priceByItem = useMemo(\n () => new Map(bestPrices.data?.map((entry) => [entry.styleItemId, entry])),\n [bestPrices.data]\n );\n return (\n <section className=\"mt-6\">\n <PriceCurrencySelect\n value={priceCurrency}\n onChange={setPriceCurrency}\n currencies={items.map((item) => item.currency)}\n />\n <p className=\"mb-3 text-xs text-text-secondary\">\n Retailer quotes for clipped catalog pieces use {priceCurrency} without currency conversion.\n {priceIds.length > 100 ? ' Pricing covers the first 100 linked pieces.' : ''}\n </p>\n {bestPrices.isError && (\n <p role=\"alert\" className=\"mb-3 text-sm text-status-error-text\">\n Retailer prices could not be loaded.{' '}\n <button type=\"button\" className=\"underline\" onClick={() => void bestPrices.refetch()}>\n Retry prices\n </button>\n </p>\n )}\n <h3 className=\"mb-3 text-lg font-semibold text-text-primary\">Board ({entries.length})</h3>\n {entries.length === 0 ? (\n <p className=\"rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary\">\n This lookbook has no entries yet. Clip a catalogue piece or save a look to add one.\n </p>\n ) : (\n <div className=\"columns-2 gap-4 md:columns-3\">\n {entries.map((entry, idx) => {\n const isLook = Boolean(entry.lookId);\n const look = entry.lookId ? lookById.get(entry.lookId) : undefined;\n const item = entry.styleItemId ? itemById.get(entry.styleItemId) : undefined;\n const title = isLook ? (look?.title ?? 'Saved look') : (item?.name ?? 'Clipped piece');\n const imageFileId = isLook ? look?.image?.id : item?.image?.id;\n const removing = removingEntryId === entry.id;\n const onOpen = () => {\n if (isLook && entry.lookId) navigateTo(`/looks/${entry.lookId}`);\n else if (entry.styleItemId) navigateTo(`/items/${entry.styleItemId}`);\n };\n return (\n <div\n key={entry.id}\n className=\"group relative mb-4 break-inside-avoid overflow-hidden rounded-xl border border-border-seam bg-bg-surface shadow-sm transition-shadow hover:shadow-lg\"\n >\n <button\n type=\"button\"\n onClick={onOpen}\n aria-label={`Open ${title}`}\n className=\"block w-full text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <Thumbnail\n icon={isLook ? <Sparkles className=\"h-8 w-8\" /> : <Tag className=\"h-8 w-8\" />}\n seed={entry.id}\n fileId={imageFileId}\n alt={title}\n className={`w-full rounded-none ${TILE_ASPECTS[idx % TILE_ASPECTS.length]}`}\n overlay={\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 flex flex-col gap-1.5 bg-gradient-to-t from-bg-canvas/90 via-bg-canvas/40 to-transparent p-3 pt-10\">\n {entry.note && (\n <span className=\"inline-flex w-fit max-w-full items-center rounded-md bg-bg-canvas/80 px-2 py-0.5 text-[11px] font-medium text-text-primary backdrop-blur\">\n <span className=\"truncate\">{entry.note}</span>\n </span>\n )}\n <p className=\"truncate text-sm font-semibold text-text-primary\">{title}</p>\n </div>\n }\n />\n </button>\n {entry.styleItemId && (\n <div className=\"px-3 pb-3\">\n <BestPriceBadge summary={priceByItem.get(entry.styleItemId)} onOpen={onOpen} />\n </div>\n )}\n <button\n type=\"button\"\n disabled={Boolean(removingEntryId)}\n onClick={() => onRemove(entry.id)}\n aria-label={`Remove ${title}`}\n className=\"absolute right-2 top-2 z-10 inline-flex h-7 w-7 items-center justify-center rounded-full bg-bg-surface/90 text-text-secondary opacity-100 shadow-sm backdrop-blur transition-opacity hover:text-status-error-text sm:opacity-0 sm:focus-visible:opacity-100 sm:group-hover:opacity-100 disabled:opacity-60\"\n >\n {removing ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <X className=\"h-3.5 w-3.5\" />\n )}\n </button>\n </div>\n );\n })}\n </div>\n )}\n </section>\n );\n}\n"],"mappings":"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"}
|