@burdenoff/microfe-coolandlovely 2026.625.2 → 2026.628.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 (165) hide show
  1. package/dist/coolandlovely/CoolAndLovelyRoot.js +66 -122
  2. package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
  3. package/dist/coolandlovely/CoolAndLovelyRoutes.js +87 -175
  4. package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
  5. package/dist/coolandlovely/components/Field.js +81 -0
  6. package/dist/coolandlovely/components/Field.js.map +1 -0
  7. package/dist/coolandlovely/components/StateViews.js +34 -0
  8. package/dist/coolandlovely/components/StateViews.js.map +1 -0
  9. package/dist/coolandlovely/components/StatusBadge.js +25 -22
  10. package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
  11. package/dist/coolandlovely/components/TagList.js +21 -0
  12. package/dist/coolandlovely/components/TagList.js.map +1 -0
  13. package/dist/coolandlovely/components/Thumbnail.js +29 -0
  14. package/dist/coolandlovely/components/Thumbnail.js.map +1 -0
  15. package/dist/coolandlovely/context/CoolAndLovelyContext.js +10 -10
  16. package/dist/coolandlovely/context/CoolAndLovelyContext.js.map +1 -1
  17. package/dist/coolandlovely/hooks/index.js +1 -0
  18. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +462 -169
  19. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
  20. package/dist/coolandlovely/pages/HomePage.js +251 -845
  21. package/dist/coolandlovely/pages/HomePage.js.map +1 -1
  22. package/dist/coolandlovely/pages/brands/BrandDetailPage.js +319 -0
  23. package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -0
  24. package/dist/coolandlovely/pages/brands/BrandFormPage.js +190 -0
  25. package/dist/coolandlovely/pages/brands/BrandFormPage.js.map +1 -0
  26. package/dist/coolandlovely/pages/brands/BrandsListPage.js +158 -0
  27. package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -0
  28. package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js +253 -0
  29. package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js.map +1 -0
  30. package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +206 -0
  31. package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js.map +1 -0
  32. package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js +129 -0
  33. package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js.map +1 -0
  34. package/dist/coolandlovely/pages/collections/CollectionDetailPage.js +217 -0
  35. package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -0
  36. package/dist/coolandlovely/pages/collections/CollectionFormPage.js +217 -0
  37. package/dist/coolandlovely/pages/collections/CollectionFormPage.js.map +1 -0
  38. package/dist/coolandlovely/pages/collections/CollectionsListPage.js +122 -0
  39. package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -0
  40. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +230 -0
  41. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -0
  42. package/dist/coolandlovely/pages/items/StyleItemFormPage.js +276 -0
  43. package/dist/coolandlovely/pages/items/StyleItemFormPage.js.map +1 -0
  44. package/dist/coolandlovely/pages/items/StyleItemsListPage.js +170 -0
  45. package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -0
  46. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +124 -0
  47. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -0
  48. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js +156 -0
  49. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -0
  50. package/dist/coolandlovely/pages/looks/LookDetailPage.js +238 -0
  51. package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -0
  52. package/dist/coolandlovely/pages/looks/LookFormPage.js +209 -0
  53. package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -0
  54. package/dist/coolandlovely/pages/looks/LooksListPage.js +181 -0
  55. package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -0
  56. package/dist/coolandlovely/pages/profile/StyleProfilePage.js +224 -0
  57. package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -0
  58. package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js +173 -0
  59. package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js.map +1 -0
  60. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js +172 -0
  61. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -0
  62. package/dist/coolandlovely/store/coolandlovelyStore.js +2 -6
  63. package/dist/coolandlovely/store/coolandlovelyStore.js.map +1 -1
  64. package/dist/coolandlovely/utils/formatters.js +31 -23
  65. package/dist/coolandlovely/utils/formatters.js.map +1 -1
  66. package/dist/coolandlovely/utils/icons.js +34 -0
  67. package/dist/coolandlovely/utils/icons.js.map +1 -0
  68. package/dist/index.js +4 -4
  69. package/package.json +1 -1
  70. package/dist/coolandlovely/components/InvestmentCard.js +0 -98
  71. package/dist/coolandlovely/components/InvestmentCard.js.map +0 -1
  72. package/dist/coolandlovely/components/RatingDisplay.js +0 -35
  73. package/dist/coolandlovely/components/RatingDisplay.js.map +0 -1
  74. package/dist/coolandlovely/mocks/data.js +0 -1517
  75. package/dist/coolandlovely/mocks/data.js.map +0 -1
  76. package/dist/coolandlovely/mocks/users.js +0 -34
  77. package/dist/coolandlovely/mocks/users.js.map +0 -1
  78. package/dist/coolandlovely/pages/admin/AdminAnalyticsPage.js +0 -651
  79. package/dist/coolandlovely/pages/admin/AdminAnalyticsPage.js.map +0 -1
  80. package/dist/coolandlovely/pages/admin/AdminDashboard.js +0 -673
  81. package/dist/coolandlovely/pages/admin/AdminDashboard.js.map +0 -1
  82. package/dist/coolandlovely/pages/admin/AdminFinancialPage.js +0 -427
  83. package/dist/coolandlovely/pages/admin/AdminFinancialPage.js.map +0 -1
  84. package/dist/coolandlovely/pages/admin/AdminOrdersPage.js +0 -665
  85. package/dist/coolandlovely/pages/admin/AdminOrdersPage.js.map +0 -1
  86. package/dist/coolandlovely/pages/admin/AdminProfilePage.js +0 -264
  87. package/dist/coolandlovely/pages/admin/AdminProfilePage.js.map +0 -1
  88. package/dist/coolandlovely/pages/admin/AdminSettingsPage.js +0 -654
  89. package/dist/coolandlovely/pages/admin/AdminSettingsPage.js.map +0 -1
  90. package/dist/coolandlovely/pages/admin/CartManagementPage.js +0 -874
  91. package/dist/coolandlovely/pages/admin/CartManagementPage.js.map +0 -1
  92. package/dist/coolandlovely/pages/admin/UserManagementPage.js +0 -898
  93. package/dist/coolandlovely/pages/admin/UserManagementPage.js.map +0 -1
  94. package/dist/coolandlovely/pages/cart-owner/AnalyticsDashboard.js +0 -842
  95. package/dist/coolandlovely/pages/cart-owner/AnalyticsDashboard.js.map +0 -1
  96. package/dist/coolandlovely/pages/cart-owner/BusinessSettingsPage.js +0 -705
  97. package/dist/coolandlovely/pages/cart-owner/BusinessSettingsPage.js.map +0 -1
  98. package/dist/coolandlovely/pages/cart-owner/CartOwnerDashboard.js +0 -802
  99. package/dist/coolandlovely/pages/cart-owner/CartOwnerDashboard.js.map +0 -1
  100. package/dist/coolandlovely/pages/cart-owner/CartOwnerProfilePage.js +0 -891
  101. package/dist/coolandlovely/pages/cart-owner/CartOwnerProfilePage.js.map +0 -1
  102. package/dist/coolandlovely/pages/cart-owner/CartServiceConfigPage.js +0 -639
  103. package/dist/coolandlovely/pages/cart-owner/CartServiceConfigPage.js.map +0 -1
  104. package/dist/coolandlovely/pages/cart-owner/InventoryManagementPage.js +0 -914
  105. package/dist/coolandlovely/pages/cart-owner/InventoryManagementPage.js.map +0 -1
  106. package/dist/coolandlovely/pages/cart-owner/OrderManagementPage.js +0 -882
  107. package/dist/coolandlovely/pages/cart-owner/OrderManagementPage.js.map +0 -1
  108. package/dist/coolandlovely/pages/cart-owner/StaffManagementPage.js +0 -831
  109. package/dist/coolandlovely/pages/cart-owner/StaffManagementPage.js.map +0 -1
  110. package/dist/coolandlovely/pages/common/HelpSupportPage.js +0 -1325
  111. package/dist/coolandlovely/pages/common/HelpSupportPage.js.map +0 -1
  112. package/dist/coolandlovely/pages/common/NotificationCenterPage.js +0 -671
  113. package/dist/coolandlovely/pages/common/NotificationCenterPage.js.map +0 -1
  114. package/dist/coolandlovely/pages/common/SettingsPage.js +0 -973
  115. package/dist/coolandlovely/pages/common/SettingsPage.js.map +0 -1
  116. package/dist/coolandlovely/pages/customer/BookingDetailsPage.js +0 -630
  117. package/dist/coolandlovely/pages/customer/BookingDetailsPage.js.map +0 -1
  118. package/dist/coolandlovely/pages/customer/CartDetailPage.js +0 -623
  119. package/dist/coolandlovely/pages/customer/CartDetailPage.js.map +0 -1
  120. package/dist/coolandlovely/pages/customer/CartDiscoveryPage.js +0 -558
  121. package/dist/coolandlovely/pages/customer/CartDiscoveryPage.js.map +0 -1
  122. package/dist/coolandlovely/pages/customer/CheckoutPage.js +0 -529
  123. package/dist/coolandlovely/pages/customer/CheckoutPage.js.map +0 -1
  124. package/dist/coolandlovely/pages/customer/CustomerDashboard.js +0 -538
  125. package/dist/coolandlovely/pages/customer/CustomerDashboard.js.map +0 -1
  126. package/dist/coolandlovely/pages/customer/CustomerProfilePage.js +0 -658
  127. package/dist/coolandlovely/pages/customer/CustomerProfilePage.js.map +0 -1
  128. package/dist/coolandlovely/pages/customer/DirectServiceBookingPage.js +0 -632
  129. package/dist/coolandlovely/pages/customer/DirectServiceBookingPage.js.map +0 -1
  130. package/dist/coolandlovely/pages/customer/FavoritesPage.js +0 -487
  131. package/dist/coolandlovely/pages/customer/FavoritesPage.js.map +0 -1
  132. package/dist/coolandlovely/pages/customer/OrderHistoryPage.js +0 -447
  133. package/dist/coolandlovely/pages/customer/OrderHistoryPage.js.map +0 -1
  134. package/dist/coolandlovely/pages/customer/OrderTrackingPage.js +0 -425
  135. package/dist/coolandlovely/pages/customer/OrderTrackingPage.js.map +0 -1
  136. package/dist/coolandlovely/pages/customer/PaymentMethodsPage.js +0 -494
  137. package/dist/coolandlovely/pages/customer/PaymentMethodsPage.js.map +0 -1
  138. package/dist/coolandlovely/pages/customer/ReviewsPage.js +0 -616
  139. package/dist/coolandlovely/pages/customer/ReviewsPage.js.map +0 -1
  140. package/dist/coolandlovely/pages/customer/SavedAddressesPage.js +0 -449
  141. package/dist/coolandlovely/pages/customer/SavedAddressesPage.js.map +0 -1
  142. package/dist/coolandlovely/pages/investor/InvestmentDetailsPage.js +0 -887
  143. package/dist/coolandlovely/pages/investor/InvestmentDetailsPage.js.map +0 -1
  144. package/dist/coolandlovely/pages/investor/InvestmentOpportunitiesPage.js +0 -945
  145. package/dist/coolandlovely/pages/investor/InvestmentOpportunitiesPage.js.map +0 -1
  146. package/dist/coolandlovely/pages/investor/InvestorAnalyticsPage.js +0 -687
  147. package/dist/coolandlovely/pages/investor/InvestorAnalyticsPage.js.map +0 -1
  148. package/dist/coolandlovely/pages/investor/InvestorDashboard.js +0 -455
  149. package/dist/coolandlovely/pages/investor/InvestorDashboard.js.map +0 -1
  150. package/dist/coolandlovely/pages/investor/InvestorInvestmentsPage.js +0 -405
  151. package/dist/coolandlovely/pages/investor/InvestorInvestmentsPage.js.map +0 -1
  152. package/dist/coolandlovely/pages/investor/InvestorPortfolioPage.js +0 -602
  153. package/dist/coolandlovely/pages/investor/InvestorPortfolioPage.js.map +0 -1
  154. package/dist/coolandlovely/pages/investor/InvestorProfilePage.js +0 -1070
  155. package/dist/coolandlovely/pages/investor/InvestorProfilePage.js.map +0 -1
  156. package/dist/coolandlovely/pages/worker/TaskDetailsPage.js +0 -533
  157. package/dist/coolandlovely/pages/worker/TaskDetailsPage.js.map +0 -1
  158. package/dist/coolandlovely/pages/worker/WorkerDashboard.js +0 -671
  159. package/dist/coolandlovely/pages/worker/WorkerDashboard.js.map +0 -1
  160. package/dist/coolandlovely/pages/worker/WorkerOrdersPage.js +0 -680
  161. package/dist/coolandlovely/pages/worker/WorkerOrdersPage.js.map +0 -1
  162. package/dist/coolandlovely/pages/worker/WorkerProfilePage.js +0 -692
  163. package/dist/coolandlovely/pages/worker/WorkerProfilePage.js.map +0 -1
  164. package/dist/coolandlovely/pages/worker/WorkerSchedulePage.js +0 -583
  165. package/dist/coolandlovely/pages/worker/WorkerSchedulePage.js.map +0 -1
@@ -0,0 +1,124 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { StatusBadge as n } from "../../components/StatusBadge.js";
4
+ import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
5
+ import { useLookbook as a, useRemoveLookbookEntry as o } from "../../hooks/useCoolAndLovelyApi.js";
6
+ import "../../hooks/index.js";
7
+ import { TagList as s } from "../../components/TagList.js";
8
+ import { ArrowLeft as c, BookHeart as l, Loader2 as u, Sparkles as d, Tag as f, Trash2 as p } from "lucide-react";
9
+ import { useParams as m } from "react-router-dom";
10
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
11
+ import { GlassCard as _ } from "@burdenoff/fe-libs/ui";
12
+ //#region src/coolandlovely/pages/lookbooks/LookbookDetailPage.tsx
13
+ function v() {
14
+ let { lookbookId: v } = m(), { navigateTo: y } = e(), b = a(v), x = o();
15
+ if (b.isLoading) return /* @__PURE__ */ h(t, {
16
+ title: "Lookbook",
17
+ children: /* @__PURE__ */ h(i, { label: "Loading lookbook…" })
18
+ });
19
+ if (b.isError || !b.data) return /* @__PURE__ */ h(t, {
20
+ title: "Lookbook",
21
+ children: /* @__PURE__ */ h(r, {
22
+ title: "Lookbook not found",
23
+ onRetry: () => void b.refetch()
24
+ })
25
+ });
26
+ let S = b.data, C = [...S.entries ?? []].sort((e, t) => e.position - t.position);
27
+ return /* @__PURE__ */ h(t, {
28
+ title: S.name,
29
+ description: S.description ?? void 0,
30
+ actions: /* @__PURE__ */ g("button", {
31
+ type: "button",
32
+ onClick: () => y("/lookbooks"),
33
+ 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",
34
+ children: [/* @__PURE__ */ h(c, { className: "h-4 w-4" }), " Back"]
35
+ }),
36
+ children: /* @__PURE__ */ g("div", {
37
+ className: "mx-auto max-w-3xl",
38
+ children: [/* @__PURE__ */ g(_, {
39
+ treatment: "glass",
40
+ className: "p-6",
41
+ children: [/* @__PURE__ */ g("div", {
42
+ className: "flex items-center gap-3",
43
+ children: [/* @__PURE__ */ h("div", {
44
+ className: "flex h-12 w-12 items-center justify-center rounded-lg bg-accent-purple-subtle text-text-primary",
45
+ children: /* @__PURE__ */ h(l, { className: "h-6 w-6" })
46
+ }), /* @__PURE__ */ g("div", {
47
+ className: "min-w-0 flex-1",
48
+ children: [/* @__PURE__ */ h("h2", {
49
+ className: "truncate text-xl font-semibold text-text-primary",
50
+ children: S.name
51
+ }), /* @__PURE__ */ h(n, {
52
+ status: S.visibility,
53
+ className: "mt-1"
54
+ })]
55
+ })]
56
+ }), S.tags.length > 0 && /* @__PURE__ */ h(s, {
57
+ tags: S.tags,
58
+ className: "mt-4"
59
+ })]
60
+ }), /* @__PURE__ */ g("section", {
61
+ className: "mt-6",
62
+ children: [/* @__PURE__ */ g("h3", {
63
+ className: "mb-3 text-lg font-semibold text-text-primary",
64
+ children: [
65
+ "Entries (",
66
+ C.length,
67
+ ")"
68
+ ]
69
+ }), C.length === 0 ? /* @__PURE__ */ h("p", {
70
+ className: "rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary",
71
+ children: "This lookbook has no entries yet. Clip a catalogue piece or save a look to add one."
72
+ }) : /* @__PURE__ */ h("div", {
73
+ className: "divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface",
74
+ children: C.map((e) => {
75
+ let t = !!e.lookId;
76
+ return /* @__PURE__ */ g("div", {
77
+ className: "flex items-center gap-4 px-4 py-3",
78
+ children: [
79
+ /* @__PURE__ */ h("div", {
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", {
106
+ type: "button",
107
+ disabled: x.isPending,
108
+ onClick: () => x.mutate(e.id),
109
+ "aria-label": "Remove entry",
110
+ 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",
111
+ children: x.isPending && x.variables === e.id ? /* @__PURE__ */ h(u, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ h(p, { className: "h-3.5 w-3.5" })
112
+ })
113
+ ]
114
+ }, e.id);
115
+ })
116
+ })]
117
+ })]
118
+ })
119
+ });
120
+ }
121
+ //#endregion
122
+ export { v as LookbookDetailPage };
123
+
124
+ //# sourceMappingURL=LookbookDetailPage.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,156 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { StatusBadge as n } from "../../components/StatusBadge.js";
4
+ import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
5
+ import { Thumbnail as a } from "../../components/Thumbnail.js";
6
+ import { useCreateLookbook as o, useLookbooks as s } from "../../hooks/useCoolAndLovelyApi.js";
7
+ import "../../hooks/index.js";
8
+ import { parseCsv as c, titleCase as l } from "../../utils/formatters.js";
9
+ import { TagList as u } from "../../components/TagList.js";
10
+ import { SelectField as d, TextAreaField as f, TextField as p } from "../../components/Field.js";
11
+ import { EmptyState as m } from "../../components/EmptyState.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";
16
+ //#region src/coolandlovely/pages/lookbooks/LookbooksListPage.tsx
17
+ var C = [
18
+ "PRIVATE",
19
+ "FOLLOWERS",
20
+ "PUBLIC"
21
+ ];
22
+ function w() {
23
+ let { navigateTo: w } = e(), T = s(), E = o(), [D, O] = h(!1), [k, A] = h(""), [j, M] = h(""), [N, P] = h("PRIVATE"), [F, I] = h(""), [L, R] = h(), z = T.data ?? [], B = C.map((e) => ({
24
+ value: e,
25
+ label: l(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", {
31
+ type: "button",
32
+ onClick: () => O((e) => !e),
33
+ 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
+ }),
36
+ children: [D && /* @__PURE__ */ b("form", {
37
+ onSubmit: (e) => {
38
+ if (e.preventDefault(), !k.trim()) {
39
+ R("Name is required");
40
+ return;
41
+ }
42
+ R(void 0), E.mutate({
43
+ name: k.trim(),
44
+ description: j.trim() || void 0,
45
+ visibility: N,
46
+ tags: c(F)
47
+ }, { onSuccess: (e) => {
48
+ O(!1), A(""), M(""), I(""), P("PRIVATE"), w(`/lookbooks/${e.id}`);
49
+ } });
50
+ },
51
+ className: "mb-6",
52
+ children: /* @__PURE__ */ x(S, {
53
+ treatment: "plain",
54
+ className: "p-5",
55
+ children: [
56
+ /* @__PURE__ */ x("h2", {
57
+ className: "mb-4 flex items-center gap-2 text-base font-semibold text-text-primary",
58
+ children: [/* @__PURE__ */ b(g, { className: "h-5 w-5" }), " New lookbook"]
59
+ }),
60
+ /* @__PURE__ */ x("div", {
61
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
62
+ children: [/* @__PURE__ */ b(p, {
63
+ label: "Name",
64
+ value: k,
65
+ onChange: A,
66
+ placeholder: "Summer wedding guest",
67
+ required: !0,
68
+ error: L
69
+ }), /* @__PURE__ */ b(d, {
70
+ label: "Visibility",
71
+ value: N,
72
+ onChange: (e) => P(e),
73
+ options: B
74
+ })]
75
+ }),
76
+ /* @__PURE__ */ b(f, {
77
+ label: "Description",
78
+ value: j,
79
+ onChange: M,
80
+ placeholder: "What this board is for…",
81
+ rows: 2,
82
+ className: "mt-4"
83
+ }),
84
+ /* @__PURE__ */ b(p, {
85
+ label: "Tags",
86
+ value: F,
87
+ onChange: I,
88
+ placeholder: "summer, formal",
89
+ hint: "Comma-separated",
90
+ className: "mt-4"
91
+ }),
92
+ E.isError && /* @__PURE__ */ b("p", {
93
+ className: "mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
94
+ children: E.error instanceof Error ? E.error.message : "Something went wrong"
95
+ }),
96
+ /* @__PURE__ */ b("div", {
97
+ className: "mt-4 flex justify-end",
98
+ children: /* @__PURE__ */ x("button", {
99
+ type: "submit",
100
+ disabled: E.isPending,
101
+ 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",
102
+ children: [E.isPending ? /* @__PURE__ */ b(_, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ b(v, { className: "h-4 w-4" }), "Create lookbook"]
103
+ })
104
+ })
105
+ ]
106
+ })
107
+ }), T.isLoading ? /* @__PURE__ */ b(i, { label: "Loading lookbooks…" }) : T.isError ? /* @__PURE__ */ b(r, { onRetry: () => void T.refetch() }) : z.length === 0 ? /* @__PURE__ */ b(m, {
108
+ illustration: "empty-data",
109
+ icon: /* @__PURE__ */ b(g, { className: "h-10 w-10" }),
110
+ title: "No lookbooks yet",
111
+ description: "Create a themed board to clip catalogue pieces and looks.",
112
+ action: /* @__PURE__ */ x("button", {
113
+ type: "button",
114
+ onClick: () => O(!0),
115
+ 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",
116
+ children: [/* @__PURE__ */ b(v, { className: "h-4 w-4" }), " New lookbook"]
117
+ })
118
+ }) : /* @__PURE__ */ b("div", {
119
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
120
+ children: z.map((e) => /* @__PURE__ */ x("button", {
121
+ type: "button",
122
+ onClick: () => w(`/lookbooks/${e.id}`),
123
+ 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",
124
+ children: [/* @__PURE__ */ b(a, {
125
+ icon: /* @__PURE__ */ b(g, { className: "h-9 w-9" }),
126
+ seed: e.id,
127
+ className: "h-28 w-full"
128
+ }), /* @__PURE__ */ x("div", {
129
+ className: "p-4",
130
+ children: [
131
+ /* @__PURE__ */ x("div", {
132
+ className: "flex items-start justify-between gap-2",
133
+ children: [/* @__PURE__ */ b("h3", {
134
+ className: "truncate text-base font-semibold text-text-primary",
135
+ children: e.name
136
+ }), /* @__PURE__ */ b(n, { status: e.visibility })]
137
+ }),
138
+ e.description && /* @__PURE__ */ b("p", {
139
+ className: "mt-1.5 line-clamp-2 text-sm text-text-secondary",
140
+ children: e.description
141
+ }),
142
+ e.tags.length > 0 && /* @__PURE__ */ b(u, {
143
+ tags: e.tags,
144
+ max: 4,
145
+ className: "mt-3"
146
+ })
147
+ ]
148
+ })]
149
+ }, e.id))
150
+ })]
151
+ });
152
+ }
153
+ //#endregion
154
+ export { w as LookbooksListPage };
155
+
156
+ //# sourceMappingURL=LookbooksListPage.js.map
@@ -0,0 +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`) and supports creating one\n * 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 { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { TagList } from '../../components/TagList';\nimport { TextField, TextAreaField, SelectField } from '../../components/Field';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useLookbooks, useCreateLookbook } from '../../hooks';\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 [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 },\n {\n onSuccess: (lb) => {\n setCreating(false);\n setName('');\n setDescription('');\n setTags('');\n setVisibility('PRIVATE');\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 {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-4 sm:grid-cols-2 lg:grid-cols-3\">\n {lookbooks.map((lb) => (\n <button\n key={lb.id}\n type=\"button\"\n onClick={() => navigateTo(`/lookbooks/${lb.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 <Thumbnail icon={<BookHeart className=\"h-9 w-9\" />} seed={lb.id} className=\"h-28 w-full\" />\n <div className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">{lb.name}</h3>\n <StatusBadge status={lb.visibility} />\n </div>\n {lb.description && (\n <p className=\"mt-1.5 line-clamp-2 text-sm text-text-secondary\">{lb.description}</p>\n )}\n {lb.tags.length > 0 && <TagList tags={lb.tags} max={4} className=\"mt-3\" />}\n </div>\n </button>\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,238 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { StatusBadge as n } from "../../components/StatusBadge.js";
4
+ import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
5
+ import { Thumbnail as a } from "../../components/Thumbnail.js";
6
+ import { useDeleteLook as o, useLikeLook as s, useLook as c, usePublishLook as l } from "../../hooks/useCoolAndLovelyApi.js";
7
+ import "../../hooks/index.js";
8
+ import { formatDate as u, formatPrice as d, titleCase as f } from "../../utils/formatters.js";
9
+ import { TagList as p } from "../../components/TagList.js";
10
+ import { ArrowLeft as m, Bookmark as h, Heart as g, Loader2 as _, Rocket as v, Sparkles as y, Star as b, Trash2 as x } from "lucide-react";
11
+ import { useParams as S } from "react-router-dom";
12
+ import { jsx as C, jsxs as w } from "react/jsx-runtime";
13
+ import { GlassCard as T } from "@burdenoff/fe-libs/ui";
14
+ //#region src/coolandlovely/pages/looks/LookDetailPage.tsx
15
+ function E() {
16
+ let { lookId: E } = S(), { navigateTo: D } = e(), O = c(E), k = s(), A = l(), j = o();
17
+ if (O.isLoading) return /* @__PURE__ */ C(t, {
18
+ title: "Look",
19
+ children: /* @__PURE__ */ C(i, { label: "Loading look…" })
20
+ });
21
+ if (O.isError || !O.data) return /* @__PURE__ */ C(t, {
22
+ title: "Look",
23
+ children: /* @__PURE__ */ C(r, {
24
+ title: "Look not found",
25
+ onRetry: () => void O.refetch()
26
+ })
27
+ });
28
+ let M = O.data, N = M.items ?? [], P = M.publishedAt !== null;
29
+ return /* @__PURE__ */ C(t, {
30
+ title: M.title,
31
+ description: f(M.occasion),
32
+ actions: /* @__PURE__ */ w("div", {
33
+ className: "flex items-center gap-2",
34
+ children: [
35
+ /* @__PURE__ */ w("button", {
36
+ type: "button",
37
+ onClick: () => D("/looks"),
38
+ 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",
39
+ children: [/* @__PURE__ */ C(m, { className: "h-4 w-4" }), " Back"]
40
+ }),
41
+ !P && /* @__PURE__ */ w("button", {
42
+ type: "button",
43
+ disabled: A.isPending,
44
+ onClick: () => A.mutate(M.id),
45
+ 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 disabled:opacity-50",
46
+ children: [A.isPending ? /* @__PURE__ */ C(_, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ C(v, { className: "h-4 w-4" }), "Publish"]
47
+ }),
48
+ /* @__PURE__ */ w("button", {
49
+ type: "button",
50
+ disabled: j.isPending,
51
+ onClick: () => j.mutate(M.id, { onSuccess: () => D("/looks") }),
52
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50",
53
+ children: [j.isPending ? /* @__PURE__ */ C(_, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ C(x, { className: "h-4 w-4" }), "Delete"]
54
+ })
55
+ ]
56
+ }),
57
+ children: /* @__PURE__ */ w("div", {
58
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
59
+ children: [/* @__PURE__ */ w("div", {
60
+ className: "lg:col-span-2",
61
+ children: [/* @__PURE__ */ w(T, {
62
+ treatment: "glass",
63
+ className: "overflow-hidden p-0",
64
+ children: [/* @__PURE__ */ C(a, {
65
+ icon: /* @__PURE__ */ C(y, { className: "h-14 w-14" }),
66
+ seed: M.id,
67
+ className: "h-60 w-full"
68
+ }), /* @__PURE__ */ w("div", {
69
+ className: "p-6",
70
+ children: [
71
+ /* @__PURE__ */ w("div", {
72
+ className: "flex items-center gap-2",
73
+ children: [
74
+ /* @__PURE__ */ C("h2", {
75
+ className: "text-xl font-semibold text-text-primary",
76
+ children: M.title
77
+ }),
78
+ M.isFeatured && /* @__PURE__ */ C(b, { className: "h-4 w-4 fill-status-warning-text text-status-warning-text" }),
79
+ /* @__PURE__ */ C(n, {
80
+ status: P ? "published" : "draft",
81
+ className: "ml-auto"
82
+ })
83
+ ]
84
+ }),
85
+ M.caption && /* @__PURE__ */ C("p", {
86
+ className: "mt-3 text-sm text-text-secondary",
87
+ children: M.caption
88
+ }),
89
+ M.tags.length > 0 && /* @__PURE__ */ C(p, {
90
+ tags: M.tags,
91
+ className: "mt-4",
92
+ tone: "accent"
93
+ }),
94
+ /* @__PURE__ */ w("div", {
95
+ className: "mt-5 flex items-center gap-3",
96
+ children: [/* @__PURE__ */ w("button", {
97
+ type: "button",
98
+ disabled: k.isPending,
99
+ onClick: () => k.mutate(M.id),
100
+ 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-status-error-bg-subtle disabled:opacity-50",
101
+ children: [
102
+ k.isPending ? /* @__PURE__ */ C(_, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ C(g, { className: "h-4 w-4" }),
103
+ "Like · ",
104
+ M.likeCount
105
+ ]
106
+ }), /* @__PURE__ */ w("span", {
107
+ className: "inline-flex items-center gap-1.5 text-sm text-text-secondary",
108
+ children: [
109
+ /* @__PURE__ */ C(h, { className: "h-4 w-4" }),
110
+ " ",
111
+ M.saveCount,
112
+ " saves"
113
+ ]
114
+ })]
115
+ })
116
+ ]
117
+ })]
118
+ }), /* @__PURE__ */ w("section", {
119
+ className: "mt-6",
120
+ children: [/* @__PURE__ */ w("h3", {
121
+ className: "mb-3 text-lg font-semibold text-text-primary",
122
+ children: [
123
+ "Shop the look (",
124
+ N.length,
125
+ ")"
126
+ ]
127
+ }), N.length === 0 ? /* @__PURE__ */ C("p", {
128
+ className: "rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary",
129
+ children: "No items tagged in this look yet."
130
+ }) : /* @__PURE__ */ C("div", {
131
+ className: "divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface",
132
+ children: [...N].sort((e, t) => e.position - t.position).map((e) => /* @__PURE__ */ w("button", {
133
+ type: "button",
134
+ onClick: () => e.styleItem && D(`/items/${e.styleItem.id}`),
135
+ className: "flex w-full items-center gap-4 px-4 py-3 text-left transition-colors hover:bg-bg-sunken/50",
136
+ children: [
137
+ /* @__PURE__ */ C(a, {
138
+ icon: /* @__PURE__ */ C(y, { className: "h-5 w-5" }),
139
+ seed: e.id,
140
+ className: "h-11 w-11 shrink-0"
141
+ }),
142
+ /* @__PURE__ */ w("div", {
143
+ className: "min-w-0 flex-1",
144
+ children: [/* @__PURE__ */ C("p", {
145
+ className: "truncate text-sm font-medium text-text-primary",
146
+ children: e.styleItem?.name ?? "Catalogue piece"
147
+ }), e.styling && /* @__PURE__ */ C("p", {
148
+ className: "truncate text-xs text-text-secondary",
149
+ children: e.styling
150
+ })]
151
+ }),
152
+ e.styleItem && /* @__PURE__ */ C("span", {
153
+ className: "shrink-0 text-sm font-semibold text-text-primary",
154
+ children: d(e.styleItem.price, e.styleItem.currency)
155
+ })
156
+ ]
157
+ }, e.id))
158
+ })]
159
+ })]
160
+ }), /* @__PURE__ */ w("div", {
161
+ className: "space-y-4",
162
+ children: [
163
+ /* @__PURE__ */ w(T, {
164
+ treatment: "plain",
165
+ className: "p-5",
166
+ children: [/* @__PURE__ */ C("h3", {
167
+ className: "mb-3 text-sm font-semibold text-text-primary",
168
+ children: "Details"
169
+ }), /* @__PURE__ */ w("dl", {
170
+ className: "space-y-2 text-sm",
171
+ children: [
172
+ /* @__PURE__ */ w("div", {
173
+ className: "flex justify-between gap-2",
174
+ children: [/* @__PURE__ */ C("dt", {
175
+ className: "text-text-secondary",
176
+ children: "Occasion"
177
+ }), /* @__PURE__ */ C("dd", {
178
+ className: "text-text-primary",
179
+ children: f(M.occasion)
180
+ })]
181
+ }),
182
+ /* @__PURE__ */ w("div", {
183
+ className: "flex justify-between gap-2",
184
+ children: [/* @__PURE__ */ C("dt", {
185
+ className: "text-text-secondary",
186
+ children: "Visibility"
187
+ }), /* @__PURE__ */ C("dd", {
188
+ className: "text-text-primary",
189
+ children: f(M.visibility)
190
+ })]
191
+ }),
192
+ /* @__PURE__ */ w("div", {
193
+ className: "flex justify-between gap-2",
194
+ children: [/* @__PURE__ */ C("dt", {
195
+ className: "text-text-secondary",
196
+ children: "Published"
197
+ }), /* @__PURE__ */ C("dd", {
198
+ className: "text-text-primary",
199
+ children: M.publishedAt ? u(M.publishedAt, {
200
+ hour: void 0,
201
+ minute: void 0
202
+ }) : "—"
203
+ })]
204
+ })
205
+ ]
206
+ })]
207
+ }),
208
+ M.collaborationId && /* @__PURE__ */ w("button", {
209
+ type: "button",
210
+ onClick: () => D(`/collaborations/${M.collaborationId}`),
211
+ className: "flex w-full items-center gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50",
212
+ children: [/* @__PURE__ */ C("div", {
213
+ className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-status-warning-bg-subtle text-status-warning-text",
214
+ children: /* @__PURE__ */ C(y, { className: "h-5 w-5" })
215
+ }), /* @__PURE__ */ w("div", {
216
+ className: "min-w-0",
217
+ children: [/* @__PURE__ */ C("p", {
218
+ className: "truncate text-sm font-medium text-text-primary",
219
+ children: "Part of a collaboration"
220
+ }), /* @__PURE__ */ C("p", {
221
+ className: "truncate text-xs text-text-secondary",
222
+ children: "View collaboration"
223
+ })]
224
+ })]
225
+ }),
226
+ (A.isError || j.isError || k.isError) && /* @__PURE__ */ C("p", {
227
+ className: "rounded-lg bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text",
228
+ children: (A.error ?? j.error ?? k.error) instanceof Error ? (A.error ?? j.error ?? k.error)?.message : "Action failed"
229
+ })
230
+ ]
231
+ })]
232
+ })
233
+ });
234
+ }
235
+ //#endregion
236
+ export { E as LookDetailPage };
237
+
238
+ //# sourceMappingURL=LookDetailPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LookDetailPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/looks/LookDetailPage.tsx"],"sourcesContent":["/**\n * Look Detail Page\n * @module coolandlovely/pages/looks\n *\n * Single look (`cooLook`) with its look items, like (`cooLikeLook`), publish\n * (`cooPublishLook`) and delete (`cooDeleteLook`) actions.\n */\n\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n Heart,\n Bookmark,\n Rocket,\n Trash2,\n Loader2,\n Sparkles,\n Star,\n} 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 { Thumbnail } from '../../components/Thumbnail';\nimport { TagList } from '../../components/TagList';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useLook, useLikeLook, usePublishLook, useDeleteLook } from '../../hooks';\nimport { formatPrice, formatDate, titleCase } from '../../utils/formatters';\n\nexport function LookDetailPage() {\n const { lookId } = useParams<{ lookId: string }>();\n const { navigateTo } = useCoolAndLovely();\n const query = useLook(lookId);\n const like = useLikeLook();\n const publish = usePublishLook();\n const remove = useDeleteLook();\n\n if (query.isLoading) {\n return (\n <PageLayout title=\"Look\">\n <LoadingView label=\"Loading look…\" />\n </PageLayout>\n );\n }\n\n if (query.isError || !query.data) {\n return (\n <PageLayout title=\"Look\">\n <ErrorView title=\"Look not found\" onRetry={() => void query.refetch()} />\n </PageLayout>\n );\n }\n\n const look = query.data;\n const items = look.items ?? [];\n const isPublished = look.publishedAt !== null;\n\n return (\n <PageLayout\n title={look.title}\n description={titleCase(look.occasion)}\n actions={\n <div className=\"flex items-center gap-2\">\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\" /> Back\n </button>\n {!isPublished && (\n <button\n type=\"button\"\n disabled={publish.isPending}\n onClick={() => publish.mutate(look.id)}\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 disabled:opacity-50\"\n >\n {publish.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Rocket className=\"h-4 w-4\" />\n )}\n Publish\n </button>\n )}\n <button\n type=\"button\"\n disabled={remove.isPending}\n onClick={() => remove.mutate(look.id, { onSuccess: () => 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-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n {remove.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n Delete\n </button>\n </div>\n }\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2\">\n <GlassCard treatment=\"glass\" className=\"overflow-hidden p-0\">\n <Thumbnail icon={<Sparkles className=\"h-14 w-14\" />} seed={look.id} className=\"h-60 w-full\" />\n <div className=\"p-6\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"text-xl font-semibold text-text-primary\">{look.title}</h2>\n {look.isFeatured && (\n <Star className=\"h-4 w-4 fill-status-warning-text text-status-warning-text\" />\n )}\n <StatusBadge status={isPublished ? 'published' : 'draft'} className=\"ml-auto\" />\n </div>\n {look.caption && <p className=\"mt-3 text-sm text-text-secondary\">{look.caption}</p>}\n {look.tags.length > 0 && <TagList tags={look.tags} className=\"mt-4\" tone=\"accent\" />}\n\n <div className=\"mt-5 flex items-center gap-3\">\n <button\n type=\"button\"\n disabled={like.isPending}\n onClick={() => like.mutate(look.id)}\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-status-error-bg-subtle disabled:opacity-50\"\n >\n {like.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Heart className=\"h-4 w-4\" />\n )}\n Like · {look.likeCount}\n </button>\n <span className=\"inline-flex items-center gap-1.5 text-sm text-text-secondary\">\n <Bookmark className=\"h-4 w-4\" /> {look.saveCount} saves\n </span>\n </div>\n </div>\n </GlassCard>\n\n {/* Shop the look */}\n <section className=\"mt-6\">\n <h3 className=\"mb-3 text-lg font-semibold text-text-primary\">\n Shop the look ({items.length})\n </h3>\n {items.length === 0 ? (\n <p className=\"rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary\">\n No items tagged in this look yet.\n </p>\n ) : (\n <div className=\"divide-y divide-border-seam rounded-lg border border-border-seam bg-bg-surface\">\n {[...items]\n .sort((a, b) => a.position - b.position)\n .map((li) => (\n <button\n key={li.id}\n type=\"button\"\n onClick={() => li.styleItem && navigateTo(`/items/${li.styleItem.id}`)}\n className=\"flex w-full items-center gap-4 px-4 py-3 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n <Thumbnail icon={<Sparkles className=\"h-5 w-5\" />} seed={li.id} className=\"h-11 w-11 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {li.styleItem?.name ?? 'Catalogue piece'}\n </p>\n {li.styling && (\n <p className=\"truncate text-xs text-text-secondary\">{li.styling}</p>\n )}\n </div>\n {li.styleItem && (\n <span className=\"shrink-0 text-sm font-semibold text-text-primary\">\n {formatPrice(li.styleItem.price, li.styleItem.currency)}\n </span>\n )}\n </button>\n ))}\n </div>\n )}\n </section>\n </div>\n\n <div className=\"space-y-4\">\n <GlassCard treatment=\"plain\" className=\"p-5\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">Details</h3>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between gap-2\">\n <dt className=\"text-text-secondary\">Occasion</dt>\n <dd className=\"text-text-primary\">{titleCase(look.occasion)}</dd>\n </div>\n <div className=\"flex justify-between gap-2\">\n <dt className=\"text-text-secondary\">Visibility</dt>\n <dd className=\"text-text-primary\">{titleCase(look.visibility)}</dd>\n </div>\n <div className=\"flex justify-between gap-2\">\n <dt className=\"text-text-secondary\">Published</dt>\n <dd className=\"text-text-primary\">\n {look.publishedAt\n ? formatDate(look.publishedAt, { hour: undefined, minute: undefined })\n : '—'}\n </dd>\n </div>\n </dl>\n </GlassCard>\n\n {look.collaborationId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/collaborations/${look.collaborationId}`)}\n className=\"flex w-full items-center gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-status-warning-bg-subtle text-status-warning-text\">\n <Sparkles className=\"h-5 w-5\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">Part of a collaboration</p>\n <p className=\"truncate text-xs text-text-secondary\">View collaboration</p>\n </div>\n </button>\n )}\n\n {(publish.isError || remove.isError || like.isError) && (\n <p className=\"rounded-lg bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text\">\n {(publish.error ?? remove.error ?? like.error) instanceof Error\n ? (publish.error ?? remove.error ?? like.error)?.message\n : 'Action failed'}\n </p>\n )}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}