feat: add QR code event check-in system
Backend: - Add event_checkin_tokens table with unique tokens per event - Implement GET /api/events/:slug/details endpoint (on-demand token generation) - Implement POST /api/events/checkin/:token endpoint (date validation only in production) - Implement DELETE /api/events/:slug/leave endpoint - Add comprehensive test suite for check-in endpoints Frontend: - Add EventDetailsPage with QR code display, participant list, and stats - Add EventCheckinPage with success/error screens - Add "Leave Event" button with confirmation modal to EventChatPage - Install qrcode.react library for QR code generation - Update routing and API client with new endpoints Features: - QR codes valid from (startDate-1d) to (endDate+1d) - Development mode bypasses date validation for testing - Automatic participant count tracking - Duplicate check-in prevention - Token reuse for same event (generated once, cached)
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "event_checkin_tokens" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"event_id" INTEGER NOT NULL,
|
||||
"token" VARCHAR(50) NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "event_checkin_tokens_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "event_checkin_tokens_event_id_key" ON "event_checkin_tokens"("event_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "event_checkin_tokens_token_key" ON "event_checkin_tokens"("token");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "event_checkin_tokens" ADD CONSTRAINT "event_checkin_tokens_event_id_fkey" FOREIGN KEY ("event_id") REFERENCES "events"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -75,10 +75,24 @@ model Event {
|
||||
chatRooms ChatRoom[]
|
||||
matches Match[]
|
||||
participants EventParticipant[]
|
||||
checkinToken EventCheckinToken?
|
||||
|
||||
@@map("events")
|
||||
}
|
||||
|
||||
// Event check-in tokens (QR code tokens for event access)
|
||||
model EventCheckinToken {
|
||||
id Int @id @default(autoincrement())
|
||||
eventId Int @unique @map("event_id")
|
||||
token String @unique @default(cuid()) @db.VarChar(50)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
// Relations
|
||||
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("event_checkin_tokens")
|
||||
}
|
||||
|
||||
// Chat rooms (event chat and private 1:1 chat)
|
||||
model ChatRoom {
|
||||
id Int @id @default(autoincrement())
|
||||
|
||||
Reference in New Issue
Block a user