Skip to content

Commit

Permalink
Merge branch 'main' into feature/checkin-barcode
Browse files Browse the repository at this point in the history
  • Loading branch information
taesungh authored Jan 26, 2024
2 parents db8983e + 06075bb commit c72a97a
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 10 deletions.
2 changes: 1 addition & 1 deletion apps/api/src/admin/participant_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ async def confirm_attendance_non_hacker(uid: str, director: User) -> None:
if not record or record["role"] not in NON_HACKER_ROLES:
raise ValueError

update_status = await mongodb_handler.raw_update_one(
update_status = await mongodb_handler.update_one(
Collection.USERS,
{"_id": uid},
{"status": Status.ATTENDING},
Expand Down
5 changes: 4 additions & 1 deletion apps/api/src/routers/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,10 @@ async def check_in_participant(
"/update-attendance/{uid}",
)
async def update_attendance(
uid: str, director: Annotated[User, Depends(require_role([Role.DIRECTOR]))]
uid: str,
director: Annotated[
User, Depends(require_role([Role.DIRECTOR, Role.CHECKIN_LEAD]))
],
) -> None:
"""Update status to Role.ATTENDING for non-hackers."""
try:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const ShiftingCountdown = () => {
{countdown.showFireworks && (
<div className="flex justify-center">
<Fireworks
className="w-full h-full absolute"
className="w-full h-full absolute pointer-events-none"
options={{
opacity: 0.1,
}}
Expand Down
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,27 +3,30 @@ import { useContext } from "react";
import Button from "@cloudscape-design/components/button";

import UserContext from "@/lib/admin/UserContext";
import { isCheckinLead } from "@/lib/admin/authorization";
import { Status } from "@/lib/admin/useApplicant";
import { isCheckinLead, isNonHacker } from "@/lib/admin/authorization";
import { ReviewStatus, Status } from "@/lib/admin/useApplicant";
import { Participant } from "@/lib/admin/useParticipants";
import ParticipantActionPopover from "./ParticipantActionPopover";

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,30 @@ 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) {
const content = !isCheckinLead
? "Only check-in leads can confirm non-hackers."
: "Must sign waiver first.";
if (!isCheckinLead || participant.status === ReviewStatus.reviewed) {
return (
<ParticipantActionPopover content={content}>
{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
2 changes: 1 addition & 1 deletion apps/site/src/components/dom/SceneLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const SceneLayout = ({ children }: PropsWithChildren) => {
position: "relative",
width: " 100%",
height: "100%",
overflowX: "hidden",
overflow: "hidden",
touchAction: "auto",
}}
>
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 @@ -33,7 +33,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 @@ -47,12 +47,20 @@ function useParticipants() {
`/api/admin/checkin/${participant._id}`,
participant.badge_number,
);
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 @@ -61,6 +69,7 @@ function useParticipants() {
error,
checkInParticipant,
releaseParticipantFromWaitlist,
confirmNonHacker,
};
}

Expand Down

0 comments on commit c72a97a

Please sign in to comment.