fix(admin-events): switch edit-mode load to useFetch

Top-level $fetch in <script setup> does not forward auth cookies to the
SSR request, so requireAdmin rejected and the form hydrated empty.
Client refetch then triggered hydration mismatches; in dev the
description textarea stayed DOM-empty and the browser's native required
validation blocked saves.

Switch to useFetch (SSR-aware, forwards cookies). Mirror the
admin/members/[id].vue pattern: extract populateEditForm, call it with
the initial payload, watch for client-side updates.
This commit is contained in:
Jennie Robinson Faber 2026-05-18 23:18:55 +01:00
parent 13c72b5ee0
commit 790f44b4e9

View file

@ -708,63 +708,69 @@ const onSeriesSelect = () => {
} }
}; };
// Check if we're editing an event function populateEditForm(payload) {
if (route.query.edit) { const event = payload?.data;
try { if (!event) return;
const response = await $fetch(`/api/admin/events/${route.query.edit}`); editingEvent.value = event;
const event = response.data; Object.assign(eventForm, {
title: event.title,
if (event) { description: event.description,
editingEvent.value = event; content: event.content || "",
Object.assign(eventForm, { featureImage: event.featureImage || null,
title: event.title, startDate: formatForDatetimeLocal(event.startDate),
description: event.description, endDate: formatForDatetimeLocal(event.endDate),
content: event.content || "", eventType: event.eventType,
featureImage: event.featureImage || null, location: event.location || "",
startDate: formatForDatetimeLocal(event.startDate), isOnline: event.isOnline,
endDate: formatForDatetimeLocal(event.endDate), isVisible: event.isVisible !== undefined ? event.isVisible : true,
eventType: event.eventType, isCancelled: event.isCancelled || false,
location: event.location || "", cancellationMessage: event.cancellationMessage || "",
isOnline: event.isOnline, targetCircles: event.targetCircles || [],
isVisible: event.isVisible !== undefined ? event.isVisible : true, tags: event.tags || [],
isCancelled: event.isCancelled || false, maxAttendees: event.maxAttendees || "",
cancellationMessage: event.cancellationMessage || "", registrationRequired: event.registrationRequired,
targetCircles: event.targetCircles || [], registrationDeadline: formatForDatetimeLocal(event.registrationDeadline),
tags: event.tags || [], agenda: event.agenda || [],
maxAttendees: event.maxAttendees || "", tickets: event.tickets || {
registrationRequired: event.registrationRequired, enabled: false,
registrationDeadline: formatForDatetimeLocal(event.registrationDeadline), public: {
agenda: event.agenda || [], available: false,
tickets: event.tickets || { name: "Public Ticket",
enabled: false, description: "",
public: { price: 0,
available: false, quantity: null,
name: "Public Ticket", earlyBirdPrice: null,
description: "", earlyBirdDeadline: "",
price: 0, },
quantity: null, },
earlyBirdPrice: null, series: event.series || {
earlyBirdDeadline: "", isSeriesEvent: false,
}, id: "",
}, title: "",
series: event.series || { description: "",
isSeriesEvent: false, },
id: "", });
title: "", if (event.tickets?.public?.earlyBirdDeadline) {
description: "", eventForm.tickets.public.earlyBirdDeadline = formatForDatetimeLocal(
}, event.tickets.public.earlyBirdDeadline,
}); );
if (event.tickets?.public?.earlyBirdDeadline) {
eventForm.tickets.public.earlyBirdDeadline = formatForDatetimeLocal(
event.tickets.public.earlyBirdDeadline,
);
}
}
} catch (error) {
console.error("Failed to load event for editing:", error);
} }
} }
// useFetch forwards auth cookies to SSR; $fetch did not, leaving the
// SSR-rendered form empty and triggering hydration mismatches that left
// required textareas DOM-empty in dev.
if (route.query.edit) {
const { data: editEvent, error: editError } = await useFetch(
`/api/admin/events/${route.query.edit}`,
);
if (editError.value) {
console.error("Failed to load event for editing:", editError.value);
}
if (editEvent.value) populateEditForm(editEvent.value);
watch(editEvent, populateEditForm, { immediate: false });
}
// Check if we're duplicating an event // Check if we're duplicating an event
if (route.query.duplicate && import.meta.client) { if (route.query.duplicate && import.meta.client) {
const duplicateData = sessionStorage.getItem("duplicateEventData"); const duplicateData = sessionStorage.getItem("duplicateEventData");