@burdenoff/microfe-coolandlovely 2026.706.1 → 2026.706.3

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