diff --git a/src/sprintFiles/AlertComponent.tsx b/src/sprintFiles/AlertComponent.tsx
new file mode 100644
index 0000000..5738747
--- /dev/null
+++ b/src/sprintFiles/AlertComponent.tsx
@@ -0,0 +1,41 @@
+import { Dialog, DialogContent, Alert, Button, DialogActions } from "@mui/material";
+import { useState } from "react";
+
+/**
+ * Pieces of code necessary to use this AlertComponent within a parent component:
+ * PARENT:
+ * const [errorMessage, setErrorMessage] = useState("");
+ * In the returned div,
+ * {
+ errorMessage !== "" &&
+
+ }
+ * When the error message is set in the parent, this alert component will now automatically render.
+
+ * @param message - The message for the popup to display
+ * @param setErrorMessage - The state function that is used to manage the message that's displayed
+ * @returns A dismissable Alert Component
+ */
+const AlertComponent = ({ message, setErrorMessage } : { message: string, setErrorMessage: (value: React.SetStateAction) => void}) => {
+ const [open, setOpen] = useState(true);
+
+ const handleClose = () => {
+ setErrorMessage("");
+ setOpen(false);
+ }
+ return (
+
+ )
+}
+
+export default AlertComponent;
\ No newline at end of file
diff --git a/src/sprintFiles/PinVerificationForm.tsx b/src/sprintFiles/PinVerificationForm.tsx
new file mode 100644
index 0000000..5f4d81a
--- /dev/null
+++ b/src/sprintFiles/PinVerificationForm.tsx
@@ -0,0 +1,161 @@
+import { TextInput } from "@/components/shared/forms/CustomFormikFields";
+import { selectCurrentHouse, selectCurrentUser } from "@/features/auth/authSlice";
+import { useGetScheduledShiftsQuery, useUpdateScheduledShiftMutation } from "@/features/scheduledShift/scheduledShiftApiSlice";
+import { House, ScheduledShift, Shift, User } from "@/types/schema";
+import { Container, Card, Button, Typography } from "@mui/material";
+import { Dictionary, EntityId } from "@reduxjs/toolkit";
+import { FormikHelpers, Formik, Form } from "formik";
+import { useState } from "react";
+import { useSelector } from "react-redux";
+import * as Yup from 'yup'
+import AlertComponent from "./AlertComponent";
+import { useGetShiftsQuery } from "@/features/shift/shiftApiSlice";
+import dayjs from "dayjs";
+import { VERIFIED } from "@/utils/constants";
+
+const VerificationSchema = Yup.object({
+ pinNumber: Yup.string().required('Pin Number is required'),
+})
+
+const PinVerificationForm = ({scheduledShiftID}: {scheduledShiftID: string}) => {
+ const currentHouse: House = useSelector(selectCurrentHouse) as House
+ const currentUser: User = useSelector(selectCurrentUser) as User
+ const [errorMessage, setErrorMessage] = useState("");
+
+ const {
+ data: scheduledShifts
+ } = useGetScheduledShiftsQuery(currentHouse.houseID)
+
+ const {
+ data: shifts
+ } = useGetShiftsQuery(currentHouse.houseID);
+
+ const [
+ updateScheduledShift
+ ] = useUpdateScheduledShiftMutation();
+
+ /**
+ *
+ * @param pinNumber The pin number that's entered
+ * @returns A boolean indicating if the pin number is valid for the given house and that the pin number doesn't belong to the current user
+ */
+ const verifyPinCode = (pinNumber: string) => {
+ if (!(pinNumber in currentHouse.userPINs)) {
+ setErrorMessage("Unidentified User PIN");
+ return;
+ }
+ if (currentHouse.userPINs[pinNumber] === currentUser.id) {
+ setErrorMessage("User PIN belongs to current user");
+ return;
+ }
+ return true;
+ }
+
+ /**
+ *
+ * @param scheduledEntityDictionary The entity dictionary for scheduledShifts
+ * @param shiftEntityDictionary The entity dictionary for shifts
+ * @param verifiedBy A user id for the person that verified this shift (not the current user)
+ * @returns Updates the Firebase with status = verified, verifiedBy = userID, verifiedAt = currentTime, shiftCopy = copy of the shift that this scheduledShifts points to
+ */
+
+ const updateScheduledShiftObject = async (scheduledEntityDictionary: Dictionary, shiftEntityDictionary: Dictionary, verifiedBy: string) => {
+ // Copy the shift into the scheduledShift object
+ let scheduledShiftObject = scheduledEntityDictionary[scheduledShiftID];
+ if (scheduledShiftObject === undefined) {
+ console.log("Given scheduled shift id is invalid");
+ return;
+ }
+ if (scheduledShiftObject.status === VERIFIED) {
+ setErrorMessage("Shift has already been verified");
+ return;
+ }
+ let innerShiftID = scheduledShiftObject.shiftID;
+ let shiftObject = shiftEntityDictionary[innerShiftID];
+ if (shiftObject === undefined) {
+ console.log("Inner shift id in the scheduled shfit is invalid");
+ return;
+ }
+ const data = {
+ houseId: currentHouse.houseID,
+ shiftId: scheduledShiftObject.id,
+ data: {
+ shiftCopy: JSON.parse(JSON.stringify(shiftObject)) as Shift,
+ status: VERIFIED,
+ verifiedBy: verifiedBy,
+ verifiedAt: dayjs().toString()
+ }
+ }
+ await updateScheduledShift(data);
+ console.log("success");
+ }
+
+ /**
+ *
+ * @param pinNumber - The pin number that's entered
+ * @returns Checks the the pin code is valid and then updates the firebase.
+ */
+ const onSubmit = async (values: {pinNumber: string}, formikBag: FormikHelpers) => {
+ const { pinNumber } = values;
+ if (scheduledShifts === undefined || shifts === undefined) {
+ console.log("Scheduled Shifts / Shifts not loaded");
+ return;
+ }
+ if (!verifyPinCode(pinNumber)) {
+ return;
+ }
+ let verifiedBy = currentHouse.userPINs[pinNumber];
+ await updateScheduledShiftObject(scheduledShifts.entities, shifts.entities, verifiedBy);
+ }
+
+ return (
+
+
+
+ Pin Number
+
+
+ {({ isSubmitting, values, setFieldValue }) => (
+
+ )}
+
+
+ {
+ errorMessage !== "" &&
+
+ }
+
+ )
+}
+
+export default PinVerificationForm;
\ No newline at end of file
diff --git a/src/types/schema.ts b/src/types/schema.ts
index 3e1e63f..9cb5584 100644
--- a/src/types/schema.ts
+++ b/src/types/schema.ts
@@ -1,3 +1,5 @@
+import dayjs, {Dayjs} from "dayjs"
+
export type User = {
// this id is to help the standard table generalize the id attribute
id: string
@@ -102,6 +104,7 @@ export type ScheduledShift = {
verifiedAt: string
unverifiedAt: string
penaltyHours: number
+ shiftCopy?: Shift
}
export type House = {
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index bf1cf4e..afdb1f1 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -109,4 +109,7 @@ export const DAYS = [
'thursday',
'friday',
'saturday',
-]
\ No newline at end of file
+]
+
+export const VERIFIED = 'verified';
+export const UNVERIFIED = 'unverified';
\ No newline at end of file