Skip to content

Commit

Permalink
Integrate check-in action with Participants table (#341)
Browse files Browse the repository at this point in the history
- When **Check In** action is used, show a modal with a confirmation
- Make POST request to check-in endpoint upon confirmation
- Several tasks still left as TODO
  - Need to add mutation for showing checked in on each day
  - Need to add actual instructions for check-in associates
  - Need to add Flashbar for notifications after modal completion
- Will use a similar approach for the walk-in promotion modal
  • Loading branch information
taesungh authored Jan 24, 2024
1 parent 8fdd01c commit e10d102
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 10 deletions.
32 changes: 28 additions & 4 deletions apps/site/src/app/admin/participants/Participants.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
"use client";

import useParticipants from "@/lib/admin/useParticipants";
import { useState } from "react";

import useParticipants, { Participant } from "@/lib/admin/useParticipants";

import CheckInModal from "./components/CheckInModal";
import ParticipantsTable from "./components/ParticipantsTable";

function Participants() {
const { participants, loading } = useParticipants();
const { participants, loading, checkInParticipant } = useParticipants();
const [currentParticipant, setCurrentParticipant] =
useState<Participant | null>(null);

const initiateCheckIn = (participant: Participant): void => {
setCurrentParticipant(participant);
};

const sendCheckIn = async (participant: Participant): Promise<void> => {
await checkInParticipant(participant);
setCurrentParticipant(null);
// TODO: Flashbar notification
};

return (
<>
<ParticipantsTable participants={participants} loading={loading} />;
{/* TODO: modal */}
<ParticipantsTable
participants={participants}
loading={loading}
initiateCheckIn={initiateCheckIn}
/>
<CheckInModal
onDismiss={() => setCurrentParticipant(null)}
onConfirm={sendCheckIn}
participant={currentParticipant}
/>
{/* TODO: walk-in promotion modal */}
</>
);
}
Expand Down
52 changes: 52 additions & 0 deletions apps/site/src/app/admin/participants/components/CheckInModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Box from "@cloudscape-design/components/box";
import Button from "@cloudscape-design/components/button";
import Modal from "@cloudscape-design/components/modal";
import SpaceBetween from "@cloudscape-design/components/space-between";
import TextContent from "@cloudscape-design/components/text-content";

import { Participant } from "@/lib/admin/useParticipants";

interface ActionModalProps {
onDismiss: () => void;
onConfirm: (participant: Participant) => void;
participant: Participant | null;
}

function CheckInModal({ onDismiss, onConfirm, participant }: ActionModalProps) {
if (participant === null) {
return <Modal visible={false} />;
}

return (
<Modal
onDismiss={onDismiss}
visible={true}
footer={
<Box float="right">
<SpaceBetween direction="horizontal" size="xs">
<Button variant="link" onClick={onDismiss}>
Cancel
</Button>
<Button variant="primary" onClick={() => onConfirm(participant)}>
Check In
</Button>
</SpaceBetween>
</Box>
}
header={`Check In ${participant?.first_name} ${participant?.last_name}`}
>
<SpaceBetween size="m">
<TextContent>
<ul>
{/* TODO: actual instructions for check-in associates */}
<li>Create a badge for the participant ...</li>
<li>Ask participant to sign the SPFB sheet ...</li>
</ul>
</TextContent>
{/* TODO: badge barcode input */}
</SpaceBetween>
</Modal>
);
}

export default CheckInModal;
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@ import Button from "@cloudscape-design/components/button";

import { Participant } from "@/lib/admin/useParticipants";

function ParticipantAction({ _id }: Participant) {
interface ParticipantActionProps {
participant: Participant;
initiateCheckIn: (participant: Participant) => void;
}
function ParticipantAction({
participant,
initiateCheckIn,
}: ParticipantActionProps) {
// TODO: waitlist promotion

return (
<Button variant="inline-link" ariaLabel={`Check in ${_id}`}>
<Button
variant="inline-link"
ariaLabel={`Check in ${participant._id}`}
onClick={() => initiateCheckIn(participant)}
>
Check In
</Button>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useCallback } from "react";

import Box from "@cloudscape-design/components/box";
import Header from "@cloudscape-design/components/header";
import SpaceBetween from "@cloudscape-design/components/space-between";
Expand All @@ -13,13 +15,28 @@ import RoleBadge from "./RoleBadge";
interface ParticipantsTableProps {
participants: Participant[];
loading: boolean;
initiateCheckIn: (participant: Participant) => void;
}

function ParticipantsTable({ participants, loading }: ParticipantsTableProps) {
function ParticipantsTable({
participants,
loading,
initiateCheckIn,
}: ParticipantsTableProps) {
// TODO: sorting
// TODO: search functionality
// TODO: role and status filters

const ActionCell = useCallback(
(participant: Participant) => (
<ParticipantAction
participant={participant}
initiateCheckIn={initiateCheckIn}
/>
),
[initiateCheckIn],
);

const emptyMessage = (
<Box margin={{ vertical: "xs" }} textAlign="center" color="inherit">
<SpaceBetween size="m">
Expand Down Expand Up @@ -66,7 +83,7 @@ function ParticipantsTable({ participants, loading }: ParticipantsTableProps) {
{
id: "action",
header: "Action",
cell: ParticipantAction,
cell: ActionCell,
},
]}
header={
Expand Down
14 changes: 12 additions & 2 deletions apps/site/src/lib/admin/useParticipants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,18 @@ function useParticipants() {
fetcher,
);

// TODO: implement check-in mutation
return { participants: data ?? [], loading: isLoading, error };
const checkInParticipant = async (participant: Participant) => {
console.log("Checking in", participant);
// TODO: implement mutation for showing checked in on each day
await axios.post(`/api/admin/checkin/${participant._id}`);
};

return {
participants: data ?? [],
loading: isLoading,
error,
checkInParticipant,
};
}

export default useParticipants;

0 comments on commit e10d102

Please sign in to comment.