Skip to content

Commit bfab08c

Browse files
feat: click action on event button
1 parent bd05d14 commit bfab08c

16 files changed

Lines changed: 1009 additions & 810 deletions

File tree

apps/api/go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
5656
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
5757
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
5858
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
59-
github.com/oapi-codegen/nullable v1.1.0 h1:eAh8JVc5430VtYVnq00Hrbpag9PFRGWLjxR1/3KntMs=
60-
github.com/oapi-codegen/nullable v1.1.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY=
6159
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
6260
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6361
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@tanstack/react-table": "^8.21.3",
3737
"axios": "^1.9.0",
3838
"clsx": "^2.1.1",
39+
"date-fns": "^4.1.0",
3940
"js-cookie": "^3.0.5",
4041
"ky": "^1.8.1",
4142
"nanoid": "^5.1.5",

apps/web/pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/web/src/features/Admin/EventManager/hooks/useAdminEvents.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ type Events =
88
operations["get-events"]["responses"]["200"]["content"]["application/json"];
99

1010
export async function fetchEvents(): Promise<Events> {
11-
const result = await api.get<Events>("events?include_unpublished=true").json();
11+
const result = await api
12+
.get<Events>("events?include_unpublished=true")
13+
.json();
1214
console.log(result);
1315
return result;
1416
}

apps/web/src/features/Event/components/EventButton.tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { tv } from "tailwind-variants";
33
import applicationStatus from "../applicationStatus";
44
import { Button, button, type ButtonProps } from "@/components/ui/Button";
55
import { cn } from "@/utils/cn";
6+
import { useRouter } from "@tanstack/react-router";
67

78
type ApplicationStatusTypes = keyof typeof applicationStatus;
89

@@ -25,11 +26,13 @@ export const eventButton = tv({
2526

2627
interface EventButtonProps extends ButtonProps {
2728
status: ApplicationStatusTypes;
29+
eventId: string;
2830
text?: string;
2931
}
3032

3133
const EventButton = ({
3234
status: statusProp,
35+
eventId,
3336
className,
3437
text,
3538
}: EventButtonProps) => {
@@ -38,11 +41,64 @@ const EventButton = ({
3841
variant: "skeleton",
3942
className,
4043
});
44+
const router = useRouter();
45+
46+
const onClick = () => {
47+
switch (statusProp) {
48+
case "accepted":
49+
// Make API call and then navigate to dashboard with accepted query param
50+
console.log("Accepted button clicked for event");
51+
router.navigate({
52+
to: `/events/${eventId}/dashboard`,
53+
});
54+
break;
55+
case "attending":
56+
case "staff":
57+
case "admin":
58+
case "underReview":
59+
// Navigate to the dashboard
60+
router.navigate({
61+
to: `/events/${eventId}/dashboard`,
62+
});
63+
break;
64+
case "waitlisted":
65+
// Navigate to the waitlist page
66+
router.navigate({
67+
to: `/events/${eventId}/waitlist/info`,
68+
});
69+
break;
70+
case "rejected":
71+
// Navigate to the event info page
72+
router.navigate({
73+
to: `/events/${eventId}/rejected`,
74+
});
75+
break;
76+
case "notApplied":
77+
// Navigate to the application page
78+
router.navigate({
79+
to: `/events/${eventId}/application`,
80+
});
81+
break;
82+
case "notGoing":
83+
// Navigate to the event info page
84+
router.navigate({
85+
to: `/events/${eventId}/feedback/decline`,
86+
});
87+
break;
88+
case "completed":
89+
// Navigate to the event info page
90+
router.navigate({
91+
to: `/events/${eventId}/summary`,
92+
});
93+
break;
94+
}
95+
};
4196

4297
return (
4398
<Button
4499
variant="skeleton"
45100
className={cn(eventButtonClassName, "font-semibold")}
101+
onClick={onClick}
46102
>
47103
{text || applicationStatus[statusProp].button.text}
48104
</Button>

apps/web/src/features/Event/components/EventCard.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,24 @@ const EventCard = ({
7070

7171
{status === "accepted" ? (
7272
<div className="flex gap-2">
73-
<EventButton className="w-full mt-4" status={status} />
73+
<EventButton
74+
className="w-full mt-4"
75+
status={status}
76+
eventId={eventId}
77+
/>
7478
<EventButton
7579
className="w-full mt-4"
7680
status="notGoing"
7781
text="Not Going"
82+
eventId={eventId}
7883
/>
7984
</div>
8085
) : (
81-
<EventButton className="w-full mt-4" status={status} />
86+
<EventButton
87+
className="w-full mt-4"
88+
status={status}
89+
eventId={eventId}
90+
/>
8291
)}
8392
</div>
8493
</Card>
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
import { api } from "@/lib/ky";
22
import type { operations } from "@/lib/openapi/schema";
33
import { useQuery } from "@tanstack/react-query";
4+
import { mapEventsAPIResponseToEventCardProps } from "../utils/mapper";
45

56
export const eventsQueryKey = ["events", "published"] as const;
67

78
export type EventsWithUserInfo =
89
operations["get-events"]["responses"]["200"]["content"]["application/json"];
910

1011
export async function fetchEvents(): Promise<EventsWithUserInfo> {
11-
const result = await api.get<EventsWithUserInfo>("events?include_unpublished=false").json();
12+
const result = await api
13+
.get<EventsWithUserInfo>("events?include_unpublished=false")
14+
.json();
1215
return result;
1316
}
1417

15-
export function useAdminEvents() {
18+
export function useEventsWithUserInfo() {
1619
return useQuery({
1720
queryKey: eventsQueryKey,
1821
queryFn: fetchEvents,
19-
staleTime: 1000 * 60 * 5, // 5 minutes
22+
staleTime: 1000 * 60 * 5, // 5 minutes,
23+
select: (data) => data.map(mapEventsAPIResponseToEventCardProps),
2024
});
2125
}

apps/web/src/features/Event/utils/mapper.ts

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,71 @@ function formatDateRange(start: Date, end: Date): string {
2121
return `${startMonth} ${startDay} - ${endMonth} ${endDay}`;
2222
}
2323

24-
function mapEventsAPIResponseToEventCardProps(data: EventWithUserInfo): EventCardProps {
25-
let status: keyof typeof applicationStatus = "notApplied" // Default
26-
27-
if (!data.application_status) {
28-
return {
29-
eventId: data.id,
30-
status,
31-
title: data.name,
32-
description: data.description ?? "No description",
33-
date:
34-
}
35-
}
24+
export function mapEventsAPIResponseToEventCardProps(
25+
data: EventWithUserInfo,
26+
): EventCardProps {
27+
let status: keyof typeof applicationStatus = "notApplied"; // Default
3628

37-
switch (data.application_status?.application_status) {
38-
case "under_review" && data.application_status?.valid == true:
29+
if (!data.application_status) {
30+
return {
31+
eventId: data.id,
32+
status,
33+
title: data.name,
34+
description: data.description ?? "No description",
35+
date: formatDateRange(new Date(data.start_time), new Date(data.end_time)),
36+
location: data.location ?? "Unknown",
37+
};
38+
}
3939

40+
// Handle roles cases
41+
if (data.event_role?.event_role_type === "staff") {
42+
status = "staff";
43+
} else if (data.event_role?.event_role_type === "admin") {
44+
status = "admin";
45+
} else if (data.event_role?.event_role_type === "attendee") {
46+
status = "attending";
47+
} else if (data.event_role?.event_role_type === "applicant") {
48+
// Handle application cases
49+
switch (data.application_status.application_status) {
50+
case "accepted":
51+
status = "accepted";
52+
break;
53+
case "rejected":
54+
status = "rejected";
55+
break;
56+
case "waitlisted":
57+
status = "waitlisted";
58+
break;
59+
case "submitted":
60+
case "under_review":
61+
status = "underReview";
62+
break;
63+
case "started":
64+
status = "notApplied";
65+
break;
66+
case "withdrawn":
67+
status = "notGoing";
68+
break;
69+
default:
70+
status = "notApplied"; // Default case
71+
break;
4072
}
41-
}
73+
} else {
74+
// If no specific role or application status, default to notApplied
75+
status = "notApplied";
76+
}
4277

78+
// Check if the event is completed
79+
if (new Date(data.end_time) < new Date()) {
80+
status = "completed";
81+
}
82+
83+
return {
84+
eventId: data.id,
85+
status,
86+
title: data.name,
87+
description: data.description ?? "No description",
88+
date: formatDateRange(new Date(data.start_time), new Date(data.end_time)),
89+
location: data.location ?? "Unknown",
90+
};
91+
}

0 commit comments

Comments
 (0)