@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StyleItemsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/items/StyleItemsListPage.tsx"],"sourcesContent":["/**\n * Style Items List Page\n * @module coolandlovely/pages/items\n *\n * Cursor-paginated catalogue (`cooListStyleItems`) with category & status\n * filters. Cards link to the item detail page.\n */\n\nimport { useState } from 'react';\nimport { Plus, ChevronLeft, ChevronRight, Shirt } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useStyleItems } from '../../hooks';\nimport { categoryIcon, STYLE_CATEGORIES } from '../../utils/icons';\nimport { formatPrice, titleCase } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { CooStyleCategory, CooStyleItemStatus } from '../../types';\n\nconst PAGE_SIZE = 24;\n\nconst STATUS_OPTIONS: Array<{ value: CooStyleItemStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'OUT_OF_STOCK', label: 'Out of stock' },\n { value: 'RETIRED', label: 'Retired' },\n];\n\nexport function StyleItemsListPage() {\n const { navigateTo } = useCoolAndLovely();\n const [category, setCategory] = useState<CooStyleCategory | 'ALL'>('ALL');\n const [status, setStatus] = useState<CooStyleItemStatus | 'ALL'>('ALL');\n const [offset, setOffset] = useState(0);\n\n const query = useStyleItems({\n category: category === 'ALL' ? undefined : category,\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, offset },\n });\n\n const items = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n return (\n <PageLayout\n title=\"Style Items\"\n description=\"The shoppable catalogue across every brand\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/items/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New item\n </button>\n }\n >\n {/* Status filter */}\n <div className=\"mb-3 flex flex-wrap items-center gap-2\">\n {STATUS_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setStatus(opt.value);\n setOffset(0);\n }}\n className={cn(\n 'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n status === opt.value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n\n {/* Category filter */}\n <div className=\"mb-6 flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n setCategory('ALL');\n setOffset(0);\n }}\n className={cn(\n 'rounded-full px-3 py-1.5 text-xs font-medium transition-colors',\n category === 'ALL'\n ? 'bg-accent-purple-subtle text-text-primary'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n All categories\n </button>\n {STYLE_CATEGORIES.map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => {\n setCategory(c);\n setOffset(0);\n }}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-xs font-medium transition-colors',\n category === c\n ? 'bg-accent-purple-subtle text-text-primary'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {categoryIcon(c, 14)} {titleCase(c)}\n </button>\n ))}\n </div>\n\n {query.isLoading ? (\n <LoadingView label=\"Loading catalogue…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : items.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Shirt className=\"h-10 w-10\" />}\n title=\"No items found\"\n description=\"No style items match these filters yet.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/items/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" /> New item\n </button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {items.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => navigateTo(`/items/${item.id}`)}\n className=\"overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left shadow-sm transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <div className=\"relative\">\n <Thumbnail\n icon={categoryIcon(item.category, 28)}\n seed={item.id}\n className=\"h-36 w-full\"\n />\n <div className=\"absolute right-2 top-2\">\n <StatusBadge status={item.status} />\n </div>\n </div>\n <div className=\"p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{item.name}</p>\n {item.brand?.name && (\n <p className=\"truncate text-xs text-text-secondary\">{item.brand.name}</p>\n )}\n <div className=\"mt-1.5 flex items-center justify-between\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {formatPrice(item.price, item.currency)}\n </span>\n <span className=\"text-xs text-text-secondary\">{titleCase(item.category)}</span>\n </div>\n </div>\n </button>\n ))}\n </div>\n\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-center gap-2\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" /> Previous\n </button>\n <span className=\"text-sm text-text-secondary\">Page {offset / PAGE_SIZE + 1}</span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Next <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StyleItemsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/items/StyleItemsListPage.tsx"],"sourcesContent":["/**\n * Style Items List Page\n * @module coolandlovely/pages/items\n *\n * Cursor-paginated catalogue (`cooListStyleItems`) with category & status\n * filters. Cards link to the item detail page.\n */\n\nimport { useState } from 'react';\nimport { Plus, ChevronLeft, ChevronRight, Shirt } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useStyleItems } from '../../hooks';\nimport { categoryIcon, STYLE_CATEGORIES } from '../../utils/icons';\nimport { formatPrice, titleCase } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { CooStyleCategory, CooStyleItemStatus } from '../../types';\n\nconst PAGE_SIZE = 24;\n\nconst STATUS_OPTIONS: Array<{ value: CooStyleItemStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'ACTIVE', label: 'Active' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'OUT_OF_STOCK', label: 'Out of stock' },\n { value: 'RETIRED', label: 'Retired' },\n];\n\nexport function StyleItemsListPage() {\n const { navigateTo } = useCoolAndLovely();\n const [category, setCategory] = useState<CooStyleCategory | 'ALL'>('ALL');\n const [status, setStatus] = useState<CooStyleItemStatus | 'ALL'>('ALL');\n const [offset, setOffset] = useState(0);\n\n const query = useStyleItems({\n category: category === 'ALL' ? undefined : category,\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, offset },\n });\n\n const items = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n return (\n <PageLayout\n title=\"Style Items\"\n description=\"The shoppable catalogue across every brand\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/items/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New item\n </button>\n }\n >\n {/* Status filter */}\n <div className=\"mb-3 flex flex-wrap items-center gap-2\">\n {STATUS_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setStatus(opt.value);\n setOffset(0);\n }}\n className={cn(\n 'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n status === opt.value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n\n {/* Category filter */}\n <div className=\"mb-6 flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n setCategory('ALL');\n setOffset(0);\n }}\n className={cn(\n 'rounded-full px-3 py-1.5 text-xs font-medium transition-colors',\n category === 'ALL'\n ? 'bg-accent-purple-subtle text-text-primary'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n All categories\n </button>\n {STYLE_CATEGORIES.map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => {\n setCategory(c);\n setOffset(0);\n }}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-xs font-medium transition-colors',\n category === c\n ? 'bg-accent-purple-subtle text-text-primary'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {categoryIcon(c, 14)} {titleCase(c)}\n </button>\n ))}\n </div>\n\n {query.isLoading ? (\n <LoadingView label=\"Loading catalogue…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : items.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Shirt className=\"h-10 w-10\" />}\n title=\"No items found\"\n description=\"No style items match these filters yet.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/items/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" /> New item\n </button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {items.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => navigateTo(`/items/${item.id}`)}\n className=\"overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left shadow-sm transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <div className=\"relative\">\n <Thumbnail\n icon={categoryIcon(item.category, 28)}\n seed={item.id}\n fileId={item.image?.id}\n alt={item.name}\n className=\"h-36 w-full\"\n />\n <div className=\"absolute right-2 top-2\">\n <StatusBadge status={item.status} />\n </div>\n </div>\n <div className=\"p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{item.name}</p>\n {item.brand?.name && (\n <p className=\"truncate text-xs text-text-secondary\">{item.brand.name}</p>\n )}\n <div className=\"mt-1.5 flex items-center justify-between\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {formatPrice(item.price, item.currency)}\n </span>\n <span className=\"text-xs text-text-secondary\">{titleCase(item.category)}</span>\n </div>\n </div>\n </button>\n ))}\n </div>\n\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-center gap-2\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" /> Previous\n </button>\n <span className=\"text-sm text-text-secondary\">Page {offset / PAGE_SIZE + 1}</span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Next <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -2,123 +2,214 @@ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
|
2
2
|
import { PageLayout as t } from "../../components/PageLayout.js";
|
|
3
3
|
import { StatusBadge as n } from "../../components/StatusBadge.js";
|
|
4
4
|
import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
|
|
5
|
-
import {
|
|
5
|
+
import { useAddLookbookEntry as a, useLookbook as o, useLooks as s, useRemoveLookbookEntry as c, useStyleItems as l } from "../../hooks/useCoolAndLovelyApi.js";
|
|
6
6
|
import "../../hooks/index.js";
|
|
7
|
-
import { TagList as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
7
|
+
import { TagList as u } from "../../components/TagList.js";
|
|
8
|
+
import { SelectField as d, TextField as f } from "../../components/Field.js";
|
|
9
|
+
import { useMemo as p, useState as m } from "react";
|
|
10
|
+
import { ArrowLeft as h, BookHeart as g, Loader2 as _, Plus as v, Sparkles as y, Tag as b, Trash2 as x, X as S } from "lucide-react";
|
|
11
|
+
import { useParams as C } from "react-router-dom";
|
|
12
|
+
import { jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
13
|
+
import { GlassCard as E } from "@burdenoff/fe-libs/ui";
|
|
12
14
|
//#region src/coolandlovely/pages/lookbooks/LookbookDetailPage.tsx
|
|
13
|
-
function
|
|
14
|
-
let { lookbookId:
|
|
15
|
-
|
|
15
|
+
function D() {
|
|
16
|
+
let { lookbookId: D } = C(), { navigateTo: O } = e(), k = o(D), A = c(), j = a(), [M, N] = m(!1), [P, F] = m("look"), [I, L] = m(""), [R, z] = m(""), B = s({ pagination: {
|
|
17
|
+
limit: 100,
|
|
18
|
+
offset: 0
|
|
19
|
+
} }), V = l({
|
|
20
|
+
status: "ACTIVE",
|
|
21
|
+
pagination: {
|
|
22
|
+
limit: 100,
|
|
23
|
+
offset: 0
|
|
24
|
+
}
|
|
25
|
+
}), H = p(() => (B.data?.items ?? []).map((e) => ({
|
|
26
|
+
value: e.id,
|
|
27
|
+
label: e.title
|
|
28
|
+
})), [B.data]), U = p(() => (V.data?.items ?? []).map((e) => ({
|
|
29
|
+
value: e.id,
|
|
30
|
+
label: `${e.name}${e.brand?.name ? ` · ${e.brand.name}` : ""}`
|
|
31
|
+
})), [V.data]);
|
|
32
|
+
if (k.isLoading) return /* @__PURE__ */ w(t, {
|
|
16
33
|
title: "Lookbook",
|
|
17
|
-
children: /* @__PURE__ */
|
|
34
|
+
children: /* @__PURE__ */ w(i, { label: "Loading lookbook…" })
|
|
18
35
|
});
|
|
19
|
-
if (
|
|
36
|
+
if (k.isError || !k.data) return /* @__PURE__ */ w(t, {
|
|
20
37
|
title: "Lookbook",
|
|
21
|
-
children: /* @__PURE__ */
|
|
38
|
+
children: /* @__PURE__ */ w(r, {
|
|
22
39
|
title: "Lookbook not found",
|
|
23
|
-
onRetry: () => void
|
|
40
|
+
onRetry: () => void k.refetch()
|
|
24
41
|
})
|
|
25
42
|
});
|
|
26
|
-
let
|
|
27
|
-
return /* @__PURE__ */
|
|
28
|
-
title:
|
|
29
|
-
description:
|
|
30
|
-
actions: /* @__PURE__ */
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
let W = k.data, G = [...W.entries ?? []].sort((e, t) => e.position - t.position);
|
|
44
|
+
return /* @__PURE__ */ w(t, {
|
|
45
|
+
title: W.name,
|
|
46
|
+
description: W.description ?? void 0,
|
|
47
|
+
actions: /* @__PURE__ */ T("div", {
|
|
48
|
+
className: "flex flex-wrap items-center gap-2",
|
|
49
|
+
children: [/* @__PURE__ */ T("button", {
|
|
50
|
+
type: "button",
|
|
51
|
+
onClick: () => O("/lookbooks"),
|
|
52
|
+
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",
|
|
53
|
+
children: [/* @__PURE__ */ w(h, { className: "h-4 w-4" }), " Back"]
|
|
54
|
+
}), /* @__PURE__ */ T("button", {
|
|
55
|
+
type: "button",
|
|
56
|
+
onClick: () => {
|
|
57
|
+
N((e) => !e), L("");
|
|
58
|
+
},
|
|
59
|
+
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",
|
|
60
|
+
children: [w(M ? S : v, { className: "h-4 w-4" }), M ? "Close" : "Add entry"]
|
|
61
|
+
})]
|
|
35
62
|
}),
|
|
36
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ T("div", {
|
|
37
64
|
className: "mx-auto max-w-3xl",
|
|
38
|
-
children: [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
children: [
|
|
66
|
+
/* @__PURE__ */ T(E, {
|
|
67
|
+
treatment: "glass",
|
|
68
|
+
className: "p-6",
|
|
69
|
+
children: [/* @__PURE__ */ T("div", {
|
|
70
|
+
className: "flex items-center gap-3",
|
|
71
|
+
children: [/* @__PURE__ */ w("div", {
|
|
72
|
+
className: "flex h-12 w-12 items-center justify-center rounded-lg bg-accent-purple-subtle text-text-primary",
|
|
73
|
+
children: /* @__PURE__ */ w(g, { className: "h-6 w-6" })
|
|
74
|
+
}), /* @__PURE__ */ T("div", {
|
|
75
|
+
className: "min-w-0 flex-1",
|
|
76
|
+
children: [/* @__PURE__ */ w("h2", {
|
|
77
|
+
className: "truncate text-xl font-semibold text-text-primary",
|
|
78
|
+
children: W.name
|
|
79
|
+
}), /* @__PURE__ */ w(n, {
|
|
80
|
+
status: W.visibility,
|
|
81
|
+
className: "mt-1"
|
|
82
|
+
})]
|
|
54
83
|
})]
|
|
84
|
+
}), W.tags.length > 0 && /* @__PURE__ */ w(u, {
|
|
85
|
+
tags: W.tags,
|
|
86
|
+
className: "mt-4"
|
|
55
87
|
})]
|
|
56
|
-
}),
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary",
|
|
81
|
-
children: h(t ? d : f, { className: "h-5 w-5" })
|
|
82
|
-
}),
|
|
83
|
-
/* @__PURE__ */ g("div", {
|
|
84
|
-
className: "min-w-0 flex-1",
|
|
85
|
-
children: [/* @__PURE__ */ h("p", {
|
|
86
|
-
className: "text-sm font-medium text-text-primary",
|
|
87
|
-
children: t ? "Saved look" : "Clipped piece"
|
|
88
|
-
}), e.note && /* @__PURE__ */ h("p", {
|
|
89
|
-
className: "truncate text-xs text-text-secondary",
|
|
90
|
-
children: e.note
|
|
91
|
-
})]
|
|
92
|
-
}),
|
|
93
|
-
t && e.lookId && /* @__PURE__ */ h("button", {
|
|
94
|
-
type: "button",
|
|
95
|
-
onClick: () => y(`/looks/${e.lookId}`),
|
|
96
|
-
className: "shrink-0 text-xs font-medium text-primary hover:underline",
|
|
97
|
-
children: "View"
|
|
98
|
-
}),
|
|
99
|
-
!t && e.styleItemId && /* @__PURE__ */ h("button", {
|
|
100
|
-
type: "button",
|
|
101
|
-
onClick: () => y(`/items/${e.styleItemId}`),
|
|
102
|
-
className: "shrink-0 text-xs font-medium text-primary hover:underline",
|
|
103
|
-
children: "View"
|
|
104
|
-
}),
|
|
105
|
-
/* @__PURE__ */ h("button", {
|
|
88
|
+
}),
|
|
89
|
+
M && /* @__PURE__ */ w("form", {
|
|
90
|
+
onSubmit: (e) => {
|
|
91
|
+
e.preventDefault(), !(!D || !I) && j.mutate({
|
|
92
|
+
lookbookId: D,
|
|
93
|
+
lookId: P === "look" ? I : void 0,
|
|
94
|
+
styleItemId: P === "item" ? I : void 0,
|
|
95
|
+
note: R.trim() || void 0
|
|
96
|
+
}, { onSuccess: () => {
|
|
97
|
+
L(""), z(""), N(!1);
|
|
98
|
+
} });
|
|
99
|
+
},
|
|
100
|
+
className: "mt-6",
|
|
101
|
+
children: /* @__PURE__ */ T(E, {
|
|
102
|
+
treatment: "plain",
|
|
103
|
+
className: "p-5",
|
|
104
|
+
children: [
|
|
105
|
+
/* @__PURE__ */ T("h3", {
|
|
106
|
+
className: "mb-4 flex items-center gap-2 text-base font-semibold text-text-primary",
|
|
107
|
+
children: [/* @__PURE__ */ w(v, { className: "h-5 w-5" }), " Add to this lookbook"]
|
|
108
|
+
}),
|
|
109
|
+
/* @__PURE__ */ w("div", {
|
|
110
|
+
className: "mb-4 flex flex-wrap gap-2",
|
|
111
|
+
children: ["look", "item"].map((e) => /* @__PURE__ */ w("button", {
|
|
106
112
|
type: "button",
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
className: "
|
|
111
|
-
children:
|
|
113
|
+
onClick: () => {
|
|
114
|
+
F(e), L("");
|
|
115
|
+
},
|
|
116
|
+
className: P === e ? "rounded-full bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text" : "rounded-full bg-bg-sunken px-3 py-1.5 text-sm font-medium text-text-secondary hover:text-text-primary",
|
|
117
|
+
children: e === "look" ? "Save a look" : "Clip a piece"
|
|
118
|
+
}, e))
|
|
119
|
+
}),
|
|
120
|
+
/* @__PURE__ */ w(d, {
|
|
121
|
+
label: P === "look" ? "Look" : "Style item",
|
|
122
|
+
value: I,
|
|
123
|
+
onChange: L,
|
|
124
|
+
options: P === "look" ? H : U,
|
|
125
|
+
placeholder: P === "look" ? B.isLoading ? "Loading looks…" : "Select a look" : V.isLoading ? "Loading items…" : "Select a style item"
|
|
126
|
+
}),
|
|
127
|
+
/* @__PURE__ */ w(f, {
|
|
128
|
+
label: "Note (optional)",
|
|
129
|
+
value: R,
|
|
130
|
+
onChange: z,
|
|
131
|
+
placeholder: "Why you saved it…",
|
|
132
|
+
className: "mt-4"
|
|
133
|
+
}),
|
|
134
|
+
j.isError && /* @__PURE__ */ w("p", {
|
|
135
|
+
className: "mt-3 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
|
|
136
|
+
children: j.error instanceof Error ? j.error.message : "Could not add entry"
|
|
137
|
+
}),
|
|
138
|
+
/* @__PURE__ */ w("div", {
|
|
139
|
+
className: "mt-4 flex justify-end",
|
|
140
|
+
children: /* @__PURE__ */ T("button", {
|
|
141
|
+
type: "submit",
|
|
142
|
+
disabled: !I || j.isPending,
|
|
143
|
+
className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50",
|
|
144
|
+
children: [j.isPending ? /* @__PURE__ */ w(_, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ w(v, { className: "h-4 w-4" }), "Add entry"]
|
|
112
145
|
})
|
|
113
|
-
|
|
114
|
-
|
|
146
|
+
})
|
|
147
|
+
]
|
|
115
148
|
})
|
|
116
|
-
})
|
|
117
|
-
|
|
149
|
+
}),
|
|
150
|
+
/* @__PURE__ */ T("section", {
|
|
151
|
+
className: "mt-6",
|
|
152
|
+
children: [/* @__PURE__ */ T("h3", {
|
|
153
|
+
className: "mb-3 text-lg font-semibold text-text-primary",
|
|
154
|
+
children: [
|
|
155
|
+
"Entries (",
|
|
156
|
+
G.length,
|
|
157
|
+
")"
|
|
158
|
+
]
|
|
159
|
+
}), G.length === 0 ? /* @__PURE__ */ w("p", {
|
|
160
|
+
className: "rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary",
|
|
161
|
+
children: "This lookbook has no entries yet. Clip a catalogue piece or save a look to add one."
|
|
162
|
+
}) : /* @__PURE__ */ w("div", {
|
|
163
|
+
className: "divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface",
|
|
164
|
+
children: G.map((e) => {
|
|
165
|
+
let t = !!e.lookId;
|
|
166
|
+
return /* @__PURE__ */ T("div", {
|
|
167
|
+
className: "flex items-center gap-4 px-4 py-3",
|
|
168
|
+
children: [
|
|
169
|
+
/* @__PURE__ */ w("div", {
|
|
170
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary",
|
|
171
|
+
children: w(t ? y : b, { className: "h-5 w-5" })
|
|
172
|
+
}),
|
|
173
|
+
/* @__PURE__ */ T("div", {
|
|
174
|
+
className: "min-w-0 flex-1",
|
|
175
|
+
children: [/* @__PURE__ */ w("p", {
|
|
176
|
+
className: "text-sm font-medium text-text-primary",
|
|
177
|
+
children: t ? "Saved look" : "Clipped piece"
|
|
178
|
+
}), e.note && /* @__PURE__ */ w("p", {
|
|
179
|
+
className: "truncate text-xs text-text-secondary",
|
|
180
|
+
children: e.note
|
|
181
|
+
})]
|
|
182
|
+
}),
|
|
183
|
+
t && e.lookId && /* @__PURE__ */ w("button", {
|
|
184
|
+
type: "button",
|
|
185
|
+
onClick: () => O(`/looks/${e.lookId}`),
|
|
186
|
+
className: "shrink-0 text-xs font-medium text-primary hover:underline",
|
|
187
|
+
children: "View"
|
|
188
|
+
}),
|
|
189
|
+
!t && e.styleItemId && /* @__PURE__ */ w("button", {
|
|
190
|
+
type: "button",
|
|
191
|
+
onClick: () => O(`/items/${e.styleItemId}`),
|
|
192
|
+
className: "shrink-0 text-xs font-medium text-primary hover:underline",
|
|
193
|
+
children: "View"
|
|
194
|
+
}),
|
|
195
|
+
/* @__PURE__ */ w("button", {
|
|
196
|
+
type: "button",
|
|
197
|
+
disabled: A.isPending,
|
|
198
|
+
onClick: () => A.mutate(e.id),
|
|
199
|
+
"aria-label": "Remove entry",
|
|
200
|
+
className: "inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-50",
|
|
201
|
+
children: A.isPending && A.variables === e.id ? /* @__PURE__ */ w(_, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ w(x, { className: "h-3.5 w-3.5" })
|
|
202
|
+
})
|
|
203
|
+
]
|
|
204
|
+
}, e.id);
|
|
205
|
+
})
|
|
206
|
+
})]
|
|
207
|
+
})
|
|
208
|
+
]
|
|
118
209
|
})
|
|
119
210
|
});
|
|
120
211
|
}
|
|
121
212
|
//#endregion
|
|
122
|
-
export {
|
|
213
|
+
export { D as LookbookDetailPage };
|
|
123
214
|
|
|
124
215
|
//# sourceMappingURL=LookbookDetailPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LookbookDetailPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/lookbooks/LookbookDetailPage.tsx"],"sourcesContent":["/**\n * Lookbook Detail Page\n * @module coolandlovely/pages/lookbooks\n *\n * Single lookbook (`cooLookbook`) showing its clipped entries, with per-entry\n * removal (`cooRemoveLookbookEntry`).\n */\n\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, BookHeart, Sparkles, Tag, Trash2, Loader2 } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { TagList } from '../../components/TagList';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useLookbook, useRemoveLookbookEntry } from '../../hooks';\n\nexport function LookbookDetailPage() {\n const { lookbookId } = useParams<{ lookbookId: string }>();\n const { navigateTo } = useCoolAndLovely();\n const query = useLookbook(lookbookId);\n const removeEntry = useRemoveLookbookEntry();\n\n if (query.isLoading) {\n return (\n <PageLayout title=\"Lookbook\">\n <LoadingView label=\"Loading lookbook…\" />\n </PageLayout>\n );\n }\n\n if (query.isError || !query.data) {\n return (\n <PageLayout title=\"Lookbook\">\n <ErrorView title=\"Lookbook not found\" onRetry={() => void query.refetch()} />\n </PageLayout>\n );\n }\n\n const lookbook = query.data;\n const entries = [...(lookbook.entries ?? [])].sort((a, b) => a.position - b.position);\n\n return (\n <PageLayout\n title={lookbook.name}\n description={lookbook.description ?? undefined}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/lookbooks')}\n 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\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n }\n >\n <div className=\"mx-auto max-w-3xl\">\n <GlassCard treatment=\"glass\" className=\"p-6\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-lg bg-accent-purple-subtle text-text-primary\">\n <BookHeart className=\"h-6 w-6\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"truncate text-xl font-semibold text-text-primary\">{lookbook.name}</h2>\n <StatusBadge status={lookbook.visibility} className=\"mt-1\" />\n </div>\n </div>\n {lookbook.tags.length > 0 && <TagList tags={lookbook.tags} className=\"mt-4\" />}\n </GlassCard>\n\n <section className=\"mt-6\">\n <h3 className=\"mb-3 text-lg font-semibold text-text-primary\">\n Entries ({entries.length})\n </h3>\n {entries.length === 0 ? (\n <p className=\"rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary\">\n This lookbook has no entries yet. Clip a catalogue piece or save a look to add one.\n </p>\n ) : (\n <div className=\"divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface\">\n {entries.map((entry) => {\n const isLook = Boolean(entry.lookId);\n return (\n <div key={entry.id} className=\"flex items-center gap-4 px-4 py-3\">\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n {isLook ? <Sparkles className=\"h-5 w-5\" /> : <Tag className=\"h-5 w-5\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n {isLook ? 'Saved look' : 'Clipped piece'}\n </p>\n {entry.note && (\n <p className=\"truncate text-xs text-text-secondary\">{entry.note}</p>\n )}\n </div>\n {isLook && entry.lookId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/looks/${entry.lookId}`)}\n className=\"shrink-0 text-xs font-medium text-primary hover:underline\"\n >\n View\n </button>\n )}\n {!isLook && entry.styleItemId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/items/${entry.styleItemId}`)}\n className=\"shrink-0 text-xs font-medium text-primary hover:underline\"\n >\n View\n </button>\n )}\n <button\n type=\"button\"\n disabled={removeEntry.isPending}\n onClick={() => removeEntry.mutate(entry.id)}\n aria-label=\"Remove entry\"\n className=\"inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-50\"\n >\n {removeEntry.isPending && removeEntry.variables === entry.id ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Trash2 className=\"h-3.5 w-3.5\" />\n )}\n </button>\n </div>\n );\n })}\n </div>\n )}\n </section>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LookbookDetailPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/lookbooks/LookbookDetailPage.tsx"],"sourcesContent":["/**\n * Lookbook Detail Page\n * @module coolandlovely/pages/lookbooks\n *\n * Single lookbook (`cooLookbook`) showing its clipped entries, with per-entry\n * removal (`cooRemoveLookbookEntry`).\n */\n\nimport { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, BookHeart, Sparkles, Tag, Trash2, Loader2, Plus, X } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { TagList } from '../../components/TagList';\nimport { SelectField, TextField } from '../../components/Field';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport {\n useLookbook,\n useRemoveLookbookEntry,\n useAddLookbookEntry,\n useLooks,\n useStyleItems,\n} from '../../hooks';\n\ntype EntryKind = 'look' | 'item';\n\nexport function LookbookDetailPage() {\n const { lookbookId } = useParams<{ lookbookId: string }>();\n const { navigateTo } = useCoolAndLovely();\n const query = useLookbook(lookbookId);\n const removeEntry = useRemoveLookbookEntry();\n const addEntry = useAddLookbookEntry();\n\n const [adding, setAdding] = useState(false);\n const [entryKind, setEntryKind] = useState<EntryKind>('look');\n const [selectedId, setSelectedId] = useState('');\n const [note, setNote] = useState('');\n\n const looks = useLooks({ pagination: { limit: 100, offset: 0 } });\n const items = useStyleItems({ status: 'ACTIVE', pagination: { limit: 100, offset: 0 } });\n\n const lookOptions = useMemo(\n () => (looks.data?.items ?? []).map((l) => ({ value: l.id, label: l.title })),\n [looks.data]\n );\n const itemOptions = useMemo(\n () =>\n (items.data?.items ?? []).map((i) => ({\n value: i.id,\n label: `${i.name}${i.brand?.name ? ` · ${i.brand.name}` : ''}`,\n })),\n [items.data]\n );\n\n if (query.isLoading) {\n return (\n <PageLayout title=\"Lookbook\">\n <LoadingView label=\"Loading lookbook…\" />\n </PageLayout>\n );\n }\n\n if (query.isError || !query.data) {\n return (\n <PageLayout title=\"Lookbook\">\n <ErrorView title=\"Lookbook not found\" onRetry={() => void query.refetch()} />\n </PageLayout>\n );\n }\n\n const lookbook = query.data;\n const entries = [...(lookbook.entries ?? [])].sort((a, b) => a.position - b.position);\n\n const handleAddEntry = (e: React.FormEvent) => {\n e.preventDefault();\n if (!lookbookId || !selectedId) return;\n addEntry.mutate(\n {\n lookbookId,\n lookId: entryKind === 'look' ? selectedId : undefined,\n styleItemId: entryKind === 'item' ? selectedId : undefined,\n note: note.trim() || undefined,\n },\n {\n onSuccess: () => {\n setSelectedId('');\n setNote('');\n setAdding(false);\n },\n }\n );\n };\n\n return (\n <PageLayout\n title={lookbook.name}\n description={lookbook.description ?? undefined}\n actions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/lookbooks')}\n 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\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setAdding((v) => !v);\n setSelectedId('');\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n {adding ? <X className=\"h-4 w-4\" /> : <Plus className=\"h-4 w-4\" />}\n {adding ? 'Close' : 'Add entry'}\n </button>\n </div>\n }\n >\n <div className=\"mx-auto max-w-3xl\">\n <GlassCard treatment=\"glass\" className=\"p-6\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-lg bg-accent-purple-subtle text-text-primary\">\n <BookHeart className=\"h-6 w-6\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"truncate text-xl font-semibold text-text-primary\">{lookbook.name}</h2>\n <StatusBadge status={lookbook.visibility} className=\"mt-1\" />\n </div>\n </div>\n {lookbook.tags.length > 0 && <TagList tags={lookbook.tags} className=\"mt-4\" />}\n </GlassCard>\n\n {adding && (\n <form onSubmit={handleAddEntry} className=\"mt-6\">\n <GlassCard treatment=\"plain\" className=\"p-5\">\n <h3 className=\"mb-4 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Plus className=\"h-5 w-5\" /> Add to this lookbook\n </h3>\n <div className=\"mb-4 flex flex-wrap gap-2\">\n {(['look', 'item'] as EntryKind[]).map((k) => (\n <button\n key={k}\n type=\"button\"\n onClick={() => {\n setEntryKind(k);\n setSelectedId('');\n }}\n className={\n entryKind === k\n ? 'rounded-full bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text'\n : 'rounded-full bg-bg-sunken px-3 py-1.5 text-sm font-medium text-text-secondary hover:text-text-primary'\n }\n >\n {k === 'look' ? 'Save a look' : 'Clip a piece'}\n </button>\n ))}\n </div>\n <SelectField\n label={entryKind === 'look' ? 'Look' : 'Style item'}\n value={selectedId}\n onChange={setSelectedId}\n options={entryKind === 'look' ? lookOptions : itemOptions}\n placeholder={\n entryKind === 'look'\n ? looks.isLoading\n ? 'Loading looks…'\n : 'Select a look'\n : items.isLoading\n ? 'Loading items…'\n : 'Select a style item'\n }\n />\n <TextField\n label=\"Note (optional)\"\n value={note}\n onChange={setNote}\n placeholder=\"Why you saved it…\"\n className=\"mt-4\"\n />\n {addEntry.isError && (\n <p className=\"mt-3 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {addEntry.error instanceof Error ? addEntry.error.message : 'Could not add entry'}\n </p>\n )}\n <div className=\"mt-4 flex justify-end\">\n <button\n type=\"submit\"\n disabled={!selectedId || addEntry.isPending}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {addEntry.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Plus className=\"h-4 w-4\" />\n )}\n Add entry\n </button>\n </div>\n </GlassCard>\n </form>\n )}\n\n <section className=\"mt-6\">\n <h3 className=\"mb-3 text-lg font-semibold text-text-primary\">\n Entries ({entries.length})\n </h3>\n {entries.length === 0 ? (\n <p className=\"rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary\">\n This lookbook has no entries yet. Clip a catalogue piece or save a look to add one.\n </p>\n ) : (\n <div className=\"divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface\">\n {entries.map((entry) => {\n const isLook = Boolean(entry.lookId);\n return (\n <div key={entry.id} className=\"flex items-center gap-4 px-4 py-3\">\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n {isLook ? <Sparkles className=\"h-5 w-5\" /> : <Tag className=\"h-5 w-5\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n {isLook ? 'Saved look' : 'Clipped piece'}\n </p>\n {entry.note && (\n <p className=\"truncate text-xs text-text-secondary\">{entry.note}</p>\n )}\n </div>\n {isLook && entry.lookId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/looks/${entry.lookId}`)}\n className=\"shrink-0 text-xs font-medium text-primary hover:underline\"\n >\n View\n </button>\n )}\n {!isLook && entry.styleItemId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/items/${entry.styleItemId}`)}\n className=\"shrink-0 text-xs font-medium text-primary hover:underline\"\n >\n View\n </button>\n )}\n <button\n type=\"button\"\n disabled={removeEntry.isPending}\n onClick={() => removeEntry.mutate(entry.id)}\n aria-label=\"Remove entry\"\n className=\"inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-50\"\n >\n {removeEntry.isPending && removeEntry.variables === entry.id ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Trash2 className=\"h-3.5 w-3.5\" />\n )}\n </button>\n </div>\n );\n })}\n </div>\n )}\n </section>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|