diff --git a/src/components/calendar/CreateEventModal.tsx b/src/components/calendar/CreateEventModal.tsx new file mode 100644 index 00000000..14e83299 --- /dev/null +++ b/src/components/calendar/CreateEventModal.tsx @@ -0,0 +1,299 @@ +import { + Box, + Button, + Checkbox, + CheckboxGroup, + Container, + FormLabel, + Input, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Stack, + Text, + Textarea, + VStack, + useToast +} from '@chakra-ui/react' +import { zodResolver } from '@hookform/resolvers/zod' +import { useContext, useState } from 'react' +import { useForm } from 'react-hook-form' +import type { z } from 'zod' +import { ModalContext } from '~/context/ModalContext' +import { trpc } from '~/utils/trpc' +import LoadingScreen from '../common/LoadingScreen' +import type { Attendees } from '../events/DataTable' +import { DataTable } from '../events/DataTable' +import createEventFormSchema from '../../utils/calendar/createEventFormSchema' + +type useInFormProps = { + setAttendees: React.Dispatch>; + invalidAttendees: boolean; + register: any; + errors: any; + isSubmitting: boolean; + submitBefore: boolean; +}; + +const CreateEventModal = () => { + const modal = useContext(ModalContext) + + if (!modal.id) { + console.log("modal id is undefined") + // return null + } + + const toast = useToast() + const [attendees, setAttendees] = useState([]) + // hacky use for attendees validation + const [submitBefore, setSubmitBefore] = useState(false) + const FormSchema = createEventFormSchema() + + type FormSchemaType = z.infer + + // useForm for state management except attendees which belongs in DataTable (child) + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(FormSchema), + }) + + const { data } = trpc.attendance.getAllAttendanceButSelf.useQuery() + const { mutateAsync, isLoading: isSubmitting } = + trpc.event.createEvent.useMutation() + + const invalidAttendees = attendees.length === 0 + const useInForm = { setAttendees, invalidAttendees, register, errors, isSubmitting, submitBefore } + + if (!data) return + + const formSubmit = async (formData: FormSchemaType) => { + try { + // Hacky soluton since attendees not linked to React-hook-form + if (invalidAttendees) { + throw new Error("At least one attendee must be selected") + } + + await mutateAsync({ + name: formData.eventName, + startDate: new Date(formData.startDate), + endDate: new Date(formData.endDate), + venue: formData.venue, + departments: formData.dept, + secretCode: formData.secretCode, + description: formData.description, + invitedAttendees: attendees, + }) + toast({ + duration: 3000, + status: 'success', + title: 'Success', + description: 'A new event has been successfully created', + }) + modal.onClose() + } catch (e) { + toast({ + description: (e as Error).message, + duration: 3000, + status: 'error', + title: 'Oops, an error occured!', + }) + } + } + + return ( + + + + +
+ +
+ + + + + + + + + + +
+ + + ) +} + +const Header: React.FC = () => { + return ( + + Create an Event + + + ) +} + +const Body: React.FC<{ attendeeData: Attendees[], useInForm: useInFormProps }> = ({ attendeeData, useInForm }) => { + if (!attendeeData) return + const { setAttendees, invalidAttendees, register, errors, isSubmitting, submitBefore }: useInFormProps = useInForm + + return ( + + +
+ Event Name + + {errors.eventName && ( + + {errors.eventName.message} + + )} +
+
+ Description +