@burdenoff/microfe-coolandlovely 2026.805.1 → 2026.820.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/dist/coolandlovely/CoolAndLovelyRoot.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoot.js +60 -58
- package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
- package/dist/coolandlovely/components/AddToLookbookButton.d.ts.map +1 -1
- package/dist/coolandlovely/components/AddToLookbookButton.js +1 -0
- package/dist/coolandlovely/components/AddToLookbookButton.js.map +1 -1
- package/dist/coolandlovely/components/BrandCard.d.ts +11 -0
- package/dist/coolandlovely/components/BrandCard.d.ts.map +1 -0
- package/dist/coolandlovely/components/BrandCard.js +55 -0
- package/dist/coolandlovely/components/BrandCard.js.map +1 -0
- package/dist/coolandlovely/components/CollectionCard.d.ts +11 -0
- package/dist/coolandlovely/components/CollectionCard.d.ts.map +1 -0
- package/dist/coolandlovely/components/CollectionCard.js +60 -0
- package/dist/coolandlovely/components/CollectionCard.js.map +1 -0
- package/dist/coolandlovely/components/FeedbackWidget.d.ts +4 -0
- package/dist/coolandlovely/components/FeedbackWidget.d.ts.map +1 -0
- package/dist/coolandlovely/components/FeedbackWidget.js +134 -0
- package/dist/coolandlovely/components/FeedbackWidget.js.map +1 -0
- package/dist/coolandlovely/components/LookbookCard.d.ts +11 -0
- package/dist/coolandlovely/components/LookbookCard.d.ts.map +1 -0
- package/dist/coolandlovely/components/LookbookCard.js +60 -0
- package/dist/coolandlovely/components/LookbookCard.js.map +1 -0
- package/dist/coolandlovely/components/WardrobeItemCard.d.ts +14 -0
- package/dist/coolandlovely/components/WardrobeItemCard.d.ts.map +1 -0
- package/dist/coolandlovely/components/WardrobeItemCard.js +92 -0
- package/dist/coolandlovely/components/WardrobeItemCard.js.map +1 -0
- package/dist/coolandlovely/components/index.d.ts +5 -0
- package/dist/coolandlovely/components/index.d.ts.map +1 -1
- package/dist/coolandlovely/components/index.js +26 -0
- package/dist/coolandlovely/pages/HomePage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/HomePage.js +10 -4
- package/dist/coolandlovely/pages/HomePage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js +7 -7
- package/dist/coolandlovely/pages/brands/BrandsListPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandsListPage.js +48 -89
- package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js +4 -4
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +13 -13
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js +4 -4
- package/dist/coolandlovely/pages/collections/CollectionsListPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js +28 -74
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +5 -5
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js +66 -112
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js +124 -124
- 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 +46 -120
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -1
- package/dist/stories/BrandCard.stories.d.ts +10 -0
- package/dist/stories/BrandCard.stories.d.ts.map +1 -0
- package/dist/stories/CollectionCard.stories.d.ts +10 -0
- package/dist/stories/CollectionCard.stories.d.ts.map +1 -0
- package/dist/stories/FeedbackWidget.stories.d.ts +9 -0
- package/dist/stories/FeedbackWidget.stories.d.ts.map +1 -0
- package/dist/stories/LookCard.stories.d.ts +10 -0
- package/dist/stories/LookCard.stories.d.ts.map +1 -0
- package/dist/stories/LookbookCard.stories.d.ts +10 -0
- package/dist/stories/LookbookCard.stories.d.ts.map +1 -0
- package/dist/stories/WardrobeItemCard.stories.d.ts +11 -0
- package/dist/stories/WardrobeItemCard.stories.d.ts.map +1 -0
- package/dist/stories/__fixtures__/coolandlovely.d.ts +13 -0
- package/dist/stories/__fixtures__/coolandlovely.d.ts.map +1 -0
- package/package.json +4 -1
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
2
2
|
import { cn as t } from "../../utils/cn.js";
|
|
3
3
|
import { PageLayout as n } from "../../components/PageLayout.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { useBrands as o } from "../../hooks/useCoolAndLovelyApi.js";
|
|
7
|
-
import { titleCase as s } from "../../utils/formatters.js";
|
|
4
|
+
import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
|
|
5
|
+
import { useBrands as a } from "../../hooks/useCoolAndLovelyApi.js";
|
|
8
6
|
import "../../hooks/index.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
7
|
+
import { EmptyState as o } from "../../components/EmptyState.js";
|
|
8
|
+
import { BrandCard as s } from "../../components/BrandCard.js";
|
|
9
|
+
import { useState as c } from "react";
|
|
10
|
+
import { ChevronLeft as l, ChevronRight as u, Plus as d, Star as f, Store as p } from "lucide-react";
|
|
11
|
+
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
15
12
|
//#region src/coolandlovely/pages/brands/BrandsListPage.tsx
|
|
16
|
-
var
|
|
13
|
+
var _ = 24, v = [
|
|
17
14
|
{
|
|
18
15
|
value: "ALL",
|
|
19
16
|
label: "All"
|
|
@@ -39,126 +36,88 @@ var b = 24, x = [
|
|
|
39
36
|
label: "Archived"
|
|
40
37
|
}
|
|
41
38
|
];
|
|
42
|
-
function
|
|
43
|
-
let { navigateTo:
|
|
44
|
-
status:
|
|
45
|
-
featured:
|
|
39
|
+
function y() {
|
|
40
|
+
let { navigateTo: y } = e(), [b, x] = c("ALL"), [S, C] = c(!1), [w, T] = c(0), E = a({
|
|
41
|
+
status: b === "ALL" ? void 0 : b,
|
|
42
|
+
featured: S ? !0 : void 0,
|
|
46
43
|
pagination: {
|
|
47
|
-
limit:
|
|
48
|
-
offset:
|
|
44
|
+
limit: _,
|
|
45
|
+
offset: w
|
|
49
46
|
}
|
|
50
|
-
}),
|
|
51
|
-
return /* @__PURE__ */
|
|
47
|
+
}), D = E.data?.items ?? [], O = E.data?.pageInfo.hasMore ?? !1;
|
|
48
|
+
return /* @__PURE__ */ g(n, {
|
|
52
49
|
title: "Brands",
|
|
53
50
|
description: "Storefronts on the platform with a real publish lifecycle",
|
|
54
|
-
actions: /* @__PURE__ */
|
|
51
|
+
actions: /* @__PURE__ */ g("button", {
|
|
55
52
|
type: "button",
|
|
56
|
-
onClick: () =>
|
|
53
|
+
onClick: () => y("/brands/new"),
|
|
57
54
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
|
|
58
|
-
children: [/* @__PURE__ */
|
|
55
|
+
children: [/* @__PURE__ */ h(d, { className: "h-4 w-4" }), " New brand"]
|
|
59
56
|
}),
|
|
60
|
-
children: [/* @__PURE__ */
|
|
57
|
+
children: [/* @__PURE__ */ g("div", {
|
|
61
58
|
className: "mb-6 flex flex-wrap items-center gap-2",
|
|
62
|
-
children: [
|
|
59
|
+
children: [v.map((e) => /* @__PURE__ */ h("button", {
|
|
63
60
|
type: "button",
|
|
64
61
|
onClick: () => {
|
|
65
|
-
|
|
62
|
+
x(e.value), T(0);
|
|
66
63
|
},
|
|
67
|
-
className: t("rounded-full px-3 py-1.5 text-sm font-medium transition-colors",
|
|
64
|
+
className: t("rounded-full px-3 py-1.5 text-sm font-medium transition-colors", b === e.value ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
|
|
68
65
|
children: e.label
|
|
69
|
-
}, e.value)), /* @__PURE__ */
|
|
66
|
+
}, e.value)), /* @__PURE__ */ g("button", {
|
|
70
67
|
type: "button",
|
|
71
68
|
onClick: () => {
|
|
72
|
-
|
|
69
|
+
C((e) => !e), T(0);
|
|
73
70
|
},
|
|
74
|
-
className: t("ml-auto inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors",
|
|
71
|
+
className: t("ml-auto inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors", S ? "bg-status-warning-bg-subtle text-status-warning-text" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
|
|
75
72
|
children: [
|
|
76
|
-
/* @__PURE__ */
|
|
73
|
+
/* @__PURE__ */ h(f, { className: t("h-3.5 w-3.5", S && "fill-status-warning-text") }),
|
|
77
74
|
" ",
|
|
78
75
|
"Featured"
|
|
79
76
|
]
|
|
80
77
|
})]
|
|
81
|
-
}),
|
|
78
|
+
}), E.isLoading ? /* @__PURE__ */ h(i, { label: "Loading brands…" }) : E.isError ? /* @__PURE__ */ h(r, { onRetry: () => void E.refetch() }) : D.length === 0 ? /* @__PURE__ */ h(o, {
|
|
82
79
|
illustration: "empty-data",
|
|
83
|
-
icon: /* @__PURE__ */
|
|
80
|
+
icon: /* @__PURE__ */ h(p, { className: "h-10 w-10" }),
|
|
84
81
|
title: "No brands yet",
|
|
85
82
|
description: "Launch the first storefront to start building the catalogue.",
|
|
86
|
-
action: /* @__PURE__ */
|
|
83
|
+
action: /* @__PURE__ */ g("button", {
|
|
87
84
|
type: "button",
|
|
88
|
-
onClick: () =>
|
|
85
|
+
onClick: () => y("/brands/new"),
|
|
89
86
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text",
|
|
90
|
-
children: [/* @__PURE__ */
|
|
87
|
+
children: [/* @__PURE__ */ h(d, { className: "h-4 w-4" }), " New brand"]
|
|
91
88
|
})
|
|
92
|
-
}) : /* @__PURE__ */
|
|
89
|
+
}) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h("div", {
|
|
93
90
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
94
|
-
children:
|
|
95
|
-
|
|
96
|
-
onClick: () =>
|
|
97
|
-
className: "group flex flex-col overflow-hidden rounded-xl border border-border-seam bg-bg-surface text-left shadow-sm transition-all hover:border-accent-foreground/20 hover:shadow-md",
|
|
98
|
-
children: [/* @__PURE__ */ v(c, {
|
|
99
|
-
coverFileId: e.cover?.id,
|
|
100
|
-
logoFileId: e.logo?.id,
|
|
101
|
-
name: e.name,
|
|
102
|
-
seed: e.id,
|
|
103
|
-
showLogo: !0
|
|
104
|
-
}), /* @__PURE__ */ y("div", {
|
|
105
|
-
className: "px-4 pb-4 pt-3",
|
|
106
|
-
children: [
|
|
107
|
-
/* @__PURE__ */ y("div", {
|
|
108
|
-
className: "flex min-h-[2.5rem] items-start justify-between gap-2 pl-20",
|
|
109
|
-
children: [/* @__PURE__ */ y("div", {
|
|
110
|
-
className: "min-w-0",
|
|
111
|
-
children: [/* @__PURE__ */ y("div", {
|
|
112
|
-
className: "flex items-center gap-1.5",
|
|
113
|
-
children: [/* @__PURE__ */ v("h3", {
|
|
114
|
-
className: "truncate text-base font-semibold text-text-primary",
|
|
115
|
-
children: e.name
|
|
116
|
-
}), e.isFeatured && /* @__PURE__ */ v(h, { className: "h-3.5 w-3.5 shrink-0 fill-status-warning-text text-status-warning-text" })]
|
|
117
|
-
}), /* @__PURE__ */ y("p", {
|
|
118
|
-
className: "truncate text-xs text-text-secondary",
|
|
119
|
-
children: ["@", e.handle]
|
|
120
|
-
})]
|
|
121
|
-
}), /* @__PURE__ */ v(r, { status: e.status })]
|
|
122
|
-
}),
|
|
123
|
-
e.tagline && /* @__PURE__ */ v("p", {
|
|
124
|
-
className: "mt-2 line-clamp-2 text-sm text-text-secondary",
|
|
125
|
-
children: e.tagline
|
|
126
|
-
}),
|
|
127
|
-
e.aesthetics.length > 0 && /* @__PURE__ */ v(l, {
|
|
128
|
-
tags: e.aesthetics.map(s),
|
|
129
|
-
max: 4,
|
|
130
|
-
className: "mt-3",
|
|
131
|
-
tone: "accent"
|
|
132
|
-
})
|
|
133
|
-
]
|
|
134
|
-
})]
|
|
91
|
+
children: D.map((e) => /* @__PURE__ */ h(s, {
|
|
92
|
+
brand: e,
|
|
93
|
+
onClick: () => y(`/brands/${e.id}`)
|
|
135
94
|
}, e.id))
|
|
136
|
-
}), (
|
|
95
|
+
}), (w > 0 || O) && /* @__PURE__ */ g("div", {
|
|
137
96
|
className: "mt-6 flex items-center justify-center gap-2",
|
|
138
97
|
children: [
|
|
139
|
-
/* @__PURE__ */
|
|
98
|
+
/* @__PURE__ */ g("button", {
|
|
140
99
|
type: "button",
|
|
141
|
-
disabled:
|
|
142
|
-
onClick: () =>
|
|
100
|
+
disabled: w === 0,
|
|
101
|
+
onClick: () => T((e) => Math.max(0, e - _)),
|
|
143
102
|
className: "inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40",
|
|
144
|
-
children: [/* @__PURE__ */
|
|
103
|
+
children: [/* @__PURE__ */ h(l, { className: "h-4 w-4" }), " Previous"]
|
|
145
104
|
}),
|
|
146
|
-
/* @__PURE__ */
|
|
105
|
+
/* @__PURE__ */ g("span", {
|
|
147
106
|
className: "text-sm text-text-secondary",
|
|
148
|
-
children: ["Page ",
|
|
107
|
+
children: ["Page ", w / _ + 1]
|
|
149
108
|
}),
|
|
150
|
-
/* @__PURE__ */
|
|
109
|
+
/* @__PURE__ */ g("button", {
|
|
151
110
|
type: "button",
|
|
152
|
-
disabled: !
|
|
153
|
-
onClick: () =>
|
|
111
|
+
disabled: !O,
|
|
112
|
+
onClick: () => T((e) => e + _),
|
|
154
113
|
className: "inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40",
|
|
155
|
-
children: ["Next ", /* @__PURE__ */
|
|
114
|
+
children: ["Next ", /* @__PURE__ */ h(u, { className: "h-4 w-4" })]
|
|
156
115
|
})
|
|
157
116
|
]
|
|
158
117
|
})] })]
|
|
159
118
|
});
|
|
160
119
|
}
|
|
161
120
|
//#endregion
|
|
162
|
-
export {
|
|
121
|
+
export { y as BrandsListPage };
|
|
163
122
|
|
|
164
123
|
//# sourceMappingURL=BrandsListPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrandsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/brands/BrandsListPage.tsx"],"sourcesContent":["/**\n * Brands List Page\n * @module coolandlovely/pages/brands\n *\n * Lists brand storefronts (cursor-paginated `cooListBrands`) with status &\n * featured filters. Each card links to the brand detail page.\n */\n\nimport { useState } from 'react';\nimport { Store, Plus, Star, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { BrandCover } from '../../components/BrandCover';\nimport { TagList } from '../../components/TagList';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useBrands } from '../../hooks';\nimport { titleCase } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { CooBrandStatus } from '../../types';\n\nconst PAGE_SIZE = 24;\n\nconst STATUS_OPTIONS: Array<{ value: CooBrandStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'PENDING_REVIEW', label: 'In review' },\n { value: 'SUSPENDED', label: 'Suspended' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nexport function BrandsListPage() {\n const { navigateTo } = useCoolAndLovely();\n const [status, setStatus] = useState<CooBrandStatus | 'ALL'>('ALL');\n const [featuredOnly, setFeaturedOnly] = useState(false);\n const [offset, setOffset] = useState(0);\n\n const query = useBrands({\n status: status === 'ALL' ? undefined : status,\n featured: featuredOnly ? true : undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n\n const brands = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n return (\n <PageLayout\n title=\"Brands\"\n description=\"Storefronts on the platform with a real publish lifecycle\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New brand\n </button>\n }\n >\n {/* Filters */}\n <div className=\"mb-6 flex flex-wrap items-center gap-2\">\n {STATUS_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setStatus(opt.value);\n setOffset(0);\n }}\n className={cn(\n 'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n status === opt.value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n <button\n type=\"button\"\n onClick={() => {\n setFeaturedOnly((v) => !v);\n setOffset(0);\n }}\n className={cn(\n 'ml-auto inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n featuredOnly\n ? 'bg-status-warning-bg-subtle text-status-warning-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n <Star className={cn('h-3.5 w-3.5', featuredOnly && 'fill-status-warning-text')} />{' '}\n Featured\n </button>\n </div>\n\n {query.isLoading ? (\n <LoadingView label=\"Loading brands…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : brands.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Store className=\"h-10 w-10\" />}\n title=\"No brands yet\"\n description=\"Launch the first storefront to start building the catalogue.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" /> New brand\n </button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {brands.map((brand) => (\n <button\n key={brand.id}\n type=\"button\"\n onClick={() => navigateTo(`/brands/${brand.id}`)}\n className=\"group flex flex-col overflow-hidden rounded-xl border border-border-seam bg-bg-surface text-left shadow-sm transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <BrandCover\n coverFileId={brand.cover?.id}\n logoFileId={brand.logo?.id}\n name={brand.name}\n seed={brand.id}\n showLogo\n />\n <div className=\"px-4 pb-4 pt-3\">\n <div className=\"flex min-h-[2.5rem] items-start justify-between gap-2 pl-20\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {brand.name}\n </h3>\n {brand.isFeatured && (\n <Star className=\"h-3.5 w-3.5 shrink-0 fill-status-warning-text text-status-warning-text\" />\n )}\n </div>\n <p className=\"truncate text-xs text-text-secondary\">@{brand.handle}</p>\n </div>\n <StatusBadge status={brand.status} />\n </div>\n {brand.tagline && (\n <p className=\"mt-2 line-clamp-2 text-sm text-text-secondary\">{brand.tagline}</p>\n )}\n {brand.aesthetics.length > 0 && (\n <TagList\n tags={brand.aesthetics.map(titleCase)}\n max={4}\n className=\"mt-3\"\n tone=\"accent\"\n />\n )}\n </div>\n </button>\n ))}\n </div>\n\n {/* Pagination */}\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-center gap-2\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" /> Previous\n </button>\n <span className=\"text-sm text-text-secondary\">Page {offset / PAGE_SIZE + 1}</span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Next <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BrandsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/brands/BrandsListPage.tsx"],"sourcesContent":["/**\n * Brands List Page\n * @module coolandlovely/pages/brands\n *\n * Lists brand storefronts (cursor-paginated `cooListBrands`) with status &\n * featured filters. Each card links to the brand detail page.\n */\n\nimport { useState } from 'react';\nimport { Store, Plus, ChevronLeft, ChevronRight, Star } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useBrands } from '../../hooks';\nimport { BrandCard } from '../../components/BrandCard';\nimport { cn } from '../../utils/cn';\nimport type { CooBrandStatus } from '../../types';\n\nconst PAGE_SIZE = 24;\n\nconst STATUS_OPTIONS: Array<{ value: CooBrandStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'PENDING_REVIEW', label: 'In review' },\n { value: 'SUSPENDED', label: 'Suspended' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nexport function BrandsListPage() {\n const { navigateTo } = useCoolAndLovely();\n const [status, setStatus] = useState<CooBrandStatus | 'ALL'>('ALL');\n const [featuredOnly, setFeaturedOnly] = useState(false);\n const [offset, setOffset] = useState(0);\n\n const query = useBrands({\n status: status === 'ALL' ? undefined : status,\n featured: featuredOnly ? true : undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n\n const brands = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n return (\n <PageLayout\n title=\"Brands\"\n description=\"Storefronts on the platform with a real publish lifecycle\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New brand\n </button>\n }\n >\n {/* Filters */}\n <div className=\"mb-6 flex flex-wrap items-center gap-2\">\n {STATUS_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setStatus(opt.value);\n setOffset(0);\n }}\n className={cn(\n 'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n status === opt.value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n <button\n type=\"button\"\n onClick={() => {\n setFeaturedOnly((v) => !v);\n setOffset(0);\n }}\n className={cn(\n 'ml-auto inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n featuredOnly\n ? 'bg-status-warning-bg-subtle text-status-warning-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n <Star className={cn('h-3.5 w-3.5', featuredOnly && 'fill-status-warning-text')} />{' '}\n Featured\n </button>\n </div>\n\n {query.isLoading ? (\n <LoadingView label=\"Loading brands…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : brands.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Store className=\"h-10 w-10\" />}\n title=\"No brands yet\"\n description=\"Launch the first storefront to start building the catalogue.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" /> New brand\n </button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {brands.map((brand) => (\n <BrandCard\n key={brand.id}\n brand={brand}\n onClick={() => navigateTo(`/brands/${brand.id}`)}\n />\n ))}\n </div>\n\n {/* Pagination */}\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-center gap-2\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" /> Previous\n </button>\n <span className=\"text-sm text-text-secondary\">Page {offset / PAGE_SIZE + 1}</span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Next <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -8,8 +8,8 @@ import { formatDate as l, formatPrice as u, titleCase as d } from "../../utils/f
|
|
|
8
8
|
import "../../hooks/index.js";
|
|
9
9
|
import { TagList as f } from "../../components/TagList.js";
|
|
10
10
|
import { ActorName as p } from "../../components/ActorName.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { StepTracker as m } from "../../components/StepTracker.js";
|
|
12
|
+
import { BrandCreatorAvatars as h } from "../../components/BrandCreatorAvatars.js";
|
|
13
13
|
import { ArrowLeft as g, Loader2 as _, Pencil as v, Sparkles as y, Store as b, Trash2 as x } from "lucide-react";
|
|
14
14
|
import { useParams as S } from "react-router";
|
|
15
15
|
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
@@ -84,7 +84,7 @@ function O() {
|
|
|
84
84
|
/* @__PURE__ */ w("div", {
|
|
85
85
|
className: "flex items-center gap-3",
|
|
86
86
|
children: [
|
|
87
|
-
/* @__PURE__ */ C(
|
|
87
|
+
/* @__PURE__ */ C(h, {
|
|
88
88
|
brandLogoFileId: N.brand?.logo?.id,
|
|
89
89
|
brandSeed: N.brandId,
|
|
90
90
|
creatorId: N.creatorId,
|
|
@@ -173,7 +173,7 @@ function O() {
|
|
|
173
173
|
className: "mb-3 text-sm font-semibold text-text-primary",
|
|
174
174
|
children: "Lifecycle"
|
|
175
175
|
}),
|
|
176
|
-
/* @__PURE__ */ C(
|
|
176
|
+
/* @__PURE__ */ C(m, {
|
|
177
177
|
steps: I,
|
|
178
178
|
current: N.status,
|
|
179
179
|
className: "mb-5"
|
|
@@ -4,8 +4,8 @@ import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js
|
|
|
4
4
|
import { useBrands as i, useCollaboration as a, useCreateCollaboration as o, useUpdateCollaboration as s } from "../../hooks/useCoolAndLovelyApi.js";
|
|
5
5
|
import { parseCsv as c, titleCase as l } from "../../utils/formatters.js";
|
|
6
6
|
import "../../hooks/index.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { SelectField as u, TextAreaField as d, TextField as f } from "../../components/Field.js";
|
|
8
|
+
import { ActorName as p } from "../../components/ActorName.js";
|
|
9
9
|
import { useEffect as m, useMemo as h, useState as g } from "react";
|
|
10
10
|
import { ArrowLeft as _, Handshake as v, Loader2 as y, Save as b } from "lucide-react";
|
|
11
11
|
import { useParams as x } from "react-router";
|
|
@@ -169,7 +169,7 @@ function A() {
|
|
|
169
169
|
}), /* @__PURE__ */ S("p", {
|
|
170
170
|
className: "rounded-lg border border-border-seam bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
|
|
171
171
|
children: L.data?.brand?.name ?? R.brandId
|
|
172
|
-
})] }) : /* @__PURE__ */ S(
|
|
172
|
+
})] }) : /* @__PURE__ */ S(u, {
|
|
173
173
|
id: "brandId",
|
|
174
174
|
label: "Brand",
|
|
175
175
|
value: R.brandId,
|
|
@@ -178,7 +178,7 @@ function A() {
|
|
|
178
178
|
required: !0,
|
|
179
179
|
placeholder: I.isLoading ? "Loading brands…" : "Select a brand",
|
|
180
180
|
error: B.brandId
|
|
181
|
-
}), /* @__PURE__ */ S(
|
|
181
|
+
}), /* @__PURE__ */ S(u, {
|
|
182
182
|
id: "role",
|
|
183
183
|
label: "Role",
|
|
184
184
|
value: R.role,
|
|
@@ -187,7 +187,7 @@ function A() {
|
|
|
187
187
|
disabled: G
|
|
188
188
|
})]
|
|
189
189
|
}),
|
|
190
|
-
/* @__PURE__ */ S(
|
|
190
|
+
/* @__PURE__ */ S(f, {
|
|
191
191
|
id: "title",
|
|
192
192
|
label: "Title",
|
|
193
193
|
value: R.title,
|
|
@@ -205,9 +205,9 @@ function A() {
|
|
|
205
205
|
children: "Creator"
|
|
206
206
|
}), /* @__PURE__ */ S("p", {
|
|
207
207
|
className: "rounded-lg border border-border-seam bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
|
|
208
|
-
children: /* @__PURE__ */ S(
|
|
208
|
+
children: /* @__PURE__ */ S(p, { id: R.creatorId })
|
|
209
209
|
})]
|
|
210
|
-
}) : /* @__PURE__ */ S(
|
|
210
|
+
}) : /* @__PURE__ */ S(f, {
|
|
211
211
|
id: "creatorId",
|
|
212
212
|
label: "Creator ID",
|
|
213
213
|
value: R.creatorId,
|
|
@@ -218,7 +218,7 @@ function A() {
|
|
|
218
218
|
error: B.creatorId,
|
|
219
219
|
className: "mt-4"
|
|
220
220
|
}),
|
|
221
|
-
/* @__PURE__ */ S(
|
|
221
|
+
/* @__PURE__ */ S(d, {
|
|
222
222
|
id: "brief",
|
|
223
223
|
label: "Brief",
|
|
224
224
|
value: R.brief,
|
|
@@ -230,7 +230,7 @@ function A() {
|
|
|
230
230
|
}),
|
|
231
231
|
/* @__PURE__ */ C("div", {
|
|
232
232
|
className: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
233
|
-
children: [/* @__PURE__ */ S(
|
|
233
|
+
children: [/* @__PURE__ */ S(f, {
|
|
234
234
|
id: "compensation",
|
|
235
235
|
label: "Compensation",
|
|
236
236
|
type: "number",
|
|
@@ -239,7 +239,7 @@ function A() {
|
|
|
239
239
|
placeholder: "0.00",
|
|
240
240
|
error: B.compensation,
|
|
241
241
|
disabled: G
|
|
242
|
-
}), /* @__PURE__ */ S(
|
|
242
|
+
}), /* @__PURE__ */ S(f, {
|
|
243
243
|
id: "currency",
|
|
244
244
|
label: "Currency",
|
|
245
245
|
value: R.currency,
|
|
@@ -250,14 +250,14 @@ function A() {
|
|
|
250
250
|
}),
|
|
251
251
|
/* @__PURE__ */ C("div", {
|
|
252
252
|
className: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
253
|
-
children: [/* @__PURE__ */ S(
|
|
253
|
+
children: [/* @__PURE__ */ S(f, {
|
|
254
254
|
id: "startDate",
|
|
255
255
|
label: "Start date",
|
|
256
256
|
type: "date",
|
|
257
257
|
value: R.startDate,
|
|
258
258
|
onChange: (e) => H("startDate", e),
|
|
259
259
|
disabled: G
|
|
260
|
-
}), /* @__PURE__ */ S(
|
|
260
|
+
}), /* @__PURE__ */ S(f, {
|
|
261
261
|
id: "endDate",
|
|
262
262
|
label: "End date",
|
|
263
263
|
type: "date",
|
|
@@ -266,7 +266,7 @@ function A() {
|
|
|
266
266
|
disabled: G
|
|
267
267
|
})]
|
|
268
268
|
}),
|
|
269
|
-
/* @__PURE__ */ S(
|
|
269
|
+
/* @__PURE__ */ S(f, {
|
|
270
270
|
id: "tags",
|
|
271
271
|
label: "Tags",
|
|
272
272
|
value: R.tags,
|
|
@@ -6,8 +6,8 @@ import { ErrorView as i, LoadingView as a } from "../../components/StateViews.js
|
|
|
6
6
|
import { useCollaborations as o } from "../../hooks/useCoolAndLovelyApi.js";
|
|
7
7
|
import { formatDate as s, formatPrice as c, titleCase as l } from "../../utils/formatters.js";
|
|
8
8
|
import "../../hooks/index.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { EmptyState as u } from "../../components/EmptyState.js";
|
|
10
|
+
import { ActorName as d } from "../../components/ActorName.js";
|
|
11
11
|
import { BrandCreatorAvatars as f } from "../../components/BrandCreatorAvatars.js";
|
|
12
12
|
import { useState as p } from "react";
|
|
13
13
|
import { Handshake as m, Plus as h } from "lucide-react";
|
|
@@ -62,7 +62,7 @@ function y() {
|
|
|
62
62
|
className: t("rounded-full px-3 py-1.5 text-sm font-medium transition-colors", b === e.value ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
|
|
63
63
|
children: e.label
|
|
64
64
|
}, e.value))
|
|
65
|
-
}), S.isLoading ? /* @__PURE__ */ g(a, { label: "Loading collaborations…" }) : S.isError ? /* @__PURE__ */ g(i, { onRetry: () => void S.refetch() }) : C.length === 0 ? /* @__PURE__ */ g(
|
|
65
|
+
}), S.isLoading ? /* @__PURE__ */ g(a, { label: "Loading collaborations…" }) : S.isError ? /* @__PURE__ */ g(i, { onRetry: () => void S.refetch() }) : C.length === 0 ? /* @__PURE__ */ g(u, {
|
|
66
66
|
illustration: "empty-data",
|
|
67
67
|
icon: /* @__PURE__ */ g(m, { className: "h-10 w-10" }),
|
|
68
68
|
title: "No collaborations yet",
|
|
@@ -100,7 +100,7 @@ function y() {
|
|
|
100
100
|
children: [
|
|
101
101
|
e.brand?.name ?? "Brand",
|
|
102
102
|
" × ",
|
|
103
|
-
/* @__PURE__ */ g(
|
|
103
|
+
/* @__PURE__ */ g(d, { id: e.creatorId })
|
|
104
104
|
]
|
|
105
105
|
})]
|
|
106
106
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionsListPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/collections/CollectionsListPage.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"CollectionsListPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/collections/CollectionsListPage.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,wBAAgB,mBAAmB,gCAwElC"}
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
2
2
|
import { cn as t } from "../../utils/cn.js";
|
|
3
3
|
import { PageLayout as n } from "../../components/PageLayout.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { Thumbnail as o } from "../../components/Thumbnail.js";
|
|
7
|
-
import { useCollections as s } from "../../hooks/useCoolAndLovelyApi.js";
|
|
8
|
-
import { formatDate as c, titleCase as l } from "../../utils/formatters.js";
|
|
4
|
+
import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
|
|
5
|
+
import { useCollections as a } from "../../hooks/useCoolAndLovelyApi.js";
|
|
9
6
|
import "../../hooks/index.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { useState as
|
|
13
|
-
import { Plus as
|
|
14
|
-
import {
|
|
7
|
+
import { EmptyState as o } from "../../components/EmptyState.js";
|
|
8
|
+
import { CollectionCard as s } from "../../components/CollectionCard.js";
|
|
9
|
+
import { useState as c } from "react";
|
|
10
|
+
import { Plus as l, Shapes as u } from "lucide-react";
|
|
11
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
15
12
|
//#region src/coolandlovely/pages/collections/CollectionsListPage.tsx
|
|
16
|
-
var
|
|
13
|
+
var p = [
|
|
17
14
|
{
|
|
18
15
|
value: "ALL",
|
|
19
16
|
label: "All"
|
|
@@ -39,89 +36,46 @@ var v = [
|
|
|
39
36
|
label: "Archived"
|
|
40
37
|
}
|
|
41
38
|
];
|
|
42
|
-
function
|
|
43
|
-
let { navigateTo:
|
|
44
|
-
return /* @__PURE__ */
|
|
39
|
+
function m() {
|
|
40
|
+
let { navigateTo: m } = e(), [h, g] = c("ALL"), _ = a({ status: h === "ALL" ? void 0 : h }), v = _.data ?? [];
|
|
41
|
+
return /* @__PURE__ */ f(n, {
|
|
45
42
|
title: "Collections",
|
|
46
43
|
description: "Seasonal drops and curated edits grouped by brand",
|
|
47
|
-
actions: /* @__PURE__ */
|
|
44
|
+
actions: /* @__PURE__ */ f("button", {
|
|
48
45
|
type: "button",
|
|
49
|
-
onClick: () =>
|
|
46
|
+
onClick: () => m("/collections/new"),
|
|
50
47
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
|
|
51
|
-
children: [/* @__PURE__ */
|
|
48
|
+
children: [/* @__PURE__ */ d(l, { className: "h-4 w-4" }), " New collection"]
|
|
52
49
|
}),
|
|
53
|
-
children: [/* @__PURE__ */
|
|
50
|
+
children: [/* @__PURE__ */ d("div", {
|
|
54
51
|
className: "mb-6 flex flex-wrap items-center gap-2",
|
|
55
|
-
children:
|
|
52
|
+
children: p.map((e) => /* @__PURE__ */ d("button", {
|
|
56
53
|
type: "button",
|
|
57
|
-
onClick: () =>
|
|
58
|
-
className: t("rounded-full px-3 py-1.5 text-sm font-medium transition-colors",
|
|
54
|
+
onClick: () => g(e.value),
|
|
55
|
+
className: t("rounded-full px-3 py-1.5 text-sm font-medium transition-colors", h === e.value ? "bg-accent-purple-subtle text-text-primary" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
|
|
59
56
|
children: e.label
|
|
60
57
|
}, e.value))
|
|
61
|
-
}),
|
|
58
|
+
}), _.isLoading ? /* @__PURE__ */ d(i, { label: "Loading collections…" }) : _.isError ? /* @__PURE__ */ d(r, { onRetry: () => void _.refetch() }) : v.length === 0 ? /* @__PURE__ */ d(o, {
|
|
62
59
|
illustration: "empty-data",
|
|
63
|
-
icon: /* @__PURE__ */
|
|
60
|
+
icon: /* @__PURE__ */ d(u, { className: "h-10 w-10" }),
|
|
64
61
|
title: "No collections yet",
|
|
65
62
|
description: "Group pieces into a seasonal drop to start a collection.",
|
|
66
|
-
action: /* @__PURE__ */
|
|
63
|
+
action: /* @__PURE__ */ f("button", {
|
|
67
64
|
type: "button",
|
|
68
|
-
onClick: () =>
|
|
65
|
+
onClick: () => m("/collections/new"),
|
|
69
66
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text",
|
|
70
|
-
children: [/* @__PURE__ */
|
|
67
|
+
children: [/* @__PURE__ */ d(l, { className: "h-4 w-4" }), " New collection"]
|
|
71
68
|
})
|
|
72
|
-
}) : /* @__PURE__ */
|
|
69
|
+
}) : /* @__PURE__ */ d("div", {
|
|
73
70
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
74
|
-
children:
|
|
75
|
-
|
|
76
|
-
onClick: () =>
|
|
77
|
-
className: "group overflow-hidden rounded-xl border border-border-seam bg-bg-surface text-left shadow-sm transition-all hover:border-accent-foreground/20 hover:shadow-md",
|
|
78
|
-
children: [/* @__PURE__ */ _("div", {
|
|
79
|
-
className: "relative",
|
|
80
|
-
children: [/* @__PURE__ */ g(o, {
|
|
81
|
-
icon: /* @__PURE__ */ g(m, { className: "h-10 w-10" }),
|
|
82
|
-
seed: e.id,
|
|
83
|
-
fileId: e.cover?.id,
|
|
84
|
-
alt: e.name,
|
|
85
|
-
className: "aspect-[16/10] w-full",
|
|
86
|
-
overlay: /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("div", { className: "pointer-events-none absolute inset-0 bg-gradient-to-t from-bg-canvas via-bg-canvas/55 to-transparent" }), /* @__PURE__ */ _("div", {
|
|
87
|
-
className: "absolute inset-x-0 bottom-0 flex items-end justify-between gap-2 p-4",
|
|
88
|
-
children: [/* @__PURE__ */ _("div", {
|
|
89
|
-
className: "min-w-0",
|
|
90
|
-
children: [/* @__PURE__ */ g("h3", {
|
|
91
|
-
className: "truncate text-lg font-semibold text-text-primary",
|
|
92
|
-
children: e.name
|
|
93
|
-
}), e.brand?.name && /* @__PURE__ */ g("p", {
|
|
94
|
-
className: "truncate text-xs text-text-secondary",
|
|
95
|
-
children: e.brand.name
|
|
96
|
-
})]
|
|
97
|
-
}), /* @__PURE__ */ g(r, {
|
|
98
|
-
status: e.status,
|
|
99
|
-
className: "shrink-0 shadow-sm"
|
|
100
|
-
})]
|
|
101
|
-
})] })
|
|
102
|
-
}), /* @__PURE__ */ g("span", {
|
|
103
|
-
className: "absolute right-3 top-3 rounded-full border border-border-seam bg-bg-surface/85 px-2.5 py-0.5 text-xs font-medium text-text-primary backdrop-blur-sm",
|
|
104
|
-
children: l(e.season)
|
|
105
|
-
})]
|
|
106
|
-
}), (e.publishAt || e.tags.length > 0) && /* @__PURE__ */ _("div", {
|
|
107
|
-
className: "p-4",
|
|
108
|
-
children: [e.publishAt && /* @__PURE__ */ _("p", {
|
|
109
|
-
className: "text-xs text-text-secondary",
|
|
110
|
-
children: ["Publishes ", c(e.publishAt, {
|
|
111
|
-
hour: void 0,
|
|
112
|
-
minute: void 0
|
|
113
|
-
})]
|
|
114
|
-
}), e.tags.length > 0 && /* @__PURE__ */ g(u, {
|
|
115
|
-
tags: e.tags,
|
|
116
|
-
max: 4,
|
|
117
|
-
className: e.publishAt ? "mt-2" : void 0
|
|
118
|
-
})]
|
|
119
|
-
})]
|
|
71
|
+
children: v.map((e) => /* @__PURE__ */ d(s, {
|
|
72
|
+
collection: e,
|
|
73
|
+
onClick: () => m(`/collections/${e.id}`)
|
|
120
74
|
}, e.id))
|
|
121
75
|
})]
|
|
122
76
|
});
|
|
123
77
|
}
|
|
124
78
|
//#endregion
|
|
125
|
-
export {
|
|
79
|
+
export { m as CollectionsListPage };
|
|
126
80
|
|
|
127
81
|
//# sourceMappingURL=CollectionsListPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/collections/CollectionsListPage.tsx"],"sourcesContent":["/**\n * Collections List Page\n * @module coolandlovely/pages/collections\n *\n * Lists seasonal collections (`cooListCollections`) with status filter.\n */\n\nimport { useState } from 'react';\nimport { Plus, Shapes } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport {
|
|
1
|
+
{"version":3,"file":"CollectionsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/collections/CollectionsListPage.tsx"],"sourcesContent":["/**\n * Collections List Page\n * @module coolandlovely/pages/collections\n *\n * Lists seasonal collections (`cooListCollections`) with status filter.\n */\n\nimport { useState } from 'react';\nimport { Plus, Shapes } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { CollectionCard } from '../../components/CollectionCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useCollections } from '../../hooks';\nimport { cn } from '../../utils/cn';\nimport type { CooCollectionStatus } from '../../types';\n\nconst STATUS_OPTIONS: Array<{ value: CooCollectionStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'LIVE', label: 'Live' },\n { value: 'SCHEDULED', label: 'Scheduled' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'ENDED', label: 'Ended' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nexport function CollectionsListPage() {\n const { navigateTo } = useCoolAndLovely();\n const [status, setStatus] = useState<CooCollectionStatus | 'ALL'>('ALL');\n\n const query = useCollections({ status: status === 'ALL' ? undefined : status });\n const collections = query.data ?? [];\n\n return (\n <PageLayout\n title=\"Collections\"\n description=\"Seasonal drops and curated edits grouped by brand\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/collections/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New collection\n </button>\n }\n >\n <div className=\"mb-6 flex flex-wrap items-center gap-2\">\n {STATUS_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => setStatus(opt.value)}\n className={cn(\n 'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n status === opt.value\n ? 'bg-accent-purple-subtle text-text-primary'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n\n {query.isLoading ? (\n <LoadingView label=\"Loading collections…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : collections.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Shapes className=\"h-10 w-10\" />}\n title=\"No collections yet\"\n description=\"Group pieces into a seasonal drop to start a collection.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/collections/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" /> New collection\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {collections.map((collection) => (\n <CollectionCard\n key={collection.id}\n collection={collection}\n onClick={() => navigateTo(`/collections/${collection.id}`)}\n />\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAkBA,IAAM,IAA+E;CACnF;EAAE,OAAO;EAAO,OAAO;EAAO;CAC9B;EAAE,OAAO;EAAQ,OAAO;EAAQ;CAChC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAS,OAAO;EAAS;CAClC;EAAE,OAAO;EAAY,OAAO;EAAY;CACzC;AAED,SAAgB,IAAsB;CACpC,IAAM,EAAE,kBAAe,GAAkB,EACnC,CAAC,GAAQ,KAAa,EAAsC,MAAM,EAElE,IAAQ,EAAe,EAAE,QAAQ,MAAW,QAAQ,KAAA,IAAY,GAAQ,CAAC,EACzE,IAAc,EAAM,QAAQ,EAAE;AAEpC,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAW,mBAAmB;GAC7C,WAAU;aAHZ,CAKE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,kBACrB;;YAVb,CAaE,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAe,KAAK,MACnB,kBAAC,UAAD;IAEE,MAAK;IACL,eAAe,EAAU,EAAI,MAAM;IACnC,WAAW,EACT,kEACA,MAAW,EAAI,QACX,8CACA,2DACL;cAEA,EAAI;IACE,EAXF,EAAI,MAWF,CACT;GACE,CAAA,EAEL,EAAM,YACL,kBAAC,GAAD,EAAa,OAAM,wBAAyB,CAAA,GAC1C,EAAM,UACR,kBAAC,GAAD,EAAW,eAAe,KAAK,EAAM,SAAS,EAAI,CAAA,GAChD,EAAY,WAAW,IACzB,kBAAC,GAAD;GACE,cAAa;GACb,MAAM,kBAAC,GAAD,EAAQ,WAAU,aAAc,CAAA;GACtC,OAAM;GACN,aAAY;GACZ,QACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,mBAAmB;IAC7C,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,kBACrB;;GAEX,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAY,KAAK,MAChB,kBAAC,GAAD;IAEc;IACZ,eAAe,EAAW,gBAAgB,EAAW,KAAK;IAC1D,EAHK,EAAW,GAGhB,CACF;GACE,CAAA,CAEG"}
|