Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion src/actions/attend-event.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"use server";

import { count, eq } from "drizzle-orm";

import db from "@/db";
import { eventAttendees } from "@/db/schema";
import { eventAttendees, events } from "@/db/schema";
import { auth } from "@/lib/auth";

export async function attendEvent(eventId: string): Promise<void> {
Expand All @@ -10,6 +12,35 @@ export async function attendEvent(eventId: string): Promise<void> {
if (!session?.user?.id) {
throw new Error("Unauthorized");
}

const event = await db
.select()
.from(events)
.where(eq(events.id, eventId))
.then((res) => res[0]);

if (!event) {
throw new Error("Event not found");
}

const capacity = event.capacity ?? 0;

const attendeeCount = await db
.select({ count: count() })
.from(eventAttendees)
.where(eq(eventAttendees.eventId, eventId));

if (attendeeCount[0].count >= capacity || capacity == 0) {
throw new Error("Event capacity reached");
}

const newCount = attendeeCount[0].count + 1;

await db
.update(events)
.set({ registeredUsers: newCount })
.where(eq(events.id, eventId));

await db
.insert(eventAttendees)
.values({
Expand Down
25 changes: 23 additions & 2 deletions src/actions/leave-event.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use server";

import { and, eq } from "drizzle-orm";
import { and, count, eq } from "drizzle-orm";

import db from "@/db";
import { eventAttendees } from "@/db/schema";
import { eventAttendees, events } from "@/db/schema";
import { auth } from "@/lib/auth";

export async function leaveEvent(eventId: string): Promise<void> {
Expand All @@ -13,6 +13,27 @@ export async function leaveEvent(eventId: string): Promise<void> {
throw new Error("Unauthorized");
}

const event = await db
.select()
.from(events)
.where(eq(events.id, eventId))
.then((res) => res[0]);

if (!event) {
throw new Error("Event not found");
}
const attendeeCount = await db
.select({ count: count() })
.from(eventAttendees)
.where(eq(eventAttendees.eventId, eventId));

const newCount = attendeeCount[0].count - 1;

await db
.update(events)
.set({ registeredUsers: newCount })
.where(eq(events.id, eventId));

// ✅ Remove the attendee row for this user + event
await db
.delete(eventAttendees)
Expand Down
2 changes: 2 additions & 0 deletions src/app/HomePageClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type HomePageClientProps = {
startTime: string;
endTime: string;
capacity: number | null;
registeredUsers: number | null;
streetLine: string;
description: string;
isRegistered?: boolean;
Expand Down Expand Up @@ -77,6 +78,7 @@ export default function HomePageClient({
startTime={event.startTime}
endTime={event.endTime}
capacity={event.capacity}
registeredUsers={event.registeredUsers}
streetLine={event.streetLine}
description={event.description}
isRegistered={event.isRegistered}
Expand Down
19 changes: 14 additions & 5 deletions src/app/VolunteerEventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type VolunteerEventCardProps = {
startTime: string;
endTime: string;
capacity: number | null;
registeredUsers: number | null;
streetLine: string;
description: string;
isRegistered?: boolean;
Expand All @@ -40,9 +41,9 @@ export default function VolunteerEventCard(
event.isRegistered ?? false,
);

React.useEffect(() => {
setIsRegistered(event.isRegistered ?? false);
}, [event.isRegistered]);
const [registeredUsers, setRegisteredUsers] = React.useState(
event.registeredUsers ?? 0,
);

const [isPending, setIsPending] = React.useState(false);

Expand Down Expand Up @@ -72,12 +73,20 @@ export default function VolunteerEventCard(
if (isRegistered) {
await leaveEvent(event.id);
setIsRegistered(false);
setRegisteredUsers((prev) => Math.max(prev - 1, 0));
} else {
await attendEvent(event.id);
setIsRegistered(true);
setRegisteredUsers((prev) => prev + 1);
}
} catch (error) {
console.error(error);
if (error instanceof Error) {
if (error.message === "Event capacity reached") {
alert("Sorry, this event is full! You cannot register.");
} else {
console.error(error.message);
}
}
} finally {
setIsPending(false);
}
Expand Down Expand Up @@ -105,7 +114,7 @@ export default function VolunteerEventCard(
<Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
<PersonIcon fontSize="small" />
<Typography variant="body2">
{event.capacity} slots remaining
{(event.capacity ?? 0) - registeredUsers} slots remaining
</Typography>
</Box>

Expand Down
2 changes: 2 additions & 0 deletions src/app/api/events/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export async function POST(req: Request): Promise<Response> {
const firstResult = Array.isArray(result) ? result[0] : undefined;
const latitude = firstResult?.lat ?? null;
const longitude = firstResult?.lon ?? null;
const registeredUsers = 0;

if (endTime <= startTime) {
return NextResponse.json(
Expand All @@ -70,6 +71,7 @@ export async function POST(req: Request): Promise<Response> {
startTime,
endTime,
capacity: capacity ?? null,
registeredUsers,
streetLine,
city,
state,
Expand Down
1 change: 1 addition & 0 deletions src/db/schema/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const events = pgTable("events", {
endTime: time("end_time").notNull(),

capacity: integer("capacity"),
registeredUsers: integer("registered_users"),

streetLine: text("street_line").notNull(),
city: text("city").notNull(),
Expand Down
Loading