Skip to content

Commit

Permalink
Confirm non-hacker attendance from PMS (#368)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
samderanova authored Jan 26, 2024
1 parent 365683d commit 5f9019c
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 5 deletions.
3 changes: 2 additions & 1 deletion apps/site/src/app/admin/participants/Participants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ function Participants() {
loading,
checkInParticipant,
releaseParticipantFromWaitlist,
confirmNonHacker,
} = useParticipants();
const [checkinParticipant, setCheckinParticipant] =
useState<Participant | null>(null);
Expand Down Expand Up @@ -49,6 +50,7 @@ function Participants() {
loading={loading}
initiateCheckIn={initiateCheckIn}
initiatePromotion={initiatePromotion}
initiateConfirm={confirmNonHacker}
/>
<CheckInModal
onDismiss={() => setCheckinParticipant(null)}
Expand All @@ -60,7 +62,6 @@ function Participants() {
onConfirm={sendWaitlistPromote}
participant={promoteParticipant}
/>
{/* TODO: walk-in promotion modal */}
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 = (
<Button
Expand All @@ -47,7 +50,27 @@ function ParticipantAction({
</Button>
);

if (participant.status === Status.waitlisted) {
const confirmButton = (
<Button
variant="inline-link"
ariaLabel={`Confirm attendance for ${participant._id}`}
onClick={() => initiateConfirm(participant)}
disabled={!isCheckin}
>
Confirm
</Button>
);

if (nonHacker && isWaiverSigned) {
if (role !== "director") {
return (
<ParticipantActionPopover content="Only directors are allowed to confirm non-hackers.">
{confirmButton}
</ParticipantActionPopover>
);
}
return confirmButton;
} else if (participant.status === Status.waitlisted) {
if (!isCheckin) {
return (
<ParticipantActionPopover content="Only check-in leads are allowed to promote walk-ins.">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ interface ParticipantsTableProps {
loading: boolean;
initiateCheckIn: (participant: Participant) => void;
initiatePromotion: (participant: Participant) => void;
initiateConfirm: (participant: Participant) => void;
}

function ParticipantsTable({
participants,
loading,
initiateCheckIn,
initiatePromotion,
initiateConfirm,
}: ParticipantsTableProps) {
// TODO: sorting
// TODO: search functionality
Expand All @@ -40,9 +42,10 @@ function ParticipantsTable({
participant={participant}
initiateCheckIn={initiateCheckIn}
initiatePromotion={initiatePromotion}
initiateConfirm={initiateConfirm}
/>
),
[initiateCheckIn, initiatePromotion],
[initiateCheckIn, initiatePromotion, initiateConfirm],
);

const emptyMessage = (
Expand Down
12 changes: 12 additions & 0 deletions apps/site/src/lib/admin/authorization.ts
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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);
}
11 changes: 10 additions & 1 deletion apps/site/src/lib/admin/useParticipants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const fetcher = async (url: string) => {
};

function useParticipants() {
const { data, error, isLoading } = useSWR<Participant[]>(
const { data, error, isLoading, mutate } = useSWR<Participant[]>(
"/api/admin/participants",
fetcher,
);
Expand All @@ -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 {
Expand All @@ -55,6 +63,7 @@ function useParticipants() {
error,
checkInParticipant,
releaseParticipantFromWaitlist,
confirmNonHacker,
};
}

Expand Down

0 comments on commit 5f9019c

Please sign in to comment.