From 727decac2c5531a2f2ecdbfdcb7bb6f99429c10e Mon Sep 17 00:00:00 2001 From: Sophie Han <32656696+sophiiehan@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:14:10 -0800 Subject: [PATCH 01/15] initial --- package.json | 1 + src/App.tsx | 5 +- src/views/portal/admin/QRCheckIn/index.tsx | 61 ++++++++ src/views/portal/admin/UserManagement/api.ts | 153 +++++++++++++++++++ src/views/portal/admin/index.tsx | 6 + yarn.lock | 42 +++++ 6 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 src/views/portal/admin/QRCheckIn/index.tsx create mode 100644 src/views/portal/admin/UserManagement/api.ts diff --git a/package.json b/package.json index bd024cc..13c355a 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.47.0", "react-hot-toast": "^2.4.1", + "react-qr-reader": "^3.0.0-beta-1", "react-router-dom": "^6.6.1", "zod": "^3.22.4" }, diff --git a/src/App.tsx b/src/App.tsx index 5c34cab..4a1ac72 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -32,6 +32,8 @@ import ScrollToAnchor from "./components/scrollControl/ScrollToAnchor" import Team from "./views/team" import ApplicationClosed from "./views/ApplicationClosed" +import QRCheckIn from "./views/portal/admin/QRCheckIn" + const App: React.FC = () => { const { auth: { loading }, @@ -70,7 +72,8 @@ const App: React.FC = () => { {/* You cannot be logged in to access these routes*/} }> - } /> + {/* } /> */} + } /> } /> }> } /> diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx new file mode 100644 index 0000000..2d9cee7 --- /dev/null +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -0,0 +1,61 @@ +import React, { useState, Dispatch } from "react" +import { QrReader } from "react-qr-reader" +import { + checkIn, + getHacker, + HackerQRProps, +} from "../UserManagement/api" + + +const QRCheckInContainer: React.FC = () => { + const [modalOpen, setModalOpen] = useState(false) + // const { getAccessTokenSilently } = useAuth0() + // const { setBanner } = useBanner() + const [hacker, setHacker] = useState({ + firstName: "", + lastName: "", + email: "", + id: "", + }) + + return ( +
+ + {/* Temporary space for sidebar, replaced with actual sidebar later */} + +
+ {/* Sidebar component, swap this element with another sidebar if you like */} +
+
+ Sidebar +
+
+
+ + {/* QR code page */} +
+
+
QR Code Check-In
+
+ +
+
+ {/* QR Camera */} + +
+
+
+
+ ) + } + + const QRCheckIn = () => ( + + ) + + export default QRCheckIn \ No newline at end of file diff --git a/src/views/portal/admin/UserManagement/api.ts b/src/views/portal/admin/UserManagement/api.ts new file mode 100644 index 0000000..99aa5fa --- /dev/null +++ b/src/views/portal/admin/UserManagement/api.ts @@ -0,0 +1,153 @@ +import axios from "axios" +import { Dispatch } from "react" +// import { Message } from "../../../../../contexts/PortalBanners/PortalBanner" + +export interface HackerProps { + id: string + email: string + firstName: string + lastName: string + checkedIn: boolean + attendanceStatus: string +} + +export interface HackerQRProps { + id: string + firstName: string + lastName: string + email: string +} + +const checkIn = async ( + getAccessTokenSilently: any, + setBanner: Dispatch<"Banner">, + hackerId: string +) => { + try { + const token = await getAccessTokenSilently() + const checkInAxiosRequest = { + method: "put", + url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/checkIn/${hackerId}`, + headers: { + "Content-Type": "application/json", + "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", + Authorization: `Bearer ${token}`, + }, + } + const res = await axios(checkInAxiosRequest) + // setBanner({ message: res.data.message, messageType: "SUCCESS" }) + } catch (err) { + console.log(err) + // if (axios.isAxiosError(err)) { + // const axiosError: any = err + // setBanner({ + // message: axiosError.response.data.error, + // messageType: "ERROR", + // }) + // } + } +} + +const rsvp = async ( + getAccessTokenSilently: any, + setBanner: Dispatch<"Message">, + hackerId: string +) => { + try { + const token = await getAccessTokenSilently() + const checkInAxiosRequest = { + method: "put", + url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/RSVPHacker`, + headers: { + "Content-Type": "application/json", + "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", + Authorization: `Bearer ${token}`, + }, + data: { + hackerID: hackerId, + }, + } + const res = await axios(checkInAxiosRequest) + // setBanner({ message: res.data.message, messageType: "SUCCESS" }) + } catch (err) { + console.log(err) + // if (axios.isAxiosError(err)) { + // const axiosError: any = err + // setBanner({ + // message: axiosError.response.data.error, + // messageType: "ERROR", + // }) + // } + } +} + +const getHacker = async ( + getAccessTokenSilently: any, + setBanner: Dispatch<"Message">, + setHacker: Dispatch, + id: string +) => { + try { + const token = await getAccessTokenSilently() + const getHackersAxiosRequest = { + method: "get", + /* eslint-disable */ + url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/getHacker/${id}`, + /* eslint-enable */ + headers: { + "Content-Type": "application/json", + "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", + Authorization: `Bearer ${token}`, + }, + } + const res = await axios(getHackersAxiosRequest) + const hackerData = res.data.hacker + + setHacker(hackerData) + } catch (err) { + if (axios.isAxiosError(err)) { + const axiosError: any = err + // setBanner({ + // message: axiosError.response.data.error, + // messageType: "ERROR", + // }) + } + } +} + +const getHackers = async ( + getAccessTokenSilently: any, + setBanner: Dispatch<"Message">, + setHackers: Dispatch> +) => { + try { + const token = await getAccessTokenSilently() + const getHackersAxiosRequest = { + method: "get", + /* eslint-disable */ + url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/getHackers`, + /* eslint-enable */ + headers: { + "Content-Type": "application/json", + "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", + Authorization: `Bearer ${token}`, + }, + } + const res = await axios(getHackersAxiosRequest) + const hackersData = res.data.hackers + + setHackers(hackersData) + } catch (err) { + if (axios.isAxiosError(err)) { + const axiosError: any = err + // setBanner({ + // message: axiosError.response.data.error, + // messageType: "ERROR", + // }) + } + } +} + +export { checkIn, getHacker, rsvp } + +export default getHackers diff --git a/src/views/portal/admin/index.tsx b/src/views/portal/admin/index.tsx index d6cc55c..ca2624e 100644 --- a/src/views/portal/admin/index.tsx +++ b/src/views/portal/admin/index.tsx @@ -5,6 +5,7 @@ import { NewspaperIcon, UserGroupIcon, UsersIcon, + CameraIcon, } from "@heroicons/react/24/outline" const nav = [ @@ -28,6 +29,11 @@ const nav = [ href: "/portal/admin/teams", icon: UserGroupIcon, }, + { + name: "QR Check-In", + href: "/portal/admin/QRCheckIn", + icon: CameraIcon, + }, ] const PortalAdmin = () => { diff --git a/yarn.lock b/yarn.lock index 4b4c700..5cef0d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1355,6 +1355,27 @@ "@types/babel__core" "^7.20.3" react-refresh "^0.14.0" +"@zxing/browser@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@zxing/browser/-/browser-0.0.7.tgz#5fa7680a867b660f48d3288fdf63e0174ad531c7" + integrity sha512-AepzMgDnD6EjxewqmXpHJsi4S3Gw9ilZJLIbTf6fWuWySEcHBodnGu3p7FWlgq1Sd5QyfPhTum5z3CBkkhMVng== + optionalDependencies: + "@zxing/text-encoding" "^0.9.0" + +"@zxing/library@^0.18.3": + version "0.18.6" + resolved "https://registry.yarnpkg.com/@zxing/library/-/library-0.18.6.tgz#717af8c6c1fd982865e21051afdd7b470ae6674c" + integrity sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw== + dependencies: + ts-custom-error "^3.0.0" + optionalDependencies: + "@zxing/text-encoding" "~0.9.0" + +"@zxing/text-encoding@^0.9.0", "@zxing/text-encoding@~0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" + integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== + abbrev@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -6125,6 +6146,15 @@ react-jss@^10.9.2: theming "^3.3.0" tiny-warning "^1.0.2" +react-qr-reader@^3.0.0-beta-1: + version "3.0.0-beta-1" + resolved "https://registry.yarnpkg.com/react-qr-reader/-/react-qr-reader-3.0.0-beta-1.tgz#e04a20876409313439959d8e0ea6df3ba6e36d68" + integrity sha512-5HeFH9x/BlziRYQYGK2AeWS9WiKYZtGGMs9DXy3bcySTX3C9UJL9EwcPnWw8vlf7JP4FcrAlr1SnZ5nsWLQGyw== + dependencies: + "@zxing/browser" "0.0.7" + "@zxing/library" "^0.18.3" + rollup "^2.67.2" + react-refresh@^0.14.0: version "0.14.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" @@ -6371,6 +6401,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup@^2.67.2: + version "2.79.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" + integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== + optionalDependencies: + fsevents "~2.3.2" + rollup@^3.27.1: version "3.29.4" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" @@ -7043,6 +7080,11 @@ triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== +ts-custom-error@^3.0.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1" + integrity sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" From eef2adccf5da227ed3431bc623026b9c0f54b3ac Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Fri, 12 Jan 2024 14:19:51 -0800 Subject: [PATCH 02/15] add check-in cloud funciton --- package.json | 1 + src/App.tsx | 6 +- src/utils/apis/cloudFunctions.ts | 29 ++++ src/views/portal/admin/QRCheckIn/index.tsx | 96 ++++++------ src/views/portal/admin/UserManagement/api.ts | 153 ------------------- src/views/portal/admin/index.tsx | 2 +- src/views/portal/hacker/dashboard/index.tsx | 24 +++ src/views/portal/hacker/index.tsx | 21 ++- yarn.lock | 13 ++ 9 files changed, 136 insertions(+), 209 deletions(-) delete mode 100644 src/views/portal/admin/UserManagement/api.ts create mode 100644 src/views/portal/hacker/dashboard/index.tsx diff --git a/package.json b/package.json index c958c5c..7b51cea 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.47.0", "react-hot-toast": "^2.4.1", + "react-qr-code": "^2.0.12", "react-qr-reader": "^3.0.0-beta-1", "react-router-dom": "^6.6.1", "recharts": "^2.9.3", diff --git a/src/App.tsx b/src/App.tsx index 9029cb0..8ed06d0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -32,6 +32,7 @@ import Team from "./views/team" import ApplicationClosed from "./views/ApplicationClosed" import QRCheckIn from "./views/portal/admin/QRCheckIn" +import DashbaordHacker from "./views/portal/hacker/dashboard" const App: React.FC = () => { const { @@ -75,8 +76,7 @@ const App: React.FC = () => { {/* You cannot be logged in to access these routes*/} }> - {/* } /> */} - } /> + } /> } /> }> } /> @@ -109,6 +109,7 @@ const App: React.FC = () => { }> }> + } /> {/* Hacker Portal sub-routes go here*/} @@ -122,6 +123,7 @@ const App: React.FC = () => { /> } /> } /> + } /> diff --git a/src/utils/apis/cloudFunctions.ts b/src/utils/apis/cloudFunctions.ts index ffbe903..fcba6d5 100644 --- a/src/utils/apis/cloudFunctions.ts +++ b/src/utils/apis/cloudFunctions.ts @@ -260,3 +260,32 @@ export const getStatistics = async () => { throw err as Error } } + +/** + * CruzHacks-2024-Backend API endpoint for checking in a user + */ +export const checkInUser = async (uid: string) => { + try { + const response = await axios.post(`${API_URL}/auth/checkIn`, null, { + params: { + uid, + }, + }) + + const { data, error } = response.data + + if (error) throw new Error(error) + + return data as User + } catch (err) { + if (isAxiosError(err)) { + if (err.response?.data?.error) { + console.error(err.response.data.error) + throw new Error(err.response.data.error) + } + console.error(err) + throw new Error(err.message) + } + throw err as Error + } +} diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index 2d9cee7..6e1f2d0 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -1,61 +1,53 @@ -import React, { useState, Dispatch } from "react" +import React from "react" import { QrReader } from "react-qr-reader" -import { - checkIn, - getHacker, - HackerQRProps, -} from "../UserManagement/api" - +import { checkInUser } from "../../../../utils/apis/cloudFunctions" +import toast from "react-hot-toast" +import { isString } from "../../../../utils/string" const QRCheckInContainer: React.FC = () => { - const [modalOpen, setModalOpen] = useState(false) - // const { getAccessTokenSilently } = useAuth0() - // const { setBanner } = useBanner() - const [hacker, setHacker] = useState({ - firstName: "", - lastName: "", - email: "", - id: "", - }) - - return ( -
+ const handleScanUID = async (result: string) => { + try { + const uid = result + const hacker = await checkInUser(uid) + toast.success(`Successfully checked in ${hacker.displayName}`) + } catch (error) { + if (error && isString((error as Error).message)) { + const errorMessage = (error as Error).message + toast.error(errorMessage) + } + } + } - {/* Temporary space for sidebar, replaced with actual sidebar later */} - -
- {/* Sidebar component, swap this element with another sidebar if you like */} -
-
- Sidebar -
-
-
+ return ( +
+
+
QR Code Check-In
+
- {/* QR code page */} -
-
-
QR Code Check-In
-
+
+
+ {/* QR Camera */} + { + if (result) { + handleScanUID(result.getText()) + } -
-
- {/* QR Camera */} - -
-
+ if (error) { + console.info(error) + } + }} + />
- ) - } - - const QRCheckIn = () => ( - +
) - - export default QRCheckIn \ No newline at end of file +} + +const QRCheckIn = () => + +export default QRCheckIn diff --git a/src/views/portal/admin/UserManagement/api.ts b/src/views/portal/admin/UserManagement/api.ts deleted file mode 100644 index 99aa5fa..0000000 --- a/src/views/portal/admin/UserManagement/api.ts +++ /dev/null @@ -1,153 +0,0 @@ -import axios from "axios" -import { Dispatch } from "react" -// import { Message } from "../../../../../contexts/PortalBanners/PortalBanner" - -export interface HackerProps { - id: string - email: string - firstName: string - lastName: string - checkedIn: boolean - attendanceStatus: string -} - -export interface HackerQRProps { - id: string - firstName: string - lastName: string - email: string -} - -const checkIn = async ( - getAccessTokenSilently: any, - setBanner: Dispatch<"Banner">, - hackerId: string -) => { - try { - const token = await getAccessTokenSilently() - const checkInAxiosRequest = { - method: "put", - url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/checkIn/${hackerId}`, - headers: { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", - Authorization: `Bearer ${token}`, - }, - } - const res = await axios(checkInAxiosRequest) - // setBanner({ message: res.data.message, messageType: "SUCCESS" }) - } catch (err) { - console.log(err) - // if (axios.isAxiosError(err)) { - // const axiosError: any = err - // setBanner({ - // message: axiosError.response.data.error, - // messageType: "ERROR", - // }) - // } - } -} - -const rsvp = async ( - getAccessTokenSilently: any, - setBanner: Dispatch<"Message">, - hackerId: string -) => { - try { - const token = await getAccessTokenSilently() - const checkInAxiosRequest = { - method: "put", - url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/RSVPHacker`, - headers: { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", - Authorization: `Bearer ${token}`, - }, - data: { - hackerID: hackerId, - }, - } - const res = await axios(checkInAxiosRequest) - // setBanner({ message: res.data.message, messageType: "SUCCESS" }) - } catch (err) { - console.log(err) - // if (axios.isAxiosError(err)) { - // const axiosError: any = err - // setBanner({ - // message: axiosError.response.data.error, - // messageType: "ERROR", - // }) - // } - } -} - -const getHacker = async ( - getAccessTokenSilently: any, - setBanner: Dispatch<"Message">, - setHacker: Dispatch, - id: string -) => { - try { - const token = await getAccessTokenSilently() - const getHackersAxiosRequest = { - method: "get", - /* eslint-disable */ - url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/getHacker/${id}`, - /* eslint-enable */ - headers: { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", - Authorization: `Bearer ${token}`, - }, - } - const res = await axios(getHackersAxiosRequest) - const hackerData = res.data.hacker - - setHacker(hackerData) - } catch (err) { - if (axios.isAxiosError(err)) { - const axiosError: any = err - // setBanner({ - // message: axiosError.response.data.error, - // messageType: "ERROR", - // }) - } - } -} - -const getHackers = async ( - getAccessTokenSilently: any, - setBanner: Dispatch<"Message">, - setHackers: Dispatch> -) => { - try { - const token = await getAccessTokenSilently() - const getHackersAxiosRequest = { - method: "get", - /* eslint-disable */ - url: `${process.env.REACT_APP_ENDPOINT_URL}/admin/getHackers`, - /* eslint-enable */ - headers: { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": process.env.REACT_APP_CORS_ORIGIN || "", - Authorization: `Bearer ${token}`, - }, - } - const res = await axios(getHackersAxiosRequest) - const hackersData = res.data.hackers - - setHackers(hackersData) - } catch (err) { - if (axios.isAxiosError(err)) { - const axiosError: any = err - // setBanner({ - // message: axiosError.response.data.error, - // messageType: "ERROR", - // }) - } - } -} - -export { checkIn, getHacker, rsvp } - -export default getHackers diff --git a/src/views/portal/admin/index.tsx b/src/views/portal/admin/index.tsx index ca2624e..685077f 100644 --- a/src/views/portal/admin/index.tsx +++ b/src/views/portal/admin/index.tsx @@ -31,7 +31,7 @@ const nav = [ }, { name: "QR Check-In", - href: "/portal/admin/QRCheckIn", + href: "/portal/admin/check-in", icon: CameraIcon, }, ] diff --git a/src/views/portal/hacker/dashboard/index.tsx b/src/views/portal/hacker/dashboard/index.tsx new file mode 100644 index 0000000..a797c2d --- /dev/null +++ b/src/views/portal/hacker/dashboard/index.tsx @@ -0,0 +1,24 @@ +import React from "react" +import QRCode from "react-qr-code" +import useAuth from "../../../../hooks/useAuth" + +const DashbaordHacker = () => { + const { + auth: { user }, + } = useAuth() + + return ( +
+

Dashbaord

+ + {user ? ( + + ) : ( + // SHOULD NEVER HAPPEN +

No User

+ )} +
+ ) +} + +export default DashbaordHacker diff --git a/src/views/portal/hacker/index.tsx b/src/views/portal/hacker/index.tsx index c51ffc0..37f85d0 100644 --- a/src/views/portal/hacker/index.tsx +++ b/src/views/portal/hacker/index.tsx @@ -1,7 +1,26 @@ import React from "react" +import Sidebar from "../Sidebar" +import { CameraIcon, HomeIcon } from "@heroicons/react/24/outline" + +const nav = [ + { + name: "Dashboard", + href: "/portal/hacker", + icon: HomeIcon, + }, + // { + // name: "Check In", + // href: "/portal/hacker/check-in", + // icon: CameraIcon, + // }, +] const HackerPortal = () => { - return
HackerPortal
+ return ( +
+ +
+ ) } export default HackerPortal diff --git a/yarn.lock b/yarn.lock index 40d015f..f78dbb3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6114,6 +6114,11 @@ pupa@^2.1.1: dependencies: escape-goat "^2.0.0" +qr.js@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" + integrity sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ== + qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -6247,6 +6252,14 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-qr-code@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/react-qr-code/-/react-qr-code-2.0.12.tgz#98f99e9ad5ede46d73ab819e2dd9925c5f5d7a2d" + integrity sha512-k+pzP5CKLEGBRwZsDPp98/CAJeXlsYRHM2iZn1Sd5Th/HnKhIZCSg27PXO58zk8z02RaEryg+60xa4vyywMJwg== + dependencies: + prop-types "^15.8.1" + qr.js "0.0.0" + react-qr-reader@^3.0.0-beta-1: version "3.0.0-beta-1" resolved "https://registry.yarnpkg.com/react-qr-reader/-/react-qr-reader-3.0.0-beta-1.tgz#e04a20876409313439959d8e0ea6df3ba6e36d68" From e100bf4cb4308d43d5bf18a425f34c3597f8fd87 Mon Sep 17 00:00:00 2001 From: Sophie Han <32656696+sophiiehan@users.noreply.github.com> Date: Sat, 13 Jan 2024 21:24:13 -0800 Subject: [PATCH 03/15] styled both hacker and admin check-in pages --- src/App.tsx | 2 + src/views/portal/admin/QRCheckIn/index.tsx | 50 ++++++++++++--------- src/views/portal/hacker/QRCode/index.tsx | 35 +++++++++++++++ src/views/portal/hacker/dashboard/index.tsx | 9 +--- src/views/portal/hacker/index.tsx | 10 ++--- 5 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 src/views/portal/hacker/QRCode/index.tsx diff --git a/src/App.tsx b/src/App.tsx index 8ed06d0..3690ec5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -33,6 +33,7 @@ import ApplicationClosed from "./views/ApplicationClosed" import QRCheckIn from "./views/portal/admin/QRCheckIn" import DashbaordHacker from "./views/portal/hacker/dashboard" +import QRCodeHacker from "./views/portal/hacker/QRCode" const App: React.FC = () => { const { @@ -111,6 +112,7 @@ const App: React.FC = () => { }> } /> {/* Hacker Portal sub-routes go here*/} + } /> }> diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index 6e1f2d0..4ef084e 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -19,29 +19,39 @@ const QRCheckInContainer: React.FC = () => { } return ( -
-
-
QR Code Check-In
+
+
+
+

Check-In QR Code Scanner

+

+ Scan a Hacker's QR Code in the camera box below to check them in at the beginning of the event. +

+
-
-
- {/* QR Camera */} - { - if (result) { - handleScanUID(result.getText()) - } +
+
+

+ When prompted, make sure to enable camera permissions. +

+
+ {/* QR Camera */} + { + if (result) { + handleScanUID(result.getText()) + } - if (error) { - console.info(error) - } - }} - /> + if (error) { + console.info(error) + } + }} + /> +
diff --git a/src/views/portal/hacker/QRCode/index.tsx b/src/views/portal/hacker/QRCode/index.tsx new file mode 100644 index 0000000..8de8f09 --- /dev/null +++ b/src/views/portal/hacker/QRCode/index.tsx @@ -0,0 +1,35 @@ +import React from "react" +import QRCode from "react-qr-code" +import useAuth from "../../../../hooks/useAuth" + +const QRCodeHacker = () => { + const { + auth: { user }, + } = useAuth() + + return ( +
+
+
+

Check-In QR Code

+

+ Present this QR code to a CruzHacks Organizer to check-in to the event. +

+
+
+ +
+ {user ? ( + + ) : ( + // SHOULD NEVER HAPPEN +

No User

+ )} +
+
+ ) +} + +export default QRCodeHacker \ No newline at end of file diff --git a/src/views/portal/hacker/dashboard/index.tsx b/src/views/portal/hacker/dashboard/index.tsx index a797c2d..eecd05c 100644 --- a/src/views/portal/hacker/dashboard/index.tsx +++ b/src/views/portal/hacker/dashboard/index.tsx @@ -9,14 +9,7 @@ const DashbaordHacker = () => { return (
-

Dashbaord

- - {user ? ( - - ) : ( - // SHOULD NEVER HAPPEN -

No User

- )} +

Dashboard

) } diff --git a/src/views/portal/hacker/index.tsx b/src/views/portal/hacker/index.tsx index 37f85d0..8ef328e 100644 --- a/src/views/portal/hacker/index.tsx +++ b/src/views/portal/hacker/index.tsx @@ -8,11 +8,11 @@ const nav = [ href: "/portal/hacker", icon: HomeIcon, }, - // { - // name: "Check In", - // href: "/portal/hacker/check-in", - // icon: CameraIcon, - // }, + { + name: "Check In", + href: "/portal/hacker/check-in", + icon: CameraIcon, + }, ] const HackerPortal = () => { From b46659ae94a8ace141e68d82c1747f00c6de4c15 Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Sun, 14 Jan 2024 16:23:56 -0800 Subject: [PATCH 04/15] update node version --- .github/workflows/firebase-hosting-merge-development.yml | 4 ++-- .github/workflows/firebase-hosting-merge-production.yml | 4 ++-- .github/workflows/firebase-hosting-pull-request.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/firebase-hosting-merge-development.yml b/.github/workflows/firebase-hosting-merge-development.yml index d609cf0..070e322 100644 --- a/.github/workflows/firebase-hosting-merge-development.yml +++ b/.github/workflows/firebase-hosting-merge-development.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: 16 + node-version: 18 - name: Install Dependencies run: yarn install --frozen-lockfile - name: Create Production Build @@ -39,7 +39,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: 16 + node-version: 18 - name: Install Dependencies run: yarn install --frozen-lockfile - name: Lint diff --git a/.github/workflows/firebase-hosting-merge-production.yml b/.github/workflows/firebase-hosting-merge-production.yml index 0039356..583ed68 100644 --- a/.github/workflows/firebase-hosting-merge-production.yml +++ b/.github/workflows/firebase-hosting-merge-production.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: 16 + node-version: 18 - name: Install Dependencies run: yarn install --frozen-lockfile - name: Create Production Build @@ -39,7 +39,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: 16 + node-version: 18 - name: Install Dependencies run: yarn install --frozen-lockfile - name: Lint diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index 0c89003..4273a34 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: 16 + node-version: 18 - name: Install Dependencies run: yarn install --frozen-lockfile - name: Create Production Build @@ -36,7 +36,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: 16 + node-version: 18 - name: Install Dependencies run: yarn install --frozen-lockfile - name: Lint From aea3b84cc1d5bfd5939b6e146f56672b5060824d Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Sun, 14 Jan 2024 16:37:17 -0800 Subject: [PATCH 05/15] fix lint --- src/views/portal/admin/QRCheckIn/index.tsx | 9 ++++++--- src/views/portal/hacker/QRCode/index.tsx | 4 ++-- src/views/portal/hacker/dashboard/index.tsx | 9 ++++----- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index 4ef084e..0fc9e62 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -22,14 +22,17 @@ const QRCheckInContainer: React.FC = () => {
-

Check-In QR Code Scanner

+

+ Check-In QR Code Scanner +

- Scan a Hacker's QR Code in the camera box below to check them in at the beginning of the event. + Scan a Hacker's QR Code in the camera box below to check them + in at the beginning of the event.

-
+

When prompted, make sure to enable camera permissions. diff --git a/src/views/portal/hacker/QRCode/index.tsx b/src/views/portal/hacker/QRCode/index.tsx index 8de8f09..5af87e2 100644 --- a/src/views/portal/hacker/QRCode/index.tsx +++ b/src/views/portal/hacker/QRCode/index.tsx @@ -18,7 +18,7 @@ const QRCodeHacker = () => {

-
+
{user ? ( { ) } -export default QRCodeHacker \ No newline at end of file +export default QRCodeHacker diff --git a/src/views/portal/hacker/dashboard/index.tsx b/src/views/portal/hacker/dashboard/index.tsx index eecd05c..250fb2f 100644 --- a/src/views/portal/hacker/dashboard/index.tsx +++ b/src/views/portal/hacker/dashboard/index.tsx @@ -1,11 +1,10 @@ import React from "react" -import QRCode from "react-qr-code" -import useAuth from "../../../../hooks/useAuth" +// import useAuth from "../../../../hooks/useAuth" const DashbaordHacker = () => { - const { - auth: { user }, - } = useAuth() + // const { + // auth: { user }, + // } = useAuth() return (
From 517137b95c7ad8484cef9f4117570cc1d07efaa1 Mon Sep 17 00:00:00 2001 From: Sophie Han <32656696+sophiiehan@users.noreply.github.com> Date: Sun, 14 Jan 2024 16:53:28 -0800 Subject: [PATCH 06/15] add toast error scan --- src/views/portal/admin/QRCheckIn/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index 0fc9e62..c9ded29 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -51,6 +51,7 @@ const QRCheckInContainer: React.FC = () => { if (error) { console.info(error) + toast.error(error.message) } }} /> From 05f557303fb357a8881070b7c9602ed244889b49 Mon Sep 17 00:00:00 2001 From: Sophie Han <32656696+sophiiehan@users.noreply.github.com> Date: Sun, 14 Jan 2024 17:03:34 -0800 Subject: [PATCH 07/15] fixed error --- src/views/portal/admin/QRCheckIn/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index c9ded29..d7509c6 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -50,8 +50,7 @@ const QRCheckInContainer: React.FC = () => { } if (error) { - console.info(error) - toast.error(error.message) + console.error(error) } }} /> From c98b8be67baa0e4516959e2f1b2894c88d15287e Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 16:22:47 -0800 Subject: [PATCH 08/15] try Zxing video camera --- package.json | 2 +- src/views/portal/admin/QRCheckIn/index.tsx | 76 ++++++++++++---------- yarn.lock | 44 ++++--------- 3 files changed, 57 insertions(+), 65 deletions(-) diff --git a/package.json b/package.json index 7b51cea..74de684 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,8 @@ "react-hook-form": "^7.47.0", "react-hot-toast": "^2.4.1", "react-qr-code": "^2.0.12", - "react-qr-reader": "^3.0.0-beta-1", "react-router-dom": "^6.6.1", + "react-zxing": "^2.0.0", "recharts": "^2.9.3", "zod": "^3.22.4" }, diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index d7509c6..83b4866 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -1,14 +1,28 @@ import React from "react" -import { QrReader } from "react-qr-reader" +import { useZxing } from "react-zxing" import { checkInUser } from "../../../../utils/apis/cloudFunctions" import toast from "react-hot-toast" import { isString } from "../../../../utils/string" +import { CameraIcon } from "@heroicons/react/24/outline" +import type { User } from "firebase/auth" const QRCheckInContainer: React.FC = () => { + const { ref } = useZxing({ + onDecodeResult: result => { + console.log(result) + handleScanUID(result.getText()) + }, + onError: error => { + console.error(error) + }, + }) + const [lastScanned, setLastScanned] = React.useState() + const handleScanUID = async (result: string) => { try { const uid = result const hacker = await checkInUser(uid) + setLastScanned(hacker) toast.success(`Successfully checked in ${hacker.displayName}`) } catch (error) { if (error && isString((error as Error).message)) { @@ -19,43 +33,37 @@ const QRCheckInContainer: React.FC = () => { } return ( -
-
-
-

- Check-In QR Code Scanner -

-

- Scan a Hacker's QR Code in the camera box below to check them - in at the beginning of the event. -

-
+
+
+

+ Check-In QR Code Scanner +

+

+ Scan a Hacker's QR Code in the camera box below to check them in + at the beginning of the event. +

-
-
-

- When prompted, make sure to enable camera permissions. -

-
- {/* QR Camera */} - { - if (result) { - handleScanUID(result.getText()) - } +
+
+ {/* eslint-disable-next-line jsx-a11y/media-has-caption */} +
+

+ When prompted, make sure to enable{" "} + permissions. +

+ {lastScanned && ( +
+

Last Scanned

+

{lastScanned.email}

+

{lastScanned.displayName}

+
+ )}
) diff --git a/yarn.lock b/yarn.lock index f78dbb3..2be9d74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1424,23 +1424,16 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.14.0" -"@zxing/browser@0.0.7": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@zxing/browser/-/browser-0.0.7.tgz#5fa7680a867b660f48d3288fdf63e0174ad531c7" - integrity sha512-AepzMgDnD6EjxewqmXpHJsi4S3Gw9ilZJLIbTf6fWuWySEcHBodnGu3p7FWlgq1Sd5QyfPhTum5z3CBkkhMVng== - optionalDependencies: - "@zxing/text-encoding" "^0.9.0" - -"@zxing/library@^0.18.3": - version "0.18.6" - resolved "https://registry.yarnpkg.com/@zxing/library/-/library-0.18.6.tgz#717af8c6c1fd982865e21051afdd7b470ae6674c" - integrity sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw== +"@zxing/library@^0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@zxing/library/-/library-0.20.0.tgz#11bc411b87693015389555c589da61532879be7b" + integrity sha512-6Ev6rcqVjMakZFIDvbUf0dtpPGeZMTfyxYg4HkVWioWeN7cRcnUWT3bU6sdohc82O1nPXcjq6WiGfXX2Pnit6A== dependencies: - ts-custom-error "^3.0.0" + ts-custom-error "^3.2.1" optionalDependencies: "@zxing/text-encoding" "~0.9.0" -"@zxing/text-encoding@^0.9.0", "@zxing/text-encoding@~0.9.0": +"@zxing/text-encoding@~0.9.0": version "0.9.0" resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== @@ -6260,15 +6253,6 @@ react-qr-code@^2.0.12: prop-types "^15.8.1" qr.js "0.0.0" -react-qr-reader@^3.0.0-beta-1: - version "3.0.0-beta-1" - resolved "https://registry.yarnpkg.com/react-qr-reader/-/react-qr-reader-3.0.0-beta-1.tgz#e04a20876409313439959d8e0ea6df3ba6e36d68" - integrity sha512-5HeFH9x/BlziRYQYGK2AeWS9WiKYZtGGMs9DXy3bcySTX3C9UJL9EwcPnWw8vlf7JP4FcrAlr1SnZ5nsWLQGyw== - dependencies: - "@zxing/browser" "0.0.7" - "@zxing/library" "^0.18.3" - rollup "^2.67.2" - react-refresh@^0.14.0: version "0.14.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" @@ -6317,6 +6301,13 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" +react-zxing@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-zxing/-/react-zxing-2.0.0.tgz#fffee191fa642b3832c2fe17977cbad651bb6d3f" + integrity sha512-tZV0UnWDnL+xUUVv15N8w04iKP2RJsraDZvN+t5VBb/3jDqmneLkfDs/beFS0l67aL55UCMN44mFmdx9mHqSrQ== + dependencies: + "@zxing/library" "^0.20.0" + react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" @@ -6554,13 +6545,6 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@^2.67.2: - version "2.79.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" - integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== - optionalDependencies: - fsevents "~2.3.2" - rollup@^3.27.1: version "3.29.4" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" @@ -7233,7 +7217,7 @@ triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== -ts-custom-error@^3.0.0: +ts-custom-error@^3.2.1: version "3.3.1" resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1" integrity sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A== From 2df779d0208078b300d9377f073ddce4005165e9 Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 16:47:42 -0800 Subject: [PATCH 09/15] add auth token --- src/utils/apis/cloudFunctions.ts | 7 ++++++- src/views/portal/admin/QRCheckIn/index.tsx | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/utils/apis/cloudFunctions.ts b/src/utils/apis/cloudFunctions.ts index b4c42f2..c24cb10 100644 --- a/src/utils/apis/cloudFunctions.ts +++ b/src/utils/apis/cloudFunctions.ts @@ -294,12 +294,17 @@ export const getStatistics = async () => { /** * CruzHacks-2024-Backend API endpoint for checking in a user */ -export const checkInUser = async (uid: string) => { +export const checkInUser = async (userSession: User, uid: string) => { try { + const idToken = await userSession.getIdToken(false) + const response = await axios.post(`${API_URL}/auth/checkIn`, null, { params: { uid, }, + headers: { + Authorization: `Bearer ${idToken}`, + }, }) const { data, error } = response.data diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index 6b98d86..dc52847 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -5,8 +5,13 @@ import toast from "react-hot-toast" import { isString } from "../../../../utils/string" import { CameraIcon } from "@heroicons/react/24/outline" import type { User } from "firebase/auth" +import useAuth from "../../../../hooks/useAuth" const QRCheckInContainer: React.FC = () => { + const { + auth: { user }, + } = useAuth() + const { ref } = useZxing({ onDecodeResult: result => { console.log(result) @@ -20,8 +25,9 @@ const QRCheckInContainer: React.FC = () => { const handleScanUID = async (result: string) => { try { + if (!user) throw "No user session found" const uid = result - const hacker = await checkInUser(uid) + const hacker = await checkInUser(user, uid) setLastScanned(hacker) toast.success(`Successfully checked in ${hacker.displayName}`) } catch (error) { From 90aefbb3b8d3d0fe7e9b7782437437838fa8f87c Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 16:55:59 -0800 Subject: [PATCH 10/15] add lastScanned --- src/views/portal/admin/QRCheckIn/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index dc52847..925b640 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -28,6 +28,8 @@ const QRCheckInContainer: React.FC = () => { if (!user) throw "No user session found" const uid = result const hacker = await checkInUser(user, uid) + console.log("Scanned", hacker) + setLastScanned(hacker) toast.success(`Successfully checked in ${hacker.displayName}`) } catch (error) { @@ -50,7 +52,7 @@ const QRCheckInContainer: React.FC = () => {

-
+
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
)} +
{JSON.stringify(lastScanned, null, 2)}
) From dba178aa31e7b282e4eec036ba4c63a1f947fc81 Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 17:29:55 -0800 Subject: [PATCH 11/15] add last scanned styling --- src/utils/apis/cloudFunctions.ts | 2 +- src/views/portal/admin/QRCheckIn/index.tsx | 44 ++++++++++++++++------ src/views/portal/hacker/teams/index.tsx | 1 - 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/utils/apis/cloudFunctions.ts b/src/utils/apis/cloudFunctions.ts index c24cb10..bfa29c5 100644 --- a/src/utils/apis/cloudFunctions.ts +++ b/src/utils/apis/cloudFunctions.ts @@ -311,7 +311,7 @@ export const checkInUser = async (userSession: User, uid: string) => { if (error) throw new Error(error) - return data as User + return data.userRecord as User } catch (err) { if (isAxiosError(err)) { if (err.response?.data?.error) { diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index 925b640..f2c8266 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -2,7 +2,7 @@ import React from "react" import { useZxing } from "react-zxing" import { checkInUser } from "../../../../utils/apis/cloudFunctions" import toast from "react-hot-toast" -import { isString } from "../../../../utils/string" +import { classNames, isString } from "../../../../utils/string" import { CameraIcon } from "@heroicons/react/24/outline" import type { User } from "firebase/auth" import useAuth from "../../../../hooks/useAuth" @@ -21,14 +21,13 @@ const QRCheckInContainer: React.FC = () => { console.error(error) }, }) - const [lastScanned, setLastScanned] = React.useState() + const [lastScanned, setLastScanned] = React.useState(user) const handleScanUID = async (result: string) => { try { if (!user) throw "No user session found" const uid = result const hacker = await checkInUser(user, uid) - console.log("Scanned", hacker) setLastScanned(hacker) toast.success(`Successfully checked in ${hacker.displayName}`) @@ -52,12 +51,12 @@ const QRCheckInContainer: React.FC = () => {

-
-
+
+
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
{lastScanned && ( -
-

Last Scanned

-

{lastScanned.email}

-

{lastScanned.displayName}

+
+

Last Scanned

+
    +
  • + Name:{" "} + + {lastScanned.displayName ?? "< NO NAME >"} + +
  • +
  • + Email:{" "} + + {lastScanned.email ?? "< NO NAME >"} + +
  • +
)} -
{JSON.stringify(lastScanned, null, 2)}
) diff --git a/src/views/portal/hacker/teams/index.tsx b/src/views/portal/hacker/teams/index.tsx index 56e387d..2476bbf 100644 --- a/src/views/portal/hacker/teams/index.tsx +++ b/src/views/portal/hacker/teams/index.tsx @@ -42,7 +42,6 @@ const TeamHacker = () => { }, []) useEffect(() => { - console.log("fromt useEffect", teamPage) teamPage.teamName !== "" ? setTeamStatus("INTEAM") : setTeamStatus("JOIN") }, [teamPage]) From 2de319a65d6c2a3ca6e0eea2754820d6cf2cd7b2 Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 17:32:15 -0800 Subject: [PATCH 12/15] fix initial state error --- src/views/portal/admin/QRCheckIn/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index f2c8266..0d567e5 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -21,7 +21,7 @@ const QRCheckInContainer: React.FC = () => { console.error(error) }, }) - const [lastScanned, setLastScanned] = React.useState(user) + const [lastScanned, setLastScanned] = React.useState() const handleScanUID = async (result: string) => { try { From bf579caaa9d3b5ec553c37bd4f0d390b4bb4fa19 Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 17:56:03 -0800 Subject: [PATCH 13/15] decodeAttempt time --- src/views/portal/admin/QRCheckIn/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index 0d567e5..f45e803 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -17,6 +17,7 @@ const QRCheckInContainer: React.FC = () => { console.log(result) handleScanUID(result.getText()) }, + timeBetweenDecodingAttempts: 100, onError: error => { console.error(error) }, From 064b74a81203adf5254690d22181595d67c5df82 Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 23:28:57 -0800 Subject: [PATCH 14/15] timeout decrease 100 -> 50 --- src/views/portal/admin/QRCheckIn/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/portal/admin/QRCheckIn/index.tsx b/src/views/portal/admin/QRCheckIn/index.tsx index f45e803..37b2fae 100644 --- a/src/views/portal/admin/QRCheckIn/index.tsx +++ b/src/views/portal/admin/QRCheckIn/index.tsx @@ -17,7 +17,7 @@ const QRCheckInContainer: React.FC = () => { console.log(result) handleScanUID(result.getText()) }, - timeBetweenDecodingAttempts: 100, + timeBetweenDecodingAttempts: 50, onError: error => { console.error(error) }, From c7c0e255d1057ad3e66a16f941be249968ae0286 Mon Sep 17 00:00:00 2001 From: Zack Traczyk Date: Tue, 16 Jan 2024 23:57:48 -0800 Subject: [PATCH 15/15] fix hacker styling --- src/views/portal/hacker/QRCode/index.tsx | 37 +++++++++++++----------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/views/portal/hacker/QRCode/index.tsx b/src/views/portal/hacker/QRCode/index.tsx index 5af87e2..87c7778 100644 --- a/src/views/portal/hacker/QRCode/index.tsx +++ b/src/views/portal/hacker/QRCode/index.tsx @@ -8,26 +8,29 @@ const QRCodeHacker = () => { } = useAuth() return ( -
-
-
-

Check-In QR Code

-

- Present this QR code to a CruzHacks Organizer to check-in to the event. -

-
+
+
+
+

+ Check-In QR Code +

+

+ Present this QR code to a CruzHacks Organizer to check-in to the + event. +

+
-
- {user ? ( - - ) : ( - // SHOULD NEVER HAPPEN -

No User

- )} +
+
+ {user ? ( + + ) : ( + // SHOULD NEVER HAPPEN +

No User

+ )}
+
) }