Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confirm non-hacker attendance from PMS #368

Merged
merged 4 commits into from
Jan 26, 2024
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
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;
samderanova marked this conversation as resolved.
Show resolved Hide resolved
} 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 @@ -17,13 +17,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 @@ -35,9 +37,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);
}
samderanova marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -29,7 +29,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 @@ -38,12 +38,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 @@ -52,6 +60,7 @@ function useParticipants() {
error,
checkInParticipant,
releaseParticipantFromWaitlist,
confirmNonHacker,
};
}

Expand Down
Loading