From b53637611023195aee0c3522829a16e9ddbbdbb1 Mon Sep 17 00:00:00 2001 From: Taesung Hwang <44419552+taesungh@users.noreply.github.com> Date: Sun, 28 Jan 2024 07:49:21 -0800 Subject: [PATCH] Implement temporary badge scanner search feature (#380) - Add **Scan Badge** button to header actions - Load modal with badge scanner to update participants search filter --- .../components/ParticipantsTable.tsx | 169 ++++++++++-------- .../components/SearchScannerModal.tsx | 45 +++++ 2 files changed, 144 insertions(+), 70 deletions(-) create mode 100644 apps/site/src/app/admin/participants/components/SearchScannerModal.tsx diff --git a/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx b/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx index f8294f72..b84e42b1 100644 --- a/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx +++ b/apps/site/src/app/admin/participants/components/ParticipantsTable.tsx @@ -17,6 +17,7 @@ import CheckinDayIcon from "./CheckinDayIcon"; import ParticipantAction from "./ParticipantAction"; import ParticipantsFilters from "./ParticipantsFilters"; import RoleBadge from "./RoleBadge"; +import SearchScannerModal from "./SearchScannerModal"; const FRIDAY = new Date("2024-01-26T12:00:00"); const SATURDAY = new Date("2024-01-27T12:00:00"); @@ -149,6 +150,7 @@ function ParticipantsTable({ sorting: {}, selection: {}, }); + const allRoles = new Set(participants.map((p) => p.role)); const roleOptions = Array.from(allRoles).map((r) => ({ value: r, label: r })); const allStatuses = new Set(participants.map((p) => p.status)); @@ -247,77 +249,104 @@ function ParticipantsTable({ ); + const [showScanner, setShowScanner] = useState(false); + + const openScanner = () => { + setShowScanner(true); + }; + + const cancelScanner = () => { + setShowScanner(false); + }; + + const useScannerValue = (value: string) => { + actions.setFiltering(value); + setShowScanner(false); + }; + return ( - Participants - } - columnDefinitions={columnDefinitions} - visibleColumns={preferences.visibleContent} - items={items} - loading={loading} - loadingText="Loading participants" - variant="full-page" - stickyColumns={{ first: 1, last: 0 }} - trackBy="_id" - empty={emptyMessage} - filter={ - - } - pagination={ - `Go to page ${pageNumber}`, - previousPageLabel: "Previous page", - }} - /> - } - preferences={ - ({ - id, - label: header, - })), - }, - ], - }} - cancelLabel="Cancel" - confirmLabel="Confirm" - title="Preferences" - preferences={preferences} - onConfirm={({ detail }) => - setPreferences( - detail as { pageSize: number; visibleContent: Array }, - ) - } - /> - } - /> + <> + +
Scan Badge} + > + Participants + + } + columnDefinitions={columnDefinitions} + visibleColumns={preferences.visibleContent} + items={items} + loading={loading} + loadingText="Loading participants" + variant="full-page" + stickyColumns={{ first: 1, last: 0 }} + trackBy="_id" + empty={emptyMessage} + filter={ + + } + pagination={ + `Go to page ${pageNumber}`, + previousPageLabel: "Previous page", + }} + /> + } + preferences={ + ({ + id, + label: header, + })), + }, + ], + }} + cancelLabel="Cancel" + confirmLabel="Confirm" + title="Preferences" + preferences={preferences} + onConfirm={({ detail }) => + setPreferences( + detail as { pageSize: number; visibleContent: Array }, + ) + } + /> + } + /> + ); } diff --git a/apps/site/src/app/admin/participants/components/SearchScannerModal.tsx b/apps/site/src/app/admin/participants/components/SearchScannerModal.tsx new file mode 100644 index 00000000..9fa1a357 --- /dev/null +++ b/apps/site/src/app/admin/participants/components/SearchScannerModal.tsx @@ -0,0 +1,45 @@ +import { useCallback } from "react"; + +import Box from "@cloudscape-design/components/box"; +import Button from "@cloudscape-design/components/button"; +import Modal from "@cloudscape-design/components/modal"; + +import BadgeScanner from "@/lib/admin/BadgeScanner"; + +export interface SearchScannerProps { + onDismiss: () => void; + onConfirm: (value: string) => void; + show: boolean; +} + +function SearchScannerModal({ + onDismiss, + onConfirm, + show, +}: SearchScannerProps) { + const onScanSuccess = useCallback( + (decodedText: string) => { + onConfirm(decodedText); + }, + [onConfirm], + ); + + return ( + + + + } + header="Scan badge" + > + {show && null} />} + + ); +} + +export default SearchScannerModal;