logic for eventGuests

This commit is contained in:
2025-06-28 15:00:08 -04:00
parent b2f3be0f0c
commit dee9066c91
8 changed files with 174 additions and 2 deletions

View File

@@ -0,0 +1,18 @@
import { NextResponse } from 'next/server'
import { mutations } from '@/lib/mutations'
export async function DELETE(_: Request, { params }: { params: { eventId: string; entryId: string } }) {
const { eventId, entryId: guestBookEntryId } = params
if (!eventId || !guestBookEntryId) {
return NextResponse.json({ message: 'Missing eventId or guestBookEntryId' }, { status: 400 })
}
try {
await mutations.removeEventGuest(eventId, guestBookEntryId)
return NextResponse.json({ success: true })
} catch (error) {
console.error('Remove Guest Error:', error)
return NextResponse.json({ message: 'Failed to remove guest from event' }, { status: 500 })
}
}

View File

@@ -0,0 +1,20 @@
// app/api/events/[eventId]/guests/[entryId]/rsvp/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { mutations } from '@/lib/mutations'
export async function PATCH(req: NextRequest, { params }: { params: { eventId: string; entryId: string } }) {
const { eventId, entryId: guestBookEntryId } = params
const { rsvp } = await req.json()
if (!['YES', 'NO', 'PENDING'].includes(rsvp)) {
return NextResponse.json({ message: 'Invalid RSVP status' }, { status: 400 })
}
try {
const updated = await mutations.updateEventGuestRsvp({ eventId, guestBookEntryId, rsvp })
return NextResponse.json(updated)
} catch (error) {
console.error('RSVP Update Error:', error)
return NextResponse.json({ message: 'Failed to update RSVP status' }, { status: 500 })
}
}

View File

@@ -0,0 +1,19 @@
import { NextRequest, NextResponse } from 'next/server'
import { mutations } from '@/lib/mutations'
export async function POST(req: NextRequest, { params }: { params: { eventId: string } }) {
const eventId = params.eventId
const { guestBookEntryId } = await req.json()
if (!eventId || !guestBookEntryId) {
return NextResponse.json({ message: 'Missing eventId or guestBookEntryId' }, { status: 400 })
}
try {
const added = await mutations.addEventGuest({ eventId, guestBookEntryId })
return NextResponse.json(added)
} catch (error) {
console.error('Add Event Guest Error:', error)
return NextResponse.json({ message: 'Failed to add guest to event' }, { status: 500 })
}
}

View File

@@ -1,5 +1,3 @@
version: '3.8'
services: services:
db: db:
image: postgres:15 image: postgres:15

View File

@@ -117,4 +117,47 @@ export const mutations = {
}) })
}, },
async addEventGuest({
eventId,
guestBookEntryId,
}: {
eventId: string,
guestBookEntryId: string,
}) {
return await prisma.eventGuest.create({
data: {
eventId,
guestBookEntryId,
rsvp: 'PENDING'
}
})
},
async updateEventGuestRsvp({
eventId,
guestBookEntryId,
rsvp,
}: {
eventId: string;
guestBookEntryId: string;
rsvp: 'YES' | 'NO' | 'PENDING';
}) {
return await prisma.eventGuest.update({
where: {
eventId_guestBookEntryId: { eventId, guestBookEntryId }, // compound unique constraint
},
data: {
rsvp,
},
});
},
async removeEventGuest(eventId: string, guestBookEntryId: string) {
return await prisma.eventGuest.delete({
where: {
eventId_guestBookEntryId: { eventId, guestBookEntryId },
},
});
},
}; };

View File

@@ -16,6 +16,48 @@ export const queries = {
return allEvents; return allEvents;
}, },
async fetchEventGuests(eventId: string) {
return await prisma.eventGuest.findMany({
where: { eventId },
include: {
guestBookEntry: true,
},
orderBy: [
{
guestBookEntry: {
lName: 'asc',
},
},
{
guestBookEntry: {
fName: 'asc'
}
}
],
});
},
async fetchAvailableGuestBookEntriesForEvent(eventId: string) {
const invitedGuests = await prisma.eventGuest.findMany({
where: { eventId },
select: { guestBookEntryId: true }
});
const excludeIds = invitedGuests.map(g => g.guestBookEntryId);
return prisma.guestBookEntry.findMany({
where: {
id: {
notIn: excludeIds,
},
},
orderBy: [
{ lName: 'asc' },
{ fName: 'asc' }
]
})
},
async singleEvent(id: string) { async singleEvent(id: string) {
const event = await prisma.event.findUnique({ const event = await prisma.event.findUnique({
where: { id }, where: { id },

View File

@@ -0,0 +1,19 @@
-- CreateTable
CREATE TABLE "EventGuest" (
"id" TEXT NOT NULL,
"eventId" TEXT NOT NULL,
"guestBookEntryId" TEXT NOT NULL,
"rsvp" "RsvpStatus" NOT NULL DEFAULT 'PENDING',
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "EventGuest_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "EventGuest_eventId_guestBookEntryId_key" ON "EventGuest"("eventId", "guestBookEntryId");
-- AddForeignKey
ALTER TABLE "EventGuest" ADD CONSTRAINT "EventGuest_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "Event"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "EventGuest" ADD CONSTRAINT "EventGuest_guestBookEntryId_fkey" FOREIGN KEY ("guestBookEntryId") REFERENCES "GuestBookEntry"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@@ -32,6 +32,7 @@ model Event {
creator User @relation("EventCreator", fields: [creatorId], references: [id]) creator User @relation("EventCreator", fields: [creatorId], references: [id])
creatorId String creatorId String
guests Guest[] guests Guest[]
eventGuests EventGuest[]
createdAt DateTime @default(now()) createdAt DateTime @default(now())
} }
@@ -70,7 +71,19 @@ model GuestBookEntry {
address String? address String?
notes String? notes String?
side String // e.g., "Brian", "Janice", etc. side String // e.g., "Brian", "Janice", etc.
eventGuests EventGuest[]
createdAt DateTime @default(now()) createdAt DateTime @default(now())
} }
model EventGuest {
id String @id @default(cuid())
event Event @relation(fields: [eventId], references: [id])
eventId String
guestBookEntry GuestBookEntry @relation(fields: [guestBookEntryId], references: [id])
guestBookEntryId String
rsvp RsvpStatus @default(PENDING)
createdAt DateTime @default(now())
@@unique([eventId, guestBookEntryId])
}