From 5f9019cef188092344516f17dc454aabf565e5e6 Mon Sep 17 00:00:00 2001 From: Sam Der Date: Fri, 26 Jan 2024 13:43:33 -0800 Subject: [PATCH] Confirm non-hacker attendance from PMS (#368) * Add confirm option for non-hackers in admin portal * update: use swr mutate on useParticipant hook * show non-hacker confirm button for waiver signed * refactor: use mutate from useSWR hook --- .../app/admin/participants/Participants.tsx | 3 ++- .../components/ParticipantAction.tsx | 27 +++++++++++++++++-- .../components/ParticipantsTable.tsx | 5 +++- apps/site/src/lib/admin/authorization.ts | 12 +++++++++ apps/site/src/lib/admin/useParticipants.ts | 11 +++++++- 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/apps/site/src/app/admin/participants/Participants.tsx b/apps/site/src/app/admin/participants/Participants.tsx index 9f7617f9..52d59963 100644 --- a/apps/site/src/app/admin/participants/Participants.tsx +++ b/apps/site/src/app/admin/participants/Participants.tsx @@ -14,6 +14,7 @@ function Participants() { loading, checkInParticipant, releaseParticipantFromWaitlist, + confirmNonHacker, } = useParticipants(); const [checkinParticipant, setCheckinParticipant] = useState(null); @@ -49,6 +50,7 @@ function Participants() { loading={loading} initiateCheckIn={initiateCheckIn} initiatePromotion={initiatePromotion} + initiateConfirm={confirmNonHacker} /> setCheckinParticipant(null)} @@ -60,7 +62,6 @@ function Participants() { onConfirm={sendWaitlistPromote} participant={promoteParticipant} /> - {/* TODO: walk-in promotion modal */} ); } diff --git a/apps/site/src/app/admin/participants/components/ParticipantAction.tsx b/apps/site/src/app/admin/participants/components/ParticipantAction.tsx index ce2afedd..6afafa85 100644 --- a/apps/site/src/app/admin/participants/components/ParticipantAction.tsx +++ b/apps/site/src/app/admin/participants/components/ParticipantAction.tsx @@ -3,7 +3,7 @@ import { useContext } from "react"; import Button from "@cloudscape-design/components/button"; import UserContext from "@/lib/admin/UserContext"; -import { isCheckinLead } from "@/lib/admin/authorization"; +import { isCheckinLead, isNonHacker } from "@/lib/admin/authorization"; import { Status } from "@/lib/admin/useApplicant"; import { Participant } from "@/lib/admin/useParticipants"; import ParticipantActionPopover from "./ParticipantActionPopover"; @@ -12,18 +12,21 @@ interface ParticipantActionProps { participant: Participant; initiateCheckIn: (participant: Participant) => void; initiatePromotion: (participant: Participant) => void; + initiateConfirm: (participant: Participant) => void; } function ParticipantAction({ participant, initiateCheckIn, initiatePromotion, + initiateConfirm, }: ParticipantActionProps) { const { role } = useContext(UserContext); const isCheckin = isCheckinLead(role); const isWaiverSigned = participant.status === Status.signed; const isAccepted = participant.status === Status.accepted; + const nonHacker = isNonHacker(participant.role); const promoteButton = ( + ); + + if (nonHacker && isWaiverSigned) { + if (role !== "director") { + return ( + + {confirmButton} + + ); + } + return confirmButton; + } else if (participant.status === Status.waitlisted) { if (!isCheckin) { return ( diff --git a/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx b/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx index e90f4155..a63a4a16 100644 --- a/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx +++ b/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx @@ -22,6 +22,7 @@ interface ParticipantsTableProps { loading: boolean; initiateCheckIn: (participant: Participant) => void; initiatePromotion: (participant: Participant) => void; + initiateConfirm: (participant: Participant) => void; } function ParticipantsTable({ @@ -29,6 +30,7 @@ function ParticipantsTable({ loading, initiateCheckIn, initiatePromotion, + initiateConfirm, }: ParticipantsTableProps) { // TODO: sorting // TODO: search functionality @@ -40,9 +42,10 @@ function ParticipantsTable({ participant={participant} initiateCheckIn={initiateCheckIn} initiatePromotion={initiatePromotion} + initiateConfirm={initiateConfirm} /> ), - [initiateCheckIn, initiatePromotion], + [initiateCheckIn, initiatePromotion, initiateConfirm], ); const emptyMessage = ( diff --git a/apps/site/src/lib/admin/authorization.ts b/apps/site/src/lib/admin/authorization.ts index aff6bf25..42cbd134 100644 --- a/apps/site/src/lib/admin/authorization.ts +++ b/apps/site/src/lib/admin/authorization.ts @@ -1,6 +1,13 @@ const ADMIN_ROLES = ["director", "reviewer", "checkin_lead"]; const CHECKIN_ROLES = ["director", "checkin_lead"]; const ORGANIZER_ROLES = ["organizer"]; +const NONHACKER_ROLES = [ + "judge", + "sponsor", + "mentor", + "volunteer", + "workshop_lead", +]; export function isApplicationManager(role: string | null) { return role !== null && ADMIN_ROLES.includes(role); @@ -16,3 +23,8 @@ export function isAdminRole(role: string | null) { export function isCheckinLead(role: string | null) { return role !== null && CHECKIN_ROLES.includes(role); } + +// refactor: this function should be placed elsewhere later +export function isNonHacker(role: string | null) { + return role !== null && NONHACKER_ROLES.includes(role); +} diff --git a/apps/site/src/lib/admin/useParticipants.ts b/apps/site/src/lib/admin/useParticipants.ts index 7376524b..f83d56f0 100644 --- a/apps/site/src/lib/admin/useParticipants.ts +++ b/apps/site/src/lib/admin/useParticipants.ts @@ -32,7 +32,7 @@ const fetcher = async (url: string) => { }; function useParticipants() { - const { data, error, isLoading } = useSWR( + const { data, error, isLoading, mutate } = useSWR( "/api/admin/participants", fetcher, ); @@ -41,12 +41,20 @@ function useParticipants() { console.log("Checking in", participant); // TODO: implement mutation for showing checked in on each day await axios.post(`/api/admin/checkin/${participant._id}`); + mutate(); }; const releaseParticipantFromWaitlist = async (participant: Participant) => { console.log(`Promoted to waitlist`, participant); // TODO: implement mutation for showing checked in on each day await axios.post(`/api/admin/waitlist-release/${participant._id}`); + mutate(); + }; + + const confirmNonHacker = async (participant: Participant) => { + console.log("Confirmed attendance for non-hacker", participant); + await axios.post(`/api/admin/update-attendance/${participant._id}`); + mutate(); }; return { @@ -55,6 +63,7 @@ function useParticipants() { error, checkInParticipant, releaseParticipantFromWaitlist, + confirmNonHacker, }; }