@scalemule/news-publication 0.0.48 → 0.0.50
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/README.md +54 -0
- package/dist/chunk-4JRWZXAP.js +62 -0
- package/dist/chunk-ABPJMDUG.js +251 -0
- package/dist/chunk-AFJ6S5WJ.js +124 -0
- package/dist/{chunk-GB36YM56.js → chunk-AMLVCZDP.js} +11 -1
- package/dist/chunk-QW3OZB22.js +616 -0
- package/dist/community-maps-view.d.cts +3 -3
- package/dist/community-maps-view.d.ts +3 -3
- package/dist/cookie-consent-banner.d.cts +2 -2
- package/dist/cookie-consent-banner.d.ts +2 -2
- package/dist/cookie-settings-view.d.cts +2 -2
- package/dist/cookie-settings-view.d.ts +2 -2
- package/dist/index.cjs +29 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/marketplace-forms.d.cts +3 -3
- package/dist/marketplace-forms.d.ts +3 -3
- package/dist/marketplace-view.d.cts +5 -5
- package/dist/marketplace-view.d.ts +5 -5
- package/dist/{meet-RWmfj3I3.d.cts → meet-BWpxY20X.d.ts} +5 -0
- package/dist/{meet-RWmfj3I3.d.ts → meet-CO9Unz5M.d.cts} +5 -0
- package/dist/meet-forms.d.cts +7 -6
- package/dist/meet-forms.d.ts +7 -6
- package/dist/meet-forms.js +2 -1
- package/dist/meet-view.cjs +22 -2
- package/dist/meet-view.d.cts +7 -5
- package/dist/meet-view.d.ts +7 -5
- package/dist/meet-view.js +21 -4
- package/dist/network-bar.d.cts +2 -2
- package/dist/network-bar.d.ts +2 -2
- package/dist/network-copyright.d.cts +2 -2
- package/dist/network-copyright.d.ts +2 -2
- package/dist/pets-auth-server.cjs +257 -0
- package/dist/pets-auth-server.d.cts +23 -0
- package/dist/pets-auth-server.d.ts +23 -0
- package/dist/pets-auth-server.js +198 -0
- package/dist/pets-forms.cjs +764 -0
- package/dist/pets-forms.d.cts +28 -0
- package/dist/pets-forms.d.ts +28 -0
- package/dist/pets-forms.js +714 -0
- package/dist/pets-interactions.cjs +333 -0
- package/dist/pets-interactions.d.cts +23 -0
- package/dist/pets-interactions.d.ts +23 -0
- package/dist/pets-interactions.js +320 -0
- package/dist/pets-plugin.cjs +546 -0
- package/dist/pets-plugin.d.cts +50 -0
- package/dist/pets-plugin.d.ts +50 -0
- package/dist/pets-plugin.js +312 -0
- package/dist/pets-publication.cjs +1014 -0
- package/dist/pets-publication.d.cts +40 -0
- package/dist/pets-publication.d.ts +40 -0
- package/dist/pets-publication.js +201 -0
- package/dist/pets-server.cjs +289 -0
- package/dist/pets-server.d.cts +42 -0
- package/dist/pets-server.d.ts +42 -0
- package/dist/pets-server.js +2 -0
- package/dist/pets-view.cjs +714 -0
- package/dist/pets-view.d.cts +58 -0
- package/dist/pets-view.d.ts +58 -0
- package/dist/pets-view.js +4 -0
- package/dist/pets.cjs +138 -0
- package/dist/pets.d.cts +127 -0
- package/dist/pets.d.ts +127 -0
- package/dist/pets.js +1 -0
- package/dist/sponsorship-view.d.cts +2 -2
- package/dist/sponsorship-view.d.ts +2 -2
- package/dist/sponsorship-view.js +2 -62
- package/dist/story-review.d.cts +6 -6
- package/dist/story-review.d.ts +6 -6
- package/dist/theme-toggle.d.cts +2 -2
- package/dist/theme-toggle.d.ts +2 -2
- package/dist/verified-card.d.cts +3 -3
- package/dist/verified-card.d.ts +3 -3
- package/package.json +45 -3
- package/pets.css +746 -0
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { PawMark } from './chunk-QW3OZB22.js';
|
|
3
|
+
import './chunk-4JRWZXAP.js';
|
|
4
|
+
import './chunk-66GI2IX6.js';
|
|
5
|
+
import { PET_PHOTO_CATEGORIES, PET_CELEBRATIONS, PET_SAFETY } from './chunk-AFJ6S5WJ.js';
|
|
6
|
+
import { useState, useEffect, useRef } from 'react';
|
|
7
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function localDateTime(value) {
|
|
10
|
+
const date = new Date(value);
|
|
11
|
+
if (!Number.isFinite(date.getTime())) return "";
|
|
12
|
+
return new Date(date.getTime() - date.getTimezoneOffset() * 6e4).toISOString().slice(0, 16);
|
|
13
|
+
}
|
|
14
|
+
var empty = {
|
|
15
|
+
name: "",
|
|
16
|
+
species: "Dog",
|
|
17
|
+
story: "",
|
|
18
|
+
breed: "",
|
|
19
|
+
personality: "",
|
|
20
|
+
activities: [],
|
|
21
|
+
category: "cute",
|
|
22
|
+
attribution: ""
|
|
23
|
+
};
|
|
24
|
+
async function call(url, method, data) {
|
|
25
|
+
const response = await fetch(url, {
|
|
26
|
+
method,
|
|
27
|
+
credentials: "same-origin",
|
|
28
|
+
headers: data instanceof FormData ? void 0 : { "content-type": "application/json" },
|
|
29
|
+
body: data === void 0 ? void 0 : data instanceof FormData ? data : JSON.stringify(data)
|
|
30
|
+
});
|
|
31
|
+
const body = await response.json();
|
|
32
|
+
if (!response.ok)
|
|
33
|
+
throw new Error(
|
|
34
|
+
typeof body.error === "string" ? body.error : body.error?.message || "We couldn\u2019t save this contribution. Please try again."
|
|
35
|
+
);
|
|
36
|
+
return body.data ?? body;
|
|
37
|
+
}
|
|
38
|
+
function PetSignIn({ returnTo = "/account" }) {
|
|
39
|
+
const [busy, setBusy] = useState(false), [error, setError] = useState("");
|
|
40
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
41
|
+
/* @__PURE__ */ jsx(
|
|
42
|
+
"button",
|
|
43
|
+
{
|
|
44
|
+
disabled: busy,
|
|
45
|
+
onClick: async () => {
|
|
46
|
+
setBusy(true);
|
|
47
|
+
setError("");
|
|
48
|
+
try {
|
|
49
|
+
const { url } = await call(
|
|
50
|
+
"/api/paw-auth/start?" + new URLSearchParams({ next: returnTo }),
|
|
51
|
+
"POST"
|
|
52
|
+
);
|
|
53
|
+
window.location.assign(url);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
setError(
|
|
56
|
+
e instanceof Error ? e.message : "Sign-in is unavailable."
|
|
57
|
+
);
|
|
58
|
+
setBusy(false);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
children: busy ? "Opening sign-in\u2026" : "Continue with your network sign-in"
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "paw-error", children: error }),
|
|
65
|
+
/* @__PURE__ */ jsx("p", { className: "paw-safety", children: "Your existing network sign-in works here. Public browsing is always open." })
|
|
66
|
+
] });
|
|
67
|
+
}
|
|
68
|
+
function PetSubmissionForm({
|
|
69
|
+
communities,
|
|
70
|
+
policy,
|
|
71
|
+
profiles = [],
|
|
72
|
+
initial,
|
|
73
|
+
defaultCommunity,
|
|
74
|
+
apiPath = "/api/pets",
|
|
75
|
+
accountUrl = "/account",
|
|
76
|
+
onSaved
|
|
77
|
+
}) {
|
|
78
|
+
const [deviceReady, setDeviceReady] = useState(false);
|
|
79
|
+
useEffect(() => setDeviceReady(true), []);
|
|
80
|
+
const [kind, setKind] = useState(initial?.kind || "spotlight"), [content, setContent] = useState(initial?.content || empty);
|
|
81
|
+
const [community, setCommunity] = useState(
|
|
82
|
+
initial?.area_id || defaultCommunity || ""
|
|
83
|
+
), [visibility, setVisibility] = useState(
|
|
84
|
+
initial?.visibility || "private"
|
|
85
|
+
);
|
|
86
|
+
const [profileId, setProfileId] = useState(
|
|
87
|
+
initial?.profile_id || null
|
|
88
|
+
);
|
|
89
|
+
const [files, setFiles] = useState([]);
|
|
90
|
+
const [step, setStep] = useState(0), [consent, setConsent] = useState(false), [busy, setBusy] = useState(false), [error, setError] = useState(""), [progress, setProgress] = useState(0), [saved, setSaved] = useState();
|
|
91
|
+
const receipt = useRef(
|
|
92
|
+
initial ? { id: initial.id, revision: initial.revision } : null
|
|
93
|
+
);
|
|
94
|
+
const key = useRef("");
|
|
95
|
+
const uploads = useRef(/* @__PURE__ */ new Set());
|
|
96
|
+
useEffect(
|
|
97
|
+
() => () => files.forEach((f) => URL.revokeObjectURL(f.preview)),
|
|
98
|
+
[files]
|
|
99
|
+
);
|
|
100
|
+
const change = (field, value) => setContent((previous) => ({ ...previous, [field]: value }));
|
|
101
|
+
const needsPermission = kind !== "profile" || visibility === "public" || files.length > 0;
|
|
102
|
+
async function save() {
|
|
103
|
+
setBusy(true);
|
|
104
|
+
setError("");
|
|
105
|
+
try {
|
|
106
|
+
if (!community || !content.name.trim())
|
|
107
|
+
throw new Error("Choose a community and enter your pet\u2019s name.");
|
|
108
|
+
if (needsPermission && !consent)
|
|
109
|
+
throw new Error("Read and accept the publication permission.");
|
|
110
|
+
if (["spotlight", "photo", "adoption"].includes(kind) && !files.length && !initial?.media.length)
|
|
111
|
+
throw new Error("Choose at least one authentic photograph.");
|
|
112
|
+
const permission = consent ? { version: policy.version, accepted: true } : null;
|
|
113
|
+
const input = {
|
|
114
|
+
area_id: community,
|
|
115
|
+
kind,
|
|
116
|
+
content: {
|
|
117
|
+
...content,
|
|
118
|
+
activities: content.activities.filter((v) => v.trim())
|
|
119
|
+
},
|
|
120
|
+
profile_id: kind === "profile" ? null : profileId,
|
|
121
|
+
visibility: kind === "profile" ? visibility : "public",
|
|
122
|
+
consent: permission
|
|
123
|
+
};
|
|
124
|
+
if (!key.current) key.current = crypto.randomUUID();
|
|
125
|
+
if (!receipt.current) {
|
|
126
|
+
const result2 = await call(
|
|
127
|
+
apiPath,
|
|
128
|
+
"POST",
|
|
129
|
+
{ ...input, submit: false, idempotency_key: key.current }
|
|
130
|
+
);
|
|
131
|
+
receipt.current = { id: result2.id, revision: result2.revision || 1 };
|
|
132
|
+
} else if (initial && progress === 0) {
|
|
133
|
+
const result2 = await call(
|
|
134
|
+
`${apiPath}/${receipt.current.id}`,
|
|
135
|
+
"PUT",
|
|
136
|
+
{
|
|
137
|
+
...input,
|
|
138
|
+
submit: false,
|
|
139
|
+
expected_revision: receipt.current.revision
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
receipt.current = result2;
|
|
143
|
+
}
|
|
144
|
+
setProgress(1);
|
|
145
|
+
for (const [index, photo] of files.entries()) {
|
|
146
|
+
if (!uploads.current.has(photo.key)) {
|
|
147
|
+
const form = new FormData();
|
|
148
|
+
form.set("file", photo.file);
|
|
149
|
+
form.set("caption", content.name);
|
|
150
|
+
form.set("attribution", content.attribution);
|
|
151
|
+
form.set("rights_confirmed", "true");
|
|
152
|
+
form.set("consent_version", policy.version);
|
|
153
|
+
form.set("idempotency_key", photo.key);
|
|
154
|
+
await call(
|
|
155
|
+
`${apiPath}/submissions/${receipt.current.id}/media`,
|
|
156
|
+
"POST",
|
|
157
|
+
form
|
|
158
|
+
);
|
|
159
|
+
uploads.current.add(photo.key);
|
|
160
|
+
}
|
|
161
|
+
setProgress(index + 2);
|
|
162
|
+
}
|
|
163
|
+
const result = await call(
|
|
164
|
+
`${apiPath}/${receipt.current.id}`,
|
|
165
|
+
"PUT",
|
|
166
|
+
{
|
|
167
|
+
...input,
|
|
168
|
+
submit: input.visibility === "public",
|
|
169
|
+
expected_revision: receipt.current.revision
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
receipt.current = result;
|
|
173
|
+
setSaved(result.id);
|
|
174
|
+
onSaved?.(result.id);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
setError(
|
|
177
|
+
e instanceof Error ? e.message : "We couldn\u2019t save this contribution. Please try again."
|
|
178
|
+
);
|
|
179
|
+
} finally {
|
|
180
|
+
setBusy(false);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (saved)
|
|
184
|
+
return /* @__PURE__ */ jsxs("section", { className: "paw-form", role: "status", children: [
|
|
185
|
+
/* @__PURE__ */ jsx(PawMark, { size: 56 }),
|
|
186
|
+
/* @__PURE__ */ jsx("h1", { children: kind === "profile" && visibility === "private" ? "A little home for your pet." : "Your story is in good hands." }),
|
|
187
|
+
/* @__PURE__ */ jsx("p", { children: kind === "profile" && visibility === "private" ? "Your profile is saved privately. Only you can see it." : "Your contribution is saved for editorial review. It will appear publicly only after approval." }),
|
|
188
|
+
/* @__PURE__ */ jsx("a", { href: accountUrl, children: "View your pets and submissions" })
|
|
189
|
+
] });
|
|
190
|
+
return /* @__PURE__ */ jsxs(
|
|
191
|
+
"form",
|
|
192
|
+
{
|
|
193
|
+
className: "paw-form",
|
|
194
|
+
onSubmit: (event) => {
|
|
195
|
+
event.preventDefault();
|
|
196
|
+
if (step === 0) {
|
|
197
|
+
setError("");
|
|
198
|
+
setStep(1);
|
|
199
|
+
} else void save();
|
|
200
|
+
},
|
|
201
|
+
children: [
|
|
202
|
+
/* @__PURE__ */ jsx("p", { className: "paw-context", children: step === 0 ? "Your pet\u2019s story" : "Your private preview" }),
|
|
203
|
+
/* @__PURE__ */ jsx("h1", { children: kind === "celebration" && content.category === "memorial" ? "Remember a beloved companion." : "Someone worth meeting." }),
|
|
204
|
+
/* @__PURE__ */ jsx("p", { className: "paw-safety", children: "Choose a community, never a home address. Keep phone numbers, email addresses and microchip details out of your story." }),
|
|
205
|
+
step === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
206
|
+
!initial && /* @__PURE__ */ jsxs("label", { children: [
|
|
207
|
+
"What would you like to share?",
|
|
208
|
+
/* @__PURE__ */ jsxs(
|
|
209
|
+
"select",
|
|
210
|
+
{
|
|
211
|
+
value: kind,
|
|
212
|
+
onChange: (e) => {
|
|
213
|
+
const k = e.target.value;
|
|
214
|
+
setKind(k);
|
|
215
|
+
setContent((c) => ({
|
|
216
|
+
...c,
|
|
217
|
+
source: ["event", "adoption"].includes(k) ? {
|
|
218
|
+
organization: "",
|
|
219
|
+
official_url: "",
|
|
220
|
+
availability_confirmed: false
|
|
221
|
+
} : null,
|
|
222
|
+
event: k === "event" ? {
|
|
223
|
+
starts_at: "",
|
|
224
|
+
ends_at: "",
|
|
225
|
+
event_type: "adoption",
|
|
226
|
+
cost: "unknown",
|
|
227
|
+
cost_verified: false
|
|
228
|
+
} : null
|
|
229
|
+
}));
|
|
230
|
+
change(
|
|
231
|
+
"category",
|
|
232
|
+
k === "celebration" ? "birthday" : k === "photo" ? "cute" : ""
|
|
233
|
+
);
|
|
234
|
+
},
|
|
235
|
+
children: [
|
|
236
|
+
/* @__PURE__ */ jsx("option", { value: "spotlight", children: "Paw of the Week submission" }),
|
|
237
|
+
/* @__PURE__ */ jsx("option", { value: "profile", children: "Pet profile" }),
|
|
238
|
+
/* @__PURE__ */ jsx("option", { value: "photo", children: "Photo board" }),
|
|
239
|
+
/* @__PURE__ */ jsx("option", { value: "celebration", children: "Pet celebration" }),
|
|
240
|
+
/* @__PURE__ */ jsx("option", { value: "lost", children: "Lost pet report" }),
|
|
241
|
+
/* @__PURE__ */ jsx("option", { value: "found", children: "Found pet report" }),
|
|
242
|
+
/* @__PURE__ */ jsx("option", { value: "event", children: "Organization event" }),
|
|
243
|
+
/* @__PURE__ */ jsx("option", { value: "adoption", children: "Shelter or rescue adoption listing" })
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
] }),
|
|
248
|
+
!initial && kind !== "profile" && profiles.length > 0 && /* @__PURE__ */ jsxs("label", { children: [
|
|
249
|
+
"Start with one of your pets",
|
|
250
|
+
/* @__PURE__ */ jsxs(
|
|
251
|
+
"select",
|
|
252
|
+
{
|
|
253
|
+
value: profileId || "",
|
|
254
|
+
onChange: (e) => {
|
|
255
|
+
const p = profiles.find((p2) => p2.id === e.target.value);
|
|
256
|
+
setProfileId(p?.id || null);
|
|
257
|
+
if (p) {
|
|
258
|
+
setContent({
|
|
259
|
+
...p.content,
|
|
260
|
+
category: content.category,
|
|
261
|
+
source: content.source,
|
|
262
|
+
event: content.event
|
|
263
|
+
});
|
|
264
|
+
setCommunity(p.area_id);
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
children: [
|
|
268
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Enter pet details" }),
|
|
269
|
+
profiles.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.content.name }, p.id))
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
)
|
|
273
|
+
] }),
|
|
274
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
275
|
+
kind === "event" ? "Event title" : "Pet name",
|
|
276
|
+
/* @__PURE__ */ jsx(
|
|
277
|
+
"input",
|
|
278
|
+
{
|
|
279
|
+
required: true,
|
|
280
|
+
maxLength: 100,
|
|
281
|
+
value: content.name,
|
|
282
|
+
onChange: (e) => change("name", e.target.value),
|
|
283
|
+
autoComplete: "off"
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
] }),
|
|
287
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
288
|
+
"Species",
|
|
289
|
+
/* @__PURE__ */ jsx(
|
|
290
|
+
"input",
|
|
291
|
+
{
|
|
292
|
+
required: true,
|
|
293
|
+
maxLength: 50,
|
|
294
|
+
value: content.species,
|
|
295
|
+
onChange: (e) => change("species", e.target.value)
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
] }),
|
|
299
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
300
|
+
"Home community",
|
|
301
|
+
/* @__PURE__ */ jsxs(
|
|
302
|
+
"select",
|
|
303
|
+
{
|
|
304
|
+
required: true,
|
|
305
|
+
value: community,
|
|
306
|
+
onChange: (e) => setCommunity(e.target.value),
|
|
307
|
+
children: [
|
|
308
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Choose a community" }),
|
|
309
|
+
communities.map((c) => /* @__PURE__ */ jsx("option", { value: c.id, children: c.name }, c.id))
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
] }),
|
|
314
|
+
kind === "profile" && /* @__PURE__ */ jsxs("fieldset", { children: [
|
|
315
|
+
/* @__PURE__ */ jsx("legend", { children: "A few favorite things" }),
|
|
316
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
317
|
+
"Breed or mix (optional)",
|
|
318
|
+
/* @__PURE__ */ jsx(
|
|
319
|
+
"input",
|
|
320
|
+
{
|
|
321
|
+
value: content.breed,
|
|
322
|
+
maxLength: 100,
|
|
323
|
+
onChange: (e) => change("breed", e.target.value)
|
|
324
|
+
}
|
|
325
|
+
)
|
|
326
|
+
] }),
|
|
327
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
328
|
+
"Birthday (optional)",
|
|
329
|
+
/* @__PURE__ */ jsx(
|
|
330
|
+
"input",
|
|
331
|
+
{
|
|
332
|
+
type: "date",
|
|
333
|
+
value: content.birthday || "",
|
|
334
|
+
onChange: (e) => change("birthday", e.target.value || null)
|
|
335
|
+
}
|
|
336
|
+
)
|
|
337
|
+
] }),
|
|
338
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
339
|
+
"Adoption anniversary (optional)",
|
|
340
|
+
/* @__PURE__ */ jsx(
|
|
341
|
+
"input",
|
|
342
|
+
{
|
|
343
|
+
type: "date",
|
|
344
|
+
value: content.adoption_anniversary || "",
|
|
345
|
+
onChange: (e) => change("adoption_anniversary", e.target.value || null)
|
|
346
|
+
}
|
|
347
|
+
)
|
|
348
|
+
] }),
|
|
349
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
350
|
+
"Personality",
|
|
351
|
+
/* @__PURE__ */ jsx(
|
|
352
|
+
"input",
|
|
353
|
+
{
|
|
354
|
+
maxLength: 300,
|
|
355
|
+
value: content.personality,
|
|
356
|
+
onChange: (e) => change("personality", e.target.value)
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
] }),
|
|
360
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
361
|
+
"Favorite activities, separated by commas",
|
|
362
|
+
/* @__PURE__ */ jsx(
|
|
363
|
+
"input",
|
|
364
|
+
{
|
|
365
|
+
value: content.activities.join(", "),
|
|
366
|
+
onChange: (e) => change(
|
|
367
|
+
"activities",
|
|
368
|
+
e.target.value.split(",").map((v) => v.trim()).slice(0, 8)
|
|
369
|
+
)
|
|
370
|
+
}
|
|
371
|
+
)
|
|
372
|
+
] }),
|
|
373
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
374
|
+
"Profile privacy",
|
|
375
|
+
/* @__PURE__ */ jsxs(
|
|
376
|
+
"select",
|
|
377
|
+
{
|
|
378
|
+
value: visibility,
|
|
379
|
+
onChange: (e) => setVisibility(e.target.value),
|
|
380
|
+
children: [
|
|
381
|
+
/* @__PURE__ */ jsx("option", { value: "private", children: "Private \u2014 only me" }),
|
|
382
|
+
/* @__PURE__ */ jsx("option", { value: "public", children: "Public \u2014 after editorial review" })
|
|
383
|
+
]
|
|
384
|
+
}
|
|
385
|
+
)
|
|
386
|
+
] })
|
|
387
|
+
] }),
|
|
388
|
+
(kind === "photo" || kind === "celebration") && /* @__PURE__ */ jsxs("label", { children: [
|
|
389
|
+
kind === "photo" ? "Photo category" : "Celebration",
|
|
390
|
+
/* @__PURE__ */ jsx(
|
|
391
|
+
"select",
|
|
392
|
+
{
|
|
393
|
+
value: content.category,
|
|
394
|
+
onChange: (e) => change("category", e.target.value),
|
|
395
|
+
children: (kind === "photo" ? PET_PHOTO_CATEGORIES : PET_CELEBRATIONS).map(([value, label]) => /* @__PURE__ */ jsx("option", { value, children: label }, value))
|
|
396
|
+
}
|
|
397
|
+
)
|
|
398
|
+
] }),
|
|
399
|
+
["lost", "found", "celebration"].includes(kind) && /* @__PURE__ */ jsxs("label", { children: [
|
|
400
|
+
kind === "lost" ? "Date last seen" : kind === "found" ? "Date found" : "Celebration date (optional)",
|
|
401
|
+
/* @__PURE__ */ jsx(
|
|
402
|
+
"input",
|
|
403
|
+
{
|
|
404
|
+
required: kind !== "celebration",
|
|
405
|
+
type: "date",
|
|
406
|
+
value: content.date || "",
|
|
407
|
+
onChange: (e) => change("date", e.target.value || null)
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
] }),
|
|
411
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
412
|
+
kind === "profile" ? "A little biography" : "Your story",
|
|
413
|
+
/* @__PURE__ */ jsx(
|
|
414
|
+
"textarea",
|
|
415
|
+
{
|
|
416
|
+
required: kind !== "profile",
|
|
417
|
+
maxLength: 4e3,
|
|
418
|
+
value: content.story,
|
|
419
|
+
onChange: (e) => change("story", e.target.value)
|
|
420
|
+
}
|
|
421
|
+
)
|
|
422
|
+
] }),
|
|
423
|
+
kind === "adoption" && /* @__PURE__ */ jsxs("label", { children: [
|
|
424
|
+
"Approximate age (optional)",
|
|
425
|
+
/* @__PURE__ */ jsx(
|
|
426
|
+
"input",
|
|
427
|
+
{
|
|
428
|
+
value: content.age_description || "",
|
|
429
|
+
maxLength: 80,
|
|
430
|
+
onChange: (e) => change("age_description", e.target.value)
|
|
431
|
+
}
|
|
432
|
+
)
|
|
433
|
+
] }),
|
|
434
|
+
content.source && /* @__PURE__ */ jsxs("fieldset", { children: [
|
|
435
|
+
/* @__PURE__ */ jsx("legend", { children: "Official organization and source" }),
|
|
436
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
437
|
+
"Organization name",
|
|
438
|
+
/* @__PURE__ */ jsx(
|
|
439
|
+
"input",
|
|
440
|
+
{
|
|
441
|
+
required: true,
|
|
442
|
+
maxLength: 200,
|
|
443
|
+
value: content.source.organization,
|
|
444
|
+
onChange: (e) => change("source", {
|
|
445
|
+
...content.source,
|
|
446
|
+
organization: e.target.value
|
|
447
|
+
})
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
] }),
|
|
451
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
452
|
+
"Official listing or registration link",
|
|
453
|
+
/* @__PURE__ */ jsx(
|
|
454
|
+
"input",
|
|
455
|
+
{
|
|
456
|
+
required: true,
|
|
457
|
+
type: "url",
|
|
458
|
+
pattern: "https://.*",
|
|
459
|
+
value: content.source.official_url,
|
|
460
|
+
onChange: (e) => change("source", {
|
|
461
|
+
...content.source,
|
|
462
|
+
official_url: e.target.value
|
|
463
|
+
})
|
|
464
|
+
}
|
|
465
|
+
)
|
|
466
|
+
] }),
|
|
467
|
+
/* @__PURE__ */ jsx("p", { children: "Editors verify the organization, permission to use photographs, and listing information. Availability and event costs are never assumed." })
|
|
468
|
+
] }),
|
|
469
|
+
content.event && /* @__PURE__ */ jsxs("fieldset", { children: [
|
|
470
|
+
/* @__PURE__ */ jsx("legend", { children: "Event schedule" }),
|
|
471
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
472
|
+
"Enter times in your device\u2019s timezone (",
|
|
473
|
+
deviceReady ? Intl.DateTimeFormat().resolvedOptions().timeZone : "your device timezone",
|
|
474
|
+
"). They display in Pacific time."
|
|
475
|
+
] }),
|
|
476
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
477
|
+
"Starts",
|
|
478
|
+
/* @__PURE__ */ jsx(
|
|
479
|
+
"input",
|
|
480
|
+
{
|
|
481
|
+
type: "datetime-local",
|
|
482
|
+
required: true,
|
|
483
|
+
value: deviceReady ? localDateTime(content.event.starts_at) : "",
|
|
484
|
+
onChange: (e) => {
|
|
485
|
+
if (e.target.value)
|
|
486
|
+
change("event", {
|
|
487
|
+
...content.event,
|
|
488
|
+
starts_at: new Date(e.target.value).toISOString()
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
)
|
|
493
|
+
] }),
|
|
494
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
495
|
+
"Ends",
|
|
496
|
+
/* @__PURE__ */ jsx(
|
|
497
|
+
"input",
|
|
498
|
+
{
|
|
499
|
+
type: "datetime-local",
|
|
500
|
+
required: true,
|
|
501
|
+
value: deviceReady ? localDateTime(content.event.ends_at) : "",
|
|
502
|
+
onChange: (e) => {
|
|
503
|
+
if (e.target.value)
|
|
504
|
+
change("event", {
|
|
505
|
+
...content.event,
|
|
506
|
+
ends_at: new Date(e.target.value).toISOString()
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
)
|
|
511
|
+
] }),
|
|
512
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
513
|
+
"Event type",
|
|
514
|
+
/* @__PURE__ */ jsx(
|
|
515
|
+
"select",
|
|
516
|
+
{
|
|
517
|
+
value: content.event.event_type,
|
|
518
|
+
onChange: (e) => change("event", {
|
|
519
|
+
...content.event,
|
|
520
|
+
event_type: e.target.value
|
|
521
|
+
}),
|
|
522
|
+
children: [
|
|
523
|
+
"adoption",
|
|
524
|
+
"veterinary",
|
|
525
|
+
"vaccination",
|
|
526
|
+
"walk",
|
|
527
|
+
"festival",
|
|
528
|
+
"fundraiser",
|
|
529
|
+
"workshop",
|
|
530
|
+
"celebration"
|
|
531
|
+
].map((type) => /* @__PURE__ */ jsx("option", { value: type, children: type }, type))
|
|
532
|
+
}
|
|
533
|
+
)
|
|
534
|
+
] }),
|
|
535
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
536
|
+
"Reported cost",
|
|
537
|
+
/* @__PURE__ */ jsxs(
|
|
538
|
+
"select",
|
|
539
|
+
{
|
|
540
|
+
value: content.event.cost,
|
|
541
|
+
onChange: (e) => change("event", {
|
|
542
|
+
...content.event,
|
|
543
|
+
cost: e.target.value
|
|
544
|
+
}),
|
|
545
|
+
children: [
|
|
546
|
+
/* @__PURE__ */ jsx("option", { value: "unknown", children: "Check with organization" }),
|
|
547
|
+
/* @__PURE__ */ jsx("option", { value: "free", children: "Submitted as free \u2014 requires verification" }),
|
|
548
|
+
/* @__PURE__ */ jsx("option", { value: "paid", children: "Paid registration" })
|
|
549
|
+
]
|
|
550
|
+
}
|
|
551
|
+
)
|
|
552
|
+
] })
|
|
553
|
+
] }),
|
|
554
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
555
|
+
"Your public photo credit",
|
|
556
|
+
/* @__PURE__ */ jsx(
|
|
557
|
+
"input",
|
|
558
|
+
{
|
|
559
|
+
maxLength: 100,
|
|
560
|
+
value: content.attribution,
|
|
561
|
+
onChange: (e) => change("attribution", e.target.value),
|
|
562
|
+
placeholder: "Name you want published"
|
|
563
|
+
}
|
|
564
|
+
)
|
|
565
|
+
] }),
|
|
566
|
+
initial?.media.map((photo) => /* @__PURE__ */ jsxs("figure", { className: "paw-photo", children: [
|
|
567
|
+
/* @__PURE__ */ jsx(
|
|
568
|
+
"img",
|
|
569
|
+
{
|
|
570
|
+
src: `${apiPath}/submissions/${initial.id}/media/${photo.id}`,
|
|
571
|
+
alt: photo.caption || content.name,
|
|
572
|
+
width: 640,
|
|
573
|
+
height: 480
|
|
574
|
+
}
|
|
575
|
+
),
|
|
576
|
+
/* @__PURE__ */ jsx("figcaption", { children: photo.attribution })
|
|
577
|
+
] }, photo.id)),
|
|
578
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
579
|
+
"Authentic photographs",
|
|
580
|
+
/* @__PURE__ */ jsx(
|
|
581
|
+
"input",
|
|
582
|
+
{
|
|
583
|
+
type: "file",
|
|
584
|
+
accept: "image/jpeg,image/png,image/webp",
|
|
585
|
+
multiple: true,
|
|
586
|
+
onChange: (e) => {
|
|
587
|
+
const selected = Array.from(e.target.files || []);
|
|
588
|
+
if (selected.length + (initial?.media.length || 0) > 10 || selected.some((f) => f.size > 8 * 1024 * 1024)) {
|
|
589
|
+
setError(
|
|
590
|
+
"Choose up to ten JPEG, PNG or WebP photographs, each under 8 MB."
|
|
591
|
+
);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
setError("");
|
|
595
|
+
setFiles(
|
|
596
|
+
selected.map((file) => ({
|
|
597
|
+
file,
|
|
598
|
+
key: crypto.randomUUID(),
|
|
599
|
+
preview: URL.createObjectURL(file)
|
|
600
|
+
}))
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
)
|
|
605
|
+
] }),
|
|
606
|
+
/* @__PURE__ */ jsx("small", { children: "JPEG, PNG or WebP, up to 8 MB each. Photos are checked before publication and location metadata is removed." }),
|
|
607
|
+
["lost", "found"].includes(kind) && /* @__PURE__ */ jsxs("p", { className: "paw-safety", children: [
|
|
608
|
+
PET_SAFETY.recovery,
|
|
609
|
+
" Private recovery contact is not available yet."
|
|
610
|
+
] })
|
|
611
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
612
|
+
/* @__PURE__ */ jsxs(
|
|
613
|
+
"article",
|
|
614
|
+
{
|
|
615
|
+
className: content.category === "memorial" ? "paw-memorial" : "",
|
|
616
|
+
children: [
|
|
617
|
+
/* @__PURE__ */ jsx("p", { className: "paw-context", children: communities.find((c) => c.id === community)?.name }),
|
|
618
|
+
/* @__PURE__ */ jsx("h2", { children: content.name }),
|
|
619
|
+
!files.length && initial?.media[0] && /* @__PURE__ */ jsxs("figure", { className: "paw-photo", children: [
|
|
620
|
+
/* @__PURE__ */ jsx(
|
|
621
|
+
"img",
|
|
622
|
+
{
|
|
623
|
+
src: `${apiPath}/submissions/${initial.id}/media/${initial.media[0].id}`,
|
|
624
|
+
alt: initial.media[0].caption || content.name,
|
|
625
|
+
width: 800,
|
|
626
|
+
height: 600
|
|
627
|
+
}
|
|
628
|
+
),
|
|
629
|
+
/* @__PURE__ */ jsx("figcaption", { children: initial.media[0].attribution })
|
|
630
|
+
] }),
|
|
631
|
+
files[0] && /* @__PURE__ */ jsxs("figure", { className: "paw-photo", children: [
|
|
632
|
+
/* @__PURE__ */ jsx(
|
|
633
|
+
"img",
|
|
634
|
+
{
|
|
635
|
+
src: files[0].preview,
|
|
636
|
+
alt: `Private preview of ${content.name}`,
|
|
637
|
+
width: 800,
|
|
638
|
+
height: 600
|
|
639
|
+
}
|
|
640
|
+
),
|
|
641
|
+
/* @__PURE__ */ jsx("figcaption", { children: content.attribution })
|
|
642
|
+
] }),
|
|
643
|
+
/* @__PURE__ */ jsx("p", { style: { whiteSpace: "pre-wrap" }, children: content.story })
|
|
644
|
+
]
|
|
645
|
+
}
|
|
646
|
+
),
|
|
647
|
+
/* @__PURE__ */ jsx("p", { children: kind === "profile" && visibility === "private" ? "This profile will remain private." : "This is a private preview. Editors will review your contribution before anyone else can see it." }),
|
|
648
|
+
needsPermission && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
649
|
+
/* @__PURE__ */ jsxs("details", { children: [
|
|
650
|
+
/* @__PURE__ */ jsx("summary", { children: "Publication permission and guidelines" }),
|
|
651
|
+
/* @__PURE__ */ jsx("p", { children: policy.text }),
|
|
652
|
+
/* @__PURE__ */ jsx("p", { children: policy.guidelines })
|
|
653
|
+
] }),
|
|
654
|
+
/* @__PURE__ */ jsxs("label", { className: "paw-consent", children: [
|
|
655
|
+
/* @__PURE__ */ jsx(
|
|
656
|
+
"input",
|
|
657
|
+
{
|
|
658
|
+
type: "checkbox",
|
|
659
|
+
required: true,
|
|
660
|
+
checked: consent,
|
|
661
|
+
onChange: (e) => setConsent(e.target.checked)
|
|
662
|
+
}
|
|
663
|
+
),
|
|
664
|
+
/* @__PURE__ */ jsx("span", { children: "I have read and accept the publication permission. These are authentic photographs I have permission to share." })
|
|
665
|
+
] })
|
|
666
|
+
] })
|
|
667
|
+
] }),
|
|
668
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "paw-error", children: error }),
|
|
669
|
+
busy && /* @__PURE__ */ jsxs("label", { children: [
|
|
670
|
+
"Saving your contribution",
|
|
671
|
+
/* @__PURE__ */ jsx("progress", { value: progress, max: files.length + 2 })
|
|
672
|
+
] }),
|
|
673
|
+
/* @__PURE__ */ jsxs("div", { className: "paw-form-actions", children: [
|
|
674
|
+
step === 1 && /* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: () => setStep(0), children: "Keep editing" }),
|
|
675
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, type: "submit", children: busy ? "Saving\u2026" : step === 0 ? "Preview your story" : kind === "profile" && visibility === "private" ? "Save private profile" : "Submit for editorial review" })
|
|
676
|
+
] })
|
|
677
|
+
]
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
function PetOwnerActions({
|
|
682
|
+
resource,
|
|
683
|
+
apiPath = "/api/pets",
|
|
684
|
+
submitUrl = "/submit"
|
|
685
|
+
}) {
|
|
686
|
+
const [error, setError] = useState(""), [confirm, setConfirm] = useState(false), [busy, setBusy] = useState(false);
|
|
687
|
+
async function act(action) {
|
|
688
|
+
setBusy(true);
|
|
689
|
+
setError("");
|
|
690
|
+
try {
|
|
691
|
+
await call(
|
|
692
|
+
`${apiPath}/${resource.id}${action === "reunited" ? "/reunited" : ""}`,
|
|
693
|
+
action === "delete" ? "DELETE" : "POST",
|
|
694
|
+
{ expected_revision: resource.revision }
|
|
695
|
+
);
|
|
696
|
+
window.location.reload();
|
|
697
|
+
} catch (e) {
|
|
698
|
+
setError(e instanceof Error ? e.message : "Please try again.");
|
|
699
|
+
setBusy(false);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return /* @__PURE__ */ jsxs("div", { className: "paw-form-actions", children: [
|
|
703
|
+
/* @__PURE__ */ jsx("a", { href: `${submitUrl}?edit=${resource.id}`, children: "Edit details or privacy" }),
|
|
704
|
+
["lost", "found"].includes(resource.kind) && !resource.reunited_at && /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => void act("reunited"), children: "Mark reunited" }),
|
|
705
|
+
confirm ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
706
|
+
/* @__PURE__ */ jsx("span", { children: "Remove this contribution and its public photographs?" }),
|
|
707
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => void act("delete"), children: "Yes, remove" }),
|
|
708
|
+
/* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setConfirm(false), children: "Keep it" })
|
|
709
|
+
] }) : /* @__PURE__ */ jsx("button", { disabled: busy, onClick: () => setConfirm(true), children: "Delete" }),
|
|
710
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", children: error })
|
|
711
|
+
] });
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
export { PetOwnerActions, PetSignIn, PetSubmissionForm };
|