@scalemule/news-publication 0.0.53 → 0.0.56
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/{chunk-KNO2LIDQ.js → chunk-ZALGE4PF.js} +43 -72
- package/dist/pets-forms.cjs +657 -492
- package/dist/pets-forms.js +640 -479
- package/dist/pets-plugin.cjs +9 -1
- package/dist/pets-plugin.js +10 -2
- package/dist/pets-publication.cjs +43 -311
- package/dist/pets-publication.js +1 -1
- package/dist/pets-view.cjs +43 -72
- package/dist/pets-view.js +1 -1
- package/images/README.md +8 -0
- package/images/paw-neighborhood-mobile.webp +0 -0
- package/package.json +3 -2
- package/pets.css +650 -100
- package/tokens/broadsheet.css +34 -0
package/dist/pets-forms.cjs
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var React = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
|
+
|
|
7
11
|
// src/pets.ts
|
|
8
12
|
var PET_PHOTO_CATEGORIES = [
|
|
9
13
|
["cute", "Cute pets"],
|
|
@@ -141,7 +145,7 @@ async function call(url, method, data) {
|
|
|
141
145
|
return body.data ?? body;
|
|
142
146
|
}
|
|
143
147
|
function PetSignIn({ returnTo = "/account" }) {
|
|
144
|
-
const [busy, setBusy] =
|
|
148
|
+
const [busy, setBusy] = React.useState(false), [error, setError] = React.useState("");
|
|
145
149
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
146
150
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
147
151
|
"button",
|
|
@@ -170,6 +174,56 @@ function PetSignIn({ returnTo = "/account" }) {
|
|
|
170
174
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-safety", children: "Your existing network sign-in works here. Public browsing is always open." })
|
|
171
175
|
] });
|
|
172
176
|
}
|
|
177
|
+
var FieldErrors = React.createContext({ errors: {}, clear: () => {
|
|
178
|
+
} });
|
|
179
|
+
function PetField({
|
|
180
|
+
children,
|
|
181
|
+
className = ""
|
|
182
|
+
}) {
|
|
183
|
+
const id = React.useId();
|
|
184
|
+
const { errors, clear } = React.useContext(FieldErrors);
|
|
185
|
+
const error = errors[id];
|
|
186
|
+
const nodes = React__default.default.Children.toArray(children);
|
|
187
|
+
const label = nodes.filter((node) => typeof node === "string").join(" ").trim();
|
|
188
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: `paw-field ${className}`, htmlFor: id, children: [
|
|
189
|
+
nodes.map((node) => {
|
|
190
|
+
if (!React__default.default.isValidElement(node) || !["input", "select", "textarea", "progress"].includes(
|
|
191
|
+
String(node.type)
|
|
192
|
+
))
|
|
193
|
+
return node;
|
|
194
|
+
const original = node.props.onChange;
|
|
195
|
+
return React__default.default.cloneElement(node, {
|
|
196
|
+
id,
|
|
197
|
+
"data-field-label": label,
|
|
198
|
+
"aria-invalid": error ? true : void 0,
|
|
199
|
+
"aria-describedby": [node.props["aria-describedby"], error ? `${id}-error` : void 0].filter(Boolean).join(" ") || void 0,
|
|
200
|
+
onChange: (event) => {
|
|
201
|
+
clear(id);
|
|
202
|
+
original?.(event);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}),
|
|
206
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "paw-field-error", id: `${id}-error`, children: error })
|
|
207
|
+
] });
|
|
208
|
+
}
|
|
209
|
+
function fieldMessage(control, blank = false) {
|
|
210
|
+
const label = control.dataset.fieldLabel || "this field";
|
|
211
|
+
if (control.validity.valueMissing || blank) {
|
|
212
|
+
if (control instanceof HTMLInputElement && control.type === "checkbox")
|
|
213
|
+
return "Accept the publication permission to continue.";
|
|
214
|
+
if (control instanceof HTMLInputElement && control.type === "file")
|
|
215
|
+
return "Add at least one photograph of your pet.";
|
|
216
|
+
if (label === "Pet name") return "Add your pet\u2019s name.";
|
|
217
|
+
if (label === "Home community") return "Choose your home community.";
|
|
218
|
+
if (label === "Your story") return "Tell us a little about your pet.";
|
|
219
|
+
return `Add ${label.toLowerCase()} to continue.`;
|
|
220
|
+
}
|
|
221
|
+
if (control.validity.typeMismatch || control.validity.patternMismatch)
|
|
222
|
+
return "Enter a complete, valid link, including https://.";
|
|
223
|
+
if (control.validity.rangeUnderflow || control.validity.rangeOverflow)
|
|
224
|
+
return "Choose a value within the allowed range.";
|
|
225
|
+
return `Check ${label.toLowerCase()} and try again.`;
|
|
226
|
+
}
|
|
173
227
|
function PetSubmissionForm({
|
|
174
228
|
communities,
|
|
175
229
|
policy,
|
|
@@ -180,25 +234,27 @@ function PetSubmissionForm({
|
|
|
180
234
|
accountUrl = "/account",
|
|
181
235
|
onSaved
|
|
182
236
|
}) {
|
|
183
|
-
const [
|
|
184
|
-
|
|
185
|
-
const [
|
|
186
|
-
|
|
237
|
+
const [fieldErrors, setFieldErrors] = React.useState({});
|
|
238
|
+
const formRef = React.useRef(null);
|
|
239
|
+
const [deviceReady, setDeviceReady] = React.useState(false);
|
|
240
|
+
React.useEffect(() => setDeviceReady(true), []);
|
|
241
|
+
const [kind, setKind] = React.useState(initial?.kind || "spotlight"), [content, setContent] = React.useState(initial?.content || empty);
|
|
242
|
+
const [community, setCommunity] = React.useState(
|
|
187
243
|
initial?.area_id || defaultCommunity || ""
|
|
188
|
-
), [visibility, setVisibility] =
|
|
244
|
+
), [visibility, setVisibility] = React.useState(
|
|
189
245
|
initial?.visibility || "private"
|
|
190
246
|
);
|
|
191
|
-
const [profileId, setProfileId] =
|
|
247
|
+
const [profileId, setProfileId] = React.useState(
|
|
192
248
|
initial?.profile_id || null
|
|
193
249
|
);
|
|
194
|
-
const [files, setFiles] =
|
|
195
|
-
const [step, setStep] =
|
|
196
|
-
const receipt =
|
|
250
|
+
const [files, setFiles] = React.useState([]);
|
|
251
|
+
const [step, setStep] = React.useState(0), [consent, setConsent] = React.useState(false), [busy, setBusy] = React.useState(false), [error, setError] = React.useState(""), [progress, setProgress] = React.useState(0), [saved, setSaved] = React.useState();
|
|
252
|
+
const receipt = React.useRef(
|
|
197
253
|
initial ? { id: initial.id, revision: initial.revision } : null
|
|
198
254
|
);
|
|
199
|
-
const key =
|
|
200
|
-
const uploads =
|
|
201
|
-
|
|
255
|
+
const key = React.useRef("");
|
|
256
|
+
const uploads = React.useRef(/* @__PURE__ */ new Set());
|
|
257
|
+
React.useEffect(
|
|
202
258
|
() => () => files.forEach((f) => URL.revokeObjectURL(f.preview)),
|
|
203
259
|
[files]
|
|
204
260
|
);
|
|
@@ -292,499 +348,608 @@ function PetSubmissionForm({
|
|
|
292
348
|
/* @__PURE__ */ jsxRuntime.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." }),
|
|
293
349
|
/* @__PURE__ */ jsxRuntime.jsx("a", { href: accountUrl, children: "View your pets and submissions" })
|
|
294
350
|
] });
|
|
295
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
296
|
-
|
|
351
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
352
|
+
FieldErrors.Provider,
|
|
297
353
|
{
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
354
|
+
value: {
|
|
355
|
+
errors: fieldErrors,
|
|
356
|
+
clear: (id) => setFieldErrors((old) => {
|
|
357
|
+
const next = { ...old };
|
|
358
|
+
delete next[id];
|
|
359
|
+
return next;
|
|
360
|
+
})
|
|
305
361
|
},
|
|
306
|
-
children:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
setContent((c) => ({
|
|
324
|
-
...c,
|
|
325
|
-
source: ["event", "adoption"].includes(k) ? {
|
|
326
|
-
organization: "",
|
|
327
|
-
official_url: "",
|
|
328
|
-
availability_confirmed: false
|
|
329
|
-
} : null,
|
|
330
|
-
event: k === "event" ? {
|
|
331
|
-
starts_at: "",
|
|
332
|
-
ends_at: "",
|
|
333
|
-
event_type: "adoption",
|
|
334
|
-
cost: "unknown",
|
|
335
|
-
cost_verified: false
|
|
336
|
-
} : null
|
|
337
|
-
}));
|
|
338
|
-
change(
|
|
339
|
-
"category",
|
|
340
|
-
k === "celebration" ? "birthday" : k === "photo" ? "cute" : ""
|
|
341
|
-
);
|
|
342
|
-
},
|
|
343
|
-
children: [
|
|
344
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "spotlight", children: "Paw of the Week submission" }),
|
|
345
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "profile", children: "Pet profile" }),
|
|
346
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "photo", children: "Photo board" }),
|
|
347
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "celebration", children: "Pet celebration" }),
|
|
348
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "lost", children: "Lost pet report" }),
|
|
349
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "found", children: "Found pet report" }),
|
|
350
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "event", children: "Organization event" }),
|
|
351
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "adoption", children: "Shelter or rescue adoption listing" })
|
|
352
|
-
]
|
|
353
|
-
}
|
|
354
|
-
)
|
|
355
|
-
] }),
|
|
356
|
-
!initial && kind !== "profile" && profiles.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
357
|
-
"Start with one of your pets",
|
|
358
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
359
|
-
"select",
|
|
360
|
-
{
|
|
361
|
-
value: profileId || "",
|
|
362
|
-
onChange: (e) => {
|
|
363
|
-
const p = profiles.find((p2) => p2.id === e.target.value);
|
|
364
|
-
setProfileId(p?.id || null);
|
|
365
|
-
if (p) {
|
|
366
|
-
setContent({
|
|
367
|
-
...p.content,
|
|
368
|
-
category: content.category,
|
|
369
|
-
source: content.source,
|
|
370
|
-
event: content.event
|
|
371
|
-
});
|
|
372
|
-
setCommunity(
|
|
373
|
-
communities.some((c) => c.id === p.area_id) ? p.area_id : defaultCommunity || ""
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
},
|
|
377
|
-
children: [
|
|
378
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Enter pet details" }),
|
|
379
|
-
profiles.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.id, children: p.content.name }, p.id))
|
|
380
|
-
]
|
|
381
|
-
}
|
|
382
|
-
)
|
|
383
|
-
] }),
|
|
384
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
385
|
-
kind === "event" ? "Event title" : "Pet name",
|
|
386
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
387
|
-
"input",
|
|
388
|
-
{
|
|
389
|
-
required: true,
|
|
390
|
-
maxLength: 100,
|
|
391
|
-
value: content.name,
|
|
392
|
-
onChange: (e) => change("name", e.target.value),
|
|
393
|
-
autoComplete: "off"
|
|
394
|
-
}
|
|
395
|
-
)
|
|
396
|
-
] }),
|
|
397
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
398
|
-
"Species",
|
|
399
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
400
|
-
"input",
|
|
401
|
-
{
|
|
402
|
-
required: true,
|
|
403
|
-
maxLength: 50,
|
|
404
|
-
value: content.species,
|
|
405
|
-
onChange: (e) => change("species", e.target.value)
|
|
406
|
-
}
|
|
407
|
-
)
|
|
408
|
-
] }),
|
|
409
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
410
|
-
"Home community",
|
|
411
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
412
|
-
"select",
|
|
413
|
-
{
|
|
414
|
-
required: true,
|
|
415
|
-
value: community,
|
|
416
|
-
onChange: (e) => setCommunity(e.target.value),
|
|
417
|
-
children: [
|
|
418
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Choose a community" }),
|
|
419
|
-
communities.map((c) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: c.id, children: c.name }, c.id))
|
|
420
|
-
]
|
|
362
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
363
|
+
"form",
|
|
364
|
+
{
|
|
365
|
+
ref: formRef,
|
|
366
|
+
noValidate: true,
|
|
367
|
+
className: "paw-form paw-submission",
|
|
368
|
+
onSubmit: (event) => {
|
|
369
|
+
event.preventDefault();
|
|
370
|
+
const errors = {};
|
|
371
|
+
let first;
|
|
372
|
+
for (const element of Array.from(event.currentTarget.elements)) {
|
|
373
|
+
if (!(element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement))
|
|
374
|
+
continue;
|
|
375
|
+
const blank = element.required && element.type !== "checkbox" && element.type !== "file" && !element.value.trim();
|
|
376
|
+
if (element.willValidate && (!element.validity.valid || blank)) {
|
|
377
|
+
errors[element.id] = fieldMessage(element, blank);
|
|
378
|
+
first ||= element;
|
|
421
379
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
/* @__PURE__ */ jsxRuntime.
|
|
440
|
-
"
|
|
441
|
-
{
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
value: content.adoption_anniversary || "",
|
|
455
|
-
onChange: (e) => change("adoption_anniversary", e.target.value || null)
|
|
456
|
-
}
|
|
457
|
-
)
|
|
458
|
-
] }),
|
|
459
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
460
|
-
"Personality",
|
|
461
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
462
|
-
"input",
|
|
463
|
-
{
|
|
464
|
-
maxLength: 300,
|
|
465
|
-
value: content.personality,
|
|
466
|
-
onChange: (e) => change("personality", e.target.value)
|
|
467
|
-
}
|
|
468
|
-
)
|
|
380
|
+
}
|
|
381
|
+
setFieldErrors(errors);
|
|
382
|
+
if (first) {
|
|
383
|
+
first.focus();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (step === 0) {
|
|
387
|
+
setError("");
|
|
388
|
+
setStep(1);
|
|
389
|
+
requestAnimationFrame(() => {
|
|
390
|
+
formRef.current?.querySelector("h1")?.focus({ preventScroll: true });
|
|
391
|
+
formRef.current?.scrollIntoView({ block: "start" });
|
|
392
|
+
});
|
|
393
|
+
} else void save();
|
|
394
|
+
},
|
|
395
|
+
children: [
|
|
396
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "paw-form-intro", children: [
|
|
397
|
+
/* @__PURE__ */ jsxRuntime.jsxs("ol", { className: "paw-form-steps", "aria-label": "Submission progress", children: [
|
|
398
|
+
/* @__PURE__ */ jsxRuntime.jsx("li", { "aria-current": step === 0 ? "step" : void 0, children: "1. Their story" }),
|
|
399
|
+
/* @__PURE__ */ jsxRuntime.jsx("li", { "aria-current": step === 1 ? "step" : void 0, children: "2. Preview & permission" })
|
|
400
|
+
] }),
|
|
401
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { tabIndex: -1, children: kind === "celebration" && content.category === "memorial" ? "Remember a beloved companion." : ["lost", "found"].includes(kind) ? "Help them find home." : step === 1 ? "Looking good." : "Tell their story." }),
|
|
402
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-form-description", children: step === 0 ? content.category === "memorial" ? "Share a memory of a companion you\u2019ll always remember." : ["lost", "found"].includes(kind) ? "A clear description and an approximate location can help neighbors recognize a missing pet." : kind === "event" ? "Help neighbors discover your organization\u2019s pet community event." : "A favorite photograph. A little personality. A story your neighbors will love." : "Take a moment to check the details. You can always go back and make changes." }),
|
|
403
|
+
/* @__PURE__ */ jsxRuntime.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." }),
|
|
404
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-form-assurance", children: [
|
|
405
|
+
/* @__PURE__ */ jsxRuntime.jsx(PawMark, { size: 28 }),
|
|
406
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
407
|
+
"Yours to share.",
|
|
408
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
409
|
+
"Reviewed with care."
|
|
410
|
+
] })
|
|
411
|
+
] })
|
|
469
412
|
] }),
|
|
470
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
413
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-form-body", children: [
|
|
414
|
+
step === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
415
|
+
!initial && /* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
416
|
+
"What would you like to share?",
|
|
417
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
418
|
+
"select",
|
|
419
|
+
{
|
|
420
|
+
value: kind,
|
|
421
|
+
onChange: (e) => {
|
|
422
|
+
const k = e.target.value;
|
|
423
|
+
setKind(k);
|
|
424
|
+
setFieldErrors({});
|
|
425
|
+
setContent((c) => ({
|
|
426
|
+
...c,
|
|
427
|
+
source: ["event", "adoption"].includes(k) ? {
|
|
428
|
+
organization: "",
|
|
429
|
+
official_url: "",
|
|
430
|
+
availability_confirmed: false
|
|
431
|
+
} : null,
|
|
432
|
+
event: k === "event" ? {
|
|
433
|
+
starts_at: "",
|
|
434
|
+
ends_at: "",
|
|
435
|
+
event_type: "adoption",
|
|
436
|
+
cost: "unknown",
|
|
437
|
+
cost_verified: false
|
|
438
|
+
} : null
|
|
439
|
+
}));
|
|
440
|
+
change(
|
|
441
|
+
"category",
|
|
442
|
+
k === "celebration" ? "birthday" : k === "photo" ? "cute" : ""
|
|
443
|
+
);
|
|
444
|
+
},
|
|
445
|
+
children: [
|
|
446
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "spotlight", children: "Paw of the Week submission" }),
|
|
447
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "profile", children: "Pet profile" }),
|
|
448
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "photo", children: "Photo board" }),
|
|
449
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "celebration", children: "Pet celebration" }),
|
|
450
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "lost", children: "Lost pet report" }),
|
|
451
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "found", children: "Found pet report" }),
|
|
452
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "event", children: "Organization event" }),
|
|
453
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "adoption", children: "Shelter or rescue adoption listing" })
|
|
454
|
+
]
|
|
455
|
+
}
|
|
479
456
|
)
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
512
|
-
"input",
|
|
513
|
-
{
|
|
514
|
-
required: kind !== "celebration",
|
|
515
|
-
type: "date",
|
|
516
|
-
value: content.date || "",
|
|
517
|
-
onChange: (e) => change("date", e.target.value || null)
|
|
518
|
-
}
|
|
519
|
-
)
|
|
520
|
-
] }),
|
|
521
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
522
|
-
kind === "profile" ? "A little biography" : "Your story",
|
|
523
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
524
|
-
"textarea",
|
|
525
|
-
{
|
|
526
|
-
required: kind !== "profile",
|
|
527
|
-
maxLength: 4e3,
|
|
528
|
-
value: content.story,
|
|
529
|
-
onChange: (e) => change("story", e.target.value)
|
|
530
|
-
}
|
|
531
|
-
)
|
|
532
|
-
] }),
|
|
533
|
-
kind === "adoption" && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
534
|
-
"Approximate age (optional)",
|
|
535
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
536
|
-
"input",
|
|
537
|
-
{
|
|
538
|
-
value: content.age_description || "",
|
|
539
|
-
maxLength: 80,
|
|
540
|
-
onChange: (e) => change("age_description", e.target.value)
|
|
541
|
-
}
|
|
542
|
-
)
|
|
543
|
-
] }),
|
|
544
|
-
content.source && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
|
|
545
|
-
/* @__PURE__ */ jsxRuntime.jsx("legend", { children: "Official organization and source" }),
|
|
546
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
547
|
-
"Organization name",
|
|
548
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
549
|
-
"input",
|
|
550
|
-
{
|
|
551
|
-
required: true,
|
|
552
|
-
maxLength: 200,
|
|
553
|
-
value: content.source.organization,
|
|
554
|
-
onChange: (e) => change("source", {
|
|
555
|
-
...content.source,
|
|
556
|
-
organization: e.target.value
|
|
557
|
-
})
|
|
558
|
-
}
|
|
559
|
-
)
|
|
560
|
-
] }),
|
|
561
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
562
|
-
"Official listing or registration link",
|
|
563
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
564
|
-
"input",
|
|
565
|
-
{
|
|
566
|
-
required: true,
|
|
567
|
-
type: "url",
|
|
568
|
-
pattern: "https://.*",
|
|
569
|
-
value: content.source.official_url,
|
|
570
|
-
onChange: (e) => change("source", {
|
|
571
|
-
...content.source,
|
|
572
|
-
official_url: e.target.value
|
|
573
|
-
})
|
|
574
|
-
}
|
|
575
|
-
)
|
|
576
|
-
] }),
|
|
577
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Editors verify the organization, permission to use photographs, and listing information. Availability and event costs are never assumed." })
|
|
578
|
-
] }),
|
|
579
|
-
content.event && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
|
|
580
|
-
/* @__PURE__ */ jsxRuntime.jsx("legend", { children: "Event schedule" }),
|
|
581
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
582
|
-
"Enter times in your device\u2019s timezone (",
|
|
583
|
-
deviceReady ? Intl.DateTimeFormat().resolvedOptions().timeZone : "your device timezone",
|
|
584
|
-
"). They display in Pacific time."
|
|
585
|
-
] }),
|
|
586
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
587
|
-
"Starts",
|
|
588
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
589
|
-
"input",
|
|
590
|
-
{
|
|
591
|
-
type: "datetime-local",
|
|
592
|
-
required: true,
|
|
593
|
-
value: deviceReady ? localDateTime(content.event.starts_at) : "",
|
|
594
|
-
onChange: (e) => {
|
|
595
|
-
if (e.target.value)
|
|
596
|
-
change("event", {
|
|
597
|
-
...content.event,
|
|
598
|
-
starts_at: new Date(e.target.value).toISOString()
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
)
|
|
603
|
-
] }),
|
|
604
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
605
|
-
"Ends",
|
|
606
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
607
|
-
"input",
|
|
608
|
-
{
|
|
609
|
-
type: "datetime-local",
|
|
610
|
-
required: true,
|
|
611
|
-
value: deviceReady ? localDateTime(content.event.ends_at) : "",
|
|
612
|
-
onChange: (e) => {
|
|
613
|
-
if (e.target.value)
|
|
614
|
-
change("event", {
|
|
615
|
-
...content.event,
|
|
616
|
-
ends_at: new Date(e.target.value).toISOString()
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
)
|
|
621
|
-
] }),
|
|
622
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
623
|
-
"Event type",
|
|
624
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
625
|
-
"select",
|
|
626
|
-
{
|
|
627
|
-
value: content.event.event_type,
|
|
628
|
-
onChange: (e) => change("event", {
|
|
629
|
-
...content.event,
|
|
630
|
-
event_type: e.target.value
|
|
631
|
-
}),
|
|
632
|
-
children: [
|
|
633
|
-
"adoption",
|
|
634
|
-
"veterinary",
|
|
635
|
-
"vaccination",
|
|
636
|
-
"walk",
|
|
637
|
-
"festival",
|
|
638
|
-
"fundraiser",
|
|
639
|
-
"workshop",
|
|
640
|
-
"celebration"
|
|
641
|
-
].map((type) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: type, children: type }, type))
|
|
642
|
-
}
|
|
643
|
-
)
|
|
644
|
-
] }),
|
|
645
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
646
|
-
"Reported cost",
|
|
647
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
648
|
-
"select",
|
|
649
|
-
{
|
|
650
|
-
value: content.event.cost,
|
|
651
|
-
onChange: (e) => change("event", {
|
|
652
|
-
...content.event,
|
|
653
|
-
cost: e.target.value
|
|
654
|
-
}),
|
|
655
|
-
children: [
|
|
656
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "unknown", children: "Check with organization" }),
|
|
657
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "free", children: "Submitted as free \u2014 requires verification" }),
|
|
658
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "paid", children: "Paid registration" })
|
|
659
|
-
]
|
|
660
|
-
}
|
|
661
|
-
)
|
|
662
|
-
] })
|
|
663
|
-
] }),
|
|
664
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
665
|
-
"Your public photo credit",
|
|
666
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
667
|
-
"input",
|
|
668
|
-
{
|
|
669
|
-
maxLength: 100,
|
|
670
|
-
value: content.attribution,
|
|
671
|
-
onChange: (e) => change("attribution", e.target.value),
|
|
672
|
-
placeholder: "Name you want published"
|
|
673
|
-
}
|
|
674
|
-
)
|
|
675
|
-
] }),
|
|
676
|
-
initial?.media.map((photo) => /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
|
|
677
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
678
|
-
"img",
|
|
679
|
-
{
|
|
680
|
-
src: `${apiPath}/submissions/${initial.id}/media/${photo.id}`,
|
|
681
|
-
alt: photo.caption || content.name,
|
|
682
|
-
width: 640,
|
|
683
|
-
height: 480
|
|
684
|
-
}
|
|
685
|
-
),
|
|
686
|
-
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: photo.attribution })
|
|
687
|
-
] }, photo.id)),
|
|
688
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
689
|
-
"Authentic photographs",
|
|
690
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
691
|
-
"input",
|
|
692
|
-
{
|
|
693
|
-
type: "file",
|
|
694
|
-
accept: "image/jpeg,image/png,image/webp",
|
|
695
|
-
multiple: true,
|
|
696
|
-
onChange: (e) => {
|
|
697
|
-
const selected = Array.from(e.target.files || []);
|
|
698
|
-
if (selected.length + (initial?.media.length || 0) > 10 || selected.some((f) => f.size > 8 * 1024 * 1024)) {
|
|
699
|
-
setError(
|
|
700
|
-
"Choose up to ten JPEG, PNG or WebP photographs, each under 8 MB."
|
|
701
|
-
);
|
|
702
|
-
return;
|
|
703
|
-
}
|
|
704
|
-
setError("");
|
|
705
|
-
setFiles(
|
|
706
|
-
selected.map((file) => ({
|
|
707
|
-
file,
|
|
708
|
-
key: crypto.randomUUID(),
|
|
709
|
-
preview: URL.createObjectURL(file)
|
|
710
|
-
}))
|
|
711
|
-
);
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
)
|
|
715
|
-
] }),
|
|
716
|
-
/* @__PURE__ */ jsxRuntime.jsx("small", { children: "JPEG, PNG or WebP, up to 8 MB each. Photos are checked before publication and location metadata is removed." }),
|
|
717
|
-
["lost", "found"].includes(kind) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-safety", children: [
|
|
718
|
-
PET_SAFETY.recovery,
|
|
719
|
-
" Private recovery contact is not available yet."
|
|
720
|
-
] })
|
|
721
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
722
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
723
|
-
"article",
|
|
724
|
-
{
|
|
725
|
-
className: content.category === "memorial" ? "paw-memorial" : "",
|
|
726
|
-
children: [
|
|
727
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-context", children: communities.find((c) => c.id === community)?.name }),
|
|
728
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: content.name }),
|
|
729
|
-
!files.length && initial?.media[0] && /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
|
|
457
|
+
] }),
|
|
458
|
+
!initial && kind !== "profile" && profiles.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
459
|
+
"Start with one of your pets",
|
|
460
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
461
|
+
"select",
|
|
462
|
+
{
|
|
463
|
+
value: profileId || "",
|
|
464
|
+
onChange: (e) => {
|
|
465
|
+
const p = profiles.find((p2) => p2.id === e.target.value);
|
|
466
|
+
setProfileId(p?.id || null);
|
|
467
|
+
if (p) {
|
|
468
|
+
setContent({
|
|
469
|
+
...p.content,
|
|
470
|
+
category: content.category,
|
|
471
|
+
source: content.source,
|
|
472
|
+
event: content.event
|
|
473
|
+
});
|
|
474
|
+
setCommunity(
|
|
475
|
+
communities.some((c) => c.id === p.area_id) ? p.area_id : defaultCommunity || ""
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
children: [
|
|
480
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Enter pet details" }),
|
|
481
|
+
profiles.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.id, children: p.content.name }, p.id))
|
|
482
|
+
]
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
] }),
|
|
486
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
487
|
+
kind === "event" ? "Event title" : "Pet name",
|
|
730
488
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
731
|
-
"
|
|
489
|
+
"input",
|
|
732
490
|
{
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
491
|
+
required: true,
|
|
492
|
+
maxLength: 100,
|
|
493
|
+
value: content.name,
|
|
494
|
+
onChange: (e) => change("name", e.target.value),
|
|
495
|
+
autoComplete: "off"
|
|
737
496
|
}
|
|
738
|
-
)
|
|
739
|
-
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: initial.media[0].attribution })
|
|
497
|
+
)
|
|
740
498
|
] }),
|
|
741
|
-
|
|
499
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
500
|
+
"Species",
|
|
501
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
502
|
+
"input",
|
|
503
|
+
{
|
|
504
|
+
required: true,
|
|
505
|
+
maxLength: 50,
|
|
506
|
+
value: content.species,
|
|
507
|
+
onChange: (e) => change("species", e.target.value)
|
|
508
|
+
}
|
|
509
|
+
)
|
|
510
|
+
] }),
|
|
511
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
512
|
+
"Home community",
|
|
513
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
514
|
+
"select",
|
|
515
|
+
{
|
|
516
|
+
required: true,
|
|
517
|
+
value: community,
|
|
518
|
+
onChange: (e) => setCommunity(e.target.value),
|
|
519
|
+
children: [
|
|
520
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Choose a community" }),
|
|
521
|
+
communities.map((c) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: c.id, children: c.name }, c.id))
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
] }),
|
|
526
|
+
kind === "profile" && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
|
|
527
|
+
/* @__PURE__ */ jsxRuntime.jsx("legend", { children: "A few favorite things" }),
|
|
528
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
529
|
+
"Breed or mix (optional)",
|
|
530
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
531
|
+
"input",
|
|
532
|
+
{
|
|
533
|
+
value: content.breed,
|
|
534
|
+
maxLength: 100,
|
|
535
|
+
onChange: (e) => change("breed", e.target.value)
|
|
536
|
+
}
|
|
537
|
+
)
|
|
538
|
+
] }),
|
|
539
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
540
|
+
"Birthday (optional)",
|
|
541
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
542
|
+
"input",
|
|
543
|
+
{
|
|
544
|
+
type: "date",
|
|
545
|
+
value: content.birthday || "",
|
|
546
|
+
onChange: (e) => change("birthday", e.target.value || null)
|
|
547
|
+
}
|
|
548
|
+
)
|
|
549
|
+
] }),
|
|
550
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
551
|
+
"Adoption anniversary (optional)",
|
|
552
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
553
|
+
"input",
|
|
554
|
+
{
|
|
555
|
+
type: "date",
|
|
556
|
+
value: content.adoption_anniversary || "",
|
|
557
|
+
onChange: (e) => change("adoption_anniversary", e.target.value || null)
|
|
558
|
+
}
|
|
559
|
+
)
|
|
560
|
+
] }),
|
|
561
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
562
|
+
"Personality",
|
|
563
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
564
|
+
"input",
|
|
565
|
+
{
|
|
566
|
+
maxLength: 300,
|
|
567
|
+
value: content.personality,
|
|
568
|
+
onChange: (e) => change("personality", e.target.value)
|
|
569
|
+
}
|
|
570
|
+
)
|
|
571
|
+
] }),
|
|
572
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
573
|
+
"Favorite activities, separated by commas",
|
|
574
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
575
|
+
"input",
|
|
576
|
+
{
|
|
577
|
+
value: content.activities.join(", "),
|
|
578
|
+
onChange: (e) => change(
|
|
579
|
+
"activities",
|
|
580
|
+
e.target.value.split(",").map((v) => v.trim()).slice(0, 8)
|
|
581
|
+
)
|
|
582
|
+
}
|
|
583
|
+
)
|
|
584
|
+
] }),
|
|
585
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
586
|
+
"Profile privacy",
|
|
587
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
588
|
+
"select",
|
|
589
|
+
{
|
|
590
|
+
value: visibility,
|
|
591
|
+
onChange: (e) => setVisibility(e.target.value),
|
|
592
|
+
children: [
|
|
593
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "private", children: "Private \u2014 only me" }),
|
|
594
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "public", children: "Public \u2014 after editorial review" })
|
|
595
|
+
]
|
|
596
|
+
}
|
|
597
|
+
)
|
|
598
|
+
] })
|
|
599
|
+
] }),
|
|
600
|
+
(kind === "photo" || kind === "celebration") && /* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
601
|
+
kind === "photo" ? "Photo category" : "Celebration",
|
|
602
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
603
|
+
"select",
|
|
604
|
+
{
|
|
605
|
+
value: content.category,
|
|
606
|
+
onChange: (e) => change("category", e.target.value),
|
|
607
|
+
children: (kind === "photo" ? PET_PHOTO_CATEGORIES : PET_CELEBRATIONS).map(([value, label]) => /* @__PURE__ */ jsxRuntime.jsx("option", { value, children: label }, value))
|
|
608
|
+
}
|
|
609
|
+
)
|
|
610
|
+
] }),
|
|
611
|
+
["lost", "found", "celebration"].includes(kind) && /* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
612
|
+
kind === "lost" ? "Date last seen" : kind === "found" ? "Date found" : "Celebration date (optional)",
|
|
613
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
614
|
+
"input",
|
|
615
|
+
{
|
|
616
|
+
required: kind !== "celebration",
|
|
617
|
+
type: "date",
|
|
618
|
+
value: content.date || "",
|
|
619
|
+
onChange: (e) => change("date", e.target.value || null)
|
|
620
|
+
}
|
|
621
|
+
)
|
|
622
|
+
] }),
|
|
623
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
624
|
+
kind === "profile" ? "A little biography" : "Your story",
|
|
625
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
626
|
+
"textarea",
|
|
627
|
+
{
|
|
628
|
+
required: kind !== "profile",
|
|
629
|
+
maxLength: 4e3,
|
|
630
|
+
value: content.story,
|
|
631
|
+
onChange: (e) => change("story", e.target.value)
|
|
632
|
+
}
|
|
633
|
+
)
|
|
634
|
+
] }),
|
|
635
|
+
kind === "adoption" && /* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
636
|
+
"Approximate age (optional)",
|
|
637
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
638
|
+
"input",
|
|
639
|
+
{
|
|
640
|
+
value: content.age_description || "",
|
|
641
|
+
maxLength: 80,
|
|
642
|
+
onChange: (e) => change("age_description", e.target.value)
|
|
643
|
+
}
|
|
644
|
+
)
|
|
645
|
+
] }),
|
|
646
|
+
content.source && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
|
|
647
|
+
/* @__PURE__ */ jsxRuntime.jsx("legend", { children: "Official organization and source" }),
|
|
648
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
649
|
+
"Organization name",
|
|
650
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
651
|
+
"input",
|
|
652
|
+
{
|
|
653
|
+
required: true,
|
|
654
|
+
maxLength: 200,
|
|
655
|
+
value: content.source.organization,
|
|
656
|
+
onChange: (e) => change("source", {
|
|
657
|
+
...content.source,
|
|
658
|
+
organization: e.target.value
|
|
659
|
+
})
|
|
660
|
+
}
|
|
661
|
+
)
|
|
662
|
+
] }),
|
|
663
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
664
|
+
"Official listing or registration link",
|
|
665
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
666
|
+
"input",
|
|
667
|
+
{
|
|
668
|
+
required: true,
|
|
669
|
+
type: "url",
|
|
670
|
+
pattern: "https://.*",
|
|
671
|
+
value: content.source.official_url,
|
|
672
|
+
onChange: (e) => change("source", {
|
|
673
|
+
...content.source,
|
|
674
|
+
official_url: e.target.value
|
|
675
|
+
})
|
|
676
|
+
}
|
|
677
|
+
)
|
|
678
|
+
] }),
|
|
679
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Editors verify the organization, permission to use photographs, and listing information. Availability and event costs are never assumed." })
|
|
680
|
+
] }),
|
|
681
|
+
content.event && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
|
|
682
|
+
/* @__PURE__ */ jsxRuntime.jsx("legend", { children: "Event schedule" }),
|
|
683
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
684
|
+
"Enter times in your device\u2019s timezone (",
|
|
685
|
+
deviceReady ? Intl.DateTimeFormat().resolvedOptions().timeZone : "your device timezone",
|
|
686
|
+
"). They display in Pacific time."
|
|
687
|
+
] }),
|
|
688
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
689
|
+
"Starts",
|
|
690
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
691
|
+
"input",
|
|
692
|
+
{
|
|
693
|
+
type: "datetime-local",
|
|
694
|
+
required: true,
|
|
695
|
+
value: deviceReady ? localDateTime(content.event.starts_at) : "",
|
|
696
|
+
onChange: (e) => {
|
|
697
|
+
if (e.target.value)
|
|
698
|
+
change("event", {
|
|
699
|
+
...content.event,
|
|
700
|
+
starts_at: new Date(e.target.value).toISOString()
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
)
|
|
705
|
+
] }),
|
|
706
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
707
|
+
"Ends",
|
|
708
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
709
|
+
"input",
|
|
710
|
+
{
|
|
711
|
+
type: "datetime-local",
|
|
712
|
+
required: true,
|
|
713
|
+
value: deviceReady ? localDateTime(content.event.ends_at) : "",
|
|
714
|
+
onChange: (e) => {
|
|
715
|
+
if (e.target.value)
|
|
716
|
+
change("event", {
|
|
717
|
+
...content.event,
|
|
718
|
+
ends_at: new Date(e.target.value).toISOString()
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
)
|
|
723
|
+
] }),
|
|
724
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
725
|
+
"Event type",
|
|
726
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
727
|
+
"select",
|
|
728
|
+
{
|
|
729
|
+
value: content.event.event_type,
|
|
730
|
+
onChange: (e) => change("event", {
|
|
731
|
+
...content.event,
|
|
732
|
+
event_type: e.target.value
|
|
733
|
+
}),
|
|
734
|
+
children: [
|
|
735
|
+
"adoption",
|
|
736
|
+
"veterinary",
|
|
737
|
+
"vaccination",
|
|
738
|
+
"walk",
|
|
739
|
+
"festival",
|
|
740
|
+
"fundraiser",
|
|
741
|
+
"workshop",
|
|
742
|
+
"celebration"
|
|
743
|
+
].map((type) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: type, children: type }, type))
|
|
744
|
+
}
|
|
745
|
+
)
|
|
746
|
+
] }),
|
|
747
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
748
|
+
"Reported cost",
|
|
749
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
750
|
+
"select",
|
|
751
|
+
{
|
|
752
|
+
value: content.event.cost,
|
|
753
|
+
onChange: (e) => change("event", {
|
|
754
|
+
...content.event,
|
|
755
|
+
cost: e.target.value
|
|
756
|
+
}),
|
|
757
|
+
children: [
|
|
758
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "unknown", children: "Check with organization" }),
|
|
759
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "free", children: "Submitted as free \u2014 requires verification" }),
|
|
760
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "paid", children: "Paid registration" })
|
|
761
|
+
]
|
|
762
|
+
}
|
|
763
|
+
)
|
|
764
|
+
] })
|
|
765
|
+
] }),
|
|
766
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
767
|
+
"Your public photo credit",
|
|
768
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
769
|
+
"input",
|
|
770
|
+
{
|
|
771
|
+
maxLength: 100,
|
|
772
|
+
value: content.attribution,
|
|
773
|
+
onChange: (e) => change("attribution", e.target.value),
|
|
774
|
+
placeholder: "Name you want published"
|
|
775
|
+
}
|
|
776
|
+
)
|
|
777
|
+
] }),
|
|
778
|
+
initial?.media.map((photo) => /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
|
|
742
779
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
743
780
|
"img",
|
|
744
781
|
{
|
|
745
|
-
src:
|
|
746
|
-
alt:
|
|
747
|
-
width:
|
|
748
|
-
height:
|
|
782
|
+
src: `${apiPath}/submissions/${initial.id}/media/${photo.id}`,
|
|
783
|
+
alt: photo.caption || content.name,
|
|
784
|
+
width: 640,
|
|
785
|
+
height: 480
|
|
786
|
+
}
|
|
787
|
+
),
|
|
788
|
+
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: photo.attribution })
|
|
789
|
+
] }, photo.id)),
|
|
790
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { className: "paw-photo-picker", children: [
|
|
791
|
+
"Authentic photographs",
|
|
792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
793
|
+
"input",
|
|
794
|
+
{
|
|
795
|
+
type: "file",
|
|
796
|
+
className: "paw-upload-input",
|
|
797
|
+
required: ["spotlight", "photo", "adoption"].includes(kind) && !files.length && !initial?.media.length,
|
|
798
|
+
"aria-describedby": "paw-photo-guidance",
|
|
799
|
+
accept: "image/jpeg,image/png,image/webp",
|
|
800
|
+
multiple: true,
|
|
801
|
+
onChange: (e) => {
|
|
802
|
+
const selected = Array.from(e.target.files || []);
|
|
803
|
+
if (selected.length + (initial?.media.length || 0) > 10 || selected.some(
|
|
804
|
+
(f) => f.size > 8 * 1024 * 1024 || !["image/jpeg", "image/png", "image/webp"].includes(
|
|
805
|
+
f.type
|
|
806
|
+
)
|
|
807
|
+
)) {
|
|
808
|
+
setError(
|
|
809
|
+
"Choose up to ten JPEG, PNG or WebP photographs, each under 8 MB."
|
|
810
|
+
);
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
setError("");
|
|
814
|
+
setFiles(
|
|
815
|
+
selected.map((file) => ({
|
|
816
|
+
file,
|
|
817
|
+
key: crypto.randomUUID(),
|
|
818
|
+
preview: URL.createObjectURL(file)
|
|
819
|
+
}))
|
|
820
|
+
);
|
|
821
|
+
}
|
|
749
822
|
}
|
|
750
823
|
),
|
|
751
|
-
/* @__PURE__ */ jsxRuntime.
|
|
824
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "paw-upload-prompt", children: [
|
|
825
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
826
|
+
"svg",
|
|
827
|
+
{
|
|
828
|
+
viewBox: "0 0 32 32",
|
|
829
|
+
width: "32",
|
|
830
|
+
height: "32",
|
|
831
|
+
fill: "none",
|
|
832
|
+
stroke: "currentColor",
|
|
833
|
+
strokeWidth: "1.5",
|
|
834
|
+
"aria-hidden": "true",
|
|
835
|
+
children: [
|
|
836
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M11 8l2-3h6l2 3h5a3 3 0 013 3v13a3 3 0 01-3 3H6a3 3 0 01-3-3V11a3 3 0 013-3z" }),
|
|
837
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "16", cy: "17", r: "6" })
|
|
838
|
+
]
|
|
839
|
+
}
|
|
840
|
+
),
|
|
841
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: files.length ? `${files.length} ${files.length === 1 ? "photo" : "photos"} selected` : content.category === "memorial" ? "A photograph to remember them by." : ["lost", "found"].includes(kind) ? "A clear photograph helps neighbors recognize them." : "Their best angle. Their biggest personality." }),
|
|
842
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: files.length ? "Choose different photos" : "Choose photos from your device" })
|
|
843
|
+
] })
|
|
752
844
|
] }),
|
|
753
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
845
|
+
/* @__PURE__ */ jsxRuntime.jsx("small", { id: "paw-photo-guidance", children: "JPEG, PNG or WebP, up to 8 MB each. Photos are checked before publication and location metadata is removed." }),
|
|
846
|
+
files.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
847
|
+
"div",
|
|
848
|
+
{
|
|
849
|
+
className: "paw-upload-previews",
|
|
850
|
+
"aria-label": "Selected photographs",
|
|
851
|
+
children: files.map((file) => /* @__PURE__ */ jsxRuntime.jsxs("figure", { children: [
|
|
852
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
853
|
+
"img",
|
|
854
|
+
{
|
|
855
|
+
src: file.preview,
|
|
856
|
+
alt: `Selected photograph: ${file.file.name}`,
|
|
857
|
+
width: 160,
|
|
858
|
+
height: 160
|
|
859
|
+
}
|
|
860
|
+
),
|
|
861
|
+
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: file.file.name })
|
|
862
|
+
] }, file.key))
|
|
863
|
+
}
|
|
864
|
+
),
|
|
865
|
+
["lost", "found"].includes(kind) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-safety", children: [
|
|
866
|
+
PET_SAFETY.recovery,
|
|
867
|
+
" Private recovery contact is not available yet."
|
|
868
|
+
] })
|
|
869
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
870
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
871
|
+
"article",
|
|
872
|
+
{
|
|
873
|
+
className: content.category === "memorial" ? "paw-memorial" : "",
|
|
874
|
+
children: [
|
|
875
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-context", children: communities.find((c) => c.id === community)?.name }),
|
|
876
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: content.name }),
|
|
877
|
+
!files.length && initial?.media[0] && /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
|
|
878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
879
|
+
"img",
|
|
880
|
+
{
|
|
881
|
+
src: `${apiPath}/submissions/${initial.id}/media/${initial.media[0].id}`,
|
|
882
|
+
alt: initial.media[0].caption || content.name,
|
|
883
|
+
width: 800,
|
|
884
|
+
height: 600
|
|
885
|
+
}
|
|
886
|
+
),
|
|
887
|
+
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: initial.media[0].attribution })
|
|
888
|
+
] }),
|
|
889
|
+
files[0] && /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
|
|
890
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
891
|
+
"img",
|
|
892
|
+
{
|
|
893
|
+
src: files[0].preview,
|
|
894
|
+
alt: `Private preview of ${content.name}`,
|
|
895
|
+
width: 800,
|
|
896
|
+
height: 600
|
|
897
|
+
}
|
|
898
|
+
),
|
|
899
|
+
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: content.attribution })
|
|
900
|
+
] }),
|
|
901
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { whiteSpace: "pre-wrap" }, children: content.story })
|
|
902
|
+
]
|
|
903
|
+
}
|
|
904
|
+
),
|
|
905
|
+
/* @__PURE__ */ jsxRuntime.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." }),
|
|
906
|
+
needsPermission && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
907
|
+
/* @__PURE__ */ jsxRuntime.jsxs("details", { children: [
|
|
908
|
+
/* @__PURE__ */ jsxRuntime.jsx("summary", { children: "Publication permission and guidelines" }),
|
|
909
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: policy.text }),
|
|
910
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: policy.guidelines })
|
|
911
|
+
] }),
|
|
912
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PetField, { className: "paw-consent", children: [
|
|
913
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
914
|
+
"input",
|
|
915
|
+
{
|
|
916
|
+
type: "checkbox",
|
|
917
|
+
required: true,
|
|
918
|
+
checked: consent,
|
|
919
|
+
onChange: (e) => setConsent(e.target.checked)
|
|
920
|
+
}
|
|
921
|
+
),
|
|
922
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "I have read and accept the publication permission. These are authentic photographs I have permission to share." })
|
|
923
|
+
] })
|
|
924
|
+
] })
|
|
925
|
+
] }),
|
|
926
|
+
Object.keys(fieldErrors).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "paw-validation-summary", children: "A few details need your attention. Check the fields above." }),
|
|
927
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "paw-error", children: error }),
|
|
928
|
+
busy && /* @__PURE__ */ jsxRuntime.jsxs(PetField, { children: [
|
|
929
|
+
"Saving your contribution",
|
|
930
|
+
/* @__PURE__ */ jsxRuntime.jsx("progress", { value: progress, max: files.length + 2 })
|
|
931
|
+
] }),
|
|
932
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-form-actions", children: [
|
|
933
|
+
step === 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
934
|
+
"button",
|
|
935
|
+
{
|
|
936
|
+
type: "button",
|
|
937
|
+
disabled: busy,
|
|
938
|
+
onClick: () => {
|
|
939
|
+
setFieldErrors({});
|
|
940
|
+
setStep(0);
|
|
941
|
+
formRef.current?.scrollIntoView({ block: "start" });
|
|
942
|
+
},
|
|
943
|
+
children: "Keep editing"
|
|
944
|
+
}
|
|
945
|
+
),
|
|
946
|
+
/* @__PURE__ */ jsxRuntime.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" })
|
|
947
|
+
] }),
|
|
948
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-form-endnote", children: step === 0 ? "Next: a private preview. Nothing is published yet." : kind === "profile" && visibility === "private" ? "Only you can see this private profile." : "Your contribution stays private until editorial approval." })
|
|
775
949
|
] })
|
|
776
|
-
]
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
busy && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
780
|
-
"Saving your contribution",
|
|
781
|
-
/* @__PURE__ */ jsxRuntime.jsx("progress", { value: progress, max: files.length + 2 })
|
|
782
|
-
] }),
|
|
783
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-form-actions", children: [
|
|
784
|
-
step === 1 && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled: busy, onClick: () => setStep(0), children: "Keep editing" }),
|
|
785
|
-
/* @__PURE__ */ jsxRuntime.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" })
|
|
786
|
-
] })
|
|
787
|
-
]
|
|
950
|
+
]
|
|
951
|
+
}
|
|
952
|
+
)
|
|
788
953
|
}
|
|
789
954
|
);
|
|
790
955
|
}
|
|
@@ -793,7 +958,7 @@ function PetOwnerActions({
|
|
|
793
958
|
apiPath = "/api/pets",
|
|
794
959
|
submitUrl = "/submit"
|
|
795
960
|
}) {
|
|
796
|
-
const [error, setError] =
|
|
961
|
+
const [error, setError] = React.useState(""), [confirm, setConfirm] = React.useState(false), [busy, setBusy] = React.useState(false);
|
|
797
962
|
async function act(action) {
|
|
798
963
|
setBusy(true);
|
|
799
964
|
setError("");
|