@burdenoff/microfe-coolandlovely 2026.706.1 → 2026.706.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/CoolAndLovelyRoutes.js +14 -6
- package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
- package/dist/coolandlovely/components/ActorName.js +29 -0
- package/dist/coolandlovely/components/ActorName.js.map +1 -0
- package/dist/coolandlovely/components/AddToLookbookButton.js +81 -0
- package/dist/coolandlovely/components/AddToLookbookButton.js.map +1 -0
- package/dist/coolandlovely/components/Comments.js +109 -0
- package/dist/coolandlovely/components/Comments.js.map +1 -0
- package/dist/coolandlovely/components/Field.js +22 -2
- package/dist/coolandlovely/components/Field.js.map +1 -1
- package/dist/coolandlovely/components/FileImage.js +17 -0
- package/dist/coolandlovely/components/FileImage.js.map +1 -0
- package/dist/coolandlovely/components/FollowButton.js +24 -0
- package/dist/coolandlovely/components/FollowButton.js.map +1 -0
- package/dist/coolandlovely/components/ImageUploadField.js +71 -0
- package/dist/coolandlovely/components/ImageUploadField.js.map +1 -0
- package/dist/coolandlovely/components/Thumbnail.js +20 -13
- package/dist/coolandlovely/components/Thumbnail.js.map +1 -1
- package/dist/coolandlovely/hooks/index.js +2 -0
- package/dist/coolandlovely/hooks/useComments.js +68 -0
- package/dist/coolandlovely/hooks/useComments.js.map +1 -0
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +74 -4
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useFiles.js +94 -0
- package/dist/coolandlovely/hooks/useFiles.js.map +1 -0
- package/dist/coolandlovely/pages/HomePage.js +105 -87
- package/dist/coolandlovely/pages/HomePage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js +144 -122
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandFormPage.js +128 -90
- package/dist/coolandlovely/pages/brands/BrandFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandsListPage.js +2 -0
- package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js +5 -1
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionFormPage.js +117 -102
- package/dist/coolandlovely/pages/collections/CollectionFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js +2 -0
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/discover/DiscoverPage.js +223 -0
- package/dist/coolandlovely/pages/discover/DiscoverPage.js.map +1 -0
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +99 -95
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemFormPage.js +144 -130
- package/dist/coolandlovely/pages/items/StyleItemFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemsListPage.js +2 -0
- package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +190 -99
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js +81 -68
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LookDetailPage.js +195 -155
- package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LookFormPage.js +127 -88
- package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LooksListPage.js +2 -0
- package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js +169 -101
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -1
- package/dist/coolandlovely/pages/trends/TrendsPage.js +249 -0
- package/dist/coolandlovely/pages/trends/TrendsPage.js.map +1 -0
- package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js +88 -76
- package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js +2 -0
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,100 +9,114 @@ import { useBrands as c, useCollaborations as l, useLooks as u, useStyleItems as
|
|
|
9
9
|
import "../hooks/index.js";
|
|
10
10
|
import { formatRelativeTime as p, titleCase as m } from "../utils/formatters.js";
|
|
11
11
|
import { useMemo as h } from "react";
|
|
12
|
-
import { ArrowRight as g, BookHeart as _,
|
|
13
|
-
import { jsx as
|
|
14
|
-
import { EmphasisPanel as
|
|
12
|
+
import { ArrowRight as g, BookHeart as _, Compass as v, Handshake as y, Heart as b, Plus as x, Shapes as S, Shirt as C, Sparkles as w, Star as T, Store as E, TrendingUp as D, UserCircle as O } from "lucide-react";
|
|
13
|
+
import { jsx as k, jsxs as A } from "react/jsx-runtime";
|
|
14
|
+
import { EmphasisPanel as j, PagePurpose as M } from "@burdenoff/fe-libs/ui";
|
|
15
15
|
//#region src/coolandlovely/pages/HomePage.tsx
|
|
16
|
-
var
|
|
16
|
+
var N = [
|
|
17
17
|
{
|
|
18
18
|
label: "New Brand",
|
|
19
19
|
description: "Launch a storefront",
|
|
20
|
-
icon: /* @__PURE__ */
|
|
20
|
+
icon: /* @__PURE__ */ k(E, { className: "h-5 w-5" }),
|
|
21
21
|
path: "/brands/new",
|
|
22
22
|
color: "bg-accent-purple-subtle text-text-primary"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
label: "Add Style Item",
|
|
26
26
|
description: "List a piece",
|
|
27
|
-
icon: /* @__PURE__ */
|
|
27
|
+
icon: /* @__PURE__ */ k(C, { className: "h-5 w-5" }),
|
|
28
28
|
path: "/items/new",
|
|
29
29
|
color: "bg-[var(--color-accent-soft)] text-text-primary"
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
label: "Publish a Look",
|
|
33
33
|
description: "Shop-the-look outfit",
|
|
34
|
-
icon: /* @__PURE__ */
|
|
34
|
+
icon: /* @__PURE__ */ k(w, { className: "h-5 w-5" }),
|
|
35
35
|
path: "/looks/new",
|
|
36
36
|
color: "bg-status-success-bg-subtle text-status-success-text"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
label: "My Wardrobe",
|
|
40
40
|
description: "What you own",
|
|
41
|
-
icon: /* @__PURE__ */
|
|
41
|
+
icon: /* @__PURE__ */ k(b, { className: "h-5 w-5" }),
|
|
42
42
|
path: "/wardrobe",
|
|
43
43
|
color: "bg-status-warning-bg-subtle text-status-warning-text"
|
|
44
44
|
}
|
|
45
|
-
],
|
|
45
|
+
], P = [
|
|
46
46
|
{
|
|
47
47
|
label: "Brands",
|
|
48
48
|
description: "Storefronts with a publish lifecycle",
|
|
49
|
-
icon: /* @__PURE__ */
|
|
49
|
+
icon: /* @__PURE__ */ k(E, { className: "h-6 w-6" }),
|
|
50
50
|
path: "/brands",
|
|
51
51
|
color: "bg-accent-purple-subtle text-text-primary"
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
label: "Collections",
|
|
55
55
|
description: "Seasonal drops & curated edits",
|
|
56
|
-
icon: /* @__PURE__ */
|
|
56
|
+
icon: /* @__PURE__ */ k(S, { className: "h-6 w-6" }),
|
|
57
57
|
path: "/collections",
|
|
58
58
|
color: "bg-accent-blue-subtle text-accent-blue"
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
label: "Style Items",
|
|
62
62
|
description: "The shoppable catalogue",
|
|
63
|
-
icon: /* @__PURE__ */
|
|
63
|
+
icon: /* @__PURE__ */ k(C, { className: "h-6 w-6" }),
|
|
64
64
|
path: "/items",
|
|
65
65
|
color: "bg-[var(--color-accent-soft)] text-text-primary"
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
label: "Looks",
|
|
69
69
|
description: "Published shop-the-look outfits",
|
|
70
|
-
icon: /* @__PURE__ */
|
|
70
|
+
icon: /* @__PURE__ */ k(w, { className: "h-6 w-6" }),
|
|
71
71
|
path: "/looks",
|
|
72
72
|
color: "bg-status-success-bg-subtle text-status-success-text"
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
label: "Collaborations",
|
|
76
76
|
description: "Brand × creator partnerships",
|
|
77
|
-
icon: /* @__PURE__ */
|
|
77
|
+
icon: /* @__PURE__ */ k(y, { className: "h-6 w-6" }),
|
|
78
78
|
path: "/collaborations",
|
|
79
79
|
color: "bg-status-warning-bg-subtle text-status-warning-text"
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
label: "Wardrobe",
|
|
83
83
|
description: "Your digital closet & wear log",
|
|
84
|
-
icon: /* @__PURE__ */
|
|
84
|
+
icon: /* @__PURE__ */ k(b, { className: "h-6 w-6" }),
|
|
85
85
|
path: "/wardrobe",
|
|
86
86
|
color: "bg-status-error-bg-subtle text-status-error-text"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
label: "Lookbooks",
|
|
90
90
|
description: "Themed boards of saved pieces",
|
|
91
|
-
icon: /* @__PURE__ */
|
|
91
|
+
icon: /* @__PURE__ */ k(_, { className: "h-6 w-6" }),
|
|
92
92
|
path: "/lookbooks",
|
|
93
93
|
color: "bg-accent-purple-subtle text-text-primary"
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
96
|
label: "Style Profile",
|
|
97
97
|
description: "Your taste, palette & sizing",
|
|
98
|
-
icon: /* @__PURE__ */
|
|
98
|
+
icon: /* @__PURE__ */ k(O, { className: "h-6 w-6" }),
|
|
99
99
|
path: "/profile",
|
|
100
100
|
color: "bg-accent-blue-subtle text-accent-blue"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
label: "Discover",
|
|
104
|
+
description: "A feed tuned to your taste",
|
|
105
|
+
icon: /* @__PURE__ */ k(v, { className: "h-6 w-6" }),
|
|
106
|
+
path: "/discover",
|
|
107
|
+
color: "bg-[var(--color-accent-soft)] text-text-primary"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
label: "Trends",
|
|
111
|
+
description: "Live signals from platform activity",
|
|
112
|
+
icon: /* @__PURE__ */ k(D, { className: "h-6 w-6" }),
|
|
113
|
+
path: "/trends",
|
|
114
|
+
color: "bg-status-success-bg-subtle text-status-success-text"
|
|
101
115
|
}
|
|
102
116
|
];
|
|
103
|
-
function
|
|
104
|
-
let { navigateTo: _, currentUser:
|
|
105
|
-
let e =
|
|
117
|
+
function F() {
|
|
118
|
+
let { navigateTo: _, currentUser: v } = e(), S = c(), D = d(), O = u(), F = l(), I = f(), L = v?.firstName ?? v?.name ?? "there", R = S.isLoading || D.isLoading || O.isLoading || F.isLoading || I.isLoading, z = S.isError && D.isError && O.isError && F.isError, B = h(() => {
|
|
119
|
+
let e = S.data?.items ?? [], t = D.data?.items ?? [], n = O.data?.items ?? [], r = F.data ?? [], i = I.data ?? [];
|
|
106
120
|
return {
|
|
107
121
|
totalBrands: e.length,
|
|
108
122
|
publishedBrands: e.filter((e) => e.status === "PUBLISHED").length,
|
|
@@ -114,69 +128,69 @@ function N() {
|
|
|
114
128
|
wardrobeItems: i.length
|
|
115
129
|
};
|
|
116
130
|
}, [
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
131
|
+
S.data,
|
|
132
|
+
D.data,
|
|
133
|
+
O.data,
|
|
120
134
|
F.data,
|
|
121
135
|
I.data
|
|
122
|
-
]), V = h(() => [...
|
|
123
|
-
if (R) return /* @__PURE__ */
|
|
136
|
+
]), V = h(() => [...O.data?.items ?? []].slice(0, 6), [O.data]), H = h(() => [...S.data?.items ?? []].sort((e, t) => new Date(t.updatedAt).getTime() - new Date(e.updatedAt).getTime()).slice(0, 4), [S.data]);
|
|
137
|
+
if (R) return /* @__PURE__ */ k(n, {
|
|
124
138
|
title: "CoolAndLovely",
|
|
125
|
-
children: /* @__PURE__ */
|
|
139
|
+
children: /* @__PURE__ */ k(o, { label: "Loading your style command center…" })
|
|
126
140
|
});
|
|
127
|
-
if (z) return /* @__PURE__ */
|
|
141
|
+
if (z) return /* @__PURE__ */ k(n, {
|
|
128
142
|
title: "CoolAndLovely",
|
|
129
|
-
children: /* @__PURE__ */
|
|
143
|
+
children: /* @__PURE__ */ k(a, {
|
|
130
144
|
title: "Could not load CoolAndLovely",
|
|
131
145
|
message: "The fashion service did not respond. Please try again.",
|
|
132
146
|
onRetry: () => {
|
|
133
|
-
|
|
147
|
+
S.refetch(), D.refetch(), O.refetch(), F.refetch(), I.refetch();
|
|
134
148
|
}
|
|
135
149
|
})
|
|
136
150
|
});
|
|
137
151
|
let U = [
|
|
138
152
|
{
|
|
139
|
-
icon: /* @__PURE__ */
|
|
153
|
+
icon: /* @__PURE__ */ k(E, { className: "h-5 w-5" }),
|
|
140
154
|
value: B.totalBrands.toString(),
|
|
141
155
|
label: "Brands",
|
|
142
156
|
sub: `${B.publishedBrands} published`
|
|
143
157
|
},
|
|
144
158
|
{
|
|
145
|
-
icon: /* @__PURE__ */
|
|
159
|
+
icon: /* @__PURE__ */ k(C, { className: "h-5 w-5" }),
|
|
146
160
|
value: B.totalStyleItems.toString(),
|
|
147
161
|
label: "Style Items",
|
|
148
162
|
sub: `${B.activeStyleItems} active`
|
|
149
163
|
},
|
|
150
164
|
{
|
|
151
|
-
icon: /* @__PURE__ */
|
|
165
|
+
icon: /* @__PURE__ */ k(w, { className: "h-5 w-5" }),
|
|
152
166
|
value: B.totalLooks.toString(),
|
|
153
167
|
label: "Looks",
|
|
154
168
|
sub: `${B.featuredLooks} featured`
|
|
155
169
|
},
|
|
156
170
|
{
|
|
157
|
-
icon: /* @__PURE__ */
|
|
171
|
+
icon: /* @__PURE__ */ k(y, { className: "h-5 w-5" }),
|
|
158
172
|
value: B.activeCollaborations.toString(),
|
|
159
173
|
label: "Active Collabs",
|
|
160
174
|
sub: `${B.wardrobeItems} in wardrobe`
|
|
161
175
|
}
|
|
162
176
|
];
|
|
163
|
-
return /* @__PURE__ */
|
|
177
|
+
return /* @__PURE__ */ A(n, {
|
|
164
178
|
title: `Hello, ${L}`,
|
|
165
179
|
description: "Your fashion & lifestyle command center",
|
|
166
180
|
hero: !0,
|
|
167
181
|
children: [
|
|
168
|
-
/* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ k(M, {
|
|
169
183
|
className: "mb-6",
|
|
170
184
|
children: "CoolAndLovely connects the three sides of style on one workspace-native model: brands launch storefronts and seasonal collections, you build a wardrobe and lookbooks, and creators publish shop-the-look outfits and run brand collaborations. Jump into any module below — all data is live from the CoolAndLovely service."
|
|
171
185
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
186
|
+
/* @__PURE__ */ A(j, {
|
|
173
187
|
className: "mb-8",
|
|
174
|
-
children: [/* @__PURE__ */
|
|
188
|
+
children: [/* @__PURE__ */ k("h2", {
|
|
175
189
|
className: "mb-4 text-lg font-semibold text-text-primary",
|
|
176
190
|
children: "At a glance"
|
|
177
|
-
}), /* @__PURE__ */
|
|
191
|
+
}), /* @__PURE__ */ k("div", {
|
|
178
192
|
className: "grid grid-cols-2 gap-4 lg:grid-cols-4",
|
|
179
|
-
children: U.map((e) => /* @__PURE__ */
|
|
193
|
+
children: U.map((e) => /* @__PURE__ */ k(r, {
|
|
180
194
|
icon: e.icon,
|
|
181
195
|
value: e.value,
|
|
182
196
|
label: e.label,
|
|
@@ -185,101 +199,103 @@ function N() {
|
|
|
185
199
|
}, e.label))
|
|
186
200
|
})]
|
|
187
201
|
}),
|
|
188
|
-
/* @__PURE__ */
|
|
202
|
+
/* @__PURE__ */ A("section", {
|
|
189
203
|
className: "mb-8",
|
|
190
|
-
children: [/* @__PURE__ */
|
|
204
|
+
children: [/* @__PURE__ */ k("h2", {
|
|
191
205
|
className: "mb-4 text-lg font-semibold text-text-primary",
|
|
192
206
|
children: "Quick actions"
|
|
193
|
-
}), /* @__PURE__ */
|
|
207
|
+
}), /* @__PURE__ */ k("div", {
|
|
194
208
|
className: "grid grid-cols-2 gap-4 lg:grid-cols-4",
|
|
195
|
-
children:
|
|
209
|
+
children: N.map((e) => /* @__PURE__ */ A("button", {
|
|
196
210
|
type: "button",
|
|
197
211
|
onClick: () => _(e.path),
|
|
198
212
|
className: t("flex items-start gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left shadow-sm transition-all", "hover:border-accent-foreground/20 hover:shadow-md"),
|
|
199
213
|
children: [
|
|
200
|
-
/* @__PURE__ */
|
|
214
|
+
/* @__PURE__ */ k("div", {
|
|
201
215
|
className: t("flex h-10 w-10 shrink-0 items-center justify-center rounded-lg", e.color),
|
|
202
216
|
children: e.icon
|
|
203
217
|
}),
|
|
204
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ A("div", {
|
|
205
219
|
className: "min-w-0 flex-1",
|
|
206
|
-
children: [/* @__PURE__ */
|
|
220
|
+
children: [/* @__PURE__ */ k("p", {
|
|
207
221
|
className: "text-sm font-semibold text-text-primary",
|
|
208
222
|
children: e.label
|
|
209
|
-
}), /* @__PURE__ */
|
|
223
|
+
}), /* @__PURE__ */ k("p", {
|
|
210
224
|
className: "mt-0.5 text-xs text-text-secondary",
|
|
211
225
|
children: e.description
|
|
212
226
|
})]
|
|
213
227
|
}),
|
|
214
|
-
/* @__PURE__ */
|
|
228
|
+
/* @__PURE__ */ k(x, { className: "mt-1 h-4 w-4 shrink-0 text-text-secondary" })
|
|
215
229
|
]
|
|
216
230
|
}, e.label))
|
|
217
231
|
})]
|
|
218
232
|
}),
|
|
219
|
-
/* @__PURE__ */
|
|
233
|
+
/* @__PURE__ */ A("section", {
|
|
220
234
|
className: "mb-8",
|
|
221
|
-
children: [/* @__PURE__ */
|
|
235
|
+
children: [/* @__PURE__ */ k("h2", {
|
|
222
236
|
className: "mb-4 text-lg font-semibold text-text-primary",
|
|
223
237
|
children: "Explore"
|
|
224
|
-
}), /* @__PURE__ */
|
|
238
|
+
}), /* @__PURE__ */ k("div", {
|
|
225
239
|
className: "grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4",
|
|
226
|
-
children:
|
|
240
|
+
children: P.map((e) => /* @__PURE__ */ A("button", {
|
|
227
241
|
type: "button",
|
|
228
242
|
onClick: () => _(e.path),
|
|
229
243
|
className: "flex flex-col gap-3 rounded-lg border border-border-seam bg-bg-surface p-5 text-left transition-all hover:border-accent-foreground/20 hover:shadow-md",
|
|
230
|
-
children: [/* @__PURE__ */
|
|
244
|
+
children: [/* @__PURE__ */ k("div", {
|
|
231
245
|
className: t("flex h-12 w-12 items-center justify-center rounded-full", e.color),
|
|
232
246
|
children: e.icon
|
|
233
|
-
}), /* @__PURE__ */
|
|
247
|
+
}), /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("p", {
|
|
234
248
|
className: "text-sm font-semibold text-text-primary",
|
|
235
249
|
children: e.label
|
|
236
|
-
}), /* @__PURE__ */
|
|
250
|
+
}), /* @__PURE__ */ k("p", {
|
|
237
251
|
className: "mt-0.5 text-xs text-text-secondary",
|
|
238
252
|
children: e.description
|
|
239
253
|
})] })]
|
|
240
254
|
}, e.label))
|
|
241
255
|
})]
|
|
242
256
|
}),
|
|
243
|
-
/* @__PURE__ */
|
|
257
|
+
/* @__PURE__ */ A("section", {
|
|
244
258
|
className: "mb-8",
|
|
245
|
-
children: [/* @__PURE__ */
|
|
259
|
+
children: [/* @__PURE__ */ A("div", {
|
|
246
260
|
className: "mb-4 flex items-center justify-between",
|
|
247
|
-
children: [/* @__PURE__ */
|
|
261
|
+
children: [/* @__PURE__ */ k("h2", {
|
|
248
262
|
className: "text-lg font-semibold text-text-primary",
|
|
249
263
|
children: "Latest looks"
|
|
250
|
-
}), /* @__PURE__ */
|
|
264
|
+
}), /* @__PURE__ */ A("button", {
|
|
251
265
|
type: "button",
|
|
252
266
|
onClick: () => _("/looks"),
|
|
253
267
|
className: "flex items-center gap-1 text-sm font-medium text-primary hover:underline",
|
|
254
|
-
children: ["View all ", /* @__PURE__ */
|
|
268
|
+
children: ["View all ", /* @__PURE__ */ k(g, { className: "h-3.5 w-3.5" })]
|
|
255
269
|
})]
|
|
256
|
-
}), V.length === 0 ? /* @__PURE__ */
|
|
270
|
+
}), V.length === 0 ? /* @__PURE__ */ k("p", {
|
|
257
271
|
className: "rounded-lg border border-border-seam bg-bg-surface p-6 text-sm text-text-secondary",
|
|
258
272
|
children: "No looks published yet. Be the first to publish a shop-the-look outfit."
|
|
259
|
-
}) : /* @__PURE__ */
|
|
273
|
+
}) : /* @__PURE__ */ k("div", {
|
|
260
274
|
className: "grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6",
|
|
261
|
-
children: V.map((e) => /* @__PURE__ */
|
|
275
|
+
children: V.map((e) => /* @__PURE__ */ A("button", {
|
|
262
276
|
type: "button",
|
|
263
277
|
onClick: () => _(`/looks/${e.id}`),
|
|
264
278
|
className: "group overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-all hover:border-accent-foreground/20 hover:shadow-md",
|
|
265
|
-
children: [/* @__PURE__ */
|
|
266
|
-
icon: /* @__PURE__ */
|
|
279
|
+
children: [/* @__PURE__ */ k(s, {
|
|
280
|
+
icon: /* @__PURE__ */ k(w, { className: "h-7 w-7" }),
|
|
267
281
|
seed: e.id,
|
|
282
|
+
fileId: e.image?.id,
|
|
283
|
+
alt: e.title,
|
|
268
284
|
className: "h-28 w-full"
|
|
269
|
-
}), /* @__PURE__ */
|
|
285
|
+
}), /* @__PURE__ */ A("div", {
|
|
270
286
|
className: "p-3",
|
|
271
|
-
children: [/* @__PURE__ */
|
|
287
|
+
children: [/* @__PURE__ */ k("p", {
|
|
272
288
|
className: "truncate text-sm font-medium text-text-primary",
|
|
273
289
|
children: e.title
|
|
274
|
-
}), /* @__PURE__ */
|
|
290
|
+
}), /* @__PURE__ */ A("div", {
|
|
275
291
|
className: "mt-1.5 flex items-center justify-between",
|
|
276
|
-
children: [/* @__PURE__ */
|
|
292
|
+
children: [/* @__PURE__ */ k("span", {
|
|
277
293
|
className: "text-xs text-text-secondary",
|
|
278
294
|
children: m(e.occasion)
|
|
279
|
-
}), /* @__PURE__ */
|
|
295
|
+
}), /* @__PURE__ */ A("span", {
|
|
280
296
|
className: "flex items-center gap-1 text-xs text-text-secondary",
|
|
281
297
|
children: [
|
|
282
|
-
/* @__PURE__ */
|
|
298
|
+
/* @__PURE__ */ k(b, { className: "h-3 w-3" }),
|
|
283
299
|
" ",
|
|
284
300
|
e.likeCount
|
|
285
301
|
]
|
|
@@ -289,44 +305,46 @@ function N() {
|
|
|
289
305
|
}, e.id))
|
|
290
306
|
})]
|
|
291
307
|
}),
|
|
292
|
-
H.length > 0 && /* @__PURE__ */
|
|
308
|
+
H.length > 0 && /* @__PURE__ */ A("section", { children: [/* @__PURE__ */ A("div", {
|
|
293
309
|
className: "mb-4 flex items-center justify-between",
|
|
294
|
-
children: [/* @__PURE__ */
|
|
310
|
+
children: [/* @__PURE__ */ k("h2", {
|
|
295
311
|
className: "text-lg font-semibold text-text-primary",
|
|
296
312
|
children: "Recently updated brands"
|
|
297
|
-
}), /* @__PURE__ */
|
|
313
|
+
}), /* @__PURE__ */ A("button", {
|
|
298
314
|
type: "button",
|
|
299
315
|
onClick: () => _("/brands"),
|
|
300
316
|
className: "flex items-center gap-1 text-sm font-medium text-primary hover:underline",
|
|
301
|
-
children: ["View all ", /* @__PURE__ */
|
|
317
|
+
children: ["View all ", /* @__PURE__ */ k(g, { className: "h-3.5 w-3.5" })]
|
|
302
318
|
})]
|
|
303
|
-
}), /* @__PURE__ */
|
|
319
|
+
}), /* @__PURE__ */ k("div", {
|
|
304
320
|
className: "divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface",
|
|
305
|
-
children: H.map((e) => /* @__PURE__ */
|
|
321
|
+
children: H.map((e) => /* @__PURE__ */ A("button", {
|
|
306
322
|
type: "button",
|
|
307
323
|
onClick: () => _(`/brands/${e.id}`),
|
|
308
324
|
className: "flex w-full items-center gap-4 px-4 py-3 text-left transition-colors hover:bg-bg-sunken/50",
|
|
309
325
|
children: [
|
|
310
|
-
/* @__PURE__ */
|
|
311
|
-
icon: /* @__PURE__ */
|
|
326
|
+
/* @__PURE__ */ k(s, {
|
|
327
|
+
icon: /* @__PURE__ */ k(E, { className: "h-5 w-5" }),
|
|
312
328
|
seed: e.id,
|
|
329
|
+
fileId: e.logo?.id ?? e.cover?.id,
|
|
330
|
+
alt: e.name,
|
|
313
331
|
className: "h-11 w-11 shrink-0"
|
|
314
332
|
}),
|
|
315
|
-
/* @__PURE__ */
|
|
333
|
+
/* @__PURE__ */ A("div", {
|
|
316
334
|
className: "min-w-0 flex-1",
|
|
317
|
-
children: [/* @__PURE__ */
|
|
335
|
+
children: [/* @__PURE__ */ A("div", {
|
|
318
336
|
className: "flex items-center gap-2",
|
|
319
|
-
children: [/* @__PURE__ */
|
|
337
|
+
children: [/* @__PURE__ */ k("p", {
|
|
320
338
|
className: "truncate text-sm font-medium text-text-primary",
|
|
321
339
|
children: e.name
|
|
322
|
-
}), e.isFeatured && /* @__PURE__ */
|
|
323
|
-
}), /* @__PURE__ */
|
|
340
|
+
}), e.isFeatured && /* @__PURE__ */ k(T, { className: "h-3.5 w-3.5 fill-status-warning-text text-status-warning-text" })]
|
|
341
|
+
}), /* @__PURE__ */ A("p", {
|
|
324
342
|
className: "truncate text-xs text-text-secondary",
|
|
325
343
|
children: ["@", e.handle]
|
|
326
344
|
})]
|
|
327
345
|
}),
|
|
328
|
-
/* @__PURE__ */
|
|
329
|
-
/* @__PURE__ */
|
|
346
|
+
/* @__PURE__ */ k(i, { status: e.status }),
|
|
347
|
+
/* @__PURE__ */ k("span", {
|
|
330
348
|
className: "hidden shrink-0 text-xs text-text-secondary sm:inline",
|
|
331
349
|
children: p(e.updatedAt)
|
|
332
350
|
})
|
|
@@ -337,6 +355,6 @@ function N() {
|
|
|
337
355
|
});
|
|
338
356
|
}
|
|
339
357
|
//#endregion
|
|
340
|
-
export {
|
|
358
|
+
export { F as HomePage };
|
|
341
359
|
|
|
342
360
|
//# sourceMappingURL=HomePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HomePage.js","names":[],"sources":["../../../src/coolandlovely/pages/HomePage.tsx"],"sourcesContent":["/**\n * Overview / Home Page\n * @module coolandlovely/pages\n *\n * The CoolAndLovely command center landing page: a style-operating-system\n * dashboard rolling up live catalog (brands, items), social (looks,\n * collaborations) and the shopper's own wardrobe — all from real `coo*` ops.\n */\n\nimport { useMemo } from 'react';\nimport {\n Store,\n Shirt,\n Sparkles,\n Handshake,\n Shapes,\n Heart,\n ArrowRight,\n Star,\n Plus,\n BookHeart,\n UserCircle,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { MetricsCard } from '../components/MetricsCard';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { LoadingView, ErrorView } from '../components/StateViews';\nimport { Thumbnail } from '../components/Thumbnail';\nimport { useCoolAndLovely } from '../context/CoolAndLovelyContext';\nimport { useBrands, useStyleItems, useLooks, useCollaborations, useWardrobeItems } from '../hooks';\nimport { formatRelativeTime, titleCase } from '../utils/formatters';\nimport { cn } from '../utils/cn';\nimport type { DashboardStats } from '../types';\n\ninterface QuickAction {\n label: string;\n description: string;\n icon: React.ReactNode;\n path: string;\n color: string;\n}\n\nconst quickActions: QuickAction[] = [\n {\n label: 'New Brand',\n description: 'Launch a storefront',\n icon: <Store className=\"h-5 w-5\" />,\n path: '/brands/new',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n {\n label: 'Add Style Item',\n description: 'List a piece',\n icon: <Shirt className=\"h-5 w-5\" />,\n path: '/items/new',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n {\n label: 'Publish a Look',\n description: 'Shop-the-look outfit',\n icon: <Sparkles className=\"h-5 w-5\" />,\n path: '/looks/new',\n color: 'bg-status-success-bg-subtle text-status-success-text',\n },\n {\n label: 'My Wardrobe',\n description: 'What you own',\n icon: <Heart className=\"h-5 w-5\" />,\n path: '/wardrobe',\n color: 'bg-status-warning-bg-subtle text-status-warning-text',\n },\n];\n\nconst modules = [\n {\n label: 'Brands',\n description: 'Storefronts with a publish lifecycle',\n icon: <Store className=\"h-6 w-6\" />,\n path: '/brands',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n {\n label: 'Collections',\n description: 'Seasonal drops & curated edits',\n icon: <Shapes className=\"h-6 w-6\" />,\n path: '/collections',\n color: 'bg-accent-blue-subtle text-accent-blue',\n },\n {\n label: 'Style Items',\n description: 'The shoppable catalogue',\n icon: <Shirt className=\"h-6 w-6\" />,\n path: '/items',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n {\n label: 'Looks',\n description: 'Published shop-the-look outfits',\n icon: <Sparkles className=\"h-6 w-6\" />,\n path: '/looks',\n color: 'bg-status-success-bg-subtle text-status-success-text',\n },\n {\n label: 'Collaborations',\n description: 'Brand × creator partnerships',\n icon: <Handshake className=\"h-6 w-6\" />,\n path: '/collaborations',\n color: 'bg-status-warning-bg-subtle text-status-warning-text',\n },\n {\n label: 'Wardrobe',\n description: 'Your digital closet & wear log',\n icon: <Heart className=\"h-6 w-6\" />,\n path: '/wardrobe',\n color: 'bg-status-error-bg-subtle text-status-error-text',\n },\n {\n label: 'Lookbooks',\n description: 'Themed boards of saved pieces',\n icon: <BookHeart className=\"h-6 w-6\" />,\n path: '/lookbooks',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n {\n label: 'Style Profile',\n description: 'Your taste, palette & sizing',\n icon: <UserCircle className=\"h-6 w-6\" />,\n path: '/profile',\n color: 'bg-accent-blue-subtle text-accent-blue',\n },\n];\n\nexport function HomePage() {\n const { navigateTo, currentUser } = useCoolAndLovely();\n\n const brands = useBrands();\n const items = useStyleItems();\n const looks = useLooks();\n const collaborations = useCollaborations();\n const wardrobe = useWardrobeItems();\n\n const firstName = currentUser?.firstName ?? currentUser?.name ?? 'there';\n\n const isLoading =\n brands.isLoading ||\n items.isLoading ||\n looks.isLoading ||\n collaborations.isLoading ||\n wardrobe.isLoading;\n\n const isError = brands.isError && items.isError && looks.isError && collaborations.isError;\n\n const stats = useMemo<DashboardStats>(() => {\n const brandItems = brands.data?.items ?? [];\n const styleItems = items.data?.items ?? [];\n const lookItems = looks.data?.items ?? [];\n const collabs = collaborations.data ?? [];\n const wardrobeItems = wardrobe.data ?? [];\n return {\n totalBrands: brandItems.length,\n publishedBrands: brandItems.filter((b) => b.status === 'PUBLISHED').length,\n totalStyleItems: styleItems.length,\n activeStyleItems: styleItems.filter((i) => i.status === 'ACTIVE').length,\n totalLooks: lookItems.length,\n featuredLooks: lookItems.filter((l) => l.isFeatured).length,\n activeCollaborations: collabs.filter(\n (c) => c.status === 'ACCEPTED' || c.status === 'IN_PROGRESS'\n ).length,\n wardrobeItems: wardrobeItems.length,\n };\n }, [brands.data, items.data, looks.data, collaborations.data, wardrobe.data]);\n\n const latestLooks = useMemo(() => [...(looks.data?.items ?? [])].slice(0, 6), [looks.data]);\n\n const recentBrands = useMemo(\n () =>\n [...(brands.data?.items ?? [])]\n .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())\n .slice(0, 4),\n [brands.data]\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"CoolAndLovely\">\n <LoadingView label=\"Loading your style command center…\" />\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"CoolAndLovely\">\n <ErrorView\n title=\"Could not load CoolAndLovely\"\n message=\"The fashion service did not respond. Please try again.\"\n onRetry={() => {\n void brands.refetch();\n void items.refetch();\n void looks.refetch();\n void collaborations.refetch();\n void wardrobe.refetch();\n }}\n />\n </PageLayout>\n );\n }\n\n const metrics = [\n {\n icon: <Store className=\"h-5 w-5\" />,\n value: stats.totalBrands.toString(),\n label: 'Brands',\n sub: `${stats.publishedBrands} published`,\n },\n {\n icon: <Shirt className=\"h-5 w-5\" />,\n value: stats.totalStyleItems.toString(),\n label: 'Style Items',\n sub: `${stats.activeStyleItems} active`,\n },\n {\n icon: <Sparkles className=\"h-5 w-5\" />,\n value: stats.totalLooks.toString(),\n label: 'Looks',\n sub: `${stats.featuredLooks} featured`,\n },\n {\n icon: <Handshake className=\"h-5 w-5\" />,\n value: stats.activeCollaborations.toString(),\n label: 'Active Collabs',\n sub: `${stats.wardrobeItems} in wardrobe`,\n },\n ];\n\n return (\n <PageLayout\n title={`Hello, ${firstName}`}\n description=\"Your fashion & lifestyle command center\"\n hero\n >\n <PagePurpose className=\"mb-6\">\n CoolAndLovely connects the three sides of style on one workspace-native model: brands launch\n storefronts and seasonal collections, you build a wardrobe and lookbooks, and creators\n publish shop-the-look outfits and run brand collaborations. Jump into any module below — all\n data is live from the CoolAndLovely service.\n </PagePurpose>\n\n {/* Headline metrics — the one emphasis zone for this page */}\n <EmphasisPanel className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">At a glance</h2>\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n {metrics.map((m) => (\n <MetricsCard\n key={m.label}\n icon={m.icon}\n value={m.value}\n label={m.label}\n trendValue={m.sub}\n trend=\"neutral\"\n />\n ))}\n </div>\n </EmphasisPanel>\n\n {/* Quick Actions */}\n <section className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Quick actions</h2>\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n {quickActions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n onClick={() => navigateTo(action.path)}\n className={cn(\n 'flex items-start gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left shadow-sm transition-all',\n 'hover:border-accent-foreground/20 hover:shadow-md'\n )}\n >\n <div\n className={cn(\n 'flex h-10 w-10 shrink-0 items-center justify-center rounded-lg',\n action.color\n )}\n >\n {action.icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-semibold text-text-primary\">{action.label}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{action.description}</p>\n </div>\n <Plus className=\"mt-1 h-4 w-4 shrink-0 text-text-secondary\" />\n </button>\n ))}\n </div>\n </section>\n\n {/* Modules */}\n <section className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Explore</h2>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {modules.map((mod) => (\n <button\n key={mod.label}\n type=\"button\"\n onClick={() => navigateTo(mod.path)}\n className=\"flex flex-col gap-3 rounded-lg border border-border-seam bg-bg-surface p-5 text-left transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <div\n className={cn('flex h-12 w-12 items-center justify-center rounded-full', mod.color)}\n >\n {mod.icon}\n </div>\n <div>\n <p className=\"text-sm font-semibold text-text-primary\">{mod.label}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{mod.description}</p>\n </div>\n </button>\n ))}\n </div>\n </section>\n\n {/* Latest looks */}\n <section className=\"mb-8\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Latest looks</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/looks')}\n className=\"flex items-center gap-1 text-sm font-medium text-primary hover:underline\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n {latestLooks.length === 0 ? (\n <p className=\"rounded-lg border border-border-seam bg-bg-surface p-6 text-sm text-text-secondary\">\n No looks published yet. Be the first to publish a shop-the-look outfit.\n </p>\n ) : (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6\">\n {latestLooks.map((look) => (\n <button\n key={look.id}\n type=\"button\"\n onClick={() => navigateTo(`/looks/${look.id}`)}\n className=\"group overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <Thumbnail\n icon={<Sparkles className=\"h-7 w-7\" />}\n seed={look.id}\n className=\"h-28 w-full\"\n />\n <div className=\"p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{look.title}</p>\n <div className=\"mt-1.5 flex items-center justify-between\">\n <span className=\"text-xs text-text-secondary\">{titleCase(look.occasion)}</span>\n <span className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Heart className=\"h-3 w-3\" /> {look.likeCount}\n </span>\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n </section>\n\n {/* Recent brands */}\n {recentBrands.length > 0 && (\n <section>\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Recently updated brands</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands')}\n className=\"flex items-center gap-1 text-sm font-medium text-primary hover:underline\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div className=\"divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface\">\n {recentBrands.map((brand) => (\n <button\n key={brand.id}\n type=\"button\"\n onClick={() => navigateTo(`/brands/${brand.id}`)}\n className=\"flex w-full items-center gap-4 px-4 py-3 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n <Thumbnail\n icon={<Store className=\"h-5 w-5\" />}\n seed={brand.id}\n className=\"h-11 w-11 shrink-0\"\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{brand.name}</p>\n {brand.isFeatured && (\n <Star className=\"h-3.5 w-3.5 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 <span className=\"hidden shrink-0 text-xs text-text-secondary sm:inline\">\n {formatRelativeTime(brand.updatedAt)}\n </span>\n </button>\n ))}\n </div>\n </section>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HomePage.js","names":[],"sources":["../../../src/coolandlovely/pages/HomePage.tsx"],"sourcesContent":["/**\n * Overview / Home Page\n * @module coolandlovely/pages\n *\n * The CoolAndLovely command center landing page: a style-operating-system\n * dashboard rolling up live catalog (brands, items), social (looks,\n * collaborations) and the shopper's own wardrobe — all from real `coo*` ops.\n */\n\nimport { useMemo } from 'react';\nimport {\n Store,\n Shirt,\n Sparkles,\n Handshake,\n Shapes,\n Heart,\n ArrowRight,\n Star,\n Plus,\n BookHeart,\n UserCircle,\n Compass,\n TrendingUp,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { MetricsCard } from '../components/MetricsCard';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { LoadingView, ErrorView } from '../components/StateViews';\nimport { Thumbnail } from '../components/Thumbnail';\nimport { useCoolAndLovely } from '../context/CoolAndLovelyContext';\nimport { useBrands, useStyleItems, useLooks, useCollaborations, useWardrobeItems } from '../hooks';\nimport { formatRelativeTime, titleCase } from '../utils/formatters';\nimport { cn } from '../utils/cn';\nimport type { DashboardStats } from '../types';\n\ninterface QuickAction {\n label: string;\n description: string;\n icon: React.ReactNode;\n path: string;\n color: string;\n}\n\nconst quickActions: QuickAction[] = [\n {\n label: 'New Brand',\n description: 'Launch a storefront',\n icon: <Store className=\"h-5 w-5\" />,\n path: '/brands/new',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n {\n label: 'Add Style Item',\n description: 'List a piece',\n icon: <Shirt className=\"h-5 w-5\" />,\n path: '/items/new',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n {\n label: 'Publish a Look',\n description: 'Shop-the-look outfit',\n icon: <Sparkles className=\"h-5 w-5\" />,\n path: '/looks/new',\n color: 'bg-status-success-bg-subtle text-status-success-text',\n },\n {\n label: 'My Wardrobe',\n description: 'What you own',\n icon: <Heart className=\"h-5 w-5\" />,\n path: '/wardrobe',\n color: 'bg-status-warning-bg-subtle text-status-warning-text',\n },\n];\n\nconst modules = [\n {\n label: 'Brands',\n description: 'Storefronts with a publish lifecycle',\n icon: <Store className=\"h-6 w-6\" />,\n path: '/brands',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n {\n label: 'Collections',\n description: 'Seasonal drops & curated edits',\n icon: <Shapes className=\"h-6 w-6\" />,\n path: '/collections',\n color: 'bg-accent-blue-subtle text-accent-blue',\n },\n {\n label: 'Style Items',\n description: 'The shoppable catalogue',\n icon: <Shirt className=\"h-6 w-6\" />,\n path: '/items',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n {\n label: 'Looks',\n description: 'Published shop-the-look outfits',\n icon: <Sparkles className=\"h-6 w-6\" />,\n path: '/looks',\n color: 'bg-status-success-bg-subtle text-status-success-text',\n },\n {\n label: 'Collaborations',\n description: 'Brand × creator partnerships',\n icon: <Handshake className=\"h-6 w-6\" />,\n path: '/collaborations',\n color: 'bg-status-warning-bg-subtle text-status-warning-text',\n },\n {\n label: 'Wardrobe',\n description: 'Your digital closet & wear log',\n icon: <Heart className=\"h-6 w-6\" />,\n path: '/wardrobe',\n color: 'bg-status-error-bg-subtle text-status-error-text',\n },\n {\n label: 'Lookbooks',\n description: 'Themed boards of saved pieces',\n icon: <BookHeart className=\"h-6 w-6\" />,\n path: '/lookbooks',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n {\n label: 'Style Profile',\n description: 'Your taste, palette & sizing',\n icon: <UserCircle className=\"h-6 w-6\" />,\n path: '/profile',\n color: 'bg-accent-blue-subtle text-accent-blue',\n },\n {\n label: 'Discover',\n description: 'A feed tuned to your taste',\n icon: <Compass className=\"h-6 w-6\" />,\n path: '/discover',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n {\n label: 'Trends',\n description: 'Live signals from platform activity',\n icon: <TrendingUp className=\"h-6 w-6\" />,\n path: '/trends',\n color: 'bg-status-success-bg-subtle text-status-success-text',\n },\n];\n\nexport function HomePage() {\n const { navigateTo, currentUser } = useCoolAndLovely();\n\n const brands = useBrands();\n const items = useStyleItems();\n const looks = useLooks();\n const collaborations = useCollaborations();\n const wardrobe = useWardrobeItems();\n\n const firstName = currentUser?.firstName ?? currentUser?.name ?? 'there';\n\n const isLoading =\n brands.isLoading ||\n items.isLoading ||\n looks.isLoading ||\n collaborations.isLoading ||\n wardrobe.isLoading;\n\n const isError = brands.isError && items.isError && looks.isError && collaborations.isError;\n\n const stats = useMemo<DashboardStats>(() => {\n const brandItems = brands.data?.items ?? [];\n const styleItems = items.data?.items ?? [];\n const lookItems = looks.data?.items ?? [];\n const collabs = collaborations.data ?? [];\n const wardrobeItems = wardrobe.data ?? [];\n return {\n totalBrands: brandItems.length,\n publishedBrands: brandItems.filter((b) => b.status === 'PUBLISHED').length,\n totalStyleItems: styleItems.length,\n activeStyleItems: styleItems.filter((i) => i.status === 'ACTIVE').length,\n totalLooks: lookItems.length,\n featuredLooks: lookItems.filter((l) => l.isFeatured).length,\n activeCollaborations: collabs.filter(\n (c) => c.status === 'ACCEPTED' || c.status === 'IN_PROGRESS'\n ).length,\n wardrobeItems: wardrobeItems.length,\n };\n }, [brands.data, items.data, looks.data, collaborations.data, wardrobe.data]);\n\n const latestLooks = useMemo(() => [...(looks.data?.items ?? [])].slice(0, 6), [looks.data]);\n\n const recentBrands = useMemo(\n () =>\n [...(brands.data?.items ?? [])]\n .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())\n .slice(0, 4),\n [brands.data]\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"CoolAndLovely\">\n <LoadingView label=\"Loading your style command center…\" />\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"CoolAndLovely\">\n <ErrorView\n title=\"Could not load CoolAndLovely\"\n message=\"The fashion service did not respond. Please try again.\"\n onRetry={() => {\n void brands.refetch();\n void items.refetch();\n void looks.refetch();\n void collaborations.refetch();\n void wardrobe.refetch();\n }}\n />\n </PageLayout>\n );\n }\n\n const metrics = [\n {\n icon: <Store className=\"h-5 w-5\" />,\n value: stats.totalBrands.toString(),\n label: 'Brands',\n sub: `${stats.publishedBrands} published`,\n },\n {\n icon: <Shirt className=\"h-5 w-5\" />,\n value: stats.totalStyleItems.toString(),\n label: 'Style Items',\n sub: `${stats.activeStyleItems} active`,\n },\n {\n icon: <Sparkles className=\"h-5 w-5\" />,\n value: stats.totalLooks.toString(),\n label: 'Looks',\n sub: `${stats.featuredLooks} featured`,\n },\n {\n icon: <Handshake className=\"h-5 w-5\" />,\n value: stats.activeCollaborations.toString(),\n label: 'Active Collabs',\n sub: `${stats.wardrobeItems} in wardrobe`,\n },\n ];\n\n return (\n <PageLayout\n title={`Hello, ${firstName}`}\n description=\"Your fashion & lifestyle command center\"\n hero\n >\n <PagePurpose className=\"mb-6\">\n CoolAndLovely connects the three sides of style on one workspace-native model: brands launch\n storefronts and seasonal collections, you build a wardrobe and lookbooks, and creators\n publish shop-the-look outfits and run brand collaborations. Jump into any module below — all\n data is live from the CoolAndLovely service.\n </PagePurpose>\n\n {/* Headline metrics — the one emphasis zone for this page */}\n <EmphasisPanel className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">At a glance</h2>\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n {metrics.map((m) => (\n <MetricsCard\n key={m.label}\n icon={m.icon}\n value={m.value}\n label={m.label}\n trendValue={m.sub}\n trend=\"neutral\"\n />\n ))}\n </div>\n </EmphasisPanel>\n\n {/* Quick Actions */}\n <section className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Quick actions</h2>\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n {quickActions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n onClick={() => navigateTo(action.path)}\n className={cn(\n 'flex items-start gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left shadow-sm transition-all',\n 'hover:border-accent-foreground/20 hover:shadow-md'\n )}\n >\n <div\n className={cn(\n 'flex h-10 w-10 shrink-0 items-center justify-center rounded-lg',\n action.color\n )}\n >\n {action.icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-semibold text-text-primary\">{action.label}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{action.description}</p>\n </div>\n <Plus className=\"mt-1 h-4 w-4 shrink-0 text-text-secondary\" />\n </button>\n ))}\n </div>\n </section>\n\n {/* Modules */}\n <section className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Explore</h2>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {modules.map((mod) => (\n <button\n key={mod.label}\n type=\"button\"\n onClick={() => navigateTo(mod.path)}\n className=\"flex flex-col gap-3 rounded-lg border border-border-seam bg-bg-surface p-5 text-left transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <div\n className={cn('flex h-12 w-12 items-center justify-center rounded-full', mod.color)}\n >\n {mod.icon}\n </div>\n <div>\n <p className=\"text-sm font-semibold text-text-primary\">{mod.label}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{mod.description}</p>\n </div>\n </button>\n ))}\n </div>\n </section>\n\n {/* Latest looks */}\n <section className=\"mb-8\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Latest looks</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/looks')}\n className=\"flex items-center gap-1 text-sm font-medium text-primary hover:underline\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n {latestLooks.length === 0 ? (\n <p className=\"rounded-lg border border-border-seam bg-bg-surface p-6 text-sm text-text-secondary\">\n No looks published yet. Be the first to publish a shop-the-look outfit.\n </p>\n ) : (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6\">\n {latestLooks.map((look) => (\n <button\n key={look.id}\n type=\"button\"\n onClick={() => navigateTo(`/looks/${look.id}`)}\n className=\"group overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <Thumbnail\n icon={<Sparkles className=\"h-7 w-7\" />}\n seed={look.id}\n fileId={look.image?.id}\n alt={look.title}\n className=\"h-28 w-full\"\n />\n <div className=\"p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{look.title}</p>\n <div className=\"mt-1.5 flex items-center justify-between\">\n <span className=\"text-xs text-text-secondary\">{titleCase(look.occasion)}</span>\n <span className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Heart className=\"h-3 w-3\" /> {look.likeCount}\n </span>\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n </section>\n\n {/* Recent brands */}\n {recentBrands.length > 0 && (\n <section>\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Recently updated brands</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands')}\n className=\"flex items-center gap-1 text-sm font-medium text-primary hover:underline\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n <div className=\"divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface\">\n {recentBrands.map((brand) => (\n <button\n key={brand.id}\n type=\"button\"\n onClick={() => navigateTo(`/brands/${brand.id}`)}\n className=\"flex w-full items-center gap-4 px-4 py-3 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n <Thumbnail\n icon={<Store className=\"h-5 w-5\" />}\n seed={brand.id}\n fileId={brand.logo?.id ?? brand.cover?.id}\n alt={brand.name}\n className=\"h-11 w-11 shrink-0\"\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{brand.name}</p>\n {brand.isFeatured && (\n <Star className=\"h-3.5 w-3.5 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 <span className=\"hidden shrink-0 text-xs text-text-secondary sm:inline\">\n {formatRelativeTime(brand.updatedAt)}\n </span>\n </button>\n ))}\n </div>\n </section>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|