@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.
- package/dist/coolandlovely/CoolAndLovelyRoot.js +66 -122
- package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.js +87 -175
- package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
- package/dist/coolandlovely/components/Field.js +81 -0
- package/dist/coolandlovely/components/Field.js.map +1 -0
- package/dist/coolandlovely/components/StateViews.js +34 -0
- package/dist/coolandlovely/components/StateViews.js.map +1 -0
- package/dist/coolandlovely/components/StatusBadge.js +25 -22
- package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
- package/dist/coolandlovely/components/TagList.js +21 -0
- package/dist/coolandlovely/components/TagList.js.map +1 -0
- package/dist/coolandlovely/components/Thumbnail.js +29 -0
- package/dist/coolandlovely/components/Thumbnail.js.map +1 -0
- package/dist/coolandlovely/context/CoolAndLovelyContext.js +10 -10
- package/dist/coolandlovely/context/CoolAndLovelyContext.js.map +1 -1
- package/dist/coolandlovely/hooks/index.js +1 -0
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +462 -169
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
- package/dist/coolandlovely/pages/HomePage.js +251 -845
- package/dist/coolandlovely/pages/HomePage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js +319 -0
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -0
- package/dist/coolandlovely/pages/brands/BrandFormPage.js +190 -0
- package/dist/coolandlovely/pages/brands/BrandFormPage.js.map +1 -0
- package/dist/coolandlovely/pages/brands/BrandsListPage.js +158 -0
- package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js +253 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js.map +1 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +206 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js.map +1 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js +129 -0
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js.map +1 -0
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js +217 -0
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -0
- package/dist/coolandlovely/pages/collections/CollectionFormPage.js +217 -0
- package/dist/coolandlovely/pages/collections/CollectionFormPage.js.map +1 -0
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js +122 -0
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -0
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +230 -0
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -0
- package/dist/coolandlovely/pages/items/StyleItemFormPage.js +276 -0
- package/dist/coolandlovely/pages/items/StyleItemFormPage.js.map +1 -0
- package/dist/coolandlovely/pages/items/StyleItemsListPage.js +170 -0
- package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -0
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +124 -0
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -0
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js +156 -0
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -0
- package/dist/coolandlovely/pages/looks/LookDetailPage.js +238 -0
- package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -0
- package/dist/coolandlovely/pages/looks/LookFormPage.js +209 -0
- package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -0
- package/dist/coolandlovely/pages/looks/LooksListPage.js +181 -0
- package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -0
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js +224 -0
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -0
- package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js +173 -0
- package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js.map +1 -0
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js +172 -0
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -0
- package/dist/coolandlovely/store/coolandlovelyStore.js +2 -6
- package/dist/coolandlovely/store/coolandlovelyStore.js.map +1 -1
- package/dist/coolandlovely/utils/formatters.js +31 -23
- package/dist/coolandlovely/utils/formatters.js.map +1 -1
- package/dist/coolandlovely/utils/icons.js +34 -0
- package/dist/coolandlovely/utils/icons.js.map +1 -0
- package/dist/index.js +4 -4
- package/package.json +1 -1
- package/dist/coolandlovely/components/InvestmentCard.js +0 -98
- package/dist/coolandlovely/components/InvestmentCard.js.map +0 -1
- package/dist/coolandlovely/components/RatingDisplay.js +0 -35
- package/dist/coolandlovely/components/RatingDisplay.js.map +0 -1
- package/dist/coolandlovely/mocks/data.js +0 -1517
- package/dist/coolandlovely/mocks/data.js.map +0 -1
- package/dist/coolandlovely/mocks/users.js +0 -34
- package/dist/coolandlovely/mocks/users.js.map +0 -1
- package/dist/coolandlovely/pages/admin/AdminAnalyticsPage.js +0 -651
- package/dist/coolandlovely/pages/admin/AdminAnalyticsPage.js.map +0 -1
- package/dist/coolandlovely/pages/admin/AdminDashboard.js +0 -673
- package/dist/coolandlovely/pages/admin/AdminDashboard.js.map +0 -1
- package/dist/coolandlovely/pages/admin/AdminFinancialPage.js +0 -427
- package/dist/coolandlovely/pages/admin/AdminFinancialPage.js.map +0 -1
- package/dist/coolandlovely/pages/admin/AdminOrdersPage.js +0 -665
- package/dist/coolandlovely/pages/admin/AdminOrdersPage.js.map +0 -1
- package/dist/coolandlovely/pages/admin/AdminProfilePage.js +0 -264
- package/dist/coolandlovely/pages/admin/AdminProfilePage.js.map +0 -1
- package/dist/coolandlovely/pages/admin/AdminSettingsPage.js +0 -654
- package/dist/coolandlovely/pages/admin/AdminSettingsPage.js.map +0 -1
- package/dist/coolandlovely/pages/admin/CartManagementPage.js +0 -874
- package/dist/coolandlovely/pages/admin/CartManagementPage.js.map +0 -1
- package/dist/coolandlovely/pages/admin/UserManagementPage.js +0 -898
- package/dist/coolandlovely/pages/admin/UserManagementPage.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/AnalyticsDashboard.js +0 -842
- package/dist/coolandlovely/pages/cart-owner/AnalyticsDashboard.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/BusinessSettingsPage.js +0 -705
- package/dist/coolandlovely/pages/cart-owner/BusinessSettingsPage.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/CartOwnerDashboard.js +0 -802
- package/dist/coolandlovely/pages/cart-owner/CartOwnerDashboard.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/CartOwnerProfilePage.js +0 -891
- package/dist/coolandlovely/pages/cart-owner/CartOwnerProfilePage.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/CartServiceConfigPage.js +0 -639
- package/dist/coolandlovely/pages/cart-owner/CartServiceConfigPage.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/InventoryManagementPage.js +0 -914
- package/dist/coolandlovely/pages/cart-owner/InventoryManagementPage.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/OrderManagementPage.js +0 -882
- package/dist/coolandlovely/pages/cart-owner/OrderManagementPage.js.map +0 -1
- package/dist/coolandlovely/pages/cart-owner/StaffManagementPage.js +0 -831
- package/dist/coolandlovely/pages/cart-owner/StaffManagementPage.js.map +0 -1
- package/dist/coolandlovely/pages/common/HelpSupportPage.js +0 -1325
- package/dist/coolandlovely/pages/common/HelpSupportPage.js.map +0 -1
- package/dist/coolandlovely/pages/common/NotificationCenterPage.js +0 -671
- package/dist/coolandlovely/pages/common/NotificationCenterPage.js.map +0 -1
- package/dist/coolandlovely/pages/common/SettingsPage.js +0 -973
- package/dist/coolandlovely/pages/common/SettingsPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/BookingDetailsPage.js +0 -630
- package/dist/coolandlovely/pages/customer/BookingDetailsPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/CartDetailPage.js +0 -623
- package/dist/coolandlovely/pages/customer/CartDetailPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/CartDiscoveryPage.js +0 -558
- package/dist/coolandlovely/pages/customer/CartDiscoveryPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/CheckoutPage.js +0 -529
- package/dist/coolandlovely/pages/customer/CheckoutPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/CustomerDashboard.js +0 -538
- package/dist/coolandlovely/pages/customer/CustomerDashboard.js.map +0 -1
- package/dist/coolandlovely/pages/customer/CustomerProfilePage.js +0 -658
- package/dist/coolandlovely/pages/customer/CustomerProfilePage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/DirectServiceBookingPage.js +0 -632
- package/dist/coolandlovely/pages/customer/DirectServiceBookingPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/FavoritesPage.js +0 -487
- package/dist/coolandlovely/pages/customer/FavoritesPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/OrderHistoryPage.js +0 -447
- package/dist/coolandlovely/pages/customer/OrderHistoryPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/OrderTrackingPage.js +0 -425
- package/dist/coolandlovely/pages/customer/OrderTrackingPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/PaymentMethodsPage.js +0 -494
- package/dist/coolandlovely/pages/customer/PaymentMethodsPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/ReviewsPage.js +0 -616
- package/dist/coolandlovely/pages/customer/ReviewsPage.js.map +0 -1
- package/dist/coolandlovely/pages/customer/SavedAddressesPage.js +0 -449
- package/dist/coolandlovely/pages/customer/SavedAddressesPage.js.map +0 -1
- package/dist/coolandlovely/pages/investor/InvestmentDetailsPage.js +0 -887
- package/dist/coolandlovely/pages/investor/InvestmentDetailsPage.js.map +0 -1
- package/dist/coolandlovely/pages/investor/InvestmentOpportunitiesPage.js +0 -945
- package/dist/coolandlovely/pages/investor/InvestmentOpportunitiesPage.js.map +0 -1
- package/dist/coolandlovely/pages/investor/InvestorAnalyticsPage.js +0 -687
- package/dist/coolandlovely/pages/investor/InvestorAnalyticsPage.js.map +0 -1
- package/dist/coolandlovely/pages/investor/InvestorDashboard.js +0 -455
- package/dist/coolandlovely/pages/investor/InvestorDashboard.js.map +0 -1
- package/dist/coolandlovely/pages/investor/InvestorInvestmentsPage.js +0 -405
- package/dist/coolandlovely/pages/investor/InvestorInvestmentsPage.js.map +0 -1
- package/dist/coolandlovely/pages/investor/InvestorPortfolioPage.js +0 -602
- package/dist/coolandlovely/pages/investor/InvestorPortfolioPage.js.map +0 -1
- package/dist/coolandlovely/pages/investor/InvestorProfilePage.js +0 -1070
- package/dist/coolandlovely/pages/investor/InvestorProfilePage.js.map +0 -1
- package/dist/coolandlovely/pages/worker/TaskDetailsPage.js +0 -533
- package/dist/coolandlovely/pages/worker/TaskDetailsPage.js.map +0 -1
- package/dist/coolandlovely/pages/worker/WorkerDashboard.js +0 -671
- package/dist/coolandlovely/pages/worker/WorkerDashboard.js.map +0 -1
- package/dist/coolandlovely/pages/worker/WorkerOrdersPage.js +0 -680
- package/dist/coolandlovely/pages/worker/WorkerOrdersPage.js.map +0 -1
- package/dist/coolandlovely/pages/worker/WorkerProfilePage.js +0 -692
- package/dist/coolandlovely/pages/worker/WorkerProfilePage.js.map +0 -1
- package/dist/coolandlovely/pages/worker/WorkerSchedulePage.js +0 -583
- package/dist/coolandlovely/pages/worker/WorkerSchedulePage.js.map +0 -1
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
2
|
+
import { PageLayout as t } from "../../components/PageLayout.js";
|
|
3
|
+
import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js";
|
|
4
|
+
import { useBrand as i, useCreateBrand as a, useUpdateBrand as o } from "../../hooks/useCoolAndLovelyApi.js";
|
|
5
|
+
import "../../hooks/index.js";
|
|
6
|
+
import { parseCsv as s } from "../../utils/formatters.js";
|
|
7
|
+
import { TextAreaField as c, TextField as l } from "../../components/Field.js";
|
|
8
|
+
import { useEffect as u, useState as d } from "react";
|
|
9
|
+
import { ArrowLeft as f, Loader2 as p, Save as m, Store as h } from "lucide-react";
|
|
10
|
+
import { useParams as g } from "react-router-dom";
|
|
11
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
12
|
+
import { GlassCard as y } from "@burdenoff/fe-libs/ui";
|
|
13
|
+
//#region src/coolandlovely/pages/brands/BrandFormPage.tsx
|
|
14
|
+
var b = {
|
|
15
|
+
name: "",
|
|
16
|
+
handle: "",
|
|
17
|
+
tagline: "",
|
|
18
|
+
bio: "",
|
|
19
|
+
aesthetics: "",
|
|
20
|
+
tags: "",
|
|
21
|
+
websiteUrl: ""
|
|
22
|
+
};
|
|
23
|
+
function x() {
|
|
24
|
+
let { brandId: x } = g(), S = !!x, { navigateTo: C } = e(), w = i(S ? x : void 0), T = a(), E = o(), [D, O] = d(b), [k, A] = d({});
|
|
25
|
+
u(() => {
|
|
26
|
+
if (S && w.data) {
|
|
27
|
+
let e = w.data;
|
|
28
|
+
O({
|
|
29
|
+
name: e.name,
|
|
30
|
+
handle: e.handle,
|
|
31
|
+
tagline: e.tagline ?? "",
|
|
32
|
+
bio: e.bio ?? "",
|
|
33
|
+
aesthetics: e.aesthetics.join(", "),
|
|
34
|
+
tags: e.tags.join(", "),
|
|
35
|
+
websiteUrl: e.websiteUrl ?? ""
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}, [S, w.data]);
|
|
39
|
+
let j = (e, t) => O((n) => ({
|
|
40
|
+
...n,
|
|
41
|
+
[e]: t
|
|
42
|
+
})), M = S ? E : T, N = () => {
|
|
43
|
+
let e = {};
|
|
44
|
+
return D.name.trim() || (e.name = "Name is required"), !S && !D.handle.trim() && (e.handle = "Handle is required"), A(e), Object.keys(e).length === 0;
|
|
45
|
+
};
|
|
46
|
+
return S && w.isLoading ? /* @__PURE__ */ _(t, {
|
|
47
|
+
title: "Edit brand",
|
|
48
|
+
children: /* @__PURE__ */ _(r, { label: "Loading brand…" })
|
|
49
|
+
}) : S && (w.isError || !w.data) ? /* @__PURE__ */ _(t, {
|
|
50
|
+
title: "Edit brand",
|
|
51
|
+
children: /* @__PURE__ */ _(n, {
|
|
52
|
+
title: "Brand not found",
|
|
53
|
+
onRetry: () => void w.refetch()
|
|
54
|
+
})
|
|
55
|
+
}) : /* @__PURE__ */ _(t, {
|
|
56
|
+
title: S ? "Edit brand" : "New brand",
|
|
57
|
+
description: S ? "Update this storefront" : "Launch a new storefront on the platform",
|
|
58
|
+
actions: /* @__PURE__ */ v("button", {
|
|
59
|
+
type: "button",
|
|
60
|
+
onClick: () => C(S && x ? `/brands/${x}` : "/brands"),
|
|
61
|
+
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",
|
|
62
|
+
children: [/* @__PURE__ */ _(f, { className: "h-4 w-4" }), " Cancel"]
|
|
63
|
+
}),
|
|
64
|
+
children: /* @__PURE__ */ _("form", {
|
|
65
|
+
onSubmit: (e) => {
|
|
66
|
+
e.preventDefault(), N() && (S && x ? E.mutate({
|
|
67
|
+
id: x,
|
|
68
|
+
input: {
|
|
69
|
+
name: D.name.trim(),
|
|
70
|
+
tagline: D.tagline.trim() || void 0,
|
|
71
|
+
bio: D.bio.trim() || void 0,
|
|
72
|
+
aesthetics: s(D.aesthetics),
|
|
73
|
+
tags: s(D.tags),
|
|
74
|
+
websiteUrl: D.websiteUrl.trim() || void 0
|
|
75
|
+
}
|
|
76
|
+
}, { onSuccess: () => C(`/brands/${x}`) }) : T.mutate({
|
|
77
|
+
name: D.name.trim(),
|
|
78
|
+
handle: D.handle.trim(),
|
|
79
|
+
tagline: D.tagline.trim() || void 0,
|
|
80
|
+
bio: D.bio.trim() || void 0,
|
|
81
|
+
aesthetics: s(D.aesthetics),
|
|
82
|
+
tags: s(D.tags),
|
|
83
|
+
websiteUrl: D.websiteUrl.trim() || void 0
|
|
84
|
+
}, { onSuccess: (e) => C(`/brands/${e.id}`) }));
|
|
85
|
+
},
|
|
86
|
+
className: "mx-auto max-w-2xl",
|
|
87
|
+
children: /* @__PURE__ */ v(y, {
|
|
88
|
+
treatment: "plain",
|
|
89
|
+
className: "p-6",
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ v("div", {
|
|
92
|
+
className: "mb-6 flex items-center gap-3",
|
|
93
|
+
children: [/* @__PURE__ */ _("div", {
|
|
94
|
+
className: "flex h-11 w-11 items-center justify-center rounded-lg bg-accent-purple-subtle text-text-primary",
|
|
95
|
+
children: /* @__PURE__ */ _(h, { className: "h-5 w-5" })
|
|
96
|
+
}), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("h2", {
|
|
97
|
+
className: "text-base font-semibold text-text-primary",
|
|
98
|
+
children: "Storefront details"
|
|
99
|
+
}), /* @__PURE__ */ _("p", {
|
|
100
|
+
className: "text-xs text-text-secondary",
|
|
101
|
+
children: "Imagery (logo/cover) is attached via the workspace files service."
|
|
102
|
+
})] })]
|
|
103
|
+
}),
|
|
104
|
+
/* @__PURE__ */ v("div", {
|
|
105
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
106
|
+
children: [/* @__PURE__ */ _(l, {
|
|
107
|
+
id: "name",
|
|
108
|
+
label: "Brand name",
|
|
109
|
+
value: D.name,
|
|
110
|
+
onChange: (e) => j("name", e),
|
|
111
|
+
placeholder: "Aurora Atelier",
|
|
112
|
+
required: !0,
|
|
113
|
+
error: k.name
|
|
114
|
+
}), /* @__PURE__ */ _(l, {
|
|
115
|
+
id: "handle",
|
|
116
|
+
label: "Handle",
|
|
117
|
+
value: D.handle,
|
|
118
|
+
onChange: (e) => j("handle", e),
|
|
119
|
+
placeholder: "aurora-atelier",
|
|
120
|
+
required: !S,
|
|
121
|
+
hint: S ? "Handle cannot be changed after creation" : "Unique per workspace",
|
|
122
|
+
error: k.handle
|
|
123
|
+
})]
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ _(l, {
|
|
126
|
+
id: "tagline",
|
|
127
|
+
label: "Tagline",
|
|
128
|
+
value: D.tagline,
|
|
129
|
+
onChange: (e) => j("tagline", e),
|
|
130
|
+
placeholder: "Quiet luxury, loud ideas",
|
|
131
|
+
className: "mt-4"
|
|
132
|
+
}),
|
|
133
|
+
/* @__PURE__ */ _(c, {
|
|
134
|
+
id: "bio",
|
|
135
|
+
label: "Bio",
|
|
136
|
+
value: D.bio,
|
|
137
|
+
onChange: (e) => j("bio", e),
|
|
138
|
+
placeholder: "Tell shoppers what your brand stands for…",
|
|
139
|
+
rows: 4,
|
|
140
|
+
className: "mt-4"
|
|
141
|
+
}),
|
|
142
|
+
/* @__PURE__ */ v("div", {
|
|
143
|
+
className: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
144
|
+
children: [/* @__PURE__ */ _(l, {
|
|
145
|
+
id: "aesthetics",
|
|
146
|
+
label: "Aesthetics",
|
|
147
|
+
value: D.aesthetics,
|
|
148
|
+
onChange: (e) => j("aesthetics", e),
|
|
149
|
+
placeholder: "minimal, Y2K, coastal",
|
|
150
|
+
hint: "Comma-separated descriptors"
|
|
151
|
+
}), /* @__PURE__ */ _(l, {
|
|
152
|
+
id: "tags",
|
|
153
|
+
label: "Tags",
|
|
154
|
+
value: D.tags,
|
|
155
|
+
onChange: (e) => j("tags", e),
|
|
156
|
+
placeholder: "sustainable, handmade",
|
|
157
|
+
hint: "Comma-separated"
|
|
158
|
+
})]
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ _(l, {
|
|
161
|
+
id: "websiteUrl",
|
|
162
|
+
label: "Website",
|
|
163
|
+
type: "url",
|
|
164
|
+
value: D.websiteUrl,
|
|
165
|
+
onChange: (e) => j("websiteUrl", e),
|
|
166
|
+
placeholder: "https://example.com",
|
|
167
|
+
className: "mt-4"
|
|
168
|
+
}),
|
|
169
|
+
M.isError && /* @__PURE__ */ _("p", {
|
|
170
|
+
className: "mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
|
|
171
|
+
children: M.error instanceof Error ? M.error.message : "Something went wrong"
|
|
172
|
+
}),
|
|
173
|
+
/* @__PURE__ */ _("div", {
|
|
174
|
+
className: "mt-6 flex justify-end gap-2",
|
|
175
|
+
children: /* @__PURE__ */ v("button", {
|
|
176
|
+
type: "submit",
|
|
177
|
+
disabled: M.isPending,
|
|
178
|
+
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",
|
|
179
|
+
children: [M.isPending ? /* @__PURE__ */ _(p, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ _(m, { className: "h-4 w-4" }), S ? "Save changes" : "Create brand"]
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
]
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
export { x as BrandFormPage };
|
|
189
|
+
|
|
190
|
+
//# sourceMappingURL=BrandFormPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrandFormPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/brands/BrandFormPage.tsx"],"sourcesContent":["/**\n * Brand Create / Edit Page\n * @module coolandlovely/pages/brands\n *\n * Drives `cooCreateBrand` (new) and `cooUpdateBrand` (edit). The route param\n * `brandId` distinguishes the two modes.\n */\n\nimport { useEffect, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Loader2, Save, Store } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { TextField, TextAreaField } from '../../components/Field';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useBrand, useCreateBrand, useUpdateBrand } from '../../hooks';\nimport { parseCsv } from '../../utils/formatters';\n\ninterface FormState {\n name: string;\n handle: string;\n tagline: string;\n bio: string;\n aesthetics: string;\n tags: string;\n websiteUrl: string;\n}\n\nconst EMPTY: FormState = {\n name: '',\n handle: '',\n tagline: '',\n bio: '',\n aesthetics: '',\n tags: '',\n websiteUrl: '',\n};\n\nexport function BrandFormPage() {\n const { brandId } = useParams<{ brandId: string }>();\n const isEdit = Boolean(brandId);\n const { navigateTo } = useCoolAndLovely();\n\n const existing = useBrand(isEdit ? brandId : undefined);\n const createBrand = useCreateBrand();\n const updateBrand = useUpdateBrand();\n\n const [form, setForm] = useState<FormState>(EMPTY);\n const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({});\n\n useEffect(() => {\n if (isEdit && existing.data) {\n const b = existing.data;\n setForm({\n name: b.name,\n handle: b.handle,\n tagline: b.tagline ?? '',\n bio: b.bio ?? '',\n aesthetics: b.aesthetics.join(', '),\n tags: b.tags.join(', '),\n websiteUrl: b.websiteUrl ?? '',\n });\n }\n }, [isEdit, existing.data]);\n\n const setField = <K extends keyof FormState>(key: K, value: FormState[K]) =>\n setForm((f) => ({ ...f, [key]: value }));\n\n const mutation = isEdit ? updateBrand : createBrand;\n\n const validate = (): boolean => {\n const next: Partial<Record<keyof FormState, string>> = {};\n if (!form.name.trim()) next.name = 'Name is required';\n if (!isEdit && !form.handle.trim()) next.handle = 'Handle is required';\n setErrors(next);\n return Object.keys(next).length === 0;\n };\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!validate()) return;\n\n if (isEdit && brandId) {\n updateBrand.mutate(\n {\n id: brandId,\n input: {\n name: form.name.trim(),\n tagline: form.tagline.trim() || undefined,\n bio: form.bio.trim() || undefined,\n aesthetics: parseCsv(form.aesthetics),\n tags: parseCsv(form.tags),\n websiteUrl: form.websiteUrl.trim() || undefined,\n },\n },\n { onSuccess: () => navigateTo(`/brands/${brandId}`) }\n );\n } else {\n createBrand.mutate(\n {\n name: form.name.trim(),\n handle: form.handle.trim(),\n tagline: form.tagline.trim() || undefined,\n bio: form.bio.trim() || undefined,\n aesthetics: parseCsv(form.aesthetics),\n tags: parseCsv(form.tags),\n websiteUrl: form.websiteUrl.trim() || undefined,\n },\n { onSuccess: (brand) => navigateTo(`/brands/${brand.id}`) }\n );\n }\n };\n\n if (isEdit && existing.isLoading) {\n return (\n <PageLayout title=\"Edit brand\">\n <LoadingView label=\"Loading brand…\" />\n </PageLayout>\n );\n }\n\n if (isEdit && (existing.isError || !existing.data)) {\n return (\n <PageLayout title=\"Edit brand\">\n <ErrorView title=\"Brand not found\" onRetry={() => void existing.refetch()} />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={isEdit ? 'Edit brand' : 'New brand'}\n description={isEdit ? 'Update this storefront' : 'Launch a new storefront on the platform'}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo(isEdit && brandId ? `/brands/${brandId}` : '/brands')}\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-accent-purple-subtle text-text-primary\">\n <Store className=\"h-5 w-5\" />\n </div>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Storefront details</h2>\n <p className=\"text-xs text-text-secondary\">\n Imagery (logo/cover) is attached via the workspace files service.\n </p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n id=\"name\"\n label=\"Brand name\"\n value={form.name}\n onChange={(v) => setField('name', v)}\n placeholder=\"Aurora Atelier\"\n required\n error={errors.name}\n />\n <TextField\n id=\"handle\"\n label=\"Handle\"\n value={form.handle}\n onChange={(v) => setField('handle', v)}\n placeholder=\"aurora-atelier\"\n required={!isEdit}\n hint={isEdit ? 'Handle cannot be changed after creation' : 'Unique per workspace'}\n error={errors.handle}\n />\n </div>\n\n <TextField\n id=\"tagline\"\n label=\"Tagline\"\n value={form.tagline}\n onChange={(v) => setField('tagline', v)}\n placeholder=\"Quiet luxury, loud ideas\"\n className=\"mt-4\"\n />\n\n <TextAreaField\n id=\"bio\"\n label=\"Bio\"\n value={form.bio}\n onChange={(v) => setField('bio', v)}\n placeholder=\"Tell shoppers what your brand stands for…\"\n rows={4}\n className=\"mt-4\"\n />\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n id=\"aesthetics\"\n label=\"Aesthetics\"\n value={form.aesthetics}\n onChange={(v) => setField('aesthetics', v)}\n placeholder=\"minimal, Y2K, coastal\"\n hint=\"Comma-separated descriptors\"\n />\n <TextField\n id=\"tags\"\n label=\"Tags\"\n value={form.tags}\n onChange={(v) => setField('tags', v)}\n placeholder=\"sustainable, handmade\"\n hint=\"Comma-separated\"\n />\n </div>\n\n <TextField\n id=\"websiteUrl\"\n label=\"Website\"\n type=\"url\"\n value={form.websiteUrl}\n onChange={(v) => setField('websiteUrl', v)}\n placeholder=\"https://example.com\"\n className=\"mt-4\"\n />\n\n {mutation.isError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {mutation.error instanceof Error ? mutation.error.message : 'Something went wrong'}\n </p>\n )}\n\n <div className=\"mt-6 flex justify-end gap-2\">\n <button\n type=\"submit\"\n disabled={mutation.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 {mutation.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n {isEdit ? 'Save changes' : 'Create brand'}\n </button>\n </div>\n </GlassCard>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
2
|
+
import { cn as t } from "../../utils/cn.js";
|
|
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 { useBrands as s } from "../../hooks/useCoolAndLovelyApi.js";
|
|
8
|
+
import "../../hooks/index.js";
|
|
9
|
+
import { titleCase as c } from "../../utils/formatters.js";
|
|
10
|
+
import { TagList as l } from "../../components/TagList.js";
|
|
11
|
+
import { EmptyState as u } from "../../components/EmptyState.js";
|
|
12
|
+
import { useState as d } from "react";
|
|
13
|
+
import { ChevronLeft as f, ChevronRight as p, Plus as m, Star as h, Store as g } from "lucide-react";
|
|
14
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
15
|
+
//#region src/coolandlovely/pages/brands/BrandsListPage.tsx
|
|
16
|
+
var b = 24, x = [
|
|
17
|
+
{
|
|
18
|
+
value: "ALL",
|
|
19
|
+
label: "All"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
value: "PUBLISHED",
|
|
23
|
+
label: "Published"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
value: "DRAFT",
|
|
27
|
+
label: "Draft"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
value: "PENDING_REVIEW",
|
|
31
|
+
label: "In review"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: "SUSPENDED",
|
|
35
|
+
label: "Suspended"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
value: "ARCHIVED",
|
|
39
|
+
label: "Archived"
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
function S() {
|
|
43
|
+
let { navigateTo: S } = e(), [C, w] = d("ALL"), [T, E] = d(!1), [D, O] = d(0), k = s({
|
|
44
|
+
status: C === "ALL" ? void 0 : C,
|
|
45
|
+
featured: T ? !0 : void 0,
|
|
46
|
+
pagination: {
|
|
47
|
+
limit: b,
|
|
48
|
+
offset: D
|
|
49
|
+
}
|
|
50
|
+
}), A = k.data?.items ?? [], j = k.data?.pageInfo.hasMore ?? !1;
|
|
51
|
+
return /* @__PURE__ */ y(n, {
|
|
52
|
+
title: "Brands",
|
|
53
|
+
description: "Storefronts on the platform with a real publish lifecycle",
|
|
54
|
+
actions: /* @__PURE__ */ y("button", {
|
|
55
|
+
type: "button",
|
|
56
|
+
onClick: () => S("/brands/new"),
|
|
57
|
+
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",
|
|
58
|
+
children: [/* @__PURE__ */ v(m, { className: "h-4 w-4" }), " New brand"]
|
|
59
|
+
}),
|
|
60
|
+
children: [/* @__PURE__ */ y("div", {
|
|
61
|
+
className: "mb-6 flex flex-wrap items-center gap-2",
|
|
62
|
+
children: [x.map((e) => /* @__PURE__ */ v("button", {
|
|
63
|
+
type: "button",
|
|
64
|
+
onClick: () => {
|
|
65
|
+
w(e.value), O(0);
|
|
66
|
+
},
|
|
67
|
+
className: t("rounded-full px-3 py-1.5 text-sm font-medium transition-colors", C === e.value ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
|
|
68
|
+
children: e.label
|
|
69
|
+
}, e.value)), /* @__PURE__ */ y("button", {
|
|
70
|
+
type: "button",
|
|
71
|
+
onClick: () => {
|
|
72
|
+
E((e) => !e), O(0);
|
|
73
|
+
},
|
|
74
|
+
className: t("ml-auto inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors", T ? "bg-status-warning-bg-subtle text-status-warning-text" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
|
|
75
|
+
children: [/* @__PURE__ */ v(h, { className: t("h-3.5 w-3.5", T && "fill-status-warning-text") }), " Featured"]
|
|
76
|
+
})]
|
|
77
|
+
}), k.isLoading ? /* @__PURE__ */ v(a, { label: "Loading brands…" }) : k.isError ? /* @__PURE__ */ v(i, { onRetry: () => void k.refetch() }) : A.length === 0 ? /* @__PURE__ */ v(u, {
|
|
78
|
+
illustration: "empty-data",
|
|
79
|
+
icon: /* @__PURE__ */ v(g, { className: "h-10 w-10" }),
|
|
80
|
+
title: "No brands yet",
|
|
81
|
+
description: "Launch the first storefront to start building the catalogue.",
|
|
82
|
+
action: /* @__PURE__ */ y("button", {
|
|
83
|
+
type: "button",
|
|
84
|
+
onClick: () => S("/brands/new"),
|
|
85
|
+
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",
|
|
86
|
+
children: [/* @__PURE__ */ v(m, { className: "h-4 w-4" }), " New brand"]
|
|
87
|
+
})
|
|
88
|
+
}) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("div", {
|
|
89
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
90
|
+
children: A.map((e) => /* @__PURE__ */ y("button", {
|
|
91
|
+
type: "button",
|
|
92
|
+
onClick: () => S(`/brands/${e.id}`),
|
|
93
|
+
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",
|
|
94
|
+
children: [/* @__PURE__ */ v(o, {
|
|
95
|
+
icon: /* @__PURE__ */ v(g, { className: "h-9 w-9" }),
|
|
96
|
+
seed: e.id,
|
|
97
|
+
className: "h-32 w-full"
|
|
98
|
+
}), /* @__PURE__ */ y("div", {
|
|
99
|
+
className: "p-4",
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ y("div", {
|
|
102
|
+
className: "flex items-start justify-between gap-2",
|
|
103
|
+
children: [/* @__PURE__ */ y("div", {
|
|
104
|
+
className: "min-w-0",
|
|
105
|
+
children: [/* @__PURE__ */ y("div", {
|
|
106
|
+
className: "flex items-center gap-1.5",
|
|
107
|
+
children: [/* @__PURE__ */ v("h3", {
|
|
108
|
+
className: "truncate text-base font-semibold text-text-primary",
|
|
109
|
+
children: e.name
|
|
110
|
+
}), e.isFeatured && /* @__PURE__ */ v(h, { className: "h-3.5 w-3.5 shrink-0 fill-status-warning-text text-status-warning-text" })]
|
|
111
|
+
}), /* @__PURE__ */ y("p", {
|
|
112
|
+
className: "truncate text-xs text-text-secondary",
|
|
113
|
+
children: ["@", e.handle]
|
|
114
|
+
})]
|
|
115
|
+
}), /* @__PURE__ */ v(r, { status: e.status })]
|
|
116
|
+
}),
|
|
117
|
+
e.tagline && /* @__PURE__ */ v("p", {
|
|
118
|
+
className: "mt-2 line-clamp-2 text-sm text-text-secondary",
|
|
119
|
+
children: e.tagline
|
|
120
|
+
}),
|
|
121
|
+
e.aesthetics.length > 0 && /* @__PURE__ */ v(l, {
|
|
122
|
+
tags: e.aesthetics.map(c),
|
|
123
|
+
max: 4,
|
|
124
|
+
className: "mt-3",
|
|
125
|
+
tone: "accent"
|
|
126
|
+
})
|
|
127
|
+
]
|
|
128
|
+
})]
|
|
129
|
+
}, e.id))
|
|
130
|
+
}), (D > 0 || j) && /* @__PURE__ */ y("div", {
|
|
131
|
+
className: "mt-6 flex items-center justify-center gap-2",
|
|
132
|
+
children: [
|
|
133
|
+
/* @__PURE__ */ y("button", {
|
|
134
|
+
type: "button",
|
|
135
|
+
disabled: D === 0,
|
|
136
|
+
onClick: () => O((e) => Math.max(0, e - b)),
|
|
137
|
+
className: "inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40",
|
|
138
|
+
children: [/* @__PURE__ */ v(f, { className: "h-4 w-4" }), " Previous"]
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ y("span", {
|
|
141
|
+
className: "text-sm text-text-secondary",
|
|
142
|
+
children: ["Page ", D / b + 1]
|
|
143
|
+
}),
|
|
144
|
+
/* @__PURE__ */ y("button", {
|
|
145
|
+
type: "button",
|
|
146
|
+
disabled: !j,
|
|
147
|
+
onClick: () => O((e) => e + b),
|
|
148
|
+
className: "inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40",
|
|
149
|
+
children: ["Next ", /* @__PURE__ */ v(p, { className: "h-4 w-4" })]
|
|
150
|
+
})
|
|
151
|
+
]
|
|
152
|
+
})] })]
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
export { S as BrandsListPage };
|
|
157
|
+
|
|
158
|
+
//# sourceMappingURL=BrandsListPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrandsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/brands/BrandsListPage.tsx"],"sourcesContent":["/**\n * Brands List Page\n * @module coolandlovely/pages/brands\n *\n * Lists brand storefronts (cursor-paginated `cooListBrands`) with status &\n * featured filters. Each card links to the brand detail page.\n */\n\nimport { useState } from 'react';\nimport { Store, Plus, Star, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { TagList } from '../../components/TagList';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useBrands } from '../../hooks';\nimport { titleCase } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { CooBrandStatus } from '../../types';\n\nconst PAGE_SIZE = 24;\n\nconst STATUS_OPTIONS: Array<{ value: CooBrandStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'DRAFT', label: 'Draft' },\n { value: 'PENDING_REVIEW', label: 'In review' },\n { value: 'SUSPENDED', label: 'Suspended' },\n { value: 'ARCHIVED', label: 'Archived' },\n];\n\nexport function BrandsListPage() {\n const { navigateTo } = useCoolAndLovely();\n const [status, setStatus] = useState<CooBrandStatus | 'ALL'>('ALL');\n const [featuredOnly, setFeaturedOnly] = useState(false);\n const [offset, setOffset] = useState(0);\n\n const query = useBrands({\n status: status === 'ALL' ? undefined : status,\n featured: featuredOnly ? true : undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n\n const brands = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n return (\n <PageLayout\n title=\"Brands\"\n description=\"Storefronts on the platform with a real publish lifecycle\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New brand\n </button>\n }\n >\n {/* Filters */}\n <div className=\"mb-6 flex flex-wrap items-center gap-2\">\n {STATUS_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => {\n setStatus(opt.value);\n setOffset(0);\n }}\n className={cn(\n 'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n status === opt.value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n <button\n type=\"button\"\n onClick={() => {\n setFeaturedOnly((v) => !v);\n setOffset(0);\n }}\n className={cn(\n 'ml-auto inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n featuredOnly\n ? 'bg-status-warning-bg-subtle text-status-warning-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n <Star className={cn('h-3.5 w-3.5', featuredOnly && 'fill-status-warning-text')} /> Featured\n </button>\n </div>\n\n {query.isLoading ? (\n <LoadingView label=\"Loading brands…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : brands.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Store className=\"h-10 w-10\" />}\n title=\"No brands yet\"\n description=\"Launch the first storefront to start building the catalogue.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/brands/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" /> New brand\n </button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {brands.map((brand) => (\n <button\n key={brand.id}\n type=\"button\"\n onClick={() => navigateTo(`/brands/${brand.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\n icon={<Store className=\"h-9 w-9\" />}\n seed={brand.id}\n className=\"h-32 w-full\"\n />\n <div className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {brand.name}\n </h3>\n {brand.isFeatured && (\n <Star className=\"h-3.5 w-3.5 shrink-0 fill-status-warning-text text-status-warning-text\" />\n )}\n </div>\n <p className=\"truncate text-xs text-text-secondary\">@{brand.handle}</p>\n </div>\n <StatusBadge status={brand.status} />\n </div>\n {brand.tagline && (\n <p className=\"mt-2 line-clamp-2 text-sm text-text-secondary\">{brand.tagline}</p>\n )}\n {brand.aesthetics.length > 0 && (\n <TagList tags={brand.aesthetics.map(titleCase)} max={4} className=\"mt-3\" tone=\"accent\" />\n )}\n </div>\n </button>\n ))}\n </div>\n\n {/* Pagination */}\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-center gap-2\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <ChevronLeft className=\"h-4 w-4\" /> Previous\n </button>\n <span className=\"text-sm text-text-secondary\">Page {offset / PAGE_SIZE + 1}</span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40\"\n >\n Next <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,253 @@
|
|
|
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 { useCollaboration as o, useTransitionCollaboration as s } from "../../hooks/useCoolAndLovelyApi.js";
|
|
7
|
+
import "../../hooks/index.js";
|
|
8
|
+
import { formatDate as c, formatPrice as l, titleCase as u } from "../../utils/formatters.js";
|
|
9
|
+
import { TagList as d } from "../../components/TagList.js";
|
|
10
|
+
import { ArrowLeft as f, Handshake as p, Loader2 as m, Sparkles as h, Store as g } from "lucide-react";
|
|
11
|
+
import { useParams as _ } from "react-router-dom";
|
|
12
|
+
import { jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
13
|
+
import { GlassCard as b } from "@burdenoff/fe-libs/ui";
|
|
14
|
+
//#region src/coolandlovely/pages/collaborations/CollaborationDetailPage.tsx
|
|
15
|
+
var x = {
|
|
16
|
+
PROPOSED: [
|
|
17
|
+
"ACCEPTED",
|
|
18
|
+
"DECLINED",
|
|
19
|
+
"CANCELLED"
|
|
20
|
+
],
|
|
21
|
+
ACCEPTED: ["IN_PROGRESS", "CANCELLED"],
|
|
22
|
+
IN_PROGRESS: ["PUBLISHED", "CANCELLED"],
|
|
23
|
+
PUBLISHED: [],
|
|
24
|
+
DECLINED: [],
|
|
25
|
+
CANCELLED: []
|
|
26
|
+
};
|
|
27
|
+
function S() {
|
|
28
|
+
let { collaborationId: S } = _(), { navigateTo: C } = e(), w = o(S), T = s();
|
|
29
|
+
if (w.isLoading) return /* @__PURE__ */ v(t, {
|
|
30
|
+
title: "Collaboration",
|
|
31
|
+
children: /* @__PURE__ */ v(i, { label: "Loading collaboration…" })
|
|
32
|
+
});
|
|
33
|
+
if (w.isError || !w.data) return /* @__PURE__ */ v(t, {
|
|
34
|
+
title: "Collaboration",
|
|
35
|
+
children: /* @__PURE__ */ v(r, {
|
|
36
|
+
title: "Collaboration not found",
|
|
37
|
+
onRetry: () => void w.refetch()
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
let E = w.data, D = E.looks ?? [], O = x[E.status];
|
|
41
|
+
return /* @__PURE__ */ v(t, {
|
|
42
|
+
title: E.title,
|
|
43
|
+
description: E.brand?.name ?? void 0,
|
|
44
|
+
actions: /* @__PURE__ */ y("button", {
|
|
45
|
+
type: "button",
|
|
46
|
+
onClick: () => C("/collaborations"),
|
|
47
|
+
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",
|
|
48
|
+
children: [/* @__PURE__ */ v(f, { className: "h-4 w-4" }), " Back"]
|
|
49
|
+
}),
|
|
50
|
+
children: /* @__PURE__ */ y("div", {
|
|
51
|
+
className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
|
|
52
|
+
children: [/* @__PURE__ */ y("div", {
|
|
53
|
+
className: "lg:col-span-2",
|
|
54
|
+
children: [/* @__PURE__ */ y(b, {
|
|
55
|
+
treatment: "glass",
|
|
56
|
+
className: "p-6",
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ y("div", {
|
|
59
|
+
className: "flex items-center gap-3",
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ v(a, {
|
|
62
|
+
icon: /* @__PURE__ */ v(p, { className: "h-6 w-6" }),
|
|
63
|
+
seed: E.id,
|
|
64
|
+
className: "h-12 w-12 shrink-0"
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ y("div", {
|
|
67
|
+
className: "min-w-0 flex-1",
|
|
68
|
+
children: [/* @__PURE__ */ v("h2", {
|
|
69
|
+
className: "truncate text-xl font-semibold text-text-primary",
|
|
70
|
+
children: E.title
|
|
71
|
+
}), /* @__PURE__ */ y("p", {
|
|
72
|
+
className: "text-xs text-text-secondary",
|
|
73
|
+
children: [u(E.role), " collaboration"]
|
|
74
|
+
})]
|
|
75
|
+
}),
|
|
76
|
+
/* @__PURE__ */ v(n, { status: E.status })
|
|
77
|
+
]
|
|
78
|
+
}),
|
|
79
|
+
E.brief && /* @__PURE__ */ v("p", {
|
|
80
|
+
className: "mt-4 text-sm text-text-secondary",
|
|
81
|
+
children: E.brief
|
|
82
|
+
}),
|
|
83
|
+
E.tags.length > 0 && /* @__PURE__ */ v(d, {
|
|
84
|
+
tags: E.tags,
|
|
85
|
+
className: "mt-4",
|
|
86
|
+
tone: "accent"
|
|
87
|
+
})
|
|
88
|
+
]
|
|
89
|
+
}), /* @__PURE__ */ y("section", {
|
|
90
|
+
className: "mt-6",
|
|
91
|
+
children: [/* @__PURE__ */ y("h3", {
|
|
92
|
+
className: "mb-3 text-lg font-semibold text-text-primary",
|
|
93
|
+
children: [
|
|
94
|
+
"Attributed looks (",
|
|
95
|
+
D.length,
|
|
96
|
+
")"
|
|
97
|
+
]
|
|
98
|
+
}), D.length === 0 ? /* @__PURE__ */ v("p", {
|
|
99
|
+
className: "rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary",
|
|
100
|
+
children: "No looks attributed to this collaboration yet."
|
|
101
|
+
}) : /* @__PURE__ */ v("div", {
|
|
102
|
+
className: "grid grid-cols-2 gap-3 sm:grid-cols-3",
|
|
103
|
+
children: D.map((e) => /* @__PURE__ */ y("button", {
|
|
104
|
+
type: "button",
|
|
105
|
+
onClick: () => C(`/looks/${e.id}`),
|
|
106
|
+
className: "overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-all hover:border-accent-foreground/20 hover:shadow-md",
|
|
107
|
+
children: [/* @__PURE__ */ v(a, {
|
|
108
|
+
icon: /* @__PURE__ */ v(h, { className: "h-6 w-6" }),
|
|
109
|
+
seed: e.id,
|
|
110
|
+
className: "h-24 w-full"
|
|
111
|
+
}), /* @__PURE__ */ y("div", {
|
|
112
|
+
className: "p-3",
|
|
113
|
+
children: [/* @__PURE__ */ v("p", {
|
|
114
|
+
className: "truncate text-sm font-medium text-text-primary",
|
|
115
|
+
children: e.title
|
|
116
|
+
}), /* @__PURE__ */ v("p", {
|
|
117
|
+
className: "mt-0.5 text-xs text-text-secondary",
|
|
118
|
+
children: u(e.occasion)
|
|
119
|
+
})]
|
|
120
|
+
})]
|
|
121
|
+
}, e.id))
|
|
122
|
+
})]
|
|
123
|
+
})]
|
|
124
|
+
}), /* @__PURE__ */ y("div", {
|
|
125
|
+
className: "space-y-4",
|
|
126
|
+
children: [
|
|
127
|
+
/* @__PURE__ */ y(b, {
|
|
128
|
+
treatment: "insight",
|
|
129
|
+
className: "p-5",
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ v("h3", {
|
|
132
|
+
className: "mb-3 text-sm font-semibold text-text-primary",
|
|
133
|
+
children: "Lifecycle"
|
|
134
|
+
}),
|
|
135
|
+
/* @__PURE__ */ y("div", {
|
|
136
|
+
className: "mb-3 flex items-center gap-2",
|
|
137
|
+
children: [/* @__PURE__ */ v("span", {
|
|
138
|
+
className: "text-sm text-text-secondary",
|
|
139
|
+
children: "Current:"
|
|
140
|
+
}), /* @__PURE__ */ v(n, { status: E.status })]
|
|
141
|
+
}),
|
|
142
|
+
O.length === 0 ? /* @__PURE__ */ v("p", {
|
|
143
|
+
className: "text-xs text-text-secondary",
|
|
144
|
+
children: "This collaboration is in a terminal state."
|
|
145
|
+
}) : /* @__PURE__ */ v("div", {
|
|
146
|
+
className: "flex flex-col gap-2",
|
|
147
|
+
children: O.map((e) => /* @__PURE__ */ y("button", {
|
|
148
|
+
type: "button",
|
|
149
|
+
disabled: T.isPending,
|
|
150
|
+
onClick: () => T.mutate({
|
|
151
|
+
id: E.id,
|
|
152
|
+
status: e
|
|
153
|
+
}),
|
|
154
|
+
className: "inline-flex items-center justify-center gap-2 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50",
|
|
155
|
+
children: [
|
|
156
|
+
T.isPending && /* @__PURE__ */ v(m, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
157
|
+
"Move to ",
|
|
158
|
+
u(e)
|
|
159
|
+
]
|
|
160
|
+
}, e))
|
|
161
|
+
}),
|
|
162
|
+
T.isError && /* @__PURE__ */ v("p", {
|
|
163
|
+
className: "mt-2 text-xs text-status-error-text",
|
|
164
|
+
children: T.error instanceof Error ? T.error.message : "Transition failed"
|
|
165
|
+
})
|
|
166
|
+
]
|
|
167
|
+
}),
|
|
168
|
+
/* @__PURE__ */ y(b, {
|
|
169
|
+
treatment: "plain",
|
|
170
|
+
className: "p-5",
|
|
171
|
+
children: [/* @__PURE__ */ v("h3", {
|
|
172
|
+
className: "mb-3 text-sm font-semibold text-text-primary",
|
|
173
|
+
children: "Terms"
|
|
174
|
+
}), /* @__PURE__ */ y("dl", {
|
|
175
|
+
className: "space-y-2 text-sm",
|
|
176
|
+
children: [
|
|
177
|
+
/* @__PURE__ */ y("div", {
|
|
178
|
+
className: "flex justify-between gap-2",
|
|
179
|
+
children: [/* @__PURE__ */ v("dt", {
|
|
180
|
+
className: "text-text-secondary",
|
|
181
|
+
children: "Role"
|
|
182
|
+
}), /* @__PURE__ */ v("dd", {
|
|
183
|
+
className: "text-text-primary",
|
|
184
|
+
children: u(E.role)
|
|
185
|
+
})]
|
|
186
|
+
}),
|
|
187
|
+
/* @__PURE__ */ y("div", {
|
|
188
|
+
className: "flex justify-between gap-2",
|
|
189
|
+
children: [/* @__PURE__ */ v("dt", {
|
|
190
|
+
className: "text-text-secondary",
|
|
191
|
+
children: "Compensation"
|
|
192
|
+
}), /* @__PURE__ */ v("dd", {
|
|
193
|
+
className: "text-text-primary",
|
|
194
|
+
children: l(E.compensation, E.currency)
|
|
195
|
+
})]
|
|
196
|
+
}),
|
|
197
|
+
/* @__PURE__ */ y("div", {
|
|
198
|
+
className: "flex justify-between gap-2",
|
|
199
|
+
children: [/* @__PURE__ */ v("dt", {
|
|
200
|
+
className: "text-text-secondary",
|
|
201
|
+
children: "Starts"
|
|
202
|
+
}), /* @__PURE__ */ v("dd", {
|
|
203
|
+
className: "text-text-primary",
|
|
204
|
+
children: E.startDate ? c(E.startDate, {
|
|
205
|
+
hour: void 0,
|
|
206
|
+
minute: void 0
|
|
207
|
+
}) : "—"
|
|
208
|
+
})]
|
|
209
|
+
}),
|
|
210
|
+
/* @__PURE__ */ y("div", {
|
|
211
|
+
className: "flex justify-between gap-2",
|
|
212
|
+
children: [/* @__PURE__ */ v("dt", {
|
|
213
|
+
className: "text-text-secondary",
|
|
214
|
+
children: "Ends"
|
|
215
|
+
}), /* @__PURE__ */ v("dd", {
|
|
216
|
+
className: "text-text-primary",
|
|
217
|
+
children: E.endDate ? c(E.endDate, {
|
|
218
|
+
hour: void 0,
|
|
219
|
+
minute: void 0
|
|
220
|
+
}) : "—"
|
|
221
|
+
})]
|
|
222
|
+
})
|
|
223
|
+
]
|
|
224
|
+
})]
|
|
225
|
+
}),
|
|
226
|
+
E.brand && /* @__PURE__ */ y("button", {
|
|
227
|
+
type: "button",
|
|
228
|
+
onClick: () => C(`/brands/${E.brand?.id}`),
|
|
229
|
+
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",
|
|
230
|
+
children: [/* @__PURE__ */ v(a, {
|
|
231
|
+
icon: /* @__PURE__ */ v(g, { className: "h-5 w-5" }),
|
|
232
|
+
seed: E.brand.id,
|
|
233
|
+
className: "h-10 w-10 shrink-0"
|
|
234
|
+
}), /* @__PURE__ */ y("div", {
|
|
235
|
+
className: "min-w-0",
|
|
236
|
+
children: [/* @__PURE__ */ v("p", {
|
|
237
|
+
className: "truncate text-sm font-medium text-text-primary",
|
|
238
|
+
children: E.brand.name
|
|
239
|
+
}), /* @__PURE__ */ v("p", {
|
|
240
|
+
className: "truncate text-xs text-text-secondary",
|
|
241
|
+
children: "View brand"
|
|
242
|
+
})]
|
|
243
|
+
})]
|
|
244
|
+
})
|
|
245
|
+
]
|
|
246
|
+
})]
|
|
247
|
+
})
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
export { S as CollaborationDetailPage };
|
|
252
|
+
|
|
253
|
+
//# sourceMappingURL=CollaborationDetailPage.js.map
|