@burdenoff/microfe-coolandlovely 2026.827.1 → 2026.1024.1

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 (71) hide show
  1. package/dist/coolandlovely/components/ActivityTrail.js +7 -7
  2. package/dist/coolandlovely/components/Comments.js +4 -4
  3. package/dist/coolandlovely/components/FeedbackWidget.d.ts.map +1 -1
  4. package/dist/coolandlovely/components/FeedbackWidget.js +72 -70
  5. package/dist/coolandlovely/components/FeedbackWidget.js.map +1 -1
  6. package/dist/coolandlovely/components/LookCard.js +24 -24
  7. package/dist/coolandlovely/components/StateViews.d.ts.map +1 -1
  8. package/dist/coolandlovely/components/StateViews.js +35 -26
  9. package/dist/coolandlovely/components/StateViews.js.map +1 -1
  10. package/dist/coolandlovely/components/StatusBadge.d.ts.map +1 -1
  11. package/dist/coolandlovely/components/StatusBadge.js +45 -15
  12. package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
  13. package/dist/coolandlovely/components/VisibilityChip.d.ts.map +1 -1
  14. package/dist/coolandlovely/components/VisibilityChip.js +22 -17
  15. package/dist/coolandlovely/components/VisibilityChip.js.map +1 -1
  16. package/dist/coolandlovely/hooks/index.d.ts +1 -0
  17. package/dist/coolandlovely/hooks/index.d.ts.map +1 -1
  18. package/dist/coolandlovely/hooks/index.js +2 -1
  19. package/dist/coolandlovely/hooks/useTr.d.ts +2 -0
  20. package/dist/coolandlovely/hooks/useTr.d.ts.map +1 -0
  21. package/dist/coolandlovely/hooks/useTr.js +14 -0
  22. package/dist/coolandlovely/hooks/useTr.js.map +1 -0
  23. package/dist/coolandlovely/pages/HomePage.d.ts.map +1 -1
  24. package/dist/coolandlovely/pages/HomePage.js +172 -132
  25. package/dist/coolandlovely/pages/HomePage.js.map +1 -1
  26. package/dist/coolandlovely/pages/admin/AdminBrandsPage.js +10 -10
  27. package/dist/coolandlovely/pages/admin/AdminCollaborationsPage.js +16 -16
  28. package/dist/coolandlovely/pages/admin/AdminFeaturedItemsPage.js +17 -17
  29. package/dist/coolandlovely/pages/brands/BrandDetailPage.js +22 -22
  30. package/dist/coolandlovely/pages/brands/BrandFormPage.js +9 -9
  31. package/dist/coolandlovely/pages/brands/BrandsListPage.d.ts.map +1 -1
  32. package/dist/coolandlovely/pages/brands/BrandsListPage.js +80 -76
  33. package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -1
  34. package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js +21 -21
  35. package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +7 -7
  36. package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.d.ts.map +1 -1
  37. package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js +82 -81
  38. package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js.map +1 -1
  39. package/dist/coolandlovely/pages/collections/CollectionDetailPage.js +19 -19
  40. package/dist/coolandlovely/pages/collections/CollectionFormPage.js +9 -9
  41. package/dist/coolandlovely/pages/collections/CollectionsListPage.d.ts.map +1 -1
  42. package/dist/coolandlovely/pages/collections/CollectionsListPage.js +54 -55
  43. package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -1
  44. package/dist/coolandlovely/pages/discover/DiscoverPage.d.ts.map +1 -1
  45. package/dist/coolandlovely/pages/discover/DiscoverPage.js +322 -315
  46. package/dist/coolandlovely/pages/discover/DiscoverPage.js.map +1 -1
  47. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +21 -21
  48. package/dist/coolandlovely/pages/items/StyleItemFormPage.js +10 -10
  49. package/dist/coolandlovely/pages/items/StyleItemsListPage.d.ts.map +1 -1
  50. package/dist/coolandlovely/pages/items/StyleItemsListPage.js +105 -95
  51. package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -1
  52. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +20 -20
  53. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -1
  54. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.d.ts.map +1 -1
  55. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js +88 -79
  56. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -1
  57. package/dist/coolandlovely/pages/looks/LookDetailPage.js +18 -18
  58. package/dist/coolandlovely/pages/looks/LookFormPage.js +6 -6
  59. package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -1
  60. package/dist/coolandlovely/pages/looks/LooksListPage.d.ts.map +1 -1
  61. package/dist/coolandlovely/pages/looks/LooksListPage.js +94 -94
  62. package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -1
  63. package/dist/coolandlovely/pages/profile/StyleProfilePage.d.ts.map +1 -1
  64. package/dist/coolandlovely/pages/profile/StyleProfilePage.js +226 -199
  65. package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -1
  66. package/dist/coolandlovely/pages/trends/TrendsPage.js +8 -8
  67. package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js +5 -5
  68. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.d.ts.map +1 -1
  69. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js +71 -69
  70. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -1
  71. package/package.json +1 -1
@@ -1,139 +1,148 @@
1
1
  import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js";
3
+ import { useCreateLookbook as n, useLookbooks as r } from "../../hooks/useCoolAndLovelyApi.js";
4
4
  import { COO_FILE_FOLDERS as i } from "../../hooks/useFiles.js";
5
- import { useCreateLookbook as a, useLookbooks as o } from "../../hooks/useCoolAndLovelyApi.js";
6
- import { parseCsv as s, titleCase as c } from "../../utils/formatters.js";
5
+ import { useTr as a } from "../../hooks/useTr.js";
7
6
  import "../../hooks/index.js";
8
- import { EmptyState as l } from "../../components/EmptyState.js";
9
- import { SelectField as u, TextAreaField as d, TextField as f } from "../../components/Field.js";
10
- import { ImageUploadField as p } from "../../components/ImageUploadField.js";
11
- import { LookbookCard as m } from "../../components/LookbookCard.js";
12
- import { useState as h } from "react";
13
- import { BookHeart as g, Loader2 as _, Plus as v, X as y } from "lucide-react";
14
- import { jsx as b, jsxs as x } from "react/jsx-runtime";
15
- import { GlassCard as S } from "@burdenoff/fe-libs/ui";
7
+ import { ErrorView as o, LoadingView as s } from "../../components/StateViews.js";
8
+ import { parseCsv as c, titleCase as l } from "../../utils/formatters.js";
9
+ import { EmptyState as u } from "../../components/EmptyState.js";
10
+ import { SelectField as d, TextAreaField as f, TextField as p } from "../../components/Field.js";
11
+ import { ImageUploadField as m } from "../../components/ImageUploadField.js";
12
+ import { LookbookCard as h } from "../../components/LookbookCard.js";
13
+ import { useMemo as g, useState as _ } from "react";
14
+ import { BookHeart as v, Loader2 as y, Plus as b, X as x } from "lucide-react";
15
+ import { jsx as S, jsxs as C } from "react/jsx-runtime";
16
+ import { GlassCard as w } from "@burdenoff/fe-libs/ui";
16
17
  //#region src/coolandlovely/pages/lookbooks/LookbooksListPage.tsx
17
- var C = [
18
+ var T = [
18
19
  "PRIVATE",
19
20
  "FOLLOWERS",
20
21
  "PUBLIC"
21
22
  ];
22
- function w() {
23
- let { navigateTo: w } = e(), T = o(), E = a(), [D, O] = h(!1), [k, A] = h(""), [j, M] = h(""), [N, P] = h("PRIVATE"), [F, I] = h(""), [L, R] = h(""), [z, B] = h(), V = T.data ?? [], H = C.map((e) => ({
23
+ function E() {
24
+ let { navigateTo: E } = e(), D = a(), O = r(), k = n(), [A, j] = _(!1), [M, N] = _(""), [P, F] = _(""), [I, L] = _("PRIVATE"), [R, z] = _(""), [B, V] = _(""), [H, U] = _(), W = O.data ?? [], G = g(() => T.map((e) => ({
24
25
  value: e,
25
- label: c(e)
26
- }));
27
- return /* @__PURE__ */ x(t, {
28
- title: "Lookbooks",
29
- description: "Themed boards of saved catalogue pieces and looks",
30
- actions: /* @__PURE__ */ x("button", {
26
+ label: D(`coolandlovely.visibility.${e.toLowerCase()}`, l(e))
27
+ })), [D]);
28
+ return /* @__PURE__ */ C(t, {
29
+ title: D("coolandlovely.page.lookbooksTitle", "Lookbooks"),
30
+ description: D("coolandlovely.page.lookbooksSubtitle", "Themed boards of saved catalogue pieces and looks"),
31
+ actions: /* @__PURE__ */ C("button", {
31
32
  type: "button",
32
- onClick: () => O((e) => !e),
33
+ onClick: () => j((e) => !e),
33
34
  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",
34
- children: [b(D ? y : v, { className: "h-4 w-4" }), D ? "Close" : "New lookbook"]
35
+ children: [S(A ? x : b, { className: "h-4 w-4" }), A ? D("coolandlovely.actions.close", "Close") : D("coolandlovely.actions.newLookbook", "New lookbook")]
35
36
  }),
36
- children: [D && /* @__PURE__ */ b("form", {
37
+ children: [A && /* @__PURE__ */ S("form", {
37
38
  onSubmit: (e) => {
38
- if (e.preventDefault(), !k.trim()) {
39
- B("Name is required");
39
+ if (e.preventDefault(), !M.trim()) {
40
+ U(D("coolandlovely.validation.nameRequired", "Name is required"));
40
41
  return;
41
42
  }
42
- B(void 0), E.mutate({
43
- name: k.trim(),
44
- description: j.trim() || void 0,
45
- visibility: N,
46
- tags: s(F),
47
- coverFileId: L || void 0
43
+ U(void 0), k.mutate({
44
+ name: M.trim(),
45
+ description: P.trim() || void 0,
46
+ visibility: I,
47
+ tags: c(R),
48
+ coverFileId: B || void 0
48
49
  }, { onSuccess: (e) => {
49
- O(!1), A(""), M(""), I(""), P("PRIVATE"), R(""), w(`/lookbooks/${e.id}`);
50
+ j(!1), N(""), F(""), z(""), L("PRIVATE"), V(""), E(`/lookbooks/${e.id}`);
50
51
  } });
51
52
  },
52
53
  className: "mb-6",
53
- children: /* @__PURE__ */ x(S, {
54
+ children: /* @__PURE__ */ C(w, {
54
55
  treatment: "plain",
55
56
  className: "p-5",
56
57
  children: [
57
- /* @__PURE__ */ x("h2", {
58
+ /* @__PURE__ */ C("h2", {
58
59
  className: "mb-4 flex items-center gap-2 text-base font-semibold text-text-primary",
59
- children: [/* @__PURE__ */ b(g, { className: "h-5 w-5" }), " New lookbook"]
60
+ children: [
61
+ /* @__PURE__ */ S(v, { className: "h-5 w-5" }),
62
+ " ",
63
+ D("coolandlovely.actions.newLookbook", "New lookbook")
64
+ ]
60
65
  }),
61
- /* @__PURE__ */ x("div", {
66
+ /* @__PURE__ */ C("div", {
62
67
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
63
- children: [/* @__PURE__ */ b(f, {
64
- label: "Name",
65
- value: k,
66
- onChange: A,
67
- placeholder: "Summer wedding guest",
68
+ children: [/* @__PURE__ */ S(p, {
69
+ label: D("coolandlovely.field.name", "Name"),
70
+ value: M,
71
+ onChange: N,
72
+ placeholder: D("coolandlovely.placeholder.lookbookName", "Summer wedding guest"),
68
73
  required: !0,
69
- error: z
70
- }), /* @__PURE__ */ b(u, {
71
- label: "Visibility",
72
- value: N,
73
- onChange: (e) => P(e),
74
- options: H
74
+ error: H
75
+ }), /* @__PURE__ */ S(d, {
76
+ label: D("coolandlovely.field.visibility", "Visibility"),
77
+ value: I,
78
+ onChange: (e) => L(e),
79
+ options: G
75
80
  })]
76
81
  }),
77
- /* @__PURE__ */ b(d, {
78
- label: "Description",
79
- value: j,
80
- onChange: M,
81
- placeholder: "What this board is for…",
82
+ /* @__PURE__ */ S(f, {
83
+ label: D("coolandlovely.field.description", "Description"),
84
+ value: P,
85
+ onChange: F,
86
+ placeholder: D("coolandlovely.placeholder.lookbookDescription", "What this board is for…"),
82
87
  rows: 2,
83
88
  className: "mt-4"
84
89
  }),
85
- /* @__PURE__ */ b(f, {
86
- label: "Tags",
87
- value: F,
88
- onChange: I,
89
- placeholder: "summer, formal",
90
- hint: "Comma-separated",
90
+ /* @__PURE__ */ S(p, {
91
+ label: D("coolandlovely.field.tags", "Tags"),
92
+ value: R,
93
+ onChange: z,
94
+ placeholder: D("coolandlovely.placeholder.tags", "summer, formal"),
95
+ hint: D("coolandlovely.hint.commaSeparated", "Comma-separated"),
91
96
  className: "mt-4"
92
97
  }),
93
- /* @__PURE__ */ b(p, {
94
- label: "Cover image",
98
+ /* @__PURE__ */ S(m, {
99
+ label: D("coolandlovely.field.coverImage", "Cover image"),
95
100
  aspect: "wide",
96
- value: L,
97
- onChange: R,
101
+ value: B,
102
+ onChange: V,
98
103
  folder: i.lookbooks,
99
104
  className: "mt-4"
100
105
  }),
101
- E.isError && /* @__PURE__ */ b("p", {
106
+ k.isError && /* @__PURE__ */ S("p", {
102
107
  className: "mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
103
- children: E.error instanceof Error ? E.error.message : "Something went wrong"
108
+ children: k.error instanceof Error ? k.error.message : D("coolandlovely.error.generic", "Something went wrong")
104
109
  }),
105
- /* @__PURE__ */ b("div", {
110
+ /* @__PURE__ */ S("div", {
106
111
  className: "mt-4 flex justify-end",
107
- children: /* @__PURE__ */ x("button", {
112
+ children: /* @__PURE__ */ C("button", {
108
113
  type: "submit",
109
- disabled: E.isPending,
114
+ disabled: k.isPending,
110
115
  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",
111
- children: [E.isPending ? /* @__PURE__ */ b(_, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ b(v, { className: "h-4 w-4" }), "Create lookbook"]
116
+ children: [k.isPending ? /* @__PURE__ */ S(y, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ S(b, { className: "h-4 w-4" }), D("coolandlovely.actions.createLookbook", "Create lookbook")]
112
117
  })
113
118
  })
114
119
  ]
115
120
  })
116
- }), T.isLoading ? /* @__PURE__ */ b(r, { label: "Loading lookbooks…" }) : T.isError ? /* @__PURE__ */ b(n, { onRetry: () => void T.refetch() }) : V.length === 0 ? /* @__PURE__ */ b(l, {
121
+ }), O.isLoading ? /* @__PURE__ */ S(s, { label: D("coolandlovely.loading.lookbooks", "Loading lookbooks…") }) : O.isError ? /* @__PURE__ */ S(o, { onRetry: () => void O.refetch() }) : W.length === 0 ? /* @__PURE__ */ S(u, {
117
122
  illustration: "empty-data",
118
- icon: /* @__PURE__ */ b(g, { className: "h-10 w-10" }),
119
- title: "No lookbooks yet",
120
- description: "Create a themed board to clip catalogue pieces and looks.",
121
- action: /* @__PURE__ */ x("button", {
123
+ icon: /* @__PURE__ */ S(v, { className: "h-10 w-10" }),
124
+ title: D("coolandlovely.empty.lookbooksTitle", "No lookbooks yet"),
125
+ description: D("coolandlovely.empty.lookbooksDescription", "Create a themed board to clip catalogue pieces and looks."),
126
+ action: /* @__PURE__ */ C("button", {
122
127
  type: "button",
123
- onClick: () => O(!0),
128
+ onClick: () => j(!0),
124
129
  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",
125
- children: [/* @__PURE__ */ b(v, { className: "h-4 w-4" }), " New lookbook"]
130
+ children: [
131
+ /* @__PURE__ */ S(b, { className: "h-4 w-4" }),
132
+ " ",
133
+ D("coolandlovely.actions.newLookbook", "New lookbook")
134
+ ]
126
135
  })
127
- }) : /* @__PURE__ */ b("div", {
136
+ }) : /* @__PURE__ */ S("div", {
128
137
  className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3",
129
- children: V.map((e) => /* @__PURE__ */ b(m, {
138
+ children: W.map((e) => /* @__PURE__ */ S(h, {
130
139
  lookbook: e,
131
- onClick: () => w(`/lookbooks/${e.id}`)
140
+ onClick: () => E(`/lookbooks/${e.id}`)
132
141
  }, e.id))
133
142
  })]
134
143
  });
135
144
  }
136
145
  //#endregion
137
- export { w as LookbooksListPage };
146
+ export { E as LookbooksListPage };
138
147
 
139
148
  //# sourceMappingURL=LookbooksListPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LookbooksListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/lookbooks/LookbooksListPage.tsx"],"sourcesContent":["/**\n * Lookbooks List Page\n * @module coolandlovely/pages/lookbooks\n *\n * Lists themed lookbook boards (`cooListLookbooks`) as mood-board cards — a\n * cover, a visibility chip and (when the list selection carries entries) an\n * item count — and supports creating one inline (`cooCreateLookbook`).\n */\n\nimport { useState } from 'react';\nimport { Plus, BookHeart, Loader2, X } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { LookbookCard } from '../../components/LookbookCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { TextField, TextAreaField, SelectField } from '../../components/Field';\nimport { ImageUploadField } from '../../components/ImageUploadField';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useLookbooks, useCreateLookbook } from '../../hooks';\nimport { COO_FILE_FOLDERS } from '../../hooks/useFiles';\nimport { parseCsv, titleCase } from '../../utils/formatters';\nimport type { CooVisibility } from '../../types';\n\nconst VISIBILITIES: CooVisibility[] = ['PRIVATE', 'FOLLOWERS', 'PUBLIC'];\n\nexport function LookbooksListPage() {\n const { navigateTo } = useCoolAndLovely();\n const query = useLookbooks();\n const createLookbook = useCreateLookbook();\n\n const [creating, setCreating] = useState(false);\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [visibility, setVisibility] = useState<CooVisibility>('PRIVATE');\n const [tags, setTags] = useState('');\n const [coverFileId, setCoverFileId] = useState('');\n const [nameError, setNameError] = useState<string | undefined>();\n\n const lookbooks = query.data ?? [];\n const visibilityOptions = VISIBILITIES.map((v) => ({ value: v, label: titleCase(v) }));\n\n const handleCreate = (e: React.FormEvent) => {\n e.preventDefault();\n if (!name.trim()) {\n setNameError('Name is required');\n return;\n }\n setNameError(undefined);\n createLookbook.mutate(\n {\n name: name.trim(),\n description: description.trim() || undefined,\n visibility,\n tags: parseCsv(tags),\n coverFileId: coverFileId || undefined,\n },\n {\n onSuccess: (lb) => {\n setCreating(false);\n setName('');\n setDescription('');\n setTags('');\n setVisibility('PRIVATE');\n setCoverFileId('');\n navigateTo(`/lookbooks/${lb.id}`);\n },\n }\n );\n };\n\n return (\n <PageLayout\n title=\"Lookbooks\"\n description=\"Themed boards of saved catalogue pieces and looks\"\n actions={\n <button\n type=\"button\"\n onClick={() => setCreating((v) => !v)}\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 {creating ? <X className=\"h-4 w-4\" /> : <Plus className=\"h-4 w-4\" />}\n {creating ? 'Close' : 'New lookbook'}\n </button>\n }\n >\n {creating && (\n <form onSubmit={handleCreate} className=\"mb-6\">\n <GlassCard treatment=\"plain\" className=\"p-5\">\n <h2 className=\"mb-4 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <BookHeart className=\"h-5 w-5\" /> New lookbook\n </h2>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n label=\"Name\"\n value={name}\n onChange={setName}\n placeholder=\"Summer wedding guest\"\n required\n error={nameError}\n />\n <SelectField\n label=\"Visibility\"\n value={visibility}\n onChange={(v) => setVisibility(v as CooVisibility)}\n options={visibilityOptions}\n />\n </div>\n <TextAreaField\n label=\"Description\"\n value={description}\n onChange={setDescription}\n placeholder=\"What this board is for…\"\n rows={2}\n className=\"mt-4\"\n />\n <TextField\n label=\"Tags\"\n value={tags}\n onChange={setTags}\n placeholder=\"summer, formal\"\n hint=\"Comma-separated\"\n className=\"mt-4\"\n />\n <ImageUploadField\n label=\"Cover image\"\n aspect=\"wide\"\n value={coverFileId}\n onChange={setCoverFileId}\n folder={COO_FILE_FOLDERS.lookbooks}\n className=\"mt-4\"\n />\n {createLookbook.isError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {createLookbook.error instanceof Error\n ? createLookbook.error.message\n : 'Something went wrong'}\n </p>\n )}\n <div className=\"mt-4 flex justify-end\">\n <button\n type=\"submit\"\n disabled={createLookbook.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 {createLookbook.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Plus className=\"h-4 w-4\" />\n )}\n Create lookbook\n </button>\n </div>\n </GlassCard>\n </form>\n )}\n\n {query.isLoading ? (\n <LoadingView label=\"Loading lookbooks…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : lookbooks.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BookHeart className=\"h-10 w-10\" />}\n title=\"No lookbooks yet\"\n description=\"Create a themed board to clip catalogue pieces and looks.\"\n action={\n <button\n type=\"button\"\n onClick={() => setCreating(true)}\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 lookbook\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3\">\n {lookbooks.map((lb) => (\n <LookbookCard\n key={lb.id}\n lookbook={lb}\n onClick={() => navigateTo(`/lookbooks/${lb.id}`)}\n />\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LookbooksListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/lookbooks/LookbooksListPage.tsx"],"sourcesContent":["/**\n * Lookbooks List Page\n * @module coolandlovely/pages/lookbooks\n *\n * Lists themed lookbook boards (`cooListLookbooks`) as mood-board cards — a\n * cover, a visibility chip and (when the list selection carries entries) an\n * item count — and supports creating one inline (`cooCreateLookbook`).\n */\n\nimport { useMemo, useState } from 'react';\nimport { Plus, BookHeart, Loader2, X } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { LookbookCard } from '../../components/LookbookCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { TextField, TextAreaField, SelectField } from '../../components/Field';\nimport { ImageUploadField } from '../../components/ImageUploadField';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useLookbooks, useCreateLookbook, useTr } from '../../hooks';\nimport { COO_FILE_FOLDERS } from '../../hooks/useFiles';\nimport { parseCsv, titleCase } from '../../utils/formatters';\nimport type { CooVisibility } from '../../types';\n\nconst VISIBILITIES: CooVisibility[] = ['PRIVATE', 'FOLLOWERS', 'PUBLIC'];\n\nexport function LookbooksListPage() {\n const { navigateTo } = useCoolAndLovely();\n const tr = useTr();\n const query = useLookbooks();\n const createLookbook = useCreateLookbook();\n\n const [creating, setCreating] = useState(false);\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [visibility, setVisibility] = useState<CooVisibility>('PRIVATE');\n const [tags, setTags] = useState('');\n const [coverFileId, setCoverFileId] = useState('');\n const [nameError, setNameError] = useState<string | undefined>();\n\n const lookbooks = query.data ?? [];\n const visibilityOptions = useMemo(\n () =>\n VISIBILITIES.map((v) => ({\n value: v,\n label: tr(`coolandlovely.visibility.${v.toLowerCase()}`, titleCase(v)),\n })),\n [tr]\n );\n\n const handleCreate = (e: React.FormEvent) => {\n e.preventDefault();\n if (!name.trim()) {\n setNameError(tr('coolandlovely.validation.nameRequired', 'Name is required'));\n return;\n }\n setNameError(undefined);\n createLookbook.mutate(\n {\n name: name.trim(),\n description: description.trim() || undefined,\n visibility,\n tags: parseCsv(tags),\n coverFileId: coverFileId || undefined,\n },\n {\n onSuccess: (lb) => {\n setCreating(false);\n setName('');\n setDescription('');\n setTags('');\n setVisibility('PRIVATE');\n setCoverFileId('');\n navigateTo(`/lookbooks/${lb.id}`);\n },\n }\n );\n };\n\n return (\n <PageLayout\n title={tr('coolandlovely.page.lookbooksTitle', 'Lookbooks')}\n description={tr(\n 'coolandlovely.page.lookbooksSubtitle',\n 'Themed boards of saved catalogue pieces and looks'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => setCreating((v) => !v)}\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 {creating ? <X className=\"h-4 w-4\" /> : <Plus className=\"h-4 w-4\" />}\n {creating\n ? tr('coolandlovely.actions.close', 'Close')\n : tr('coolandlovely.actions.newLookbook', 'New lookbook')}\n </button>\n }\n >\n {creating && (\n <form onSubmit={handleCreate} className=\"mb-6\">\n <GlassCard treatment=\"plain\" className=\"p-5\">\n <h2 className=\"mb-4 flex items-center gap-2 text-base font-semibold text-text-primary\">\n <BookHeart className=\"h-5 w-5\" />{' '}\n {tr('coolandlovely.actions.newLookbook', 'New lookbook')}\n </h2>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n label={tr('coolandlovely.field.name', 'Name')}\n value={name}\n onChange={setName}\n placeholder={tr('coolandlovely.placeholder.lookbookName', 'Summer wedding guest')}\n required\n error={nameError}\n />\n <SelectField\n label={tr('coolandlovely.field.visibility', 'Visibility')}\n value={visibility}\n onChange={(v) => setVisibility(v as CooVisibility)}\n options={visibilityOptions}\n />\n </div>\n <TextAreaField\n label={tr('coolandlovely.field.description', 'Description')}\n value={description}\n onChange={setDescription}\n placeholder={tr(\n 'coolandlovely.placeholder.lookbookDescription',\n 'What this board is for…'\n )}\n rows={2}\n className=\"mt-4\"\n />\n <TextField\n label={tr('coolandlovely.field.tags', 'Tags')}\n value={tags}\n onChange={setTags}\n placeholder={tr('coolandlovely.placeholder.tags', 'summer, formal')}\n hint={tr('coolandlovely.hint.commaSeparated', 'Comma-separated')}\n className=\"mt-4\"\n />\n <ImageUploadField\n label={tr('coolandlovely.field.coverImage', 'Cover image')}\n aspect=\"wide\"\n value={coverFileId}\n onChange={setCoverFileId}\n folder={COO_FILE_FOLDERS.lookbooks}\n className=\"mt-4\"\n />\n {createLookbook.isError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {createLookbook.error instanceof Error\n ? createLookbook.error.message\n : tr('coolandlovely.error.generic', 'Something went wrong')}\n </p>\n )}\n <div className=\"mt-4 flex justify-end\">\n <button\n type=\"submit\"\n disabled={createLookbook.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 {createLookbook.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Plus className=\"h-4 w-4\" />\n )}\n {tr('coolandlovely.actions.createLookbook', 'Create lookbook')}\n </button>\n </div>\n </GlassCard>\n </form>\n )}\n\n {query.isLoading ? (\n <LoadingView label={tr('coolandlovely.loading.lookbooks', 'Loading lookbooks…')} />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : lookbooks.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BookHeart className=\"h-10 w-10\" />}\n title={tr('coolandlovely.empty.lookbooksTitle', 'No lookbooks yet')}\n description={tr(\n 'coolandlovely.empty.lookbooksDescription',\n 'Create a themed board to clip catalogue pieces and looks.'\n )}\n action={\n <button\n type=\"button\"\n onClick={() => setCreating(true)}\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\" /> {tr('coolandlovely.actions.newLookbook', 'New lookbook')}\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3\">\n {lookbooks.map((lb) => (\n <LookbookCard\n key={lb.id}\n lookbook={lb}\n onClick={() => navigateTo(`/lookbooks/${lb.id}`)}\n />\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,IAAM,IAAgC;CAAC;CAAW;CAAa;CAAS;AAExE,SAAgB,IAAoB;CAClC,IAAM,EAAE,kBAAe,GAAkB,EACnC,IAAK,GAAO,EACZ,IAAQ,GAAc,EACtB,IAAiB,GAAmB,EAEpC,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAY,KAAiB,EAAwB,UAAU,EAChE,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAW,KAAgB,GAA8B,EAE1D,IAAY,EAAM,QAAQ,EAAE,EAC5B,IAAoB,QAEtB,EAAa,KAAK,OAAO;EACvB,OAAO;EACP,OAAO,EAAG,4BAA4B,EAAE,aAAa,IAAI,EAAU,EAAE,CAAC;EACvE,EAAE,EACL,CAAC,EAAG,CACL;AA+BD,QACE,kBAAC,GAAD;EACE,OAAO,EAAG,qCAAqC,YAAY;EAC3D,aAAa,EACX,wCACA,oDACD;EACD,SACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,GAAa,MAAM,CAAC,EAAE;GACrC,WAAU;aAHZ,CAKc,EAAX,IAAY,IAA4B,GAA7B,EAAG,WAAU,WAAY,CAA+B,EACnE,IACG,EAAG,+BAA+B,QAAQ,GAC1C,EAAG,qCAAqC,eAAe,CACpD;;YAhBb,CAmBG,KACC,kBAAC,QAAD;GAAM,WAlDU,MAAuB;AAE3C,QADA,EAAE,gBAAgB,EACd,CAAC,EAAK,MAAM,EAAE;AAChB,OAAa,EAAG,yCAAyC,mBAAmB,CAAC;AAC7E;;AAGF,IADA,EAAa,KAAA,EAAU,EACvB,EAAe,OACb;KACE,MAAM,EAAK,MAAM;KACjB,aAAa,EAAY,MAAM,IAAI,KAAA;KACnC;KACA,MAAM,EAAS,EAAK;KACpB,aAAa,KAAe,KAAA;KAC7B,EACD,EACE,YAAY,MAAO;AAOjB,KANA,EAAY,GAAM,EAClB,EAAQ,GAAG,EACX,EAAe,GAAG,EAClB,EAAQ,GAAG,EACX,EAAc,UAAU,EACxB,EAAe,GAAG,EAClB,EAAW,cAAc,EAAG,KAAK;OAEpC,CACF;;GAwBiC,WAAU;aACtC,kBAAC,GAAD;IAAW,WAAU;IAAQ,WAAU;cAAvC;KACE,kBAAC,MAAD;MAAI,WAAU;gBAAd;OACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;OAAC;OACjC,EAAG,qCAAqC,eAAe;OACrD;;KACL,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OACE,OAAO,EAAG,4BAA4B,OAAO;OAC7C,OAAO;OACP,UAAU;OACV,aAAa,EAAG,0CAA0C,uBAAuB;OACjF,UAAA;OACA,OAAO;OACP,CAAA,EACF,kBAAC,GAAD;OACE,OAAO,EAAG,kCAAkC,aAAa;OACzD,OAAO;OACP,WAAW,MAAM,EAAc,EAAmB;OAClD,SAAS;OACT,CAAA,CACE;;KACN,kBAAC,GAAD;MACE,OAAO,EAAG,mCAAmC,cAAc;MAC3D,OAAO;MACP,UAAU;MACV,aAAa,EACX,iDACA,0BACD;MACD,MAAM;MACN,WAAU;MACV,CAAA;KACF,kBAAC,GAAD;MACE,OAAO,EAAG,4BAA4B,OAAO;MAC7C,OAAO;MACP,UAAU;MACV,aAAa,EAAG,kCAAkC,iBAAiB;MACnE,MAAM,EAAG,qCAAqC,kBAAkB;MAChE,WAAU;MACV,CAAA;KACF,kBAAC,GAAD;MACE,OAAO,EAAG,kCAAkC,cAAc;MAC1D,QAAO;MACP,OAAO;MACP,UAAU;MACV,QAAQ,EAAiB;MACzB,WAAU;MACV,CAAA;KACD,EAAe,WACd,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAe,iBAAiB,QAC7B,EAAe,MAAM,UACrB,EAAG,+BAA+B,uBAAuB;MAC3D,CAAA;KAEN,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,EAAe;OACzB,WAAU;iBAHZ,CAKG,EAAe,YACd,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,GAE5C,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAE7B,EAAG,wCAAwC,kBAAkB,CACvD;;MACL,CAAA;KACI;;GACP,CAAA,EAGR,EAAM,YACL,kBAAC,GAAD,EAAa,OAAO,EAAG,mCAAmC,qBAAqB,EAAI,CAAA,GACjF,EAAM,UACR,kBAAC,GAAD,EAAW,eAAe,KAAK,EAAM,SAAS,EAAI,CAAA,GAChD,EAAU,WAAW,IACvB,kBAAC,GAAD;GACE,cAAa;GACb,MAAM,kBAAC,GAAD,EAAW,WAAU,aAAc,CAAA;GACzC,OAAO,EAAG,sCAAsC,mBAAmB;GACnE,aAAa,EACX,4CACA,4DACD;GACD,QACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAY,GAAK;IAChC,WAAU;cAHZ;KAKE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;;KAAE,EAAG,qCAAqC,eAAe;KAC9E;;GAEX,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAU,KAAK,MACd,kBAAC,GAAD;IAEE,UAAU;IACV,eAAe,EAAW,cAAc,EAAG,KAAK;IAChD,EAHK,EAAG,GAGR,CACF;GACE,CAAA,CAEG"}
@@ -1,14 +1,14 @@
1
1
  import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
2
  import { cn as t } from "../../utils/cn.js";
3
3
  import { PageLayout as n } from "../../components/PageLayout.js";
4
- import { StatusBadge as r } from "../../components/StatusBadge.js";
5
- import { ErrorView as i, LoadingView as a } from "../../components/StateViews.js";
6
- import { Thumbnail as o } from "../../components/Thumbnail.js";
7
- import { useDeleteLook as s, useLikeLook as c, useLook as l, usePublishLook as u, useSaveLook as d, useUnlikeLook as f, useUnsaveLook as p, useUpdateLook as m } from "../../hooks/useCoolAndLovelyApi.js";
8
- import { AddToLookbookButton as h } from "../../components/AddToLookbookButton.js";
9
- import { formatDate as g, titleCase as _ } from "../../utils/formatters.js";
10
- import { useAssistantEntityName as v } from "../../hooks/useAssistantEntity.js";
4
+ import { useDeleteLook as r, useLikeLook as i, useLook as a, usePublishLook as o, useSaveLook as s, useUnlikeLook as c, useUnsaveLook as l, useUpdateLook as u } from "../../hooks/useCoolAndLovelyApi.js";
5
+ import { useAssistantEntityName as d } from "../../hooks/useAssistantEntity.js";
11
6
  import "../../hooks/index.js";
7
+ import { StatusBadge as f } from "../../components/StatusBadge.js";
8
+ import { ErrorView as p, LoadingView as m } from "../../components/StateViews.js";
9
+ import { Thumbnail as h } from "../../components/Thumbnail.js";
10
+ import { AddToLookbookButton as g } from "../../components/AddToLookbookButton.js";
11
+ import { formatDate as _, titleCase as v } from "../../utils/formatters.js";
12
12
  import { TagList as y } from "../../components/TagList.js";
13
13
  import { Comments as b } from "../../components/Comments.js";
14
14
  import { FollowButton as x } from "../../components/FollowButton.js";
@@ -58,14 +58,14 @@ function z({ authorId: t }) {
58
58
  });
59
59
  }
60
60
  function B() {
61
- let { lookId: C } = N(), { navigateTo: w, currentUser: L } = e(), R = l(C), B = c(), V = f(), H = d(), U = p(), W = u(), G = s(), K = m();
62
- if (v(C, R.data?.title), R.isLoading) return /* @__PURE__ */ P(n, {
61
+ let { lookId: C } = N(), { navigateTo: w, currentUser: L } = e(), R = a(C), B = i(), V = c(), H = s(), U = l(), W = o(), G = r(), K = u();
62
+ if (d(C, R.data?.title), R.isLoading) return /* @__PURE__ */ P(n, {
63
63
  title: "Look",
64
- children: /* @__PURE__ */ P(a, { label: "Loading look…" })
64
+ children: /* @__PURE__ */ P(m, { label: "Loading look…" })
65
65
  });
66
66
  if (R.isError || !R.data) return /* @__PURE__ */ P(n, {
67
67
  title: "Look",
68
- children: /* @__PURE__ */ P(i, {
68
+ children: /* @__PURE__ */ P(p, {
69
69
  title: "Look not found",
70
70
  onRetry: () => void R.refetch()
71
71
  })
@@ -73,7 +73,7 @@ function B() {
73
73
  let q = R.data, J = q.items ?? [], Y = q.publishedAt !== null, X = !!(L?.id && L.id === q.authorId);
74
74
  return /* @__PURE__ */ P(n, {
75
75
  title: q.title,
76
- description: _(q.occasion),
76
+ description: v(q.occasion),
77
77
  actions: /* @__PURE__ */ F("div", {
78
78
  className: "flex flex-wrap items-center gap-2",
79
79
  children: [
@@ -83,7 +83,7 @@ function B() {
83
83
  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",
84
84
  children: [/* @__PURE__ */ P(T, { className: "h-4 w-4" }), " Back"]
85
85
  }),
86
- /* @__PURE__ */ P(h, { lookId: q.id }),
86
+ /* @__PURE__ */ P(g, { lookId: q.id }),
87
87
  /* @__PURE__ */ F("button", {
88
88
  type: "button",
89
89
  disabled: K.isPending,
@@ -119,7 +119,7 @@ function B() {
119
119
  /* @__PURE__ */ F(I, {
120
120
  treatment: "glass",
121
121
  className: "group overflow-hidden p-0",
122
- children: [/* @__PURE__ */ P(o, {
122
+ children: [/* @__PURE__ */ P(h, {
123
123
  icon: /* @__PURE__ */ P(A, { className: "h-14 w-14" }),
124
124
  seed: q.id,
125
125
  fileId: q.image?.id,
@@ -136,7 +136,7 @@ function B() {
136
136
  children: q.title
137
137
  }),
138
138
  q.isFeatured && /* @__PURE__ */ P(j, { className: "h-4 w-4 fill-status-warning-text text-status-warning-text" }),
139
- /* @__PURE__ */ P(r, {
139
+ /* @__PURE__ */ P(f, {
140
140
  status: Y ? "published" : "draft",
141
141
  className: "ml-auto"
142
142
  })
@@ -247,7 +247,7 @@ function B() {
247
247
  children: "Occasion"
248
248
  }), /* @__PURE__ */ P("dd", {
249
249
  className: "text-text-primary",
250
- children: _(q.occasion)
250
+ children: v(q.occasion)
251
251
  })]
252
252
  }),
253
253
  /* @__PURE__ */ F("div", {
@@ -257,7 +257,7 @@ function B() {
257
257
  children: "Visibility"
258
258
  }), /* @__PURE__ */ P("dd", {
259
259
  className: "text-text-primary",
260
- children: _(q.visibility)
260
+ children: v(q.visibility)
261
261
  })]
262
262
  }),
263
263
  /* @__PURE__ */ F("div", {
@@ -267,7 +267,7 @@ function B() {
267
267
  children: "Published"
268
268
  }), /* @__PURE__ */ P("dd", {
269
269
  className: "text-text-primary",
270
- children: q.publishedAt ? g(q.publishedAt, {
270
+ children: q.publishedAt ? _(q.publishedAt, {
271
271
  hour: void 0,
272
272
  minute: void 0
273
273
  }) : "—"
@@ -1,10 +1,10 @@
1
1
  import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
2
  import { cn as t } from "../../utils/cn.js";
3
3
  import { PageLayout as n } from "../../components/PageLayout.js";
4
- import { COO_FILE_FOLDERS as r } from "../../hooks/useFiles.js";
5
- import { useCollaborations as ee, useCreateLook as i, useStyleItems as a, useUpdateLook as te } from "../../hooks/useCoolAndLovelyApi.js";
6
- import { formatPrice as o, parseCsv as s, titleCase as c } from "../../utils/formatters.js";
4
+ import { useCollaborations as r, useCreateLook as ee, useStyleItems as i, useUpdateLook as a } from "../../hooks/useCoolAndLovelyApi.js";
5
+ import { COO_FILE_FOLDERS as te } from "../../hooks/useFiles.js";
7
6
  import "../../hooks/index.js";
7
+ import { formatPrice as o, parseCsv as s, titleCase as c } from "../../utils/formatters.js";
8
8
  import { SelectField as l, TextAreaField as ne, TextField as u, ToggleField as re } from "../../components/Field.js";
9
9
  import { ImageUploadField as d } from "../../components/ImageUploadField.js";
10
10
  import { useMemo as f, useState as p } from "react";
@@ -27,10 +27,10 @@ var y = [
27
27
  "PRIVATE"
28
28
  ];
29
29
  function x() {
30
- let { navigateTo: x, currentUser: S } = e(), C = i(), w = te(), T = a({ pagination: {
30
+ let { navigateTo: x, currentUser: S } = e(), C = ee(), w = a(), T = i({ pagination: {
31
31
  limit: 100,
32
32
  offset: 0
33
- } }), E = ee(S?.id ? { creatorId: S.id } : {}), [D, ce] = p(""), [O, k] = p(""), [A, j] = p("EVERYDAY"), [M, N] = p("PUBLIC"), [P, F] = p(""), [I, L] = p(""), [R, z] = p(""), [B, V] = p(!1), [H, U] = p([]), [W, G] = p(""), [le, K] = p(), q = f(() => (T.data?.items ?? []).filter((e) => e.status !== "RETIRED"), [T.data]), J = f(() => q.map((e) => ({
33
+ } }), E = r(S?.id ? { creatorId: S.id } : {}), [D, ce] = p(""), [O, k] = p(""), [A, j] = p("EVERYDAY"), [M, N] = p("PUBLIC"), [P, F] = p(""), [I, L] = p(""), [R, z] = p(""), [B, V] = p(!1), [H, U] = p([]), [W, G] = p(""), [le, K] = p(), q = f(() => (T.data?.items ?? []).filter((e) => e.status !== "RETIRED"), [T.data]), J = f(() => q.map((e) => ({
34
34
  value: e.id,
35
35
  label: `${e.name}${e.brand?.name ? ` · ${e.brand.name}` : ""} — ${o(e.price, e.currency)}`
36
36
  })), [q]), Y = f(() => {
@@ -132,7 +132,7 @@ function x() {
132
132
  aspect: "wide",
133
133
  value: I,
134
134
  onChange: L,
135
- folder: r.looks,
135
+ folder: te.looks,
136
136
  hint: "The styled outfit shot",
137
137
  className: "mt-4"
138
138
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"LookFormPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/looks/LookFormPage.tsx"],"sourcesContent":["/**\n * Look Create Page\n * @module coolandlovely/pages/looks\n *\n * Drives `cooCreateLook`. A look is created with its title/occasion/visibility\n * and an inline list of look items (catalogue pieces + styling notes), matching\n * the `CooCreateLookInput` shape exactly.\n */\n\nimport { useMemo, useState } from 'react';\nimport { ArrowLeft, Loader2, Plus, Save, Sparkles, X } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { TextField, TextAreaField, SelectField, ToggleField } from '../../components/Field';\nimport { ImageUploadField } from '../../components/ImageUploadField';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useCreateLook, useUpdateLook, useStyleItems, useCollaborations } from '../../hooks';\nimport { COO_FILE_FOLDERS } from '../../hooks/useFiles';\nimport { parseCsv, titleCase, formatPrice } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { CooLookOccasion, CooVisibility, CooLookItemInput } from '../../types';\n\nconst OCCASIONS: CooLookOccasion[] = [\n 'EVERYDAY',\n 'WORK',\n 'EVENING',\n 'WEDDING_GUEST',\n 'VACATION',\n 'PARTY',\n 'ACTIVE',\n 'OTHER',\n];\n\nconst VISIBILITIES: CooVisibility[] = ['PUBLIC', 'FOLLOWERS', 'PRIVATE'];\n\ninterface DraftItem {\n styleItemId: string;\n styling: string;\n}\n\nexport function LookFormPage() {\n const { navigateTo, currentUser } = useCoolAndLovely();\n const createLook = useCreateLook();\n const updateLook = useUpdateLook();\n const styleItems = useStyleItems({ pagination: { limit: 100, offset: 0 } });\n // The caller's own collaborations — a look can be attributed to one.\n const collaborations = useCollaborations(currentUser?.id ? { creatorId: currentUser.id } : {});\n\n const [title, setTitle] = useState('');\n const [caption, setCaption] = useState('');\n const [occasion, setOccasion] = useState<CooLookOccasion>('EVERYDAY');\n const [visibility, setVisibility] = useState<CooVisibility>('PUBLIC');\n const [tags, setTags] = useState('');\n const [imageFileId, setImageFileId] = useState('');\n const [collaborationId, setCollaborationId] = useState('');\n const [isFeatured, setIsFeatured] = useState(false);\n const [draftItems, setDraftItems] = useState<DraftItem[]>([]);\n const [addValue, setAddValue] = useState('');\n const [titleError, setTitleError] = useState<string | undefined>();\n\n const usableItems = useMemo(\n () => (styleItems.data?.items ?? []).filter((i) => i.status !== 'RETIRED'),\n [styleItems.data]\n );\n\n const itemOptions = useMemo(\n () =>\n usableItems.map((i) => ({\n value: i.id,\n label: `${i.name}${i.brand?.name ? ` · ${i.brand.name}` : ''} — ${formatPrice(i.price, i.currency)}`,\n })),\n [usableItems]\n );\n\n // Pieces not yet added — the right-rail \"add\" picker only offers these.\n const availableOptions = useMemo(() => {\n const chosen = new Set(draftItems.map((d) => d.styleItemId));\n return itemOptions.filter((o) => !chosen.has(o.value));\n }, [itemOptions, draftItems]);\n\n const collaborationOptions = useMemo(\n () => (collaborations.data ?? []).map((c) => ({ value: c.id, label: c.title })),\n [collaborations.data]\n );\n\n const occasionOptions = OCCASIONS.map((o) => ({ value: o, label: titleCase(o) }));\n const visibilityOptions = VISIBILITIES.map((v) => ({ value: v, label: titleCase(v) }));\n\n const addDraftItem = (styleItemId: string) => {\n if (!styleItemId) return;\n setDraftItems((d) =>\n d.some((it) => it.styleItemId === styleItemId) ? d : [...d, { styleItemId, styling: '' }]\n );\n };\n const removeDraftItem = (idx: number) => setDraftItems((d) => d.filter((_, i) => i !== idx));\n const setDraftItem = (idx: number, patch: Partial<DraftItem>) =>\n setDraftItems((d) => d.map((it, i) => (i === idx ? { ...it, ...patch } : it)));\n\n const submitting = createLook.isPending || updateLook.isPending;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!title.trim()) {\n setTitleError('Title is required');\n return;\n }\n setTitleError(undefined);\n\n const items: CooLookItemInput[] = draftItems\n .filter((d) => d.styleItemId)\n .map((d, idx) => ({\n styleItemId: d.styleItemId,\n position: idx,\n styling: d.styling.trim() || undefined,\n }));\n\n createLook.mutate(\n {\n title: title.trim(),\n caption: caption.trim() || undefined,\n occasion,\n visibility,\n collaborationId: collaborationId || undefined,\n imageFileId: imageFileId || undefined,\n tags: parseCsv(tags),\n items: items.length > 0 ? items : undefined,\n },\n {\n onSuccess: (look) => {\n // isFeatured is only settable via update — feature right after create.\n if (isFeatured) {\n updateLook.mutate(\n { id: look.id, input: { isFeatured: true } },\n { onSuccess: () => navigateTo(`/looks/${look.id}`) }\n );\n } else {\n navigateTo(`/looks/${look.id}`);\n }\n },\n }\n );\n };\n\n return (\n <PageLayout\n title=\"New look\"\n description=\"Compose a shop-the-look outfit from catalogue pieces\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/looks')}\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\" /> Cancel\n </button>\n }\n >\n <form onSubmit={handleSubmit} className=\"mx-auto max-w-2xl\">\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-11 w-11 items-center justify-center rounded-lg bg-status-success-bg-subtle text-status-success-text\">\n <Sparkles className=\"h-5 w-5\" />\n </div>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Look details</h2>\n <p className=\"text-xs text-text-secondary\">\n Created as a draft — publish it from the look page.\n </p>\n </div>\n </div>\n\n <TextField\n id=\"title\"\n label=\"Title\"\n value={title}\n onChange={setTitle}\n placeholder=\"Coastal grandma, refined\"\n required\n error={titleError}\n />\n\n <TextAreaField\n id=\"caption\"\n label=\"Caption\"\n value={caption}\n onChange={setCaption}\n placeholder=\"How to style it…\"\n rows={3}\n className=\"mt-4\"\n />\n\n <ImageUploadField\n label=\"Look photo\"\n aspect=\"wide\"\n value={imageFileId}\n onChange={setImageFileId}\n folder={COO_FILE_FOLDERS.looks}\n hint=\"The styled outfit shot\"\n className=\"mt-4\"\n />\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <SelectField\n id=\"occasion\"\n label=\"Occasion\"\n value={occasion}\n onChange={(v) => setOccasion(v as CooLookOccasion)}\n options={occasionOptions}\n />\n <SelectField\n id=\"visibility\"\n label=\"Visibility\"\n value={visibility}\n onChange={(v) => setVisibility(v as CooVisibility)}\n options={visibilityOptions}\n />\n </div>\n\n <SelectField\n id=\"collaborationId\"\n label=\"Collaboration (optional)\"\n value={collaborationId}\n onChange={setCollaborationId}\n options={collaborationOptions}\n placeholder={\n collaborations.isLoading\n ? 'Loading collaborations…'\n : collaborationOptions.length === 0\n ? 'No collaborations yet'\n : 'Not part of a collaboration'\n }\n hint=\"Attribute this look to one of your collaborations\"\n className=\"mt-4\"\n />\n\n <TextField\n id=\"tags\"\n label=\"Tags\"\n value={tags}\n onChange={setTags}\n placeholder=\"linen, neutral\"\n hint=\"Comma-separated\"\n className=\"mt-4\"\n />\n\n <ToggleField\n id=\"isFeatured\"\n label=\"Feature this look\"\n checked={isFeatured}\n onChange={setIsFeatured}\n hint=\"Featured looks surface in the Featured filter and carry a star badge.\"\n className=\"mt-4\"\n />\n\n {/* Look items */}\n <div className=\"mt-6\">\n <div className=\"mb-3 flex flex-col gap-3 sm:flex-row sm:items-end\">\n <div className=\"flex-1\">\n <SelectField\n id=\"add-style-item\"\n label=\"Pieces in this look\"\n value={addValue}\n onChange={setAddValue}\n options={availableOptions}\n placeholder={\n styleItems.isLoading\n ? 'Loading catalogue…'\n : availableOptions.length === 0\n ? 'All available pieces are already added'\n : 'Select a catalogue piece'\n }\n />\n </div>\n <button\n type=\"button\"\n disabled={!addValue}\n onClick={() => {\n addDraftItem(addValue);\n setAddValue('');\n }}\n className=\"inline-flex items-center justify-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 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Plus className=\"h-4 w-4\" /> Add piece\n </button>\n </div>\n {draftItems.length === 0 ? (\n <p className=\"rounded-lg border border-dashed border-border-seam p-4 text-center text-xs text-text-secondary\">\n No pieces added yet. A look can be published without pieces and styled later.\n </p>\n ) : (\n <div className=\"space-y-3\">\n {draftItems.map((di, idx) => (\n <div key={idx} className=\"rounded-lg border border-border-seam bg-bg-surface p-3\">\n <div className=\"flex items-start gap-2\">\n <div className=\"flex-1 space-y-2\">\n <SelectField\n label={`Piece ${idx + 1}`}\n value={di.styleItemId}\n onChange={(v) => setDraftItem(idx, { styleItemId: v })}\n options={itemOptions}\n placeholder={\n styleItems.isLoading ? 'Loading items…' : 'Select a style item'\n }\n />\n <TextField\n label=\"Styling note\"\n value={di.styling}\n onChange={(v) => setDraftItem(idx, { styling: v })}\n placeholder=\"Cuff the sleeves, tuck the front…\"\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeDraftItem(idx)}\n aria-label=\"Remove piece\"\n className={cn(\n 'mt-7 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg',\n 'text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text'\n )}\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {createLook.isError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {createLook.error instanceof Error\n ? createLook.error.message\n : 'Something went wrong'}\n </p>\n )}\n\n <div className=\"mt-6 flex justify-end gap-2\">\n <button\n type=\"submit\"\n disabled={submitting}\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 {submitting ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n Create look\n </button>\n </div>\n </GlassCard>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LookFormPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/looks/LookFormPage.tsx"],"sourcesContent":["/**\n * Look Create Page\n * @module coolandlovely/pages/looks\n *\n * Drives `cooCreateLook`. A look is created with its title/occasion/visibility\n * and an inline list of look items (catalogue pieces + styling notes), matching\n * the `CooCreateLookInput` shape exactly.\n */\n\nimport { useMemo, useState } from 'react';\nimport { ArrowLeft, Loader2, Plus, Save, Sparkles, X } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { TextField, TextAreaField, SelectField, ToggleField } from '../../components/Field';\nimport { ImageUploadField } from '../../components/ImageUploadField';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useCreateLook, useUpdateLook, useStyleItems, useCollaborations } from '../../hooks';\nimport { COO_FILE_FOLDERS } from '../../hooks/useFiles';\nimport { parseCsv, titleCase, formatPrice } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { CooLookOccasion, CooVisibility, CooLookItemInput } from '../../types';\n\nconst OCCASIONS: CooLookOccasion[] = [\n 'EVERYDAY',\n 'WORK',\n 'EVENING',\n 'WEDDING_GUEST',\n 'VACATION',\n 'PARTY',\n 'ACTIVE',\n 'OTHER',\n];\n\nconst VISIBILITIES: CooVisibility[] = ['PUBLIC', 'FOLLOWERS', 'PRIVATE'];\n\ninterface DraftItem {\n styleItemId: string;\n styling: string;\n}\n\nexport function LookFormPage() {\n const { navigateTo, currentUser } = useCoolAndLovely();\n const createLook = useCreateLook();\n const updateLook = useUpdateLook();\n const styleItems = useStyleItems({ pagination: { limit: 100, offset: 0 } });\n // The caller's own collaborations — a look can be attributed to one.\n const collaborations = useCollaborations(currentUser?.id ? { creatorId: currentUser.id } : {});\n\n const [title, setTitle] = useState('');\n const [caption, setCaption] = useState('');\n const [occasion, setOccasion] = useState<CooLookOccasion>('EVERYDAY');\n const [visibility, setVisibility] = useState<CooVisibility>('PUBLIC');\n const [tags, setTags] = useState('');\n const [imageFileId, setImageFileId] = useState('');\n const [collaborationId, setCollaborationId] = useState('');\n const [isFeatured, setIsFeatured] = useState(false);\n const [draftItems, setDraftItems] = useState<DraftItem[]>([]);\n const [addValue, setAddValue] = useState('');\n const [titleError, setTitleError] = useState<string | undefined>();\n\n const usableItems = useMemo(\n () => (styleItems.data?.items ?? []).filter((i) => i.status !== 'RETIRED'),\n [styleItems.data]\n );\n\n const itemOptions = useMemo(\n () =>\n usableItems.map((i) => ({\n value: i.id,\n label: `${i.name}${i.brand?.name ? ` · ${i.brand.name}` : ''} — ${formatPrice(i.price, i.currency)}`,\n })),\n [usableItems]\n );\n\n // Pieces not yet added — the right-rail \"add\" picker only offers these.\n const availableOptions = useMemo(() => {\n const chosen = new Set(draftItems.map((d) => d.styleItemId));\n return itemOptions.filter((o) => !chosen.has(o.value));\n }, [itemOptions, draftItems]);\n\n const collaborationOptions = useMemo(\n () => (collaborations.data ?? []).map((c) => ({ value: c.id, label: c.title })),\n [collaborations.data]\n );\n\n const occasionOptions = OCCASIONS.map((o) => ({ value: o, label: titleCase(o) }));\n const visibilityOptions = VISIBILITIES.map((v) => ({ value: v, label: titleCase(v) }));\n\n const addDraftItem = (styleItemId: string) => {\n if (!styleItemId) return;\n setDraftItems((d) =>\n d.some((it) => it.styleItemId === styleItemId) ? d : [...d, { styleItemId, styling: '' }]\n );\n };\n const removeDraftItem = (idx: number) => setDraftItems((d) => d.filter((_, i) => i !== idx));\n const setDraftItem = (idx: number, patch: Partial<DraftItem>) =>\n setDraftItems((d) => d.map((it, i) => (i === idx ? { ...it, ...patch } : it)));\n\n const submitting = createLook.isPending || updateLook.isPending;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!title.trim()) {\n setTitleError('Title is required');\n return;\n }\n setTitleError(undefined);\n\n const items: CooLookItemInput[] = draftItems\n .filter((d) => d.styleItemId)\n .map((d, idx) => ({\n styleItemId: d.styleItemId,\n position: idx,\n styling: d.styling.trim() || undefined,\n }));\n\n createLook.mutate(\n {\n title: title.trim(),\n caption: caption.trim() || undefined,\n occasion,\n visibility,\n collaborationId: collaborationId || undefined,\n imageFileId: imageFileId || undefined,\n tags: parseCsv(tags),\n items: items.length > 0 ? items : undefined,\n },\n {\n onSuccess: (look) => {\n // isFeatured is only settable via update — feature right after create.\n if (isFeatured) {\n updateLook.mutate(\n { id: look.id, input: { isFeatured: true } },\n { onSuccess: () => navigateTo(`/looks/${look.id}`) }\n );\n } else {\n navigateTo(`/looks/${look.id}`);\n }\n },\n }\n );\n };\n\n return (\n <PageLayout\n title=\"New look\"\n description=\"Compose a shop-the-look outfit from catalogue pieces\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/looks')}\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\" /> Cancel\n </button>\n }\n >\n <form onSubmit={handleSubmit} className=\"mx-auto max-w-2xl\">\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-11 w-11 items-center justify-center rounded-lg bg-status-success-bg-subtle text-status-success-text\">\n <Sparkles className=\"h-5 w-5\" />\n </div>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Look details</h2>\n <p className=\"text-xs text-text-secondary\">\n Created as a draft — publish it from the look page.\n </p>\n </div>\n </div>\n\n <TextField\n id=\"title\"\n label=\"Title\"\n value={title}\n onChange={setTitle}\n placeholder=\"Coastal grandma, refined\"\n required\n error={titleError}\n />\n\n <TextAreaField\n id=\"caption\"\n label=\"Caption\"\n value={caption}\n onChange={setCaption}\n placeholder=\"How to style it…\"\n rows={3}\n className=\"mt-4\"\n />\n\n <ImageUploadField\n label=\"Look photo\"\n aspect=\"wide\"\n value={imageFileId}\n onChange={setImageFileId}\n folder={COO_FILE_FOLDERS.looks}\n hint=\"The styled outfit shot\"\n className=\"mt-4\"\n />\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <SelectField\n id=\"occasion\"\n label=\"Occasion\"\n value={occasion}\n onChange={(v) => setOccasion(v as CooLookOccasion)}\n options={occasionOptions}\n />\n <SelectField\n id=\"visibility\"\n label=\"Visibility\"\n value={visibility}\n onChange={(v) => setVisibility(v as CooVisibility)}\n options={visibilityOptions}\n />\n </div>\n\n <SelectField\n id=\"collaborationId\"\n label=\"Collaboration (optional)\"\n value={collaborationId}\n onChange={setCollaborationId}\n options={collaborationOptions}\n placeholder={\n collaborations.isLoading\n ? 'Loading collaborations…'\n : collaborationOptions.length === 0\n ? 'No collaborations yet'\n : 'Not part of a collaboration'\n }\n hint=\"Attribute this look to one of your collaborations\"\n className=\"mt-4\"\n />\n\n <TextField\n id=\"tags\"\n label=\"Tags\"\n value={tags}\n onChange={setTags}\n placeholder=\"linen, neutral\"\n hint=\"Comma-separated\"\n className=\"mt-4\"\n />\n\n <ToggleField\n id=\"isFeatured\"\n label=\"Feature this look\"\n checked={isFeatured}\n onChange={setIsFeatured}\n hint=\"Featured looks surface in the Featured filter and carry a star badge.\"\n className=\"mt-4\"\n />\n\n {/* Look items */}\n <div className=\"mt-6\">\n <div className=\"mb-3 flex flex-col gap-3 sm:flex-row sm:items-end\">\n <div className=\"flex-1\">\n <SelectField\n id=\"add-style-item\"\n label=\"Pieces in this look\"\n value={addValue}\n onChange={setAddValue}\n options={availableOptions}\n placeholder={\n styleItems.isLoading\n ? 'Loading catalogue…'\n : availableOptions.length === 0\n ? 'All available pieces are already added'\n : 'Select a catalogue piece'\n }\n />\n </div>\n <button\n type=\"button\"\n disabled={!addValue}\n onClick={() => {\n addDraftItem(addValue);\n setAddValue('');\n }}\n className=\"inline-flex items-center justify-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 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Plus className=\"h-4 w-4\" /> Add piece\n </button>\n </div>\n {draftItems.length === 0 ? (\n <p className=\"rounded-lg border border-dashed border-border-seam p-4 text-center text-xs text-text-secondary\">\n No pieces added yet. A look can be published without pieces and styled later.\n </p>\n ) : (\n <div className=\"space-y-3\">\n {draftItems.map((di, idx) => (\n <div key={idx} className=\"rounded-lg border border-border-seam bg-bg-surface p-3\">\n <div className=\"flex items-start gap-2\">\n <div className=\"flex-1 space-y-2\">\n <SelectField\n label={`Piece ${idx + 1}`}\n value={di.styleItemId}\n onChange={(v) => setDraftItem(idx, { styleItemId: v })}\n options={itemOptions}\n placeholder={\n styleItems.isLoading ? 'Loading items…' : 'Select a style item'\n }\n />\n <TextField\n label=\"Styling note\"\n value={di.styling}\n onChange={(v) => setDraftItem(idx, { styling: v })}\n placeholder=\"Cuff the sleeves, tuck the front…\"\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeDraftItem(idx)}\n aria-label=\"Remove piece\"\n className={cn(\n 'mt-7 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg',\n 'text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text'\n )}\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {createLook.isError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {createLook.error instanceof Error\n ? createLook.error.message\n : 'Something went wrong'}\n </p>\n )}\n\n <div className=\"mt-6 flex justify-end gap-2\">\n <button\n type=\"submit\"\n disabled={submitting}\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 {submitting ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n Create look\n </button>\n </div>\n </GlassCard>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LooksListPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/looks/LooksListPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4BH,wBAAgB,aAAa,gCA6I5B"}
1
+ {"version":3,"file":"LooksListPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/looks/LooksListPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA2BH,wBAAgB,aAAa,gCAqK5B"}