@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.
Files changed (66) hide show
  1. package/dist/coolandlovely/CoolAndLovelyRoutes.js +14 -6
  2. package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
  3. package/dist/coolandlovely/components/ActorName.js +29 -0
  4. package/dist/coolandlovely/components/ActorName.js.map +1 -0
  5. package/dist/coolandlovely/components/AddToLookbookButton.js +81 -0
  6. package/dist/coolandlovely/components/AddToLookbookButton.js.map +1 -0
  7. package/dist/coolandlovely/components/Comments.js +109 -0
  8. package/dist/coolandlovely/components/Comments.js.map +1 -0
  9. package/dist/coolandlovely/components/Field.js +22 -2
  10. package/dist/coolandlovely/components/Field.js.map +1 -1
  11. package/dist/coolandlovely/components/FileImage.js +17 -0
  12. package/dist/coolandlovely/components/FileImage.js.map +1 -0
  13. package/dist/coolandlovely/components/FollowButton.js +24 -0
  14. package/dist/coolandlovely/components/FollowButton.js.map +1 -0
  15. package/dist/coolandlovely/components/ImageUploadField.js +71 -0
  16. package/dist/coolandlovely/components/ImageUploadField.js.map +1 -0
  17. package/dist/coolandlovely/components/Thumbnail.js +20 -13
  18. package/dist/coolandlovely/components/Thumbnail.js.map +1 -1
  19. package/dist/coolandlovely/hooks/index.js +2 -0
  20. package/dist/coolandlovely/hooks/useComments.js +68 -0
  21. package/dist/coolandlovely/hooks/useComments.js.map +1 -0
  22. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +74 -4
  23. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
  24. package/dist/coolandlovely/hooks/useFiles.js +94 -0
  25. package/dist/coolandlovely/hooks/useFiles.js.map +1 -0
  26. package/dist/coolandlovely/pages/HomePage.js +105 -87
  27. package/dist/coolandlovely/pages/HomePage.js.map +1 -1
  28. package/dist/coolandlovely/pages/brands/BrandDetailPage.js +144 -122
  29. package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -1
  30. package/dist/coolandlovely/pages/brands/BrandFormPage.js +128 -90
  31. package/dist/coolandlovely/pages/brands/BrandFormPage.js.map +1 -1
  32. package/dist/coolandlovely/pages/brands/BrandsListPage.js +2 -0
  33. package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -1
  34. package/dist/coolandlovely/pages/collections/CollectionDetailPage.js +5 -1
  35. package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -1
  36. package/dist/coolandlovely/pages/collections/CollectionFormPage.js +117 -102
  37. package/dist/coolandlovely/pages/collections/CollectionFormPage.js.map +1 -1
  38. package/dist/coolandlovely/pages/collections/CollectionsListPage.js +2 -0
  39. package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -1
  40. package/dist/coolandlovely/pages/discover/DiscoverPage.js +223 -0
  41. package/dist/coolandlovely/pages/discover/DiscoverPage.js.map +1 -0
  42. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +99 -95
  43. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -1
  44. package/dist/coolandlovely/pages/items/StyleItemFormPage.js +144 -130
  45. package/dist/coolandlovely/pages/items/StyleItemFormPage.js.map +1 -1
  46. package/dist/coolandlovely/pages/items/StyleItemsListPage.js +2 -0
  47. package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -1
  48. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +190 -99
  49. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -1
  50. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js +81 -68
  51. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -1
  52. package/dist/coolandlovely/pages/looks/LookDetailPage.js +195 -155
  53. package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -1
  54. package/dist/coolandlovely/pages/looks/LookFormPage.js +127 -88
  55. package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -1
  56. package/dist/coolandlovely/pages/looks/LooksListPage.js +2 -0
  57. package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -1
  58. package/dist/coolandlovely/pages/profile/StyleProfilePage.js +169 -101
  59. package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -1
  60. package/dist/coolandlovely/pages/trends/TrendsPage.js +249 -0
  61. package/dist/coolandlovely/pages/trends/TrendsPage.js.map +1 -0
  62. package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js +88 -76
  63. package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js.map +1 -1
  64. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js +2 -0
  65. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -1
  66. package/package.json +1 -1
@@ -0,0 +1,223 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js";
4
+ import { Thumbnail as i } from "../../components/Thumbnail.js";
5
+ import { useLooks as a, useMyFollowing as o, useMyStyleProfile as s, useStyleItems as c } from "../../hooks/useCoolAndLovelyApi.js";
6
+ import "../../hooks/index.js";
7
+ import { titleCase as l } from "../../utils/formatters.js";
8
+ import { TagList as u } from "../../components/TagList.js";
9
+ import { EmptyState as d } from "../../components/EmptyState.js";
10
+ import { useMemo as f } from "react";
11
+ import { Compass as p, Heart as m, ShoppingBag as h, Sparkles as g, UserCheck as _, Users as v } from "lucide-react";
12
+ import { jsx as y, jsxs as b } from "react/jsx-runtime";
13
+ import { EmphasisPanel as x, PagePurpose as S } from "@burdenoff/fe-libs/ui";
14
+ //#region src/coolandlovely/pages/discover/DiscoverPage.tsx
15
+ function C(e) {
16
+ return new Set(e.map((e) => e.trim().toLowerCase()).filter(Boolean));
17
+ }
18
+ function w(e, t) {
19
+ let n = 0;
20
+ for (let r of e) t.has(r.trim().toLowerCase()) && (n += 1);
21
+ return n;
22
+ }
23
+ var T = ({ title: e, icon: t, sublabel: n, children: r }) => /* @__PURE__ */ b("section", {
24
+ className: "mt-8",
25
+ children: [/* @__PURE__ */ b("div", {
26
+ className: "mb-3",
27
+ children: [/* @__PURE__ */ b("h2", {
28
+ className: "flex items-center gap-2 text-lg font-semibold text-text-primary",
29
+ children: [
30
+ t,
31
+ " ",
32
+ e
33
+ ]
34
+ }), n ? /* @__PURE__ */ y("p", {
35
+ className: "mt-0.5 text-sm text-text-secondary",
36
+ children: n
37
+ }) : null]
38
+ }), r]
39
+ });
40
+ function E() {
41
+ let { navigateTo: E } = e(), D = s(), O = a({ pagination: {
42
+ limit: 100,
43
+ offset: 0
44
+ } }), k = c({ pagination: {
45
+ limit: 100,
46
+ offset: 0
47
+ } }), A = o(), j = D.isLoading || O.isLoading || k.isLoading, M = O.isError && k.isError, N = f(() => {
48
+ let e = D.data, t = O.data?.items ?? [], n = k.data?.items ?? [], r = new Set((A.data ?? []).map((e) => e.ownerId)), i = C([
49
+ ...e?.stylePreferences ?? [],
50
+ ...e?.palette ?? [],
51
+ ...e?.favouriteBrands ?? []
52
+ ]), a = C(e?.palette ?? []), o = C(e?.favouriteBrands ?? []), s = (e) => w(e.tags, i) * 2 + +!!i.has(e.occasion.toLowerCase()) + e.likeCount * .05 + e.saveCount * .05, c = (e) => w(e.tags, i) * 2 + w(e.colours, a) * 2 + +!!i.has(e.category.toLowerCase()) + (o.size && e.tags.some((e) => o.has(e.toLowerCase())) ? 1 : 0), l = i.size > 0, u = [...t].sort((e, t) => l ? s(t) - s(e) : t.likeCount + t.saveCount - (e.likeCount + e.saveCount)).slice(0, 8), d = [...n].filter((e) => l ? c(e) > 0 : !0).sort((e, t) => c(t) - c(e)).slice(0, 8), f = t.filter((e) => r.has(e.authorId)).sort((e, t) => t.likeCount + t.saveCount - (e.likeCount + e.saveCount)).slice(0, 8);
53
+ return {
54
+ hasProfile: !!e,
55
+ hasTaste: l,
56
+ madeForYou: u,
57
+ inYourPalette: d,
58
+ fromFollowing: f,
59
+ followingProfiles: A.data ?? []
60
+ };
61
+ }, [
62
+ D.data,
63
+ O.data,
64
+ k.data,
65
+ A.data
66
+ ]);
67
+ return j ? /* @__PURE__ */ y(t, {
68
+ title: "Discover",
69
+ children: /* @__PURE__ */ y(r, { label: "Curating your feed…" })
70
+ }) : M ? /* @__PURE__ */ y(t, {
71
+ title: "Discover",
72
+ children: /* @__PURE__ */ y(n, { onRetry: () => {
73
+ O.refetch(), k.refetch();
74
+ } })
75
+ }) : /* @__PURE__ */ b(t, {
76
+ title: "Discover",
77
+ description: "Looks and pieces tuned to your taste",
78
+ hero: !0,
79
+ children: [
80
+ /* @__PURE__ */ y(S, {
81
+ className: "mb-6",
82
+ children: "Your personalised feed, computed live from your style profile against the pieces and looks on the platform — the closer a piece matches the aesthetics, palette and brands you follow, the higher it ranks. Nothing here is fabricated."
83
+ }),
84
+ N.hasProfile ? null : /* @__PURE__ */ y(x, {
85
+ className: "mb-8",
86
+ children: /* @__PURE__ */ b("div", {
87
+ className: "flex flex-col items-start gap-3 sm:flex-row sm:items-center sm:justify-between",
88
+ children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("h2", {
89
+ className: "text-lg font-semibold text-text-primary",
90
+ children: "Build your style profile"
91
+ }), /* @__PURE__ */ y("p", {
92
+ className: "mt-1 text-sm text-text-secondary",
93
+ children: "Tell us your aesthetics, palette and favourite brands and this feed tunes itself to you."
94
+ })] }), /* @__PURE__ */ b("button", {
95
+ type: "button",
96
+ onClick: () => E("/profile"),
97
+ className: "inline-flex shrink-0 items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-opacity hover:opacity-90",
98
+ children: [/* @__PURE__ */ y(g, { className: "h-4 w-4" }), " Create profile"]
99
+ })]
100
+ })
101
+ }),
102
+ /* @__PURE__ */ y(T, {
103
+ title: "Made for you",
104
+ icon: /* @__PURE__ */ y(p, { className: "h-5 w-5" }),
105
+ sublabel: N.hasTaste ? "Ranked to match your style profile" : "Most-loved looks on the platform",
106
+ children: N.madeForYou.length === 0 ? /* @__PURE__ */ y(d, {
107
+ title: "No looks yet",
108
+ description: "Once looks are published they will appear here, tuned to your taste."
109
+ }) : /* @__PURE__ */ y("div", {
110
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
111
+ children: N.madeForYou.map((e) => /* @__PURE__ */ b("button", {
112
+ type: "button",
113
+ onClick: () => E(`/looks/${e.id}`),
114
+ className: "group flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-colors hover:border-accent-foreground/20 hover:shadow-md",
115
+ children: [/* @__PURE__ */ y(i, {
116
+ icon: /* @__PURE__ */ y(g, { className: "h-6 w-6" }),
117
+ seed: e.id,
118
+ fileId: e.image?.id,
119
+ alt: e.title,
120
+ className: "aspect-[4/5] w-full rounded-none"
121
+ }), /* @__PURE__ */ b("div", {
122
+ className: "min-w-0 p-3",
123
+ children: [
124
+ /* @__PURE__ */ y("p", {
125
+ className: "truncate text-sm font-medium text-text-primary",
126
+ children: e.title
127
+ }),
128
+ /* @__PURE__ */ y("p", {
129
+ className: "mt-0.5 text-xs text-text-secondary",
130
+ children: l(e.occasion)
131
+ }),
132
+ /* @__PURE__ */ b("span", {
133
+ className: "mt-2 inline-flex items-center gap-1 text-xs text-text-secondary",
134
+ children: [
135
+ /* @__PURE__ */ y(m, { className: "h-3.5 w-3.5" }),
136
+ " ",
137
+ e.likeCount
138
+ ]
139
+ })
140
+ ]
141
+ })]
142
+ }, e.id))
143
+ })
144
+ }),
145
+ N.inYourPalette.length > 0 ? /* @__PURE__ */ y(T, {
146
+ title: "In your palette",
147
+ icon: /* @__PURE__ */ y(h, { className: "h-5 w-5" }),
148
+ sublabel: "Pieces that match your colours, categories and tags",
149
+ children: /* @__PURE__ */ y("div", {
150
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
151
+ children: N.inYourPalette.map((e) => /* @__PURE__ */ b("button", {
152
+ type: "button",
153
+ onClick: () => E(`/items/${e.id}`),
154
+ className: "group flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-colors hover:border-accent-foreground/20 hover:shadow-md",
155
+ children: [/* @__PURE__ */ y(i, {
156
+ icon: /* @__PURE__ */ y(h, { className: "h-6 w-6" }),
157
+ seed: e.id,
158
+ fileId: e.image?.id,
159
+ alt: e.name,
160
+ className: "aspect-[4/5] w-full rounded-none"
161
+ }), /* @__PURE__ */ b("div", {
162
+ className: "min-w-0 p-3",
163
+ children: [
164
+ /* @__PURE__ */ y("p", {
165
+ className: "truncate text-sm font-medium text-text-primary",
166
+ children: e.name
167
+ }),
168
+ /* @__PURE__ */ y("p", {
169
+ className: "mt-0.5 text-xs text-text-secondary",
170
+ children: l(e.category)
171
+ }),
172
+ /* @__PURE__ */ y(u, {
173
+ tags: e.colours.slice(0, 3),
174
+ className: "mt-2"
175
+ })
176
+ ]
177
+ })]
178
+ }, e.id))
179
+ })
180
+ }) : null,
181
+ /* @__PURE__ */ y(T, {
182
+ title: "From people you follow",
183
+ icon: /* @__PURE__ */ y(_, { className: "h-5 w-5" }),
184
+ sublabel: N.followingProfiles.length === 0 ? "Follow creators and shoppers to see their looks here" : `You follow ${N.followingProfiles.length} ${N.followingProfiles.length === 1 ? "person" : "people"}`,
185
+ children: N.followingProfiles.length === 0 ? /* @__PURE__ */ y(d, {
186
+ title: "You are not following anyone yet",
187
+ description: "Open a look or a style profile and tap Follow to build a feed from people whose taste you love.",
188
+ icon: /* @__PURE__ */ y(v, { className: "h-8 w-8" })
189
+ }) : N.fromFollowing.length === 0 ? /* @__PURE__ */ y("div", {
190
+ className: "rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary",
191
+ children: "The people you follow have not published looks visible to you yet."
192
+ }) : /* @__PURE__ */ y("div", {
193
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
194
+ children: N.fromFollowing.map((e) => /* @__PURE__ */ b("button", {
195
+ type: "button",
196
+ onClick: () => E(`/looks/${e.id}`),
197
+ className: "group flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-colors hover:border-accent-foreground/20 hover:shadow-md",
198
+ children: [/* @__PURE__ */ y(i, {
199
+ icon: /* @__PURE__ */ y(g, { className: "h-6 w-6" }),
200
+ seed: e.id,
201
+ fileId: e.image?.id,
202
+ alt: e.title,
203
+ className: "aspect-[4/5] w-full rounded-none"
204
+ }), /* @__PURE__ */ b("div", {
205
+ className: "min-w-0 p-3",
206
+ children: [/* @__PURE__ */ y("p", {
207
+ className: "truncate text-sm font-medium text-text-primary",
208
+ children: e.title
209
+ }), /* @__PURE__ */ y("p", {
210
+ className: "mt-0.5 text-xs text-text-secondary",
211
+ children: l(e.occasion)
212
+ })]
213
+ })]
214
+ }, e.id))
215
+ })
216
+ })
217
+ ]
218
+ });
219
+ }
220
+ //#endregion
221
+ export { E as DiscoverPage };
222
+
223
+ //# sourceMappingURL=DiscoverPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiscoverPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/discover/DiscoverPage.tsx"],"sourcesContent":["/**\n * Discover Page\n * @module coolandlovely/pages/discover\n *\n * A profile-tuned discovery feed computed entirely client-side over the REAL\n * catalogue + social lists (cooListLooks / cooListStyleItems) and the caller's\n * own style profile (cooMyStyleProfile) + follow graph (cooMyFollowing). It only\n * ranks what is actually on the platform against the taste the shopper declared\n * — no fabricated recommendations, no black-box \"AI\" (that is roadmap). When the\n * shopper has no profile yet, it invites them to build one.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { useMemo } from 'react';\nimport { Compass, Sparkles, Heart, ShoppingBag, UserCheck, Users } from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { TagList } from '../../components/TagList';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useMyStyleProfile, useLooks, useStyleItems, useMyFollowing } from '../../hooks';\nimport type { CooLook, CooStyleItem } from '../../types';\nimport { titleCase } from '../../utils/formatters';\n\n/** Lower-cased token set used for overlap scoring. */\nfunction tokenSet(values: string[]): Set<string> {\n return new Set(values.map((v) => v.trim().toLowerCase()).filter(Boolean));\n}\n\n/** Count how many of `candidate`'s tokens appear in the taste set. */\nfunction overlap(candidate: string[], taste: Set<string>): number {\n let n = 0;\n for (const c of candidate) {\n if (taste.has(c.trim().toLowerCase())) n += 1;\n }\n return n;\n}\n\ninterface SectionProps {\n title: string;\n icon: ReactNode;\n children: ReactNode;\n sublabel?: string;\n}\n\nconst Section: FC<SectionProps> = ({ title, icon, sublabel, children }) => (\n <section className=\"mt-8\">\n <div className=\"mb-3\">\n <h2 className=\"flex items-center gap-2 text-lg font-semibold text-text-primary\">\n {icon} {title}\n </h2>\n {sublabel ? <p className=\"mt-0.5 text-sm text-text-secondary\">{sublabel}</p> : null}\n </div>\n {children}\n </section>\n);\n\nexport function DiscoverPage() {\n const { navigateTo } = useCoolAndLovely();\n const profile = useMyStyleProfile();\n const looks = useLooks({ pagination: { limit: 100, offset: 0 } });\n const items = useStyleItems({ pagination: { limit: 100, offset: 0 } });\n const following = useMyFollowing();\n\n const isLoading = profile.isLoading || looks.isLoading || items.isLoading;\n const isError = looks.isError && items.isError;\n\n const feed = useMemo(() => {\n const p = profile.data;\n const lookRows = looks.data?.items ?? [];\n const itemRows = items.data?.items ?? [];\n const followingOwners = new Set((following.data ?? []).map((f) => f.ownerId));\n\n // Taste = declared style preferences ∪ palette ∪ favourite brands.\n const taste = tokenSet([\n ...(p?.stylePreferences ?? []),\n ...(p?.palette ?? []),\n ...(p?.favouriteBrands ?? []),\n ]);\n const paletteTokens = tokenSet(p?.palette ?? []);\n const brandTokens = tokenSet(p?.favouriteBrands ?? []);\n\n const scoreLook = (l: CooLook): number =>\n overlap(l.tags, taste) * 2 +\n (taste.has(l.occasion.toLowerCase()) ? 1 : 0) +\n l.likeCount * 0.05 +\n l.saveCount * 0.05;\n\n const scoreItem = (it: CooStyleItem): number =>\n overlap(it.tags, taste) * 2 +\n overlap(it.colours, paletteTokens) * 2 +\n (taste.has(it.category.toLowerCase()) ? 1 : 0) +\n (brandTokens.size && it.tags.some((t) => brandTokens.has(t.toLowerCase())) ? 1 : 0);\n\n const hasTaste = taste.size > 0;\n\n // \"Made for you\": when the shopper has taste, rank by match then engagement;\n // otherwise fall back to most-loved looks so the feed is never empty.\n const madeForYou = [...lookRows]\n .sort((a, b) =>\n hasTaste\n ? scoreLook(b) - scoreLook(a)\n : b.likeCount + b.saveCount - (a.likeCount + a.saveCount)\n )\n .slice(0, 8);\n\n const inYourPalette = [...itemRows]\n .filter((it) => (hasTaste ? scoreItem(it) > 0 : true))\n .sort((a, b) => scoreItem(b) - scoreItem(a))\n .slice(0, 8);\n\n const fromFollowing = lookRows\n .filter((l) => followingOwners.has(l.authorId))\n .sort((a, b) => b.likeCount + b.saveCount - (a.likeCount + a.saveCount))\n .slice(0, 8);\n\n return {\n hasProfile: Boolean(p),\n hasTaste,\n madeForYou,\n inYourPalette,\n fromFollowing,\n followingProfiles: following.data ?? [],\n };\n }, [profile.data, looks.data, items.data, following.data]);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Discover\">\n <LoadingView label=\"Curating your feed…\" />\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"Discover\">\n <ErrorView\n onRetry={() => {\n void looks.refetch();\n void items.refetch();\n }}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout title=\"Discover\" description=\"Looks and pieces tuned to your taste\" hero>\n <PagePurpose className=\"mb-6\">\n Your personalised feed, computed live from your style profile against the pieces and looks on\n the platform — the closer a piece matches the aesthetics, palette and brands you follow, the\n higher it ranks. Nothing here is fabricated.\n </PagePurpose>\n\n {!feed.hasProfile ? (\n <EmphasisPanel className=\"mb-8\">\n <div className=\"flex flex-col items-start gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Build your style profile</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Tell us your aesthetics, palette and favourite brands and this feed tunes itself to you.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo('/profile')}\n className=\"inline-flex shrink-0 items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-opacity hover:opacity-90\"\n >\n <Sparkles className=\"h-4 w-4\" /> Create profile\n </button>\n </div>\n </EmphasisPanel>\n ) : null}\n\n <Section\n title=\"Made for you\"\n icon={<Compass className=\"h-5 w-5\" />}\n sublabel={feed.hasTaste ? 'Ranked to match your style profile' : 'Most-loved looks on the platform'}\n >\n {feed.madeForYou.length === 0 ? (\n <EmptyState\n title=\"No looks yet\"\n description=\"Once looks are published they will appear here, tuned to your taste.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n {feed.madeForYou.map((look) => (\n <button\n key={look.id}\n type=\"button\"\n onClick={() => navigateTo(`/looks/${look.id}`)}\n className=\"group flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-colors hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <Thumbnail\n icon={<Sparkles className=\"h-6 w-6\" />}\n seed={look.id}\n fileId={look.image?.id}\n alt={look.title}\n className=\"aspect-[4/5] w-full rounded-none\"\n />\n <div className=\"min-w-0 p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{look.title}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{titleCase(look.occasion)}</p>\n <span className=\"mt-2 inline-flex items-center gap-1 text-xs text-text-secondary\">\n <Heart className=\"h-3.5 w-3.5\" /> {look.likeCount}\n </span>\n </div>\n </button>\n ))}\n </div>\n )}\n </Section>\n\n {feed.inYourPalette.length > 0 ? (\n <Section\n title=\"In your palette\"\n icon={<ShoppingBag className=\"h-5 w-5\" />}\n sublabel=\"Pieces that match your colours, categories and tags\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n {feed.inYourPalette.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => navigateTo(`/items/${item.id}`)}\n className=\"group flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-colors hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <Thumbnail\n icon={<ShoppingBag className=\"h-6 w-6\" />}\n seed={item.id}\n fileId={item.image?.id}\n alt={item.name}\n className=\"aspect-[4/5] w-full rounded-none\"\n />\n <div className=\"min-w-0 p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{item.name}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{titleCase(item.category)}</p>\n <TagList tags={item.colours.slice(0, 3)} className=\"mt-2\" />\n </div>\n </button>\n ))}\n </div>\n </Section>\n ) : null}\n\n <Section\n title=\"From people you follow\"\n icon={<UserCheck className=\"h-5 w-5\" />}\n sublabel={\n feed.followingProfiles.length === 0\n ? 'Follow creators and shoppers to see their looks here'\n : `You follow ${feed.followingProfiles.length} ${feed.followingProfiles.length === 1 ? 'person' : 'people'}`\n }\n >\n {feed.followingProfiles.length === 0 ? (\n <EmptyState\n title=\"You are not following anyone yet\"\n description=\"Open a look or a style profile and tap Follow to build a feed from people whose taste you love.\"\n icon={<Users className=\"h-8 w-8\" />}\n />\n ) : feed.fromFollowing.length === 0 ? (\n <div className=\"rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary\">\n The people you follow have not published looks visible to you yet.\n </div>\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n {feed.fromFollowing.map((look) => (\n <button\n key={look.id}\n type=\"button\"\n onClick={() => navigateTo(`/looks/${look.id}`)}\n className=\"group flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-colors hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <Thumbnail\n icon={<Sparkles className=\"h-6 w-6\" />}\n seed={look.id}\n fileId={look.image?.id}\n alt={look.title}\n className=\"aspect-[4/5] w-full rounded-none\"\n />\n <div className=\"min-w-0 p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{look.title}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{titleCase(look.occasion)}</p>\n </div>\n </button>\n ))}\n </div>\n )}\n </Section>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -8,113 +8,117 @@ import "../../hooks/index.js";
8
8
  import { formatDate as c, formatPrice as l, titleCase as u } from "../../utils/formatters.js";
9
9
  import { TagList as d } from "../../components/TagList.js";
10
10
  import { categoryIcon as f } from "../../utils/icons.js";
11
- import { Archive as p, ArrowLeft as m, Loader2 as h, Pencil as g, Shapes as _, Store as v } from "lucide-react";
12
- import { useParams as y } from "react-router-dom";
13
- import { jsx as b, jsxs as x } from "react/jsx-runtime";
14
- import { GlassCard as S } from "@burdenoff/fe-libs/ui";
11
+ import { AddToLookbookButton as p } from "../../components/AddToLookbookButton.js";
12
+ import { Archive as m, ArrowLeft as h, Loader2 as g, Pencil as _, Shapes as v, Store as y } from "lucide-react";
13
+ import { useParams as b } from "react-router-dom";
14
+ import { jsx as x, jsxs as S } from "react/jsx-runtime";
15
+ import { GlassCard as C } from "@burdenoff/fe-libs/ui";
15
16
  //#region src/coolandlovely/pages/items/StyleItemDetailPage.tsx
16
- function C() {
17
- let { itemId: C } = y(), { navigateTo: w } = e(), T = s(C), E = o();
18
- if (T.isLoading) return /* @__PURE__ */ b(t, {
17
+ function w() {
18
+ let { itemId: w } = b(), { navigateTo: T } = e(), E = s(w), D = o();
19
+ if (E.isLoading) return /* @__PURE__ */ x(t, {
19
20
  title: "Style item",
20
- children: /* @__PURE__ */ b(i, { label: "Loading item…" })
21
+ children: /* @__PURE__ */ x(i, { label: "Loading item…" })
21
22
  });
22
- if (T.isError || !T.data) return /* @__PURE__ */ b(t, {
23
+ if (E.isError || !E.data) return /* @__PURE__ */ x(t, {
23
24
  title: "Style item",
24
- children: /* @__PURE__ */ b(r, {
25
+ children: /* @__PURE__ */ x(r, {
25
26
  title: "Item not found",
26
- onRetry: () => void T.refetch()
27
+ onRetry: () => void E.refetch()
27
28
  })
28
29
  });
29
- let D = T.data, O = D.status === "RETIRED";
30
- return /* @__PURE__ */ b(t, {
31
- title: D.name,
32
- description: D.brand?.name ?? void 0,
33
- actions: /* @__PURE__ */ x("div", {
34
- className: "flex items-center gap-2",
30
+ let O = E.data, k = O.status === "RETIRED";
31
+ return /* @__PURE__ */ x(t, {
32
+ title: O.name,
33
+ description: O.brand?.name ?? void 0,
34
+ actions: /* @__PURE__ */ S("div", {
35
+ className: "flex flex-wrap items-center gap-2",
35
36
  children: [
36
- /* @__PURE__ */ x("button", {
37
+ /* @__PURE__ */ S("button", {
37
38
  type: "button",
38
- onClick: () => w("/items"),
39
+ onClick: () => T("/items"),
39
40
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
40
- children: [/* @__PURE__ */ b(m, { className: "h-4 w-4" }), " Back"]
41
+ children: [/* @__PURE__ */ x(h, { className: "h-4 w-4" }), " Back"]
41
42
  }),
42
- /* @__PURE__ */ x("button", {
43
+ /* @__PURE__ */ x(p, { styleItemId: O.id }),
44
+ /* @__PURE__ */ S("button", {
43
45
  type: "button",
44
- onClick: () => w(`/items/${D.id}/edit`),
46
+ onClick: () => T(`/items/${O.id}/edit`),
45
47
  className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
46
- children: [/* @__PURE__ */ b(g, { className: "h-4 w-4" }), " Edit"]
48
+ children: [/* @__PURE__ */ x(_, { className: "h-4 w-4" }), " Edit"]
47
49
  }),
48
- !O && /* @__PURE__ */ x("button", {
50
+ !k && /* @__PURE__ */ S("button", {
49
51
  type: "button",
50
- disabled: E.isPending,
51
- onClick: () => E.mutate(D.id, { onSuccess: () => w("/items") }),
52
+ disabled: D.isPending,
53
+ onClick: () => D.mutate(O.id, { onSuccess: () => T("/items") }),
52
54
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50",
53
- children: [E.isPending ? /* @__PURE__ */ b(h, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ b(p, { className: "h-4 w-4" }), "Archive"]
55
+ children: [D.isPending ? /* @__PURE__ */ x(g, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ x(m, { className: "h-4 w-4" }), "Archive"]
54
56
  })
55
57
  ]
56
58
  }),
57
- children: /* @__PURE__ */ x("div", {
59
+ children: /* @__PURE__ */ S("div", {
58
60
  className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
59
- children: [/* @__PURE__ */ b("div", {
61
+ children: [/* @__PURE__ */ x("div", {
60
62
  className: "lg:col-span-2",
61
- children: /* @__PURE__ */ x(S, {
63
+ children: /* @__PURE__ */ S(C, {
62
64
  treatment: "glass",
63
65
  className: "overflow-hidden p-0",
64
- children: [/* @__PURE__ */ b(a, {
65
- icon: f(D.category, 40),
66
- seed: D.id,
66
+ children: [/* @__PURE__ */ x(a, {
67
+ icon: f(O.category, 40),
68
+ seed: O.id,
69
+ fileId: O.image?.id,
70
+ alt: O.name,
67
71
  className: "h-52 w-full"
68
- }), /* @__PURE__ */ x("div", {
72
+ }), /* @__PURE__ */ S("div", {
69
73
  className: "p-6",
70
74
  children: [
71
- /* @__PURE__ */ x("div", {
75
+ /* @__PURE__ */ S("div", {
72
76
  className: "flex items-center gap-2",
73
- children: [/* @__PURE__ */ b("h2", {
77
+ children: [/* @__PURE__ */ x("h2", {
74
78
  className: "text-xl font-semibold text-text-primary",
75
- children: D.name
76
- }), /* @__PURE__ */ b(n, {
77
- status: D.status,
79
+ children: O.name
80
+ }), /* @__PURE__ */ x(n, {
81
+ status: O.status,
78
82
  className: "ml-auto"
79
83
  })]
80
84
  }),
81
- /* @__PURE__ */ b("p", {
85
+ /* @__PURE__ */ x("p", {
82
86
  className: "mt-1 text-2xl font-bold text-text-primary tabular-nums",
83
- children: l(D.price, D.currency)
87
+ children: l(O.price, O.currency)
84
88
  }),
85
- D.description && /* @__PURE__ */ b("p", {
89
+ O.description && /* @__PURE__ */ x("p", {
86
90
  className: "mt-3 text-sm text-text-secondary",
87
- children: D.description
91
+ children: O.description
88
92
  }),
89
- /* @__PURE__ */ x("div", {
93
+ /* @__PURE__ */ S("div", {
90
94
  className: "mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2",
91
95
  children: [
92
- D.colours.length > 0 && /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("p", {
96
+ O.colours.length > 0 && /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("p", {
93
97
  className: "mb-1.5 text-xs font-medium uppercase tracking-wide text-text-secondary",
94
98
  children: "Colours"
95
- }), /* @__PURE__ */ b(d, {
96
- tags: D.colours,
99
+ }), /* @__PURE__ */ x(d, {
100
+ tags: O.colours,
97
101
  max: 10
98
102
  })] }),
99
- D.sizes.length > 0 && /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("p", {
103
+ O.sizes.length > 0 && /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("p", {
100
104
  className: "mb-1.5 text-xs font-medium uppercase tracking-wide text-text-secondary",
101
105
  children: "Sizes"
102
- }), /* @__PURE__ */ b(d, {
103
- tags: D.sizes,
106
+ }), /* @__PURE__ */ x(d, {
107
+ tags: O.sizes,
104
108
  max: 10
105
109
  })] }),
106
- D.materials.length > 0 && /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("p", {
110
+ O.materials.length > 0 && /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("p", {
107
111
  className: "mb-1.5 text-xs font-medium uppercase tracking-wide text-text-secondary",
108
112
  children: "Materials"
109
- }), /* @__PURE__ */ b(d, {
110
- tags: D.materials,
113
+ }), /* @__PURE__ */ x(d, {
114
+ tags: O.materials,
111
115
  max: 10
112
116
  })] }),
113
- D.tags.length > 0 && /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("p", {
117
+ O.tags.length > 0 && /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("p", {
114
118
  className: "mb-1.5 text-xs font-medium uppercase tracking-wide text-text-secondary",
115
119
  children: "Tags"
116
- }), /* @__PURE__ */ b(d, {
117
- tags: D.tags,
120
+ }), /* @__PURE__ */ x(d, {
121
+ tags: O.tags,
118
122
  max: 10,
119
123
  tone: "accent"
120
124
  })] })
@@ -123,56 +127,56 @@ function C() {
123
127
  ]
124
128
  })]
125
129
  })
126
- }), /* @__PURE__ */ x("div", {
130
+ }), /* @__PURE__ */ S("div", {
127
131
  className: "space-y-4",
128
132
  children: [
129
- /* @__PURE__ */ x(S, {
133
+ /* @__PURE__ */ S(C, {
130
134
  treatment: "plain",
131
135
  className: "p-5",
132
- children: [/* @__PURE__ */ b("h3", {
136
+ children: [/* @__PURE__ */ x("h3", {
133
137
  className: "mb-3 text-sm font-semibold text-text-primary",
134
138
  children: "Details"
135
- }), /* @__PURE__ */ x("dl", {
139
+ }), /* @__PURE__ */ S("dl", {
136
140
  className: "space-y-2 text-sm",
137
141
  children: [
138
- /* @__PURE__ */ x("div", {
142
+ /* @__PURE__ */ S("div", {
139
143
  className: "flex justify-between gap-2",
140
- children: [/* @__PURE__ */ b("dt", {
144
+ children: [/* @__PURE__ */ x("dt", {
141
145
  className: "text-text-secondary",
142
146
  children: "Category"
143
- }), /* @__PURE__ */ b("dd", {
147
+ }), /* @__PURE__ */ x("dd", {
144
148
  className: "text-text-primary",
145
- children: u(D.category)
149
+ children: u(O.category)
146
150
  })]
147
151
  }),
148
- /* @__PURE__ */ x("div", {
152
+ /* @__PURE__ */ S("div", {
149
153
  className: "flex justify-between gap-2",
150
- children: [/* @__PURE__ */ b("dt", {
154
+ children: [/* @__PURE__ */ x("dt", {
151
155
  className: "text-text-secondary",
152
156
  children: "SKU"
153
- }), /* @__PURE__ */ b("dd", {
157
+ }), /* @__PURE__ */ x("dd", {
154
158
  className: "text-text-primary",
155
- children: D.sku ?? "—"
159
+ children: O.sku ?? "—"
156
160
  })]
157
161
  }),
158
- /* @__PURE__ */ x("div", {
162
+ /* @__PURE__ */ S("div", {
159
163
  className: "flex justify-between gap-2",
160
- children: [/* @__PURE__ */ b("dt", {
164
+ children: [/* @__PURE__ */ x("dt", {
161
165
  className: "text-text-secondary",
162
166
  children: "Currency"
163
- }), /* @__PURE__ */ b("dd", {
167
+ }), /* @__PURE__ */ x("dd", {
164
168
  className: "text-text-primary",
165
- children: D.currency
169
+ children: O.currency
166
170
  })]
167
171
  }),
168
- /* @__PURE__ */ x("div", {
172
+ /* @__PURE__ */ S("div", {
169
173
  className: "flex justify-between gap-2",
170
- children: [/* @__PURE__ */ b("dt", {
174
+ children: [/* @__PURE__ */ x("dt", {
171
175
  className: "text-text-secondary",
172
176
  children: "Created"
173
- }), /* @__PURE__ */ b("dd", {
177
+ }), /* @__PURE__ */ x("dd", {
174
178
  className: "text-text-primary",
175
- children: c(D.createdAt, {
179
+ children: c(O.createdAt, {
176
180
  hour: void 0,
177
181
  minute: void 0
178
182
  })
@@ -181,39 +185,39 @@ function C() {
181
185
  ]
182
186
  })]
183
187
  }),
184
- D.brand && /* @__PURE__ */ x("button", {
188
+ O.brand && /* @__PURE__ */ S("button", {
185
189
  type: "button",
186
- onClick: () => w(`/brands/${D.brand?.id}`),
190
+ onClick: () => T(`/brands/${O.brand?.id}`),
187
191
  className: "flex w-full items-center gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50",
188
- children: [/* @__PURE__ */ b(a, {
189
- icon: /* @__PURE__ */ b(v, { className: "h-5 w-5" }),
190
- seed: D.brand.id,
192
+ children: [/* @__PURE__ */ x(a, {
193
+ icon: /* @__PURE__ */ x(y, { className: "h-5 w-5" }),
194
+ seed: O.brand.id,
191
195
  className: "h-10 w-10 shrink-0"
192
- }), /* @__PURE__ */ x("div", {
196
+ }), /* @__PURE__ */ S("div", {
193
197
  className: "min-w-0",
194
- children: [/* @__PURE__ */ b("p", {
198
+ children: [/* @__PURE__ */ x("p", {
195
199
  className: "truncate text-sm font-medium text-text-primary",
196
- children: D.brand.name
197
- }), /* @__PURE__ */ b("p", {
200
+ children: O.brand.name
201
+ }), /* @__PURE__ */ x("p", {
198
202
  className: "truncate text-xs text-text-secondary",
199
203
  children: "View brand"
200
204
  })]
201
205
  })]
202
206
  }),
203
- D.collection && /* @__PURE__ */ x("button", {
207
+ O.collection && /* @__PURE__ */ S("button", {
204
208
  type: "button",
205
- onClick: () => w(`/collections/${D.collection?.id}`),
209
+ onClick: () => T(`/collections/${O.collection?.id}`),
206
210
  className: "flex w-full items-center gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50",
207
- children: [/* @__PURE__ */ b(a, {
208
- icon: /* @__PURE__ */ b(_, { className: "h-5 w-5" }),
209
- seed: D.collection.id,
211
+ children: [/* @__PURE__ */ x(a, {
212
+ icon: /* @__PURE__ */ x(v, { className: "h-5 w-5" }),
213
+ seed: O.collection.id,
210
214
  className: "h-10 w-10 shrink-0"
211
- }), /* @__PURE__ */ x("div", {
215
+ }), /* @__PURE__ */ S("div", {
212
216
  className: "min-w-0",
213
- children: [/* @__PURE__ */ b("p", {
217
+ children: [/* @__PURE__ */ x("p", {
214
218
  className: "truncate text-sm font-medium text-text-primary",
215
- children: D.collection.name
216
- }), /* @__PURE__ */ b("p", {
219
+ children: O.collection.name
220
+ }), /* @__PURE__ */ x("p", {
217
221
  className: "truncate text-xs text-text-secondary",
218
222
  children: "View collection"
219
223
  })]
@@ -225,6 +229,6 @@ function C() {
225
229
  });
226
230
  }
227
231
  //#endregion
228
- export { C as StyleItemDetailPage };
232
+ export { w as StyleItemDetailPage };
229
233
 
230
234
  //# sourceMappingURL=StyleItemDetailPage.js.map