@burdenoff/microfe-coolandlovely 2026.1031.2 → 2026.1101.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coolandlovely/CoolAndLovelyRoot.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoot.js +16 -4
- package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.js +19 -15
- package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
- package/dist/coolandlovely/components/ActivityTrail.js +1 -1
- package/dist/coolandlovely/components/ActivityTrail.js.map +1 -1
- package/dist/coolandlovely/components/ActorName.js.map +1 -1
- package/dist/coolandlovely/components/AddToCartPanel.js.map +1 -1
- package/dist/coolandlovely/components/AddToLookbookButton.js.map +1 -1
- package/dist/coolandlovely/components/BrandCard.js.map +1 -1
- package/dist/coolandlovely/components/BrandCover.js.map +1 -1
- package/dist/coolandlovely/components/BrandCreatorAvatars.js.map +1 -1
- package/dist/coolandlovely/components/CollaborationFeeCard.js.map +1 -1
- package/dist/coolandlovely/components/CollectionCard.js.map +1 -1
- package/dist/coolandlovely/components/ColourSwatchRow.js.map +1 -1
- package/dist/coolandlovely/components/Comments.js.map +1 -1
- package/dist/coolandlovely/components/EmptyState.js.map +1 -1
- package/dist/coolandlovely/components/FeedbackWidget.js.map +1 -1
- package/dist/coolandlovely/components/Field.js.map +1 -1
- package/dist/coolandlovely/components/FileImage.js.map +1 -1
- package/dist/coolandlovely/components/FollowButton.js.map +1 -1
- package/dist/coolandlovely/components/FulfilmentTimeline.js.map +1 -1
- package/dist/coolandlovely/components/ImageUploadField.js +3 -1
- package/dist/coolandlovely/components/ImageUploadField.js.map +1 -1
- package/dist/coolandlovely/components/LookCard.js.map +1 -1
- package/dist/coolandlovely/components/LookbookCard.js.map +1 -1
- package/dist/coolandlovely/components/MetricsCard.js.map +1 -1
- package/dist/coolandlovely/components/PageLayout.js.map +1 -1
- package/dist/coolandlovely/components/PayForOrder.js.map +1 -1
- package/dist/coolandlovely/components/RefundPanel.js +1 -1
- package/dist/coolandlovely/components/RefundPanel.js.map +1 -1
- package/dist/coolandlovely/components/ReturnRequests.js +1 -1
- package/dist/coolandlovely/components/ReturnRequests.js.map +1 -1
- package/dist/coolandlovely/components/ShopItemCard.js.map +1 -1
- package/dist/coolandlovely/components/StateViews.js.map +1 -1
- package/dist/coolandlovely/components/StatusBadge.js +1 -1
- package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
- package/dist/coolandlovely/components/StepTracker.js.map +1 -1
- package/dist/coolandlovely/components/StockEditor.js.map +1 -1
- package/dist/coolandlovely/components/StoreListingCard.js.map +1 -1
- package/dist/coolandlovely/components/TagList.js.map +1 -1
- package/dist/coolandlovely/components/Thumbnail.js +1 -1
- package/dist/coolandlovely/components/Thumbnail.js.map +1 -1
- package/dist/coolandlovely/components/VisibilityChip.js.map +1 -1
- package/dist/coolandlovely/components/WardrobeItemCard.js.map +1 -1
- package/dist/coolandlovely/components/index.js +2 -1
- package/dist/coolandlovely/context/CoolAndLovelyContext.js +2 -1
- package/dist/coolandlovely/context/CoolAndLovelyContext.js.map +1 -1
- package/dist/coolandlovely/context/index.js +2 -1
- package/dist/coolandlovely/hooks/index.js +4 -3
- package/dist/coolandlovely/hooks/useActivity.d.ts +1 -1
- package/dist/coolandlovely/hooks/useActivity.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useActivity.js.map +1 -1
- package/dist/coolandlovely/hooks/useAssistantEntity.js.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts +4 -4
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCatalogImport.js.map +1 -1
- package/dist/coolandlovely/hooks/useComments.d.ts +1 -1
- package/dist/coolandlovely/hooks/useComments.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useComments.js.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts +7 -7
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts +24 -24
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useEditorialApi.d.ts +95 -0
- package/dist/coolandlovely/hooks/useEditorialApi.d.ts.map +1 -0
- package/dist/coolandlovely/hooks/useEditorialApi.js +107 -0
- package/dist/coolandlovely/hooks/useEditorialApi.js.map +1 -0
- package/dist/coolandlovely/hooks/useFiles.js.map +1 -1
- package/dist/coolandlovely/hooks/useInventoryApi.d.ts +1 -1
- package/dist/coolandlovely/hooks/useInventoryApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useInventoryApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useTr.js.map +1 -1
- package/dist/coolandlovely/index.js +6 -5
- package/dist/coolandlovely/pages/HomePage.js.map +1 -1
- package/dist/coolandlovely/pages/admin/AdminBrandsPage.js.map +1 -1
- package/dist/coolandlovely/pages/admin/AdminCollaborationsPage.js.map +1 -1
- package/dist/coolandlovely/pages/admin/AdminFeaturedItemsPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/ImportCatalogPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/CartPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/CreatorEarningsPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.js.map +1 -1
- package/dist/coolandlovely/pages/discover/DiscoverPage.js +1 -1
- package/dist/coolandlovely/pages/discover/DiscoverPage.js.map +1 -1
- package/dist/coolandlovely/pages/editorial/EditorialPage.d.ts +2 -0
- package/dist/coolandlovely/pages/editorial/EditorialPage.d.ts.map +1 -0
- package/dist/coolandlovely/pages/editorial/EditorialPage.js +486 -0
- package/dist/coolandlovely/pages/editorial/EditorialPage.js.map +1 -0
- package/dist/coolandlovely/pages/items/StoreListedPieceView.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -1
- package/dist/coolandlovely/pages/trends/TrendsPage.js.map +1 -1
- package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -1
- package/dist/coolandlovely/store/coolandlovelyStore.js.map +1 -1
- package/dist/coolandlovely/store/index.js +2 -1
- package/dist/coolandlovely/types/commerce.d.ts.map +1 -1
- package/dist/coolandlovely/types/index.d.ts.map +1 -1
- package/dist/coolandlovely/utils/cn.js +1 -1
- package/dist/coolandlovely/utils/cn.js.map +1 -1
- package/dist/coolandlovely/utils/formatters.js.map +1 -1
- package/dist/coolandlovely/utils/icons.js.map +1 -1
- package/dist/coolandlovely/utils/index.js +2 -1
- package/dist/coolandlovely/utils/navigation.js.map +1 -1
- package/dist/coolandlovely/utils/paymentProviders.js +22 -22
- package/dist/coolandlovely/utils/paymentProviders.js.map +1 -1
- package/dist/coolandlovely/utils/sparkline.js +13 -15
- package/dist/coolandlovely/utils/sparkline.js.map +1 -1
- package/dist/node_modules/clsx/dist/clsx.js +1 -1
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -1
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +225 -146
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -1
- package/dist/services/createSandboxAssistantTransport.js.map +1 -1
- package/dist/stories/DiscoverPage.stories.d.ts.map +1 -1
- package/dist/utils/pageContext.js +1 -1
- package/dist/utils/pageContext.js.map +1 -1
- package/package.json +6 -4
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
2
|
+
import { PageLayout as t } from "../../components/PageLayout.js";
|
|
3
|
+
import "../../context/index.js";
|
|
4
|
+
import { TextAreaField as n, TextField as r } from "../../components/Field.js";
|
|
5
|
+
import { useEditorialAction as i, useEditorialFeatures as a, useMyArticles as o, useMyTrendReports as s } from "../../hooks/useEditorialApi.js";
|
|
6
|
+
import { useState as c } from "react";
|
|
7
|
+
import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
8
|
+
import { GlassCard as f } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
//#region src/coolandlovely/pages/editorial/EditorialPage.tsx
|
|
10
|
+
var p = "rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary disabled:opacity-50";
|
|
11
|
+
function m({ label: e, options: t, value: n, onChange: r, offset: i, hasMore: a, onPage: o }) {
|
|
12
|
+
return /* @__PURE__ */ d("div", {
|
|
13
|
+
className: "flex flex-col gap-2 text-sm text-text-primary",
|
|
14
|
+
children: [/* @__PURE__ */ d("label", { children: [
|
|
15
|
+
e,
|
|
16
|
+
/* @__PURE__ */ u("select", {
|
|
17
|
+
multiple: !0,
|
|
18
|
+
value: n,
|
|
19
|
+
onChange: (e) => r([...n.filter((e) => !t.some((t) => t.id === e)), ...Array.from(e.target.selectedOptions, (e) => e.value)]),
|
|
20
|
+
className: "min-h-24 rounded-lg border border-border-seam bg-bg-surface p-2",
|
|
21
|
+
children: t.map((e) => /* @__PURE__ */ u("option", {
|
|
22
|
+
value: e.id,
|
|
23
|
+
children: e.name
|
|
24
|
+
}, e.id))
|
|
25
|
+
}),
|
|
26
|
+
/* @__PURE__ */ d("span", {
|
|
27
|
+
className: "text-xs text-text-secondary",
|
|
28
|
+
children: [
|
|
29
|
+
"Choose up to 20 published features you created. Use Ctrl or Command to select several.",
|
|
30
|
+
" ",
|
|
31
|
+
n.length,
|
|
32
|
+
" selected."
|
|
33
|
+
]
|
|
34
|
+
})
|
|
35
|
+
] }), /* @__PURE__ */ d("div", {
|
|
36
|
+
className: "flex gap-2",
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ d("button", {
|
|
39
|
+
className: p,
|
|
40
|
+
type: "button",
|
|
41
|
+
disabled: i === 0,
|
|
42
|
+
onClick: () => o(Math.max(0, i - 20)),
|
|
43
|
+
children: ["Previous ", e.toLowerCase()]
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ d("button", {
|
|
46
|
+
className: p,
|
|
47
|
+
type: "button",
|
|
48
|
+
disabled: !a,
|
|
49
|
+
onClick: () => o(i + 20),
|
|
50
|
+
children: ["Next ", e.toLowerCase()]
|
|
51
|
+
}),
|
|
52
|
+
/* @__PURE__ */ u("button", {
|
|
53
|
+
className: p,
|
|
54
|
+
type: "button",
|
|
55
|
+
disabled: !n.length,
|
|
56
|
+
onClick: () => r([]),
|
|
57
|
+
children: "Clear selection"
|
|
58
|
+
})
|
|
59
|
+
]
|
|
60
|
+
})]
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function h() {
|
|
64
|
+
let { currentUser: h, apiGatewayUrl: g } = e(), _ = g?.includes("alphagraphqlworkspaces.") || window.location.hostname.startsWith("alphaapp.") ? "https://alpha.coolandlovely.com" : "https://coolandlovely.com", v = () => ({
|
|
65
|
+
authorName: h?.name ?? "",
|
|
66
|
+
slug: "",
|
|
67
|
+
title: "",
|
|
68
|
+
summary: "",
|
|
69
|
+
body: "",
|
|
70
|
+
tags: [],
|
|
71
|
+
styleItemIds: [],
|
|
72
|
+
lookIds: [],
|
|
73
|
+
collectionIds: [],
|
|
74
|
+
brandIds: []
|
|
75
|
+
}), [y, b] = c(v), [x, S] = c(), [C, w] = c(""), [T, E] = c(0), [D, O] = c(0), [k, A] = c(0), [j, M] = c(0), [N, P] = c(0), [F, I] = c(0), [L, R] = c(""), [z, B] = c(""), [V, H] = c(""), [U, W] = c(!1), G = o(N), K = s(F), q = i(), J = a("STYLE_ITEM", T), Y = a("LOOK", D), X = a("COLLECTION", k), Z = a("BRAND", j), Q = (e, t) => b((n) => ({
|
|
76
|
+
...n,
|
|
77
|
+
[e]: t
|
|
78
|
+
})), ee = (e) => {
|
|
79
|
+
e.preventDefault(), q.mutate({
|
|
80
|
+
kind: "save",
|
|
81
|
+
id: x,
|
|
82
|
+
input: {
|
|
83
|
+
...y,
|
|
84
|
+
tags: C.split(",").map((e) => e.trim()).filter(Boolean)
|
|
85
|
+
}
|
|
86
|
+
}, { onSuccess: () => {
|
|
87
|
+
b(v()), S(void 0), w("");
|
|
88
|
+
} });
|
|
89
|
+
}, te = (e) => {
|
|
90
|
+
S(e.id), w(e.tags.join(", ")), b({
|
|
91
|
+
authorName: e.authorName,
|
|
92
|
+
title: e.title,
|
|
93
|
+
slug: e.slug,
|
|
94
|
+
summary: e.summary,
|
|
95
|
+
body: e.body,
|
|
96
|
+
tags: e.tags,
|
|
97
|
+
styleItemIds: e.styleItemIds,
|
|
98
|
+
lookIds: e.lookIds,
|
|
99
|
+
collectionIds: e.collectionIds,
|
|
100
|
+
brandIds: e.brandIds
|
|
101
|
+
});
|
|
102
|
+
}, $ = q.error ?? G.error ?? K.error ?? J.error ?? Y.error ?? X.error ?? Z.error;
|
|
103
|
+
return /* @__PURE__ */ u(t, {
|
|
104
|
+
title: "Journal and trend reports",
|
|
105
|
+
description: "Write your own editorial, feature published looks and publish dated reports from workspace catalog and public look activity.",
|
|
106
|
+
children: /* @__PURE__ */ d("div", {
|
|
107
|
+
className: "space-y-6 p-4 sm:p-6",
|
|
108
|
+
children: [
|
|
109
|
+
$ && /* @__PURE__ */ u("p", {
|
|
110
|
+
role: "alert",
|
|
111
|
+
className: "text-status-error-text",
|
|
112
|
+
children: $.message
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ d(f, {
|
|
115
|
+
treatment: "plain",
|
|
116
|
+
className: "p-5",
|
|
117
|
+
children: [/* @__PURE__ */ u("h2", {
|
|
118
|
+
className: "mb-4 text-lg font-semibold text-text-primary",
|
|
119
|
+
children: x ? "Edit draft" : "Write an article"
|
|
120
|
+
}), /* @__PURE__ */ d("form", {
|
|
121
|
+
onSubmit: ee,
|
|
122
|
+
className: "grid gap-4 sm:grid-cols-2",
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ u(r, {
|
|
125
|
+
id: "editorial-title",
|
|
126
|
+
label: "Title",
|
|
127
|
+
required: !0,
|
|
128
|
+
value: y.title,
|
|
129
|
+
onChange: (e) => Q("title", e)
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ u(r, {
|
|
132
|
+
id: "editorial-slug",
|
|
133
|
+
label: "Article address",
|
|
134
|
+
hint: "Lowercase words separated by hyphens.",
|
|
135
|
+
required: !0,
|
|
136
|
+
value: y.slug,
|
|
137
|
+
onChange: (e) => Q("slug", e)
|
|
138
|
+
}),
|
|
139
|
+
/* @__PURE__ */ u(r, {
|
|
140
|
+
id: "editorial-author",
|
|
141
|
+
label: "Public author name",
|
|
142
|
+
required: !0,
|
|
143
|
+
value: y.authorName,
|
|
144
|
+
onChange: (e) => Q("authorName", e)
|
|
145
|
+
}),
|
|
146
|
+
/* @__PURE__ */ u(r, {
|
|
147
|
+
id: "editorial-tags",
|
|
148
|
+
label: "Tags",
|
|
149
|
+
value: C,
|
|
150
|
+
onChange: w
|
|
151
|
+
}),
|
|
152
|
+
/* @__PURE__ */ u(n, {
|
|
153
|
+
id: "editorial-summary",
|
|
154
|
+
label: "Summary",
|
|
155
|
+
required: !0,
|
|
156
|
+
value: y.summary,
|
|
157
|
+
onChange: (e) => Q("summary", e),
|
|
158
|
+
className: "sm:col-span-2"
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ u(n, {
|
|
161
|
+
id: "editorial-body",
|
|
162
|
+
label: "Article",
|
|
163
|
+
required: !0,
|
|
164
|
+
rows: 12,
|
|
165
|
+
value: y.body,
|
|
166
|
+
onChange: (e) => Q("body", e),
|
|
167
|
+
hint: "Plain text. Drafts are private to you; publishing makes the article accessible to anyone with its address.",
|
|
168
|
+
className: "sm:col-span-2"
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ u(m, {
|
|
171
|
+
label: "Shop the editorial",
|
|
172
|
+
offset: T,
|
|
173
|
+
onPage: E,
|
|
174
|
+
hasMore: J.data?.pageInfo.hasMore ?? !1,
|
|
175
|
+
options: J.data?.items ?? [],
|
|
176
|
+
value: y.styleItemIds,
|
|
177
|
+
onChange: (e) => Q("styleItemIds", e)
|
|
178
|
+
}),
|
|
179
|
+
/* @__PURE__ */ u(m, {
|
|
180
|
+
label: "Featured looks",
|
|
181
|
+
offset: D,
|
|
182
|
+
onPage: O,
|
|
183
|
+
hasMore: Y.data?.pageInfo.hasMore ?? !1,
|
|
184
|
+
options: Y.data?.items ?? [],
|
|
185
|
+
value: y.lookIds,
|
|
186
|
+
onChange: (e) => Q("lookIds", e)
|
|
187
|
+
}),
|
|
188
|
+
/* @__PURE__ */ u(m, {
|
|
189
|
+
label: "Featured collections",
|
|
190
|
+
offset: k,
|
|
191
|
+
onPage: A,
|
|
192
|
+
hasMore: X.data?.pageInfo.hasMore ?? !1,
|
|
193
|
+
options: X.data?.items ?? [],
|
|
194
|
+
value: y.collectionIds,
|
|
195
|
+
onChange: (e) => Q("collectionIds", e)
|
|
196
|
+
}),
|
|
197
|
+
/* @__PURE__ */ u(m, {
|
|
198
|
+
label: "Featured brands",
|
|
199
|
+
offset: j,
|
|
200
|
+
onPage: M,
|
|
201
|
+
hasMore: Z.data?.pageInfo.hasMore ?? !1,
|
|
202
|
+
options: Z.data?.items ?? [],
|
|
203
|
+
value: y.brandIds,
|
|
204
|
+
onChange: (e) => Q("brandIds", e)
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ d("div", {
|
|
207
|
+
className: "flex items-end gap-2",
|
|
208
|
+
children: [/* @__PURE__ */ u("button", {
|
|
209
|
+
className: p,
|
|
210
|
+
type: "submit",
|
|
211
|
+
disabled: q.isPending,
|
|
212
|
+
children: "Save draft"
|
|
213
|
+
}), x && /* @__PURE__ */ u("button", {
|
|
214
|
+
className: p,
|
|
215
|
+
type: "button",
|
|
216
|
+
onClick: () => {
|
|
217
|
+
S(void 0), b(v()), w("");
|
|
218
|
+
},
|
|
219
|
+
children: "Cancel edit"
|
|
220
|
+
})]
|
|
221
|
+
})
|
|
222
|
+
]
|
|
223
|
+
})]
|
|
224
|
+
}),
|
|
225
|
+
/* @__PURE__ */ d("section", {
|
|
226
|
+
"aria-labelledby": "my-articles",
|
|
227
|
+
className: "space-y-3",
|
|
228
|
+
children: [
|
|
229
|
+
/* @__PURE__ */ u("h2", {
|
|
230
|
+
id: "my-articles",
|
|
231
|
+
className: "text-lg font-semibold text-text-primary",
|
|
232
|
+
children: "My articles"
|
|
233
|
+
}),
|
|
234
|
+
G.isLoading && /* @__PURE__ */ u("p", {
|
|
235
|
+
role: "status",
|
|
236
|
+
children: "Loading articles…"
|
|
237
|
+
}),
|
|
238
|
+
G.data?.items.length === 0 && /* @__PURE__ */ u("p", {
|
|
239
|
+
className: "text-text-secondary",
|
|
240
|
+
children: "No articles yet. Save your first draft above."
|
|
241
|
+
}),
|
|
242
|
+
G.data?.items.map((e) => /* @__PURE__ */ d(f, {
|
|
243
|
+
treatment: "plain",
|
|
244
|
+
className: "p-4",
|
|
245
|
+
children: [
|
|
246
|
+
/* @__PURE__ */ u("h3", {
|
|
247
|
+
className: "font-semibold text-text-primary",
|
|
248
|
+
children: e.title
|
|
249
|
+
}),
|
|
250
|
+
/* @__PURE__ */ d("p", {
|
|
251
|
+
className: "text-sm text-text-secondary",
|
|
252
|
+
children: [
|
|
253
|
+
e.summary,
|
|
254
|
+
" · ",
|
|
255
|
+
e.status
|
|
256
|
+
]
|
|
257
|
+
}),
|
|
258
|
+
/* @__PURE__ */ d("div", {
|
|
259
|
+
className: "mt-3 flex flex-wrap gap-2",
|
|
260
|
+
children: [
|
|
261
|
+
e.status === "DRAFT" ? /* @__PURE__ */ d(l, { children: [/* @__PURE__ */ u("button", {
|
|
262
|
+
className: p,
|
|
263
|
+
onClick: () => te(e),
|
|
264
|
+
children: "Edit"
|
|
265
|
+
}), /* @__PURE__ */ u("button", {
|
|
266
|
+
className: p,
|
|
267
|
+
disabled: q.isPending,
|
|
268
|
+
onClick: () => q.mutate({
|
|
269
|
+
kind: "status",
|
|
270
|
+
id: e.id,
|
|
271
|
+
status: "PUBLISHED"
|
|
272
|
+
}),
|
|
273
|
+
children: "Publish publicly"
|
|
274
|
+
})] }) : /* @__PURE__ */ u("button", {
|
|
275
|
+
className: p,
|
|
276
|
+
disabled: q.isPending,
|
|
277
|
+
onClick: () => q.mutate({
|
|
278
|
+
kind: "status",
|
|
279
|
+
id: e.id,
|
|
280
|
+
status: "DRAFT"
|
|
281
|
+
}),
|
|
282
|
+
children: "Return to draft"
|
|
283
|
+
}),
|
|
284
|
+
e.status === "PUBLISHED" && /* @__PURE__ */ u("a", {
|
|
285
|
+
className: p,
|
|
286
|
+
href: `${_}/journal/${encodeURIComponent(e.workspaceId)}/${encodeURIComponent(e.slug)}`,
|
|
287
|
+
target: "_blank",
|
|
288
|
+
rel: "noopener noreferrer",
|
|
289
|
+
children: "Read public article"
|
|
290
|
+
}),
|
|
291
|
+
/* @__PURE__ */ u("button", {
|
|
292
|
+
className: p,
|
|
293
|
+
disabled: q.isPending,
|
|
294
|
+
onClick: () => q.mutate({
|
|
295
|
+
kind: "status",
|
|
296
|
+
id: e.id,
|
|
297
|
+
status: "ARCHIVED"
|
|
298
|
+
}),
|
|
299
|
+
children: "Archive"
|
|
300
|
+
})
|
|
301
|
+
]
|
|
302
|
+
})
|
|
303
|
+
]
|
|
304
|
+
}, e.id)),
|
|
305
|
+
/* @__PURE__ */ d("div", {
|
|
306
|
+
className: "flex gap-2",
|
|
307
|
+
children: [/* @__PURE__ */ u("button", {
|
|
308
|
+
className: p,
|
|
309
|
+
disabled: N === 0,
|
|
310
|
+
onClick: () => P((e) => Math.max(0, e - 20)),
|
|
311
|
+
children: "Previous articles"
|
|
312
|
+
}), /* @__PURE__ */ u("button", {
|
|
313
|
+
className: p,
|
|
314
|
+
disabled: !G.data?.pageInfo.hasMore,
|
|
315
|
+
onClick: () => P((e) => e + 20),
|
|
316
|
+
children: "Next articles"
|
|
317
|
+
})]
|
|
318
|
+
})
|
|
319
|
+
]
|
|
320
|
+
}),
|
|
321
|
+
/* @__PURE__ */ d(f, {
|
|
322
|
+
treatment: "plain",
|
|
323
|
+
className: "p-5",
|
|
324
|
+
children: [
|
|
325
|
+
/* @__PURE__ */ u("h2", {
|
|
326
|
+
className: "mb-4 text-lg font-semibold text-text-primary",
|
|
327
|
+
children: "Generate a trend report"
|
|
328
|
+
}),
|
|
329
|
+
/* @__PURE__ */ u("p", {
|
|
330
|
+
className: "mb-4 text-sm text-text-secondary",
|
|
331
|
+
children: "Reports count new active catalog items and appearances in published public looks. They compare brands with the preceding period. Private looks are excluded. Wardrobe wear counts are included only if you choose to share them below."
|
|
332
|
+
}),
|
|
333
|
+
/* @__PURE__ */ d("form", {
|
|
334
|
+
className: "grid gap-4 sm:grid-cols-3",
|
|
335
|
+
onSubmit: (e) => {
|
|
336
|
+
e.preventDefault(), q.mutate({
|
|
337
|
+
kind: "report",
|
|
338
|
+
input: {
|
|
339
|
+
title: L,
|
|
340
|
+
periodStart: new Date(z).toISOString(),
|
|
341
|
+
periodEnd: new Date(V).toISOString(),
|
|
342
|
+
includeWearCounts: U
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ u(r, {
|
|
348
|
+
id: "trend-title",
|
|
349
|
+
label: "Report title",
|
|
350
|
+
value: L,
|
|
351
|
+
onChange: R,
|
|
352
|
+
required: !0
|
|
353
|
+
}),
|
|
354
|
+
/* @__PURE__ */ u(r, {
|
|
355
|
+
id: "trend-start",
|
|
356
|
+
label: "Start date (UTC)",
|
|
357
|
+
type: "date",
|
|
358
|
+
value: z,
|
|
359
|
+
onChange: B,
|
|
360
|
+
required: !0
|
|
361
|
+
}),
|
|
362
|
+
/* @__PURE__ */ u(r, {
|
|
363
|
+
id: "trend-end",
|
|
364
|
+
label: "End date (UTC, exclusive)",
|
|
365
|
+
type: "date",
|
|
366
|
+
value: V,
|
|
367
|
+
onChange: H,
|
|
368
|
+
required: !0
|
|
369
|
+
}),
|
|
370
|
+
/* @__PURE__ */ u("button", {
|
|
371
|
+
className: p,
|
|
372
|
+
disabled: q.isPending,
|
|
373
|
+
children: "Generate private draft"
|
|
374
|
+
}),
|
|
375
|
+
/* @__PURE__ */ d("label", {
|
|
376
|
+
className: "flex items-start gap-2 text-sm text-text-primary sm:col-span-3",
|
|
377
|
+
children: [/* @__PURE__ */ u("input", {
|
|
378
|
+
type: "checkbox",
|
|
379
|
+
checked: U,
|
|
380
|
+
onChange: (e) => W(e.target.checked)
|
|
381
|
+
}), /* @__PURE__ */ u("span", { children: "Include my top 20 pieces by all-time logged wears. Publishing this report will share their names and wear counts publicly; these counts cover all time, not the selected catalog period." })]
|
|
382
|
+
})
|
|
383
|
+
]
|
|
384
|
+
})
|
|
385
|
+
]
|
|
386
|
+
}),
|
|
387
|
+
/* @__PURE__ */ d("section", {
|
|
388
|
+
"aria-labelledby": "my-reports",
|
|
389
|
+
className: "space-y-3",
|
|
390
|
+
children: [
|
|
391
|
+
/* @__PURE__ */ u("h2", {
|
|
392
|
+
id: "my-reports",
|
|
393
|
+
className: "text-lg font-semibold text-text-primary",
|
|
394
|
+
children: "My trend reports"
|
|
395
|
+
}),
|
|
396
|
+
K.isLoading && /* @__PURE__ */ u("p", {
|
|
397
|
+
role: "status",
|
|
398
|
+
children: "Loading reports…"
|
|
399
|
+
}),
|
|
400
|
+
K.data?.items.length === 0 && /* @__PURE__ */ u("p", {
|
|
401
|
+
className: "text-text-secondary",
|
|
402
|
+
children: "No reports generated yet."
|
|
403
|
+
}),
|
|
404
|
+
K.data?.items.map((e) => /* @__PURE__ */ d(f, {
|
|
405
|
+
treatment: "plain",
|
|
406
|
+
className: "p-4",
|
|
407
|
+
children: [
|
|
408
|
+
/* @__PURE__ */ u("h3", {
|
|
409
|
+
className: "font-semibold text-text-primary",
|
|
410
|
+
children: e.title
|
|
411
|
+
}),
|
|
412
|
+
/* @__PURE__ */ d("p", {
|
|
413
|
+
className: "text-sm text-text-secondary",
|
|
414
|
+
children: [
|
|
415
|
+
e.periodStart.slice(0, 10),
|
|
416
|
+
" to ",
|
|
417
|
+
e.periodEnd.slice(0, 10),
|
|
418
|
+
" ·",
|
|
419
|
+
" ",
|
|
420
|
+
e.metrics.catalogItems,
|
|
421
|
+
" new items · ",
|
|
422
|
+
e.metrics.publicLookTags,
|
|
423
|
+
" public look tags"
|
|
424
|
+
]
|
|
425
|
+
}),
|
|
426
|
+
e.metrics.wearCountsIncluded && /* @__PURE__ */ u("p", {
|
|
427
|
+
className: "mt-2 text-sm text-text-secondary",
|
|
428
|
+
children: "Includes your wardrobe piece names and all-time logged wear counts. Publishing makes those details public."
|
|
429
|
+
}),
|
|
430
|
+
/* @__PURE__ */ d("div", {
|
|
431
|
+
className: "mt-3 flex flex-wrap gap-2",
|
|
432
|
+
children: [
|
|
433
|
+
/* @__PURE__ */ u("button", {
|
|
434
|
+
className: p,
|
|
435
|
+
disabled: q.isPending,
|
|
436
|
+
onClick: () => q.mutate({
|
|
437
|
+
kind: "publishReport",
|
|
438
|
+
id: e.id,
|
|
439
|
+
publish: !e.publishedAt
|
|
440
|
+
}),
|
|
441
|
+
children: e.publishedAt ? "Unpublish" : "Publish publicly"
|
|
442
|
+
}),
|
|
443
|
+
e.publishedAt && /* @__PURE__ */ u("a", {
|
|
444
|
+
className: p,
|
|
445
|
+
href: `${_}/trend-reports/${encodeURIComponent(e.id)}`,
|
|
446
|
+
target: "_blank",
|
|
447
|
+
rel: "noopener noreferrer",
|
|
448
|
+
children: "Read and export report"
|
|
449
|
+
}),
|
|
450
|
+
/* @__PURE__ */ u("button", {
|
|
451
|
+
className: p,
|
|
452
|
+
disabled: q.isPending,
|
|
453
|
+
onClick: () => q.mutate({
|
|
454
|
+
kind: "deleteReport",
|
|
455
|
+
id: e.id
|
|
456
|
+
}),
|
|
457
|
+
children: "Archive report"
|
|
458
|
+
})
|
|
459
|
+
]
|
|
460
|
+
})
|
|
461
|
+
]
|
|
462
|
+
}, e.id)),
|
|
463
|
+
/* @__PURE__ */ d("div", {
|
|
464
|
+
className: "flex gap-2",
|
|
465
|
+
children: [/* @__PURE__ */ u("button", {
|
|
466
|
+
className: p,
|
|
467
|
+
disabled: F === 0,
|
|
468
|
+
onClick: () => I((e) => Math.max(0, e - 20)),
|
|
469
|
+
children: "Previous reports"
|
|
470
|
+
}), /* @__PURE__ */ u("button", {
|
|
471
|
+
className: p,
|
|
472
|
+
disabled: !K.data?.pageInfo.hasMore,
|
|
473
|
+
onClick: () => I((e) => e + 20),
|
|
474
|
+
children: "Next reports"
|
|
475
|
+
})]
|
|
476
|
+
})
|
|
477
|
+
]
|
|
478
|
+
})
|
|
479
|
+
]
|
|
480
|
+
})
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
//#endregion
|
|
484
|
+
export { h as EditorialPage };
|
|
485
|
+
|
|
486
|
+
//# sourceMappingURL=EditorialPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorialPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/editorial/EditorialPage.tsx"],"sourcesContent":["import { useState, type FormEvent } from 'react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\n\nimport { PageLayout } from '../../components/PageLayout';\nimport { TextAreaField, TextField } from '../../components/Field';\nimport { useCoolAndLovely } from '../../context';\nimport {\n type EditorialInput,\n type EditorialArticle,\n useEditorialAction,\n useMyArticles,\n useMyTrendReports,\n useEditorialFeatures,\n} from '../../hooks/useEditorialApi';\n\nconst button =\n 'rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary disabled:opacity-50';\n\nfunction FeaturePicker({\n label,\n options,\n value,\n onChange,\n offset,\n hasMore,\n onPage,\n}: {\n label: string;\n options: Array<{ id: string; name: string }>;\n value: string[];\n onChange: (value: string[]) => void;\n offset: number;\n hasMore: boolean;\n onPage: (offset: number) => void;\n}) {\n return (\n <div className=\"flex flex-col gap-2 text-sm text-text-primary\">\n <label>\n {label}\n <select\n multiple\n value={value}\n onChange={(event) =>\n onChange([\n ...value.filter((id) => !options.some((option) => option.id === id)),\n ...Array.from(event.target.selectedOptions, (option) => option.value),\n ])\n }\n className=\"min-h-24 rounded-lg border border-border-seam bg-bg-surface p-2\"\n >\n {options.map((option) => (\n <option value={option.id} key={option.id}>\n {option.name}\n </option>\n ))}\n </select>\n <span className=\"text-xs text-text-secondary\">\n Choose up to 20 published features you created. Use Ctrl or Command to select several.{' '}\n {value.length} selected.\n </span>\n </label>\n <div className=\"flex gap-2\">\n <button\n className={button}\n type=\"button\"\n disabled={offset === 0}\n onClick={() => onPage(Math.max(0, offset - 20))}\n >\n Previous {label.toLowerCase()}\n </button>\n <button\n className={button}\n type=\"button\"\n disabled={!hasMore}\n onClick={() => onPage(offset + 20)}\n >\n Next {label.toLowerCase()}\n </button>\n <button\n className={button}\n type=\"button\"\n disabled={!value.length}\n onClick={() => onChange([])}\n >\n Clear selection\n </button>\n </div>\n </div>\n );\n}\n\nexport function EditorialPage() {\n const { currentUser, apiGatewayUrl } = useCoolAndLovely();\n const publicOrigin =\n apiGatewayUrl?.includes('alphagraphqlworkspaces.') ||\n window.location.hostname.startsWith('alphaapp.')\n ? 'https://alpha.coolandlovely.com'\n : 'https://coolandlovely.com';\n const blank = (): EditorialInput => ({\n authorName: currentUser?.name ?? '',\n slug: '',\n title: '',\n summary: '',\n body: '',\n tags: [],\n styleItemIds: [],\n lookIds: [],\n collectionIds: [],\n brandIds: [],\n });\n const [input, setInput] = useState<EditorialInput>(blank);\n const [editing, setEditing] = useState<string | undefined>();\n const [tagsText, setTagsText] = useState('');\n const [itemOffset, setItemOffset] = useState(0);\n const [lookOffset, setLookOffset] = useState(0);\n const [collectionOffset, setCollectionOffset] = useState(0);\n const [brandOffset, setBrandOffset] = useState(0);\n const [articleOffset, setArticleOffset] = useState(0);\n const [reportOffset, setReportOffset] = useState(0);\n const [reportTitle, setReportTitle] = useState('');\n const [start, setStart] = useState('');\n const [end, setEnd] = useState('');\n const [includeWearCounts, setIncludeWearCounts] = useState(false);\n const articles = useMyArticles(articleOffset);\n const reports = useMyTrendReports(reportOffset);\n const action = useEditorialAction();\n const items = useEditorialFeatures('STYLE_ITEM', itemOffset);\n const looks = useEditorialFeatures('LOOK', lookOffset);\n const collections = useEditorialFeatures('COLLECTION', collectionOffset);\n const brands = useEditorialFeatures('BRAND', brandOffset);\n const set = <K extends keyof EditorialInput>(key: K, value: EditorialInput[K]) =>\n setInput((previous) => ({ ...previous, [key]: value }));\n const save = (event: FormEvent) => {\n event.preventDefault();\n action.mutate(\n {\n kind: 'save',\n id: editing,\n input: {\n ...input,\n tags: tagsText\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean),\n },\n },\n {\n onSuccess: () => {\n setInput(blank());\n setEditing(undefined);\n setTagsText('');\n },\n }\n );\n };\n const edit = (article: EditorialArticle) => {\n setEditing(article.id);\n setTagsText(article.tags.join(', '));\n setInput({\n authorName: article.authorName,\n title: article.title,\n slug: article.slug,\n summary: article.summary,\n body: article.body,\n tags: article.tags,\n styleItemIds: article.styleItemIds,\n lookIds: article.lookIds,\n collectionIds: article.collectionIds,\n brandIds: article.brandIds,\n });\n };\n const error =\n action.error ??\n articles.error ??\n reports.error ??\n items.error ??\n looks.error ??\n collections.error ??\n brands.error;\n return (\n <PageLayout\n title=\"Journal and trend reports\"\n description=\"Write your own editorial, feature published looks and publish dated reports from workspace catalog and public look activity.\"\n >\n <div className=\"space-y-6 p-4 sm:p-6\">\n {error && (\n <p role=\"alert\" className=\"text-status-error-text\">\n {error.message}\n </p>\n )}\n <GlassCard treatment=\"plain\" className=\"p-5\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">\n {editing ? 'Edit draft' : 'Write an article'}\n </h2>\n <form onSubmit={save} className=\"grid gap-4 sm:grid-cols-2\">\n <TextField\n id=\"editorial-title\"\n label=\"Title\"\n required\n value={input.title}\n onChange={(value) => set('title', value)}\n />\n <TextField\n id=\"editorial-slug\"\n label=\"Article address\"\n hint=\"Lowercase words separated by hyphens.\"\n required\n value={input.slug}\n onChange={(value) => set('slug', value)}\n />\n <TextField\n id=\"editorial-author\"\n label=\"Public author name\"\n required\n value={input.authorName}\n onChange={(value) => set('authorName', value)}\n />\n <TextField id=\"editorial-tags\" label=\"Tags\" value={tagsText} onChange={setTagsText} />\n <TextAreaField\n id=\"editorial-summary\"\n label=\"Summary\"\n required\n value={input.summary}\n onChange={(value) => set('summary', value)}\n className=\"sm:col-span-2\"\n />\n <TextAreaField\n id=\"editorial-body\"\n label=\"Article\"\n required\n rows={12}\n value={input.body}\n onChange={(value) => set('body', value)}\n hint=\"Plain text. Drafts are private to you; publishing makes the article accessible to anyone with its address.\"\n className=\"sm:col-span-2\"\n />\n <FeaturePicker\n label=\"Shop the editorial\"\n offset={itemOffset}\n onPage={setItemOffset}\n hasMore={items.data?.pageInfo.hasMore ?? false}\n options={items.data?.items ?? []}\n value={input.styleItemIds}\n onChange={(value) => set('styleItemIds', value)}\n />\n <FeaturePicker\n label=\"Featured looks\"\n offset={lookOffset}\n onPage={setLookOffset}\n hasMore={looks.data?.pageInfo.hasMore ?? false}\n options={looks.data?.items ?? []}\n value={input.lookIds}\n onChange={(value) => set('lookIds', value)}\n />\n <FeaturePicker\n label=\"Featured collections\"\n offset={collectionOffset}\n onPage={setCollectionOffset}\n hasMore={collections.data?.pageInfo.hasMore ?? false}\n options={collections.data?.items ?? []}\n value={input.collectionIds}\n onChange={(value) => set('collectionIds', value)}\n />\n <FeaturePicker\n label=\"Featured brands\"\n offset={brandOffset}\n onPage={setBrandOffset}\n hasMore={brands.data?.pageInfo.hasMore ?? false}\n options={brands.data?.items ?? []}\n value={input.brandIds}\n onChange={(value) => set('brandIds', value)}\n />\n <div className=\"flex items-end gap-2\">\n <button className={button} type=\"submit\" disabled={action.isPending}>\n Save draft\n </button>\n {editing && (\n <button\n className={button}\n type=\"button\"\n onClick={() => {\n setEditing(undefined);\n setInput(blank());\n setTagsText('');\n }}\n >\n Cancel edit\n </button>\n )}\n </div>\n </form>\n </GlassCard>\n <section aria-labelledby=\"my-articles\" className=\"space-y-3\">\n <h2 id=\"my-articles\" className=\"text-lg font-semibold text-text-primary\">\n My articles\n </h2>\n {articles.isLoading && <p role=\"status\">Loading articles…</p>}\n {articles.data?.items.length === 0 && (\n <p className=\"text-text-secondary\">No articles yet. Save your first draft above.</p>\n )}\n {articles.data?.items.map((article) => (\n <GlassCard treatment=\"plain\" className=\"p-4\" key={article.id}>\n <h3 className=\"font-semibold text-text-primary\">{article.title}</h3>\n <p className=\"text-sm text-text-secondary\">\n {article.summary} · {article.status}\n </p>\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {article.status === 'DRAFT' ? (\n <>\n <button className={button} onClick={() => edit(article)}>\n Edit\n </button>\n <button\n className={button}\n disabled={action.isPending}\n onClick={() =>\n action.mutate({ kind: 'status', id: article.id, status: 'PUBLISHED' })\n }\n >\n Publish publicly\n </button>\n </>\n ) : (\n <button\n className={button}\n disabled={action.isPending}\n onClick={() =>\n action.mutate({ kind: 'status', id: article.id, status: 'DRAFT' })\n }\n >\n Return to draft\n </button>\n )}\n {article.status === 'PUBLISHED' && (\n <a\n className={button}\n href={`${publicOrigin}/journal/${encodeURIComponent(article.workspaceId)}/${encodeURIComponent(article.slug)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Read public article\n </a>\n )}\n <button\n className={button}\n disabled={action.isPending}\n onClick={() =>\n action.mutate({ kind: 'status', id: article.id, status: 'ARCHIVED' })\n }\n >\n Archive\n </button>\n </div>\n </GlassCard>\n ))}\n <div className=\"flex gap-2\">\n <button\n className={button}\n disabled={articleOffset === 0}\n onClick={() => setArticleOffset((value) => Math.max(0, value - 20))}\n >\n Previous articles\n </button>\n <button\n className={button}\n disabled={!articles.data?.pageInfo.hasMore}\n onClick={() => setArticleOffset((value) => value + 20)}\n >\n Next articles\n </button>\n </div>\n </section>\n <GlassCard treatment=\"plain\" className=\"p-5\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Generate a trend report</h2>\n <p className=\"mb-4 text-sm text-text-secondary\">\n Reports count new active catalog items and appearances in published public looks. They\n compare brands with the preceding period. Private looks are excluded. Wardrobe wear\n counts are included only if you choose to share them below.\n </p>\n <form\n className=\"grid gap-4 sm:grid-cols-3\"\n onSubmit={(event) => {\n event.preventDefault();\n action.mutate({\n kind: 'report',\n input: {\n title: reportTitle,\n periodStart: new Date(start).toISOString(),\n periodEnd: new Date(end).toISOString(),\n includeWearCounts,\n },\n });\n }}\n >\n <TextField\n id=\"trend-title\"\n label=\"Report title\"\n value={reportTitle}\n onChange={setReportTitle}\n required\n />\n <TextField\n id=\"trend-start\"\n label=\"Start date (UTC)\"\n type=\"date\"\n value={start}\n onChange={setStart}\n required\n />\n <TextField\n id=\"trend-end\"\n label=\"End date (UTC, exclusive)\"\n type=\"date\"\n value={end}\n onChange={setEnd}\n required\n />\n <button className={button} disabled={action.isPending}>\n Generate private draft\n </button>\n <label className=\"flex items-start gap-2 text-sm text-text-primary sm:col-span-3\">\n <input\n type=\"checkbox\"\n checked={includeWearCounts}\n onChange={(event) => setIncludeWearCounts(event.target.checked)}\n />\n <span>\n Include my top 20 pieces by all-time logged wears. Publishing this report will share\n their names and wear counts publicly; these counts cover all time, not the selected\n catalog period.\n </span>\n </label>\n </form>\n </GlassCard>\n <section aria-labelledby=\"my-reports\" className=\"space-y-3\">\n <h2 id=\"my-reports\" className=\"text-lg font-semibold text-text-primary\">\n My trend reports\n </h2>\n {reports.isLoading && <p role=\"status\">Loading reports…</p>}\n {reports.data?.items.length === 0 && (\n <p className=\"text-text-secondary\">No reports generated yet.</p>\n )}\n {reports.data?.items.map((report) => (\n <GlassCard treatment=\"plain\" className=\"p-4\" key={report.id}>\n <h3 className=\"font-semibold text-text-primary\">{report.title}</h3>\n <p className=\"text-sm text-text-secondary\">\n {report.periodStart.slice(0, 10)} to {report.periodEnd.slice(0, 10)} ·{' '}\n {report.metrics.catalogItems} new items · {report.metrics.publicLookTags} public\n look tags\n </p>\n {report.metrics.wearCountsIncluded && (\n <p className=\"mt-2 text-sm text-text-secondary\">\n Includes your wardrobe piece names and all-time logged wear counts. Publishing\n makes those details public.\n </p>\n )}\n <div className=\"mt-3 flex flex-wrap gap-2\">\n <button\n className={button}\n disabled={action.isPending}\n onClick={() =>\n action.mutate({\n kind: 'publishReport',\n id: report.id,\n publish: !report.publishedAt,\n })\n }\n >\n {report.publishedAt ? 'Unpublish' : 'Publish publicly'}\n </button>\n {report.publishedAt && (\n <a\n className={button}\n href={`${publicOrigin}/trend-reports/${encodeURIComponent(report.id)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Read and export report\n </a>\n )}\n <button\n className={button}\n disabled={action.isPending}\n onClick={() => action.mutate({ kind: 'deleteReport', id: report.id })}\n >\n Archive report\n </button>\n </div>\n </GlassCard>\n ))}\n <div className=\"flex gap-2\">\n <button\n className={button}\n disabled={reportOffset === 0}\n onClick={() => setReportOffset((value) => Math.max(0, value - 20))}\n >\n Previous reports\n </button>\n <button\n className={button}\n disabled={!reports.data?.pageInfo.hasMore}\n onClick={() => setReportOffset((value) => value + 20)}\n >\n Next reports\n </button>\n </div>\n </section>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|