feat(admin): improve export to put guests in their own row
This commit is contained in:
@@ -663,76 +663,24 @@ export const appRouter = {
|
||||
|
||||
const escapeCell = (val: string) => `"${val.replace(/"/g, '""')}"`;
|
||||
|
||||
// Main registration headers
|
||||
// Each person (registrant + guests) gets their own row.
|
||||
// Guest rows reference the registrant via "Registration ID".
|
||||
const headers = [
|
||||
"ID",
|
||||
"Row Type", // "registrant" | "guest"
|
||||
"Registration ID", // UUID of the parent registration (same for registrant + its guests)
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Email",
|
||||
"Phone",
|
||||
"Birthdate",
|
||||
"Postcode",
|
||||
// Registrant-only fields (blank for guest rows)
|
||||
"Type",
|
||||
"Art Form",
|
||||
"Experience",
|
||||
"Is Over 16",
|
||||
"Drink Card Value (EUR)",
|
||||
"Gift Amount (cents)",
|
||||
"Guest Count",
|
||||
"Guest 1 First Name",
|
||||
"Guest 1 Last Name",
|
||||
"Guest 1 Email",
|
||||
"Guest 1 Phone",
|
||||
"Guest 1 Birthdate",
|
||||
"Guest 1 Postcode",
|
||||
"Guest 2 First Name",
|
||||
"Guest 2 Last Name",
|
||||
"Guest 2 Email",
|
||||
"Guest 2 Phone",
|
||||
"Guest 2 Birthdate",
|
||||
"Guest 2 Postcode",
|
||||
"Guest 3 First Name",
|
||||
"Guest 3 Last Name",
|
||||
"Guest 3 Email",
|
||||
"Guest 3 Phone",
|
||||
"Guest 3 Birthdate",
|
||||
"Guest 3 Postcode",
|
||||
"Guest 4 First Name",
|
||||
"Guest 4 Last Name",
|
||||
"Guest 4 Email",
|
||||
"Guest 4 Phone",
|
||||
"Guest 4 Birthdate",
|
||||
"Guest 4 Postcode",
|
||||
"Guest 5 First Name",
|
||||
"Guest 5 Last Name",
|
||||
"Guest 5 Email",
|
||||
"Guest 5 Phone",
|
||||
"Guest 5 Birthdate",
|
||||
"Guest 5 Postcode",
|
||||
"Guest 6 First Name",
|
||||
"Guest 6 Last Name",
|
||||
"Guest 6 Email",
|
||||
"Guest 6 Phone",
|
||||
"Guest 6 Birthdate",
|
||||
"Guest 6 Postcode",
|
||||
"Guest 7 First Name",
|
||||
"Guest 7 Last Name",
|
||||
"Guest 7 Email",
|
||||
"Guest 7 Phone",
|
||||
"Guest 7 Birthdate",
|
||||
"Guest 7 Postcode",
|
||||
"Guest 8 First Name",
|
||||
"Guest 8 Last Name",
|
||||
"Guest 8 Email",
|
||||
"Guest 8 Phone",
|
||||
"Guest 8 Birthdate",
|
||||
"Guest 8 Postcode",
|
||||
"Guest 9 First Name",
|
||||
"Guest 9 Last Name",
|
||||
"Guest 9 Email",
|
||||
"Guest 9 Phone",
|
||||
"Guest 9 Birthdate",
|
||||
"Guest 9 Postcode",
|
||||
"Payment Status",
|
||||
"Paid At",
|
||||
"Extra Questions",
|
||||
@@ -740,24 +688,28 @@ export const appRouter = {
|
||||
"Created At",
|
||||
];
|
||||
|
||||
const MAX_GUESTS = 9;
|
||||
const rows: string[][] = [];
|
||||
|
||||
const rows = data.map((r) => {
|
||||
const guests = parseGuestsJson(r.guests);
|
||||
for (const r of data) {
|
||||
const guests = parseGuestsJson(r.guests) as Array<{
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
birthdate?: string;
|
||||
postcode?: string;
|
||||
}>;
|
||||
|
||||
// Build guest columns (up to 9 guests, 6 fields each)
|
||||
const guestCols: string[] = [];
|
||||
for (let i = 0; i < MAX_GUESTS; i++) {
|
||||
const g = guests[i];
|
||||
guestCols.push(g?.firstName ?? "");
|
||||
guestCols.push(g?.lastName ?? "");
|
||||
guestCols.push(g?.email ?? "");
|
||||
guestCols.push(g?.phone ?? "");
|
||||
guestCols.push((g as { birthdate?: string })?.birthdate ?? "");
|
||||
guestCols.push((g as { postcode?: string })?.postcode ?? "");
|
||||
}
|
||||
const paymentStatus =
|
||||
r.paymentStatus === "paid"
|
||||
? "Paid"
|
||||
: r.paymentStatus === "extra_payment_pending"
|
||||
? "Extra Payment Pending"
|
||||
: "Pending";
|
||||
|
||||
return [
|
||||
// Registrant row
|
||||
rows.push([
|
||||
"registrant",
|
||||
r.id,
|
||||
r.firstName,
|
||||
r.lastName,
|
||||
@@ -771,19 +723,39 @@ export const appRouter = {
|
||||
r.isOver16 ? "Yes" : "No",
|
||||
String(r.drinkCardValue ?? 0),
|
||||
String(r.giftAmount ?? 0),
|
||||
String(guests.length),
|
||||
...guestCols,
|
||||
r.paymentStatus === "paid"
|
||||
? "Paid"
|
||||
: r.paymentStatus === "extra_payment_pending"
|
||||
? "Extra Payment Pending"
|
||||
: "Pending",
|
||||
paymentStatus,
|
||||
r.paidAt ? r.paidAt.toISOString() : "",
|
||||
r.extraQuestions || "",
|
||||
r.cancelledAt ? r.cancelledAt.toISOString() : "",
|
||||
r.createdAt.toISOString(),
|
||||
];
|
||||
});
|
||||
]);
|
||||
|
||||
// One row per guest — link back to parent registration via Registration ID
|
||||
for (const g of guests) {
|
||||
rows.push([
|
||||
"guest",
|
||||
r.id,
|
||||
g.firstName,
|
||||
g.lastName,
|
||||
g.email || "",
|
||||
g.phone || "",
|
||||
g.birthdate || "",
|
||||
g.postcode || "",
|
||||
// Registrant-only fields left blank
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const csvContent = [
|
||||
headers.map(escapeCell).join(","),
|
||||
|
||||
Reference in New Issue
Block a user