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
if (route.query.edit) {
try {
const response = await $fetch(`/api/admin/events/${route.query.edit}`);
const event = response.data;
if (event) {
editingEvent.value = event;
Object.assign(eventForm, {
title: event.title,
description: event.description,
content: event.content || "",
featureImage: event.featureImage || null,
startDate: formatForDatetimeLocal(event.startDate),
endDate: formatForDatetimeLocal(event.endDate),
eventType: event.eventType,
location: event.location || "",
isOnline: event.isOnline,
isVisible: event.isVisible !== undefined ? event.isVisible : true,
isCancelled: event.isCancelled || false,
cancellationMessage: event.cancellationMessage || "",
targetCircles: event.targetCircles || [],
tags: event.tags || [],
maxAttendees: event.maxAttendees || "",
registrationRequired: event.registrationRequired,
registrationDeadline: formatForDatetimeLocal(event.registrationDeadline),
agenda: event.agenda || [],
tickets: event.tickets || {
enabled: false,
public: {
available: false,
name: "Public Ticket",
description: "",
price: 0,
quantity: null,
earlyBirdPrice: null,
earlyBirdDeadline: "",
},
},
series: event.series || {
isSeriesEvent: false,
id: "",
title: "",
description: "",
},
});
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);
function populateEditForm(payload) {
const event = payload?.data;
if (!event) return;
editingEvent.value = event;
Object.assign(eventForm, {
title: event.title,
description: event.description,
content: event.content || "",
featureImage: event.featureImage || null,
startDate: formatForDatetimeLocal(event.startDate),
endDate: formatForDatetimeLocal(event.endDate),
eventType: event.eventType,
location: event.location || "",
isOnline: event.isOnline,
isVisible: event.isVisible !== undefined ? event.isVisible : true,
isCancelled: event.isCancelled || false,
cancellationMessage: event.cancellationMessage || "",
targetCircles: event.targetCircles || [],
tags: event.tags || [],
maxAttendees: event.maxAttendees || "",
registrationRequired: event.registrationRequired,
registrationDeadline: formatForDatetimeLocal(event.registrationDeadline),
agenda: event.agenda || [],
tickets: event.tickets || {
enabled: false,
public: {
available: false,
name: "Public Ticket",
description: "",
price: 0,
quantity: null,
earlyBirdPrice: null,
earlyBirdDeadline: "",
},
},
series: event.series || {
isSeriesEvent: false,
id: "",
title: "",
description: "",
},
});
if (event.tickets?.public?.earlyBirdDeadline) {
eventForm.tickets.public.earlyBirdDeadline = formatForDatetimeLocal(
event.tickets.public.earlyBirdDeadline,
);
}
}
// 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
if (route.query.duplicate && import.meta.client) {
const duplicateData = sessionStorage.getItem("duplicateEventData");