diff --git a/packages/api/src/routers/index.ts b/packages/api/src/routers/index.ts index 4383f76..d16c203 100644 --- a/packages/api/src/routers/index.ts +++ b/packages/api/src/routers/index.ts @@ -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(","),