@burdenoff/microfe-coolandlovely 2026.720.1 → 2026.720.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coolandlovely/CoolAndLovelyRoutes.d.ts.map +1 -1
- package/dist/coolandlovely/CoolAndLovelyRoutes.js +8 -0
- package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
- package/dist/coolandlovely/components/Field.d.ts +3 -0
- package/dist/coolandlovely/components/Field.d.ts.map +1 -1
- package/dist/coolandlovely/components/Field.js +12 -9
- package/dist/coolandlovely/components/Field.js.map +1 -1
- package/dist/coolandlovely/components/MetricsCard.d.ts +7 -0
- package/dist/coolandlovely/components/MetricsCard.d.ts.map +1 -1
- package/dist/coolandlovely/components/MetricsCard.js +37 -13
- package/dist/coolandlovely/components/MetricsCard.js.map +1 -1
- package/dist/coolandlovely/hooks/index.d.ts +1 -1
- package/dist/coolandlovely/hooks/index.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts +54 -4
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +197 -79
- package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
- package/dist/coolandlovely/pages/HomePage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/HomePage.js +112 -101
- package/dist/coolandlovely/pages/HomePage.js.map +1 -1
- package/dist/coolandlovely/pages/brands/BrandDetailPage.js +9 -9
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js +135 -111
- package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.d.ts +5 -4
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +201 -107
- package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js +110 -99
- package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/discover/DiscoverPage.js +7 -6
- package/dist/coolandlovely/pages/discover/DiscoverPage.js.map +1 -1
- package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +4 -4
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +116 -104
- package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/looks/LookDetailPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/looks/LookDetailPage.js +15 -13
- package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.d.ts +11 -6
- package/dist/coolandlovely/pages/profile/StyleProfilePage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js +195 -176
- package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -1
- package/dist/coolandlovely/types/index.d.ts +40 -0
- package/dist/coolandlovely/types/index.d.ts.map +1 -1
- package/dist/coolandlovely/utils/index.d.ts +1 -0
- package/dist/coolandlovely/utils/index.d.ts.map +1 -1
- package/dist/coolandlovely/utils/index.js +5 -0
- package/dist/coolandlovely/utils/sparkline.d.ts +31 -0
- package/dist/coolandlovely/utils/sparkline.d.ts.map +1 -0
- package/dist/coolandlovely/utils/sparkline.js +29 -0
- package/dist/coolandlovely/utils/sparkline.js.map +1 -0
- package/dist/utils/pageContext.d.ts +8 -1
- package/dist/utils/pageContext.d.ts.map +1 -1
- package/dist/utils/pageContext.js +22 -27
- package/dist/utils/pageContext.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,198 +1,292 @@
|
|
|
1
1
|
import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
|
|
2
2
|
import { PageLayout as t } from "../../components/PageLayout.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js";
|
|
4
|
+
import { useBrands as i, useCollaboration as a, useCreateCollaboration as o, useUpdateCollaboration as s } from "../../hooks/useCoolAndLovelyApi.js";
|
|
5
|
+
import { parseCsv as c, titleCase as l } from "../../utils/formatters.js";
|
|
5
6
|
import "../../hooks/index.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { ActorName as u } from "../../components/ActorName.js";
|
|
8
|
+
import { SelectField as d, TextAreaField as f, TextField as p } from "../../components/Field.js";
|
|
9
|
+
import { useEffect as m, useMemo as h, useState as g } from "react";
|
|
10
|
+
import { ArrowLeft as _, Handshake as v, Loader2 as y, Save as b } from "lucide-react";
|
|
11
|
+
import { useParams as x } from "react-router-dom";
|
|
12
|
+
import { jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
13
|
+
import { GlassCard as w } from "@burdenoff/fe-libs/ui";
|
|
11
14
|
//#region src/coolandlovely/pages/collaborations/CollaborationFormPage.tsx
|
|
12
|
-
var
|
|
15
|
+
var T = [
|
|
13
16
|
"CREATOR",
|
|
14
17
|
"BRAND",
|
|
15
18
|
"STYLIST",
|
|
16
19
|
"PHOTOGRAPHER"
|
|
17
|
-
]
|
|
18
|
-
|
|
20
|
+
], E = new Set([
|
|
21
|
+
"PUBLISHED",
|
|
22
|
+
"DECLINED",
|
|
23
|
+
"CANCELLED"
|
|
24
|
+
]);
|
|
25
|
+
function D(e) {
|
|
19
26
|
if (!e) return;
|
|
20
27
|
let t = new Date(e);
|
|
21
28
|
return Number.isNaN(t.getTime()) ? void 0 : t.toISOString();
|
|
22
29
|
}
|
|
23
|
-
function
|
|
24
|
-
|
|
30
|
+
function O(e) {
|
|
31
|
+
if (!e) return "";
|
|
32
|
+
let t = new Date(e);
|
|
33
|
+
return Number.isNaN(t.getTime()) ? "" : t.toISOString().slice(0, 10);
|
|
34
|
+
}
|
|
35
|
+
var k = {
|
|
36
|
+
brandId: "",
|
|
37
|
+
creatorId: "",
|
|
38
|
+
title: "",
|
|
39
|
+
brief: "",
|
|
40
|
+
role: "CREATOR",
|
|
41
|
+
compensation: "",
|
|
42
|
+
currency: "USD",
|
|
43
|
+
tags: "",
|
|
44
|
+
startDate: "",
|
|
45
|
+
endDate: ""
|
|
46
|
+
};
|
|
47
|
+
function A() {
|
|
48
|
+
let { collaborationId: A } = x(), j = !!A, { navigateTo: M, currentUser: N } = e(), P = o(), F = s(), I = i({ pagination: {
|
|
25
49
|
limit: 100,
|
|
26
50
|
offset: 0
|
|
27
|
-
} }), [
|
|
28
|
-
|
|
29
|
-
creatorId:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
} }), L = a(j ? A : void 0), [R, z] = g({
|
|
52
|
+
...k,
|
|
53
|
+
creatorId: N?.id ?? ""
|
|
54
|
+
}), [B, V] = g({});
|
|
55
|
+
m(() => {
|
|
56
|
+
if (!j || !L.data) return;
|
|
57
|
+
let e = L.data;
|
|
58
|
+
z({
|
|
59
|
+
brandId: e.brandId,
|
|
60
|
+
creatorId: e.creatorId,
|
|
61
|
+
title: e.title,
|
|
62
|
+
brief: e.brief ?? "",
|
|
63
|
+
role: e.role,
|
|
64
|
+
compensation: e.compensation ? String(e.compensation) : "",
|
|
65
|
+
currency: e.currency,
|
|
66
|
+
tags: e.tags.join(", "),
|
|
67
|
+
startDate: O(e.startDate),
|
|
68
|
+
endDate: O(e.endDate)
|
|
69
|
+
});
|
|
70
|
+
}, [j, L.data]);
|
|
71
|
+
let H = (e, t) => z((n) => ({
|
|
39
72
|
...n,
|
|
40
73
|
[e]: t
|
|
41
|
-
})),
|
|
74
|
+
})), U = h(() => (I.data?.items ?? []).map((e) => ({
|
|
42
75
|
value: e.id,
|
|
43
76
|
label: e.name
|
|
44
|
-
})), [
|
|
77
|
+
})), [I.data]), W = T.map((e) => ({
|
|
45
78
|
value: e,
|
|
46
|
-
label:
|
|
47
|
-
}))
|
|
79
|
+
label: l(e)
|
|
80
|
+
}));
|
|
81
|
+
if (j && L.isLoading) return /* @__PURE__ */ S(t, {
|
|
82
|
+
title: "Edit collaboration",
|
|
83
|
+
children: /* @__PURE__ */ S(r, { label: "Loading collaboration…" })
|
|
84
|
+
});
|
|
85
|
+
if (j && (L.isError || !L.data)) return /* @__PURE__ */ S(t, {
|
|
86
|
+
title: "Edit collaboration",
|
|
87
|
+
children: /* @__PURE__ */ S(n, {
|
|
88
|
+
title: "Collaboration not found",
|
|
89
|
+
onRetry: () => void L.refetch()
|
|
90
|
+
})
|
|
91
|
+
});
|
|
92
|
+
let G = j && L.data ? E.has(L.data.status) : !1, K = () => {
|
|
48
93
|
let e = {};
|
|
49
|
-
return
|
|
50
|
-
};
|
|
51
|
-
return /* @__PURE__ */
|
|
52
|
-
title: "New collaboration",
|
|
53
|
-
description: "Propose a brand × creator partnership",
|
|
54
|
-
actions: /* @__PURE__ */
|
|
94
|
+
return R.title.trim() || (e.title = "Title is required"), j || (R.brandId || (e.brandId = "Brand is required"), R.creatorId.trim() || (e.creatorId = "Creator is required")), R.compensation && Number.isNaN(Number(R.compensation)) && (e.compensation = "Must be a number"), V(e), Object.keys(e).length === 0;
|
|
95
|
+
}, q = j ? F : P;
|
|
96
|
+
return /* @__PURE__ */ S(t, {
|
|
97
|
+
title: j ? "Edit collaboration" : "New collaboration",
|
|
98
|
+
description: j ? "Update the brief, terms and dates" : "Propose a brand × creator partnership",
|
|
99
|
+
actions: /* @__PURE__ */ C("button", {
|
|
55
100
|
type: "button",
|
|
56
|
-
onClick: () =>
|
|
101
|
+
onClick: () => M(j && A ? `/collaborations/${A}` : "/collaborations"),
|
|
57
102
|
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",
|
|
58
|
-
children: [/* @__PURE__ */
|
|
103
|
+
children: [/* @__PURE__ */ S(_, { className: "h-4 w-4" }), " Cancel"]
|
|
59
104
|
}),
|
|
60
|
-
children: /* @__PURE__ */
|
|
105
|
+
children: /* @__PURE__ */ S("form", {
|
|
61
106
|
onSubmit: (e) => {
|
|
62
|
-
e.preventDefault(),
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
107
|
+
if (e.preventDefault(), K()) {
|
|
108
|
+
if (j && A) {
|
|
109
|
+
F.mutate({
|
|
110
|
+
id: A,
|
|
111
|
+
input: {
|
|
112
|
+
title: R.title.trim(),
|
|
113
|
+
brief: R.brief.trim() || void 0,
|
|
114
|
+
role: R.role,
|
|
115
|
+
compensation: R.compensation ? Number(R.compensation) : void 0,
|
|
116
|
+
currency: R.currency.trim() || void 0,
|
|
117
|
+
tags: c(R.tags),
|
|
118
|
+
startDate: D(R.startDate),
|
|
119
|
+
endDate: D(R.endDate)
|
|
120
|
+
}
|
|
121
|
+
}, { onSuccess: (e) => M(`/collaborations/${e.id}`) });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
P.mutate({
|
|
125
|
+
brandId: R.brandId,
|
|
126
|
+
creatorId: R.creatorId.trim(),
|
|
127
|
+
title: R.title.trim(),
|
|
128
|
+
brief: R.brief.trim() || void 0,
|
|
129
|
+
role: R.role,
|
|
130
|
+
compensation: R.compensation ? Number(R.compensation) : void 0,
|
|
131
|
+
currency: R.currency.trim() || void 0,
|
|
132
|
+
tags: c(R.tags),
|
|
133
|
+
startDate: D(R.startDate),
|
|
134
|
+
endDate: D(R.endDate)
|
|
135
|
+
}, { onSuccess: (e) => M(`/collaborations/${e.id}`) });
|
|
136
|
+
}
|
|
74
137
|
},
|
|
75
138
|
className: "mx-auto max-w-2xl",
|
|
76
|
-
children: /* @__PURE__ */
|
|
139
|
+
children: /* @__PURE__ */ C(w, {
|
|
77
140
|
treatment: "plain",
|
|
78
141
|
className: "p-6",
|
|
79
142
|
children: [
|
|
80
|
-
/* @__PURE__ */
|
|
143
|
+
/* @__PURE__ */ C("div", {
|
|
81
144
|
className: "mb-6 flex items-center gap-3",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
145
|
+
children: [/* @__PURE__ */ S("div", {
|
|
83
146
|
className: "flex h-11 w-11 items-center justify-center rounded-lg bg-status-warning-bg-subtle text-status-warning-text",
|
|
84
|
-
children: /* @__PURE__ */
|
|
85
|
-
}), /* @__PURE__ */
|
|
147
|
+
children: /* @__PURE__ */ S(v, { className: "h-5 w-5" })
|
|
148
|
+
}), /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("h2", {
|
|
86
149
|
className: "text-base font-semibold text-text-primary",
|
|
87
150
|
children: "Collaboration details"
|
|
88
|
-
}), /* @__PURE__ */
|
|
151
|
+
}), /* @__PURE__ */ S("p", {
|
|
89
152
|
className: "text-xs text-text-secondary",
|
|
90
|
-
children: "Created in the Proposed state."
|
|
153
|
+
children: j ? "Brand and creator cannot be changed after proposal." : "Created in the Proposed state."
|
|
91
154
|
})] })]
|
|
92
155
|
}),
|
|
93
|
-
/* @__PURE__ */
|
|
156
|
+
G && /* @__PURE__ */ C("p", {
|
|
157
|
+
className: "mb-4 rounded-lg bg-status-warning-bg-subtle px-3 py-2 text-sm text-status-warning-text",
|
|
158
|
+
children: [
|
|
159
|
+
"This collaboration is ",
|
|
160
|
+
L.data?.status.toLowerCase(),
|
|
161
|
+
" and can no longer be edited."
|
|
162
|
+
]
|
|
163
|
+
}),
|
|
164
|
+
/* @__PURE__ */ C("div", {
|
|
94
165
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
95
|
-
children: [/* @__PURE__ */
|
|
166
|
+
children: [j ? /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("span", {
|
|
167
|
+
className: "mb-1.5 block text-sm font-medium text-text-primary",
|
|
168
|
+
children: "Brand"
|
|
169
|
+
}), /* @__PURE__ */ S("p", {
|
|
170
|
+
className: "rounded-lg border border-border-seam bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
|
|
171
|
+
children: L.data?.brand?.name ?? R.brandId
|
|
172
|
+
})] }) : /* @__PURE__ */ S(d, {
|
|
96
173
|
id: "brandId",
|
|
97
174
|
label: "Brand",
|
|
98
|
-
value:
|
|
99
|
-
onChange: (e) =>
|
|
100
|
-
options:
|
|
175
|
+
value: R.brandId,
|
|
176
|
+
onChange: (e) => H("brandId", e),
|
|
177
|
+
options: U,
|
|
101
178
|
required: !0,
|
|
102
|
-
placeholder:
|
|
103
|
-
error:
|
|
104
|
-
}), /* @__PURE__ */
|
|
179
|
+
placeholder: I.isLoading ? "Loading brands…" : "Select a brand",
|
|
180
|
+
error: B.brandId
|
|
181
|
+
}), /* @__PURE__ */ S(d, {
|
|
105
182
|
id: "role",
|
|
106
183
|
label: "Role",
|
|
107
|
-
value:
|
|
108
|
-
onChange: (e) =>
|
|
109
|
-
options:
|
|
184
|
+
value: R.role,
|
|
185
|
+
onChange: (e) => H("role", e),
|
|
186
|
+
options: W,
|
|
187
|
+
disabled: G
|
|
110
188
|
})]
|
|
111
189
|
}),
|
|
112
|
-
/* @__PURE__ */
|
|
190
|
+
/* @__PURE__ */ S(p, {
|
|
113
191
|
id: "title",
|
|
114
192
|
label: "Title",
|
|
115
|
-
value:
|
|
116
|
-
onChange: (e) =>
|
|
193
|
+
value: R.title,
|
|
194
|
+
onChange: (e) => H("title", e),
|
|
117
195
|
placeholder: "Summer capsule edit",
|
|
118
196
|
required: !0,
|
|
119
|
-
error:
|
|
120
|
-
className: "mt-4"
|
|
197
|
+
error: B.title,
|
|
198
|
+
className: "mt-4",
|
|
199
|
+
disabled: G
|
|
121
200
|
}),
|
|
122
|
-
/* @__PURE__ */
|
|
201
|
+
j ? /* @__PURE__ */ C("div", {
|
|
202
|
+
className: "mt-4",
|
|
203
|
+
children: [/* @__PURE__ */ S("span", {
|
|
204
|
+
className: "mb-1.5 block text-sm font-medium text-text-primary",
|
|
205
|
+
children: "Creator"
|
|
206
|
+
}), /* @__PURE__ */ S("p", {
|
|
207
|
+
className: "rounded-lg border border-border-seam bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
|
|
208
|
+
children: /* @__PURE__ */ S(u, { id: R.creatorId })
|
|
209
|
+
})]
|
|
210
|
+
}) : /* @__PURE__ */ S(p, {
|
|
123
211
|
id: "creatorId",
|
|
124
212
|
label: "Creator ID",
|
|
125
|
-
value:
|
|
126
|
-
onChange: (e) =>
|
|
213
|
+
value: R.creatorId,
|
|
214
|
+
onChange: (e) => H("creatorId", e),
|
|
127
215
|
placeholder: "creator user id",
|
|
128
216
|
required: !0,
|
|
129
217
|
hint: "Defaults to you. Paste another user's id to credit a different creator.",
|
|
130
|
-
error:
|
|
218
|
+
error: B.creatorId,
|
|
131
219
|
className: "mt-4"
|
|
132
220
|
}),
|
|
133
|
-
/* @__PURE__ */
|
|
221
|
+
/* @__PURE__ */ S(f, {
|
|
134
222
|
id: "brief",
|
|
135
223
|
label: "Brief",
|
|
136
|
-
value:
|
|
137
|
-
onChange: (e) =>
|
|
224
|
+
value: R.brief,
|
|
225
|
+
onChange: (e) => H("brief", e),
|
|
138
226
|
placeholder: "What is this collaboration about…",
|
|
139
227
|
rows: 4,
|
|
140
|
-
className: "mt-4"
|
|
228
|
+
className: "mt-4",
|
|
229
|
+
disabled: G
|
|
141
230
|
}),
|
|
142
|
-
/* @__PURE__ */
|
|
231
|
+
/* @__PURE__ */ C("div", {
|
|
143
232
|
className: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
144
|
-
children: [/* @__PURE__ */
|
|
233
|
+
children: [/* @__PURE__ */ S(p, {
|
|
145
234
|
id: "compensation",
|
|
146
235
|
label: "Compensation",
|
|
147
236
|
type: "number",
|
|
148
|
-
value:
|
|
149
|
-
onChange: (e) =>
|
|
237
|
+
value: R.compensation,
|
|
238
|
+
onChange: (e) => H("compensation", e),
|
|
150
239
|
placeholder: "0.00",
|
|
151
|
-
error:
|
|
152
|
-
|
|
240
|
+
error: B.compensation,
|
|
241
|
+
disabled: G
|
|
242
|
+
}), /* @__PURE__ */ S(p, {
|
|
153
243
|
id: "currency",
|
|
154
244
|
label: "Currency",
|
|
155
|
-
value:
|
|
156
|
-
onChange: (e) =>
|
|
157
|
-
placeholder: "USD"
|
|
245
|
+
value: R.currency,
|
|
246
|
+
onChange: (e) => H("currency", e),
|
|
247
|
+
placeholder: "USD",
|
|
248
|
+
disabled: G
|
|
158
249
|
})]
|
|
159
250
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
251
|
+
/* @__PURE__ */ C("div", {
|
|
161
252
|
className: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
162
|
-
children: [/* @__PURE__ */
|
|
253
|
+
children: [/* @__PURE__ */ S(p, {
|
|
163
254
|
id: "startDate",
|
|
164
255
|
label: "Start date",
|
|
165
256
|
type: "date",
|
|
166
|
-
value:
|
|
167
|
-
onChange: (e) =>
|
|
168
|
-
|
|
257
|
+
value: R.startDate,
|
|
258
|
+
onChange: (e) => H("startDate", e),
|
|
259
|
+
disabled: G
|
|
260
|
+
}), /* @__PURE__ */ S(p, {
|
|
169
261
|
id: "endDate",
|
|
170
262
|
label: "End date",
|
|
171
263
|
type: "date",
|
|
172
|
-
value:
|
|
173
|
-
onChange: (e) =>
|
|
264
|
+
value: R.endDate,
|
|
265
|
+
onChange: (e) => H("endDate", e),
|
|
266
|
+
disabled: G
|
|
174
267
|
})]
|
|
175
268
|
}),
|
|
176
|
-
/* @__PURE__ */
|
|
269
|
+
/* @__PURE__ */ S(p, {
|
|
177
270
|
id: "tags",
|
|
178
271
|
label: "Tags",
|
|
179
|
-
value:
|
|
180
|
-
onChange: (e) =>
|
|
272
|
+
value: R.tags,
|
|
273
|
+
onChange: (e) => H("tags", e),
|
|
181
274
|
placeholder: "capsule, sustainable",
|
|
182
275
|
hint: "Comma-separated",
|
|
183
|
-
className: "mt-4"
|
|
276
|
+
className: "mt-4",
|
|
277
|
+
disabled: G
|
|
184
278
|
}),
|
|
185
|
-
|
|
279
|
+
q.isError && /* @__PURE__ */ S("p", {
|
|
186
280
|
className: "mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
|
|
187
|
-
children:
|
|
281
|
+
children: q.error instanceof Error ? q.error.message : "Something went wrong"
|
|
188
282
|
}),
|
|
189
|
-
/* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ S("div", {
|
|
190
284
|
className: "mt-6 flex justify-end gap-2",
|
|
191
|
-
children: /* @__PURE__ */
|
|
285
|
+
children: /* @__PURE__ */ C("button", {
|
|
192
286
|
type: "submit",
|
|
193
|
-
disabled:
|
|
287
|
+
disabled: q.isPending || G,
|
|
194
288
|
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",
|
|
195
|
-
children: [
|
|
289
|
+
children: [q.isPending ? /* @__PURE__ */ S(y, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ S(b, { className: "h-4 w-4" }), j ? "Save changes" : "Create collaboration"]
|
|
196
290
|
})
|
|
197
291
|
})
|
|
198
292
|
]
|
|
@@ -201,6 +295,6 @@ function b() {
|
|
|
201
295
|
});
|
|
202
296
|
}
|
|
203
297
|
//#endregion
|
|
204
|
-
export {
|
|
298
|
+
export { A as CollaborationFormPage };
|
|
205
299
|
|
|
206
300
|
//# sourceMappingURL=CollaborationFormPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollaborationFormPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/collaborations/CollaborationFormPage.tsx"],"sourcesContent":["/**\n * Collaboration Create Page\n * @module coolandlovely/pages/collaborations\n *\n * Drives `cooCreateCollaboration`. Brand and creator are required by the svc\n * input; the creator defaults to the current user (you propose as a creator)\n * but can be overridden.\n */\n\nimport { useMemo, useState } from 'react';\nimport { ArrowLeft, Loader2, Save, Handshake } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { TextField, TextAreaField, SelectField } from '../../components/Field';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useCreateCollaboration, useBrands } from '../../hooks';\nimport { parseCsv, titleCase } from '../../utils/formatters';\nimport type { CooCollaboratorRole } from '../../types';\n\nconst ROLES: CooCollaboratorRole[] = ['CREATOR', 'BRAND', 'STYLIST', 'PHOTOGRAPHER'];\n\ninterface FormState {\n brandId: string;\n creatorId: string;\n title: string;\n brief: string;\n role: CooCollaboratorRole;\n compensation: string;\n currency: string;\n tags: string;\n startDate: string;\n endDate: string;\n}\n\nfunction toIso(date: string): string | undefined {\n if (!date) return undefined;\n const d = new Date(date);\n return Number.isNaN(d.getTime()) ? undefined : d.toISOString();\n}\n\nexport function CollaborationFormPage() {\n const { navigateTo, currentUser } = useCoolAndLovely();\n const createCollaboration = useCreateCollaboration();\n const brands = useBrands({ pagination: { limit: 100, offset: 0 } });\n\n const [form, setForm] = useState<FormState>({\n brandId: '',\n creatorId: currentUser?.id ?? '',\n title: '',\n brief: '',\n role: 'CREATOR',\n compensation: '',\n currency: 'USD',\n tags: '',\n startDate: '',\n endDate: '',\n });\n const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({});\n\n const setField = <K extends keyof FormState>(key: K, value: FormState[K]) =>\n setForm((f) => ({ ...f, [key]: value }));\n\n const brandOptions = useMemo(\n () => (brands.data?.items ?? []).map((b) => ({ value: b.id, label: b.name })),\n [brands.data]\n );\n const roleOptions = ROLES.map((r) => ({ value: r, label: titleCase(r) }));\n\n const validate = (): boolean => {\n const next: Partial<Record<keyof FormState, string>> = {};\n if (!form.title.trim()) next.title = 'Title is required';\n if (!form.brandId) next.brandId = 'Brand is required';\n if (!form.creatorId.trim()) next.creatorId = 'Creator is required';\n if (form.compensation && Number.isNaN(Number(form.compensation)))\n next.compensation = 'Must be a number';\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 createCollaboration.mutate(\n {\n brandId: form.brandId,\n creatorId: form.creatorId.trim(),\n title: form.title.trim(),\n brief: form.brief.trim() || undefined,\n role: form.role,\n compensation: form.compensation ? Number(form.compensation) : undefined,\n currency: form.currency.trim() || undefined,\n tags: parseCsv(form.tags),\n startDate: toIso(form.startDate),\n endDate: toIso(form.endDate),\n },\n { onSuccess: (c) => navigateTo(`/collaborations/${c.id}`) }\n );\n };\n\n return (\n <PageLayout\n title=\"New collaboration\"\n description=\"Propose a brand × creator partnership\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/collaborations')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Cancel\n </button>\n }\n >\n <form onSubmit={handleSubmit} className=\"mx-auto max-w-2xl\">\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-11 w-11 items-center justify-center rounded-lg bg-status-warning-bg-subtle text-status-warning-text\">\n <Handshake className=\"h-5 w-5\" />\n </div>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Collaboration details</h2>\n <p className=\"text-xs text-text-secondary\">Created in the Proposed state.</p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <SelectField\n id=\"brandId\"\n label=\"Brand\"\n value={form.brandId}\n onChange={(v) => setField('brandId', v)}\n options={brandOptions}\n required\n placeholder={brands.isLoading ? 'Loading brands…' : 'Select a brand'}\n error={errors.brandId}\n />\n <SelectField\n id=\"role\"\n label=\"Role\"\n value={form.role}\n onChange={(v) => setField('role', v as CooCollaboratorRole)}\n options={roleOptions}\n />\n </div>\n\n <TextField\n id=\"title\"\n label=\"Title\"\n value={form.title}\n onChange={(v) => setField('title', v)}\n placeholder=\"Summer capsule edit\"\n required\n error={errors.title}\n className=\"mt-4\"\n />\n\n <TextField\n id=\"creatorId\"\n label=\"Creator ID\"\n value={form.creatorId}\n onChange={(v) => setField('creatorId', v)}\n placeholder=\"creator user id\"\n required\n hint=\"Defaults to you. Paste another user's id to credit a different creator.\"\n error={errors.creatorId}\n className=\"mt-4\"\n />\n\n <TextAreaField\n id=\"brief\"\n label=\"Brief\"\n value={form.brief}\n onChange={(v) => setField('brief', v)}\n placeholder=\"What is this collaboration about…\"\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=\"compensation\"\n label=\"Compensation\"\n type=\"number\"\n value={form.compensation}\n onChange={(v) => setField('compensation', v)}\n placeholder=\"0.00\"\n error={errors.compensation}\n />\n <TextField\n id=\"currency\"\n label=\"Currency\"\n value={form.currency}\n onChange={(v) => setField('currency', v)}\n placeholder=\"USD\"\n />\n </div>\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n id=\"startDate\"\n label=\"Start date\"\n type=\"date\"\n value={form.startDate}\n onChange={(v) => setField('startDate', v)}\n />\n <TextField\n id=\"endDate\"\n label=\"End date\"\n type=\"date\"\n value={form.endDate}\n onChange={(v) => setField('endDate', v)}\n />\n </div>\n\n <TextField\n id=\"tags\"\n label=\"Tags\"\n value={form.tags}\n onChange={(v) => setField('tags', v)}\n placeholder=\"capsule, sustainable\"\n hint=\"Comma-separated\"\n className=\"mt-4\"\n />\n\n {createCollaboration.isError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {createCollaboration.error instanceof Error\n ? createCollaboration.error.message\n : 'Something went wrong'}\n </p>\n )}\n\n <div className=\"mt-6 flex justify-end gap-2\">\n <button\n type=\"submit\"\n disabled={createCollaboration.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 {createCollaboration.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n Create collaboration\n </button>\n </div>\n </GlassCard>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CollaborationFormPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/collaborations/CollaborationFormPage.tsx"],"sourcesContent":["/**\n * Collaboration Create / Edit Page\n * @module coolandlovely/pages/collaborations\n *\n * Create mode drives `cooCreateCollaboration`. Edit mode (route\n * `/collaborations/:collaborationId/edit`) drives `cooUpdateCollaboration` —\n * identity (brand/creator) and status are immutable there, so those fields\n * render read-only and status transitions stay on CollaborationDetailPage.\n */\n\nimport { useEffect, useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Loader2, Save, Handshake } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { TextField, TextAreaField, SelectField } from '../../components/Field';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { ActorName } from '../../components/ActorName';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport {\n useCreateCollaboration,\n useUpdateCollaboration,\n useCollaboration,\n useBrands,\n} from '../../hooks';\nimport { parseCsv, titleCase } from '../../utils/formatters';\nimport type { CooCollaboratorRole } from '../../types';\n\nconst ROLES: CooCollaboratorRole[] = ['CREATOR', 'BRAND', 'STYLIST', 'PHOTOGRAPHER'];\n\n/** Statuses past which a collaboration's terms may no longer be edited (mirrors the svc's TERMINAL_COLLABORATION_STATUSES). */\nconst TERMINAL_STATUSES = new Set(['PUBLISHED', 'DECLINED', 'CANCELLED']);\n\ninterface FormState {\n brandId: string;\n creatorId: string;\n title: string;\n brief: string;\n role: CooCollaboratorRole;\n compensation: string;\n currency: string;\n tags: string;\n startDate: string;\n endDate: string;\n}\n\nfunction toIso(date: string): string | undefined {\n if (!date) return undefined;\n const d = new Date(date);\n return Number.isNaN(d.getTime()) ? undefined : d.toISOString();\n}\n\n/** yyyy-MM-dd for a <input type=\"date\"> from an ISO string, or '' when unset. */\nfunction toDateInput(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = new Date(iso);\n return Number.isNaN(d.getTime()) ? '' : d.toISOString().slice(0, 10);\n}\n\nconst emptyForm: FormState = {\n brandId: '',\n creatorId: '',\n title: '',\n brief: '',\n role: 'CREATOR',\n compensation: '',\n currency: 'USD',\n tags: '',\n startDate: '',\n endDate: '',\n};\n\nexport function CollaborationFormPage() {\n const { collaborationId } = useParams<{ collaborationId: string }>();\n const isEditMode = Boolean(collaborationId);\n const { navigateTo, currentUser } = useCoolAndLovely();\n const createCollaboration = useCreateCollaboration();\n const updateCollaboration = useUpdateCollaboration();\n const brands = useBrands({ pagination: { limit: 100, offset: 0 } });\n const existing = useCollaboration(isEditMode ? collaborationId : undefined);\n\n const [form, setForm] = useState<FormState>({ ...emptyForm, creatorId: currentUser?.id ?? '' });\n const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({});\n\n // Prefill the form once the existing collaboration loads (edit mode only).\n useEffect(() => {\n if (!isEditMode || !existing.data) return;\n const c = existing.data;\n setForm({\n brandId: c.brandId,\n creatorId: c.creatorId,\n title: c.title,\n brief: c.brief ?? '',\n role: c.role,\n compensation: c.compensation ? String(c.compensation) : '',\n currency: c.currency,\n tags: c.tags.join(', '),\n startDate: toDateInput(c.startDate),\n endDate: toDateInput(c.endDate),\n });\n }, [isEditMode, existing.data]);\n\n const setField = <K extends keyof FormState>(key: K, value: FormState[K]) =>\n setForm((f) => ({ ...f, [key]: value }));\n\n const brandOptions = useMemo(\n () => (brands.data?.items ?? []).map((b) => ({ value: b.id, label: b.name })),\n [brands.data]\n );\n const roleOptions = ROLES.map((r) => ({ value: r, label: titleCase(r) }));\n\n if (isEditMode && existing.isLoading) {\n return (\n <PageLayout title=\"Edit collaboration\">\n <LoadingView label=\"Loading collaboration…\" />\n </PageLayout>\n );\n }\n\n if (isEditMode && (existing.isError || !existing.data)) {\n return (\n <PageLayout title=\"Edit collaboration\">\n <ErrorView title=\"Collaboration not found\" onRetry={() => void existing.refetch()} />\n </PageLayout>\n );\n }\n\n const isTerminal =\n isEditMode && existing.data ? TERMINAL_STATUSES.has(existing.data.status) : false;\n\n const validate = (): boolean => {\n const next: Partial<Record<keyof FormState, string>> = {};\n if (!form.title.trim()) next.title = 'Title is required';\n if (!isEditMode) {\n if (!form.brandId) next.brandId = 'Brand is required';\n if (!form.creatorId.trim()) next.creatorId = 'Creator is required';\n }\n if (form.compensation && Number.isNaN(Number(form.compensation)))\n next.compensation = 'Must be a number';\n setErrors(next);\n return Object.keys(next).length === 0;\n };\n\n const mutation = isEditMode ? updateCollaboration : createCollaboration;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!validate()) return;\n\n if (isEditMode && collaborationId) {\n updateCollaboration.mutate(\n {\n id: collaborationId,\n input: {\n title: form.title.trim(),\n brief: form.brief.trim() || undefined,\n role: form.role,\n compensation: form.compensation ? Number(form.compensation) : undefined,\n currency: form.currency.trim() || undefined,\n tags: parseCsv(form.tags),\n startDate: toIso(form.startDate),\n endDate: toIso(form.endDate),\n },\n },\n { onSuccess: (c) => navigateTo(`/collaborations/${c.id}`) }\n );\n return;\n }\n\n createCollaboration.mutate(\n {\n brandId: form.brandId,\n creatorId: form.creatorId.trim(),\n title: form.title.trim(),\n brief: form.brief.trim() || undefined,\n role: form.role,\n compensation: form.compensation ? Number(form.compensation) : undefined,\n currency: form.currency.trim() || undefined,\n tags: parseCsv(form.tags),\n startDate: toIso(form.startDate),\n endDate: toIso(form.endDate),\n },\n { onSuccess: (c) => navigateTo(`/collaborations/${c.id}`) }\n );\n };\n\n return (\n <PageLayout\n title={isEditMode ? 'Edit collaboration' : 'New collaboration'}\n description={\n isEditMode ? 'Update the brief, terms and dates' : 'Propose a brand × creator partnership'\n }\n actions={\n <button\n type=\"button\"\n onClick={() =>\n navigateTo(\n isEditMode && collaborationId\n ? `/collaborations/${collaborationId}`\n : '/collaborations'\n )\n }\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Cancel\n </button>\n }\n >\n <form onSubmit={handleSubmit} className=\"mx-auto max-w-2xl\">\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-11 w-11 items-center justify-center rounded-lg bg-status-warning-bg-subtle text-status-warning-text\">\n <Handshake className=\"h-5 w-5\" />\n </div>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Collaboration details</h2>\n <p className=\"text-xs text-text-secondary\">\n {isEditMode\n ? 'Brand and creator cannot be changed after proposal.'\n : 'Created in the Proposed state.'}\n </p>\n </div>\n </div>\n\n {isTerminal && (\n <p className=\"mb-4 rounded-lg bg-status-warning-bg-subtle px-3 py-2 text-sm text-status-warning-text\">\n This collaboration is {existing.data?.status.toLowerCase()} and can no longer be\n edited.\n </p>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n {isEditMode ? (\n <div>\n <span className=\"mb-1.5 block text-sm font-medium text-text-primary\">Brand</span>\n <p className=\"rounded-lg border border-border-seam bg-bg-sunken px-3 py-2 text-sm text-text-secondary\">\n {existing.data?.brand?.name ?? form.brandId}\n </p>\n </div>\n ) : (\n <SelectField\n id=\"brandId\"\n label=\"Brand\"\n value={form.brandId}\n onChange={(v) => setField('brandId', v)}\n options={brandOptions}\n required\n placeholder={brands.isLoading ? 'Loading brands…' : 'Select a brand'}\n error={errors.brandId}\n />\n )}\n <SelectField\n id=\"role\"\n label=\"Role\"\n value={form.role}\n onChange={(v) => setField('role', v as CooCollaboratorRole)}\n options={roleOptions}\n disabled={isTerminal}\n />\n </div>\n\n <TextField\n id=\"title\"\n label=\"Title\"\n value={form.title}\n onChange={(v) => setField('title', v)}\n placeholder=\"Summer capsule edit\"\n required\n error={errors.title}\n className=\"mt-4\"\n disabled={isTerminal}\n />\n\n {isEditMode ? (\n <div className=\"mt-4\">\n <span className=\"mb-1.5 block text-sm font-medium text-text-primary\">Creator</span>\n <p className=\"rounded-lg border border-border-seam bg-bg-sunken px-3 py-2 text-sm text-text-secondary\">\n <ActorName id={form.creatorId} />\n </p>\n </div>\n ) : (\n <TextField\n id=\"creatorId\"\n label=\"Creator ID\"\n value={form.creatorId}\n onChange={(v) => setField('creatorId', v)}\n placeholder=\"creator user id\"\n required\n hint=\"Defaults to you. Paste another user's id to credit a different creator.\"\n error={errors.creatorId}\n className=\"mt-4\"\n />\n )}\n\n <TextAreaField\n id=\"brief\"\n label=\"Brief\"\n value={form.brief}\n onChange={(v) => setField('brief', v)}\n placeholder=\"What is this collaboration about…\"\n rows={4}\n className=\"mt-4\"\n disabled={isTerminal}\n />\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n id=\"compensation\"\n label=\"Compensation\"\n type=\"number\"\n value={form.compensation}\n onChange={(v) => setField('compensation', v)}\n placeholder=\"0.00\"\n error={errors.compensation}\n disabled={isTerminal}\n />\n <TextField\n id=\"currency\"\n label=\"Currency\"\n value={form.currency}\n onChange={(v) => setField('currency', v)}\n placeholder=\"USD\"\n disabled={isTerminal}\n />\n </div>\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n id=\"startDate\"\n label=\"Start date\"\n type=\"date\"\n value={form.startDate}\n onChange={(v) => setField('startDate', v)}\n disabled={isTerminal}\n />\n <TextField\n id=\"endDate\"\n label=\"End date\"\n type=\"date\"\n value={form.endDate}\n onChange={(v) => setField('endDate', v)}\n disabled={isTerminal}\n />\n </div>\n\n <TextField\n id=\"tags\"\n label=\"Tags\"\n value={form.tags}\n onChange={(v) => setField('tags', v)}\n placeholder=\"capsule, sustainable\"\n hint=\"Comma-separated\"\n className=\"mt-4\"\n disabled={isTerminal}\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 || isTerminal}\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 {isEditMode ? 'Save changes' : 'Create collaboration'}\n </button>\n </div>\n </GlassCard>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/collections/CollectionDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,wBAAgB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"CollectionDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/coolandlovely/pages/collections/CollectionDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,wBAAgB,oBAAoB,gCAgPnC"}
|