diff --git a/src/components/myParas/MyParas.tsx b/src/components/myParas/MyParas.tsx deleted file mode 100644 index 70cbbdbc..00000000 --- a/src/components/myParas/MyParas.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { trpc } from "@/client/lib/trpc"; -import React from "react"; -import PersonTable from "../table/table"; -import { Para, ParaHeadCell } from "../table/tableTypes"; - -const MyParas = () => { - const utils = trpc.useContext(); - const { data: paras, isLoading } = trpc.case_manager.getMyParas.useQuery(); - - const createPara = trpc.para.createPara.useMutation({ - onSuccess: () => utils.case_manager.getMyParas.invalidate(), - onSettled: (data, error) => { - if (error) console.log(error.message); - - assignParaToCaseManager.mutate({ - para_id: data?.user_id as string, - }); - }, - }); - - const assignParaToCaseManager = trpc.case_manager.addPara.useMutation({ - onSuccess: () => utils.case_manager.getMyParas.invalidate(), - onError: (error) => console.log(error.message), - }); - - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - const data = new FormData(event.currentTarget); - - createPara.mutate({ - first_name: data.get("first_name") as string, - last_name: data.get("last_name") as string, - email: data.get("email") as string, - }); - // resetting the form this way is only necessary if the form remains visible upon adding a person. due to Materials UI, the reset form(s) will show as "touched" (TT). - (event.target as HTMLFormElement).reset(); - }; - - if (isLoading) { - return
Loading...
; - } - - const headCells: ParaHeadCell[] = [ - { - id: "first_name", - label: "First Name", - hasInput: true, - }, - { - id: "last_name", - label: "Last Name", - hasInput: true, - }, - { - id: "email", - label: "Email", - hasInput: true, - }, - ]; - - return ( - <> - - - ); -}; - -export default MyParas; diff --git a/src/components/myStudents/MyStudents.tsx b/src/components/myStudents/MyStudents.tsx deleted file mode 100644 index ef659c63..00000000 --- a/src/components/myStudents/MyStudents.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { trpc } from "@/client/lib/trpc"; -import React from "react"; -import PersonTable from "../table/table"; -import { StudentWithIep, StudentWithIepHeadcell } from "../table/tableTypes"; - -const MyStudents = () => { - const utils = trpc.useContext(); - const { data: students, isLoading } = - trpc.case_manager.getMyStudentsAndIepInfo.useQuery(); - - const { mutate } = trpc.case_manager.addStudent.useMutation({ - onSuccess: () => utils.case_manager.getMyStudentsAndIepInfo.invalidate(), - // TODO(tessa): In a future PR, we could change this to notification instead of browser alert - onError: () => - alert( - `This student is already assigned to a case manager. Please check your roster if the student is already there. Otherwise, this student is with another case manager.` - ), - }); - - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - const data = new FormData(event.currentTarget); - const grade = Number(data.get("grade")); - - mutate({ - first_name: data.get("first_name") as string, - last_name: data.get("last_name") as string, - email: data.get("email") as string, - grade, - }); - // resetting the form this way is only necessary if the form remains visible upon adding a person. due to Materials UI, the reset form(s) will show as "touched" (TT). - (event.target as HTMLFormElement).reset(); - }; - - const headCells: StudentWithIepHeadcell[] = [ - { - id: "first_name", - label: "First Name", - hasInput: true, - }, - { - id: "last_name", - label: "Last Name", - hasInput: true, - }, - { - id: "email", - label: "Email", - hasInput: true, - }, - { - id: "grade", - label: "Grade", - hasInput: true, - }, - { - id: "end_date", - label: "IEP End Date", - hasInput: false, - }, - ]; - - if (isLoading) { - return
Loading...
; - } - - return ( - - ); -}; - -export default MyStudents; diff --git a/src/components/table/table.tsx b/src/components/table/table.tsx index 3244d37b..5c33f819 100644 --- a/src/components/table/table.tsx +++ b/src/components/table/table.tsx @@ -15,10 +15,37 @@ import { styled } from "@mui/material/styles"; import { visuallyHidden } from "@mui/utils"; import SearchIcon from "@mui/icons-material/Search"; import CloseIcon from "@mui/icons-material/Close"; -import { isStudentWithIep, HeadCell, Para, StudentWithIep } from "./tableTypes"; import $table from "./Table.module.css"; import $button from "@/styles/Button.module.css"; import { useRouter } from "next/router"; +import { SelectableForTable } from "zapatos/schema"; + +export type StudentWithIep = SelectableForTable<"student"> & + SelectableForTable<"iep">; +export type Para = SelectableForTable<"user">; + +export interface HeadCell { + id: string; + label: string; + hasInput: boolean; +} + +export interface StudentWithIepHeadcell extends HeadCell { + id: keyof StudentWithIep; +} + +export interface ParaHeadCell extends HeadCell { + id: keyof Para; +} + +export function isStudentWithIep( + person: StudentWithIep | Para +): person is StudentWithIep { + return ( + (person as StudentWithIep).student_id !== undefined && + (person as StudentWithIep).iep_id !== undefined + ); +} function descendingComparator(a: T, b: T, orderBy: keyof T) { if (b[orderBy] < a[orderBy]) { diff --git a/src/components/table/tableTypes.ts b/src/components/table/tableTypes.ts deleted file mode 100644 index 558674ab..00000000 --- a/src/components/table/tableTypes.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { SelectableForTable } from "zapatos/schema"; - -export type Student = SelectableForTable<"student">; -export type Para = SelectableForTable<"user">; -export type Iep = SelectableForTable<"iep">; -export type StudentWithIep = Student & Iep; - -export interface HeadCell { - id: string; - label: string; - hasInput: boolean; -} - -export interface StudentHeadCell extends HeadCell { - id: keyof Student; -} - -export interface ParaHeadCell extends HeadCell { - id: keyof Para; -} - -export interface IepHeadCell extends HeadCell { - id: keyof Iep; -} - -export type StudentWithIepHeadcell = StudentHeadCell | IepHeadCell; - -export function isStudentWithIep( - person: StudentWithIep | Para -): person is StudentWithIep { - return ( - (person as StudentWithIep).student_id !== undefined && - (person as StudentWithIep).iep_id !== undefined - ); -} diff --git a/src/components/taskCard/taskCard.tsx b/src/components/taskCard/taskCard.tsx index 232b43f7..a262a909 100644 --- a/src/components/taskCard/taskCard.tsx +++ b/src/components/taskCard/taskCard.tsx @@ -5,9 +5,22 @@ import $button from "@/styles/Button.module.css"; import $box from "@/styles/Box.module.css"; import Link from "next/link"; import ProgressBar from "../progressBar/progressBar"; -import { ParaTaskCard } from "@/types/global"; import { differenceInWeeks, format } from "date-fns"; +interface ParaTaskCard { + task_id: string; + first_name: string; + last_name: string; + category: string; + description: string; + instructions: string | null; + target_max_attempts: number | null; + due_date: Date; + seen: boolean; + trial_count: number; + completed_trials: string | number | bigint | null; +} + interface TaskCardProps { task: ParaTaskCard; } diff --git a/src/pages/staff/index.tsx b/src/pages/staff/index.tsx index 99133c45..88b06071 100644 --- a/src/pages/staff/index.tsx +++ b/src/pages/staff/index.tsx @@ -1,8 +1,70 @@ +import { trpc } from "@/client/lib/trpc"; import React from "react"; -import MyParas from "@/components/myParas/MyParas"; +import PersonTable, { Para, ParaHeadCell } from "@/components/table/table"; -function Staff() { - return ; -} +const Staff = () => { + const utils = trpc.useContext(); + const { data: paras, isLoading } = trpc.case_manager.getMyParas.useQuery(); + + const createPara = trpc.para.createPara.useMutation({ + onSuccess: async (data) => { + await assignParaToCaseManager.mutateAsync({ + para_id: data?.user_id as string, + }); + }, + }); + + const assignParaToCaseManager = trpc.case_manager.addPara.useMutation({ + onSuccess: () => utils.case_manager.getMyParas.invalidate(), + }); + + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + const data = new FormData(event.currentTarget); + + try { + await createPara.mutateAsync({ + first_name: data.get("first_name") as string, + last_name: data.get("last_name") as string, + email: data.get("email") as string, + }); + // resetting the form this way is only necessary if the form remains visible upon adding a person. due to Materials UI, the reset form(s) will show as "touched" (TT). + (event.target as HTMLFormElement).reset(); + } catch (err) { + console.error(err); + } + }; + + if (isLoading) { + return
Loading...
; + } + + const headCells: ParaHeadCell[] = [ + { + id: "first_name", + label: "First Name", + hasInput: true, + }, + { + id: "last_name", + label: "Last Name", + hasInput: true, + }, + { + id: "email", + label: "Email", + hasInput: true, + }, + ]; + + return ( + + ); +}; export default Staff; diff --git a/src/pages/students/index.tsx b/src/pages/students/index.tsx index e6988437..6c3605a5 100644 --- a/src/pages/students/index.tsx +++ b/src/pages/students/index.tsx @@ -1,8 +1,82 @@ import React from "react"; -import MyStudents from "@/components/myStudents/MyStudents"; +import { trpc } from "@/client/lib/trpc"; +import PersonTable, { + StudentWithIep, + StudentWithIepHeadcell, +} from "@/components/table/table"; -function Students() { - return ; -} +const Students = () => { + const utils = trpc.useContext(); + const { data: students, isLoading } = + trpc.case_manager.getMyStudentsAndIepInfo.useQuery(); + + const createStudent = trpc.case_manager.addStudent.useMutation({ + onSuccess: () => utils.case_manager.getMyStudentsAndIepInfo.invalidate(), + // TODO(tessa): In a future PR, we could change this to notification instead of browser alert + onError: () => + alert( + `This student is already assigned to a case manager. Please check your roster if the student is already there. Otherwise, this student is with another case manager.` + ), + }); + + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + const data = new FormData(event.currentTarget); + + try { + await createStudent.mutateAsync({ + first_name: data.get("first_name") as string, + last_name: data.get("last_name") as string, + email: data.get("email") as string, + grade: Number(data.get("grade")), + }); + // resetting the form this way is only necessary if the form remains visible upon adding a person. due to Materials UI, the reset form(s) will show as "touched" (TT). + (event.target as HTMLFormElement).reset(); + } catch (err) { + console.error(err); + } + }; + + const headCells: StudentWithIepHeadcell[] = [ + { + id: "first_name", + label: "First Name", + hasInput: true, + }, + { + id: "last_name", + label: "Last Name", + hasInput: true, + }, + { + id: "email", + label: "Email", + hasInput: true, + }, + { + id: "grade", + label: "Grade", + hasInput: true, + }, + { + id: "end_date", + label: "IEP End Date", + hasInput: false, + }, + ]; + + if (isLoading) { + return
Loading...
; + } + + return ( + + ); +}; export default Students; diff --git a/src/types/global.ts b/src/types/global.ts index 8d1396b7..ce39004d 100644 --- a/src/types/global.ts +++ b/src/types/global.ts @@ -1,18 +1,4 @@ import { SelectableForTable } from "zapatos/schema"; -export interface ParaTaskCard { - task_id: string; - first_name: string; - last_name: string; - category: string; - description: string; - instructions: string | null; - target_max_attempts: number | null; - due_date: Date; - seen: boolean; - trial_count: number; - completed_trials: string | number | bigint | null; -} - export type Goal = SelectableForTable<"goal">; export type Subgoal = SelectableForTable<"subgoal">;