From f1c71eba095d8a987a4ddecc3957eae74c4d99d9 Mon Sep 17 00:00:00 2001 From: Chris Lawson Date: Sun, 13 Oct 2024 20:07:33 -0700 Subject: [PATCH] feat: remove department from professor --- packages/backend/src/routers/admin.ts | 21 +------ packages/backend/src/routers/professor.ts | 2 - packages/backend/src/types/schema.ts | 1 - packages/backend/src/types/schemaHelpers.ts | 2 - .../src/components/NewProfessorForm.tsx | 1 - .../frontend/src/components/ProfessorCard.tsx | 1 - .../frontend/src/hooks/useSortedCourses.ts | 49 ++++++++-------- packages/frontend/src/pages/Admin.tsx | 56 +------------------ packages/frontend/src/pages/ProfessorPage.tsx | 2 - 9 files changed, 27 insertions(+), 108 deletions(-) diff --git a/packages/backend/src/routers/admin.ts b/packages/backend/src/routers/admin.ts index d1da158c..8d28324c 100644 --- a/packages/backend/src/routers/admin.ts +++ b/packages/backend/src/routers/admin.ts @@ -1,12 +1,7 @@ import { t, protectedProcedure } from "@backend/trpc"; import { z } from "zod"; import { addRating } from "@backend/types/schemaHelpers"; -import { bulkKeys, DEPARTMENT_LIST } from "@backend/utils/const"; - -const changeDepartmentParser = z.object({ - professorId: z.string().uuid(), - department: z.enum(DEPARTMENT_LIST), -}); +import { bulkKeys } from "@backend/utils/const"; const changeNameParser = z.object({ professorId: z.string().uuid(), @@ -63,20 +58,6 @@ export const adminRouter = t.router({ await ctx.env.kvDao.putProfessor(destProfessor); await ctx.env.kvDao.removeProfessor(sourceProfessor.id); }), - changeProfessorDepartment: protectedProcedure - .input(changeDepartmentParser) - .mutation(async ({ ctx, input: { professorId, department } }) => { - const professor = await ctx.env.kvDao.getProfessor(professorId); - professor.department = department; - await ctx.env.kvDao.putProfessor(professor); - }), - changePendingProfessorDepartment: protectedProcedure - .input(changeDepartmentParser) - .mutation(async ({ ctx, input: { professorId, department } }) => { - const professor = await ctx.env.kvDao.getPendingProfessor(professorId); - professor.department = department; - await ctx.env.kvDao.putPendingProfessor(professor); - }), changeProfessorName: protectedProcedure .input(changeNameParser) .mutation(async ({ ctx, input: { professorId, firstName, lastName } }) => { diff --git a/packages/backend/src/routers/professor.ts b/packages/backend/src/routers/professor.ts index 2c19bbbf..23b261f3 100644 --- a/packages/backend/src/routers/professor.ts +++ b/packages/backend/src/routers/professor.ts @@ -17,7 +17,6 @@ export const professorRouter = t.router({ add: t.procedure .input( z.object({ - department: z.enum(DEPARTMENT_LIST), firstName: z.string(), lastName: z.string(), rating: ratingBaseParser.merge( @@ -35,7 +34,6 @@ export const professorRouter = t.router({ id: professorId, firstName: input.firstName, lastName: input.lastName, - department: input.department, courses: [input.rating.department], numEvals: 1, overallRating: input.rating.overallRating, diff --git a/packages/backend/src/types/schema.ts b/packages/backend/src/types/schema.ts index b2927e3e..ef7ad7f0 100644 --- a/packages/backend/src/types/schema.ts +++ b/packages/backend/src/types/schema.ts @@ -64,7 +64,6 @@ export type PendingRating = z.infer; export const truncatedProfessorParser = z.object({ id: z.string().uuid(), - department: z.enum(DEPARTMENT_LIST), firstName: z.string(), lastName: z.string(), numEvals: z.number(), diff --git a/packages/backend/src/types/schemaHelpers.ts b/packages/backend/src/types/schemaHelpers.ts index e241d865..ab91ce18 100644 --- a/packages/backend/src/types/schemaHelpers.ts +++ b/packages/backend/src/types/schemaHelpers.ts @@ -102,7 +102,6 @@ export function professorToTruncatedProfessor({ id, firstName, lastName, - department, courses, numEvals, overallRating, @@ -113,7 +112,6 @@ export function professorToTruncatedProfessor({ id, firstName, lastName, - department, courses, numEvals, overallRating, diff --git a/packages/frontend/src/components/NewProfessorForm.tsx b/packages/frontend/src/components/NewProfessorForm.tsx index e01a63f2..87d08dab 100644 --- a/packages/frontend/src/components/NewProfessorForm.tsx +++ b/packages/frontend/src/components/NewProfessorForm.tsx @@ -134,7 +134,6 @@ function useNewProfessorForm() { await addNewProfessorMutation({ firstName: data.professorFirstName, lastName: data.professorLastName, - department: data.professorDepartment, rating: { overallRating: data.overallRating, presentsMaterialClearly: data.presentsMaterialClearly, diff --git a/packages/frontend/src/components/ProfessorCard.tsx b/packages/frontend/src/components/ProfessorCard.tsx index f3f89f3d..566f5a9b 100644 --- a/packages/frontend/src/components/ProfessorCard.tsx +++ b/packages/frontend/src/components/ProfessorCard.tsx @@ -21,7 +21,6 @@ export function ProfessorCard({ professor }: ProfessorCardProps) { {professor?.lastName}, {professor?.firstName}
-
{professor?.department}
{professor?.overallRating.toFixed(2)}
diff --git a/packages/frontend/src/hooks/useSortedCourses.ts b/packages/frontend/src/hooks/useSortedCourses.ts index 4b73c788..da815ce9 100644 --- a/packages/frontend/src/hooks/useSortedCourses.ts +++ b/packages/frontend/src/hooks/useSortedCourses.ts @@ -13,41 +13,40 @@ export function useSortedCourses(professorId: string | undefined) { id: professorId ?? "", }); - // Put classes for professors primary department first. This is to cut down on rating spamming - // of other departments. It is possible for a professor to teach outside of the department but - // it is ok if those ratings come after the primary department + // Sort by the most common department and then by course number - // Sort Into Departments + // Group ratings by department and count occurrences in one pass const professorByDepartments = Object.entries(professorData?.reviews || {}).reduce( (acc, [course, ratings]) => { const obj: CourseRatings = { courseName: course, ratings }; const [department] = course.split(" "); - if (acc[department]) { - acc[department].push(obj); - } else { - acc[department] = [obj]; + + if (!acc[department]) { + acc[department] = { ratings: [], count: 0 }; } + + acc[department].ratings.push(obj); + acc[department].count += obj.ratings.length; + return acc; }, - {} as { [department: string]: CourseRatings[] }, + {} as { [department: string]: { ratings: CourseRatings[]; count: number } }, ); - // Sort departments by class number - Object.values(professorByDepartments).forEach((department) => - department.sort((a, b) => { - const [, aNumber] = a.courseName.split(" "); - const [, bNumber] = b.courseName.split(" "); - return parseInt(aNumber, 10) - parseInt(bNumber, 10); - }), - ); - - const primaryClasses = professorByDepartments[professorData?.department ?? ""] ?? []; - const otherClasses = Object.entries(professorByDepartments) - .filter(([department]) => department !== professorData?.department) - .flatMap(([, courseRatings]) => courseRatings); - - const sortedCourseRatings = [...primaryClasses, ...otherClasses].map((courseRating) => { - // Be carful the array is sorted in place. This is fine here but if moved could cause issues. + // Sort departments by frequency of ratings and within departments by course number + const sortedProfessorCourses = Object.entries(professorByDepartments) + .sort(([, a], [, b]) => b.count - a.count) // Sort departments by count (most common first) + .map(([, { ratings }]) => + ratings.sort((a, b) => { + const [, aNumber] = a.courseName.split(" "); + const [, bNumber] = b.courseName.split(" "); + return parseInt(aNumber, 10) - parseInt(bNumber, 10); + }), + ); + + // Flatten sorted departments into a single array of course ratings + const sortedCourseRatings = sortedProfessorCourses.flat().map((courseRating) => { + // Sort ratings by post date within each course courseRating.ratings.sort((a, b) => Date.parse(b.postDate) - Date.parse(a.postDate)); return courseRating; }); diff --git a/packages/frontend/src/pages/Admin.tsx b/packages/frontend/src/pages/Admin.tsx index 9e504c33..92cc6204 100644 --- a/packages/frontend/src/pages/Admin.tsx +++ b/packages/frontend/src/pages/Admin.tsx @@ -4,13 +4,13 @@ import { Fragment, lazy, Suspense, useState } from "react"; import { Professor, RatingReport, TruncatedProfessor } from "@backend/types/schema"; import { useQueryClient } from "@tanstack/react-query"; import { ExpanderComponentProps, TableProps } from "react-data-table-component"; -import { Department, DEPARTMENT_LIST } from "@backend/utils/const"; +import { Department } from "@backend/utils/const"; import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/solid"; import { useAuth } from "@/hooks"; import { trpc } from "@/trpc"; import { bulkInvalidationKey, useDbValues } from "@/hooks/useDbValues"; import { Button } from "@/components/forms/Button"; -import { AutoComplete, Select, TextInput } from "@/components"; +import { AutoComplete, TextInput } from "@/components"; import { professorSearch } from "@/utils/ProfessorSearch"; const DataTableLazy = lazy(() => import("react-data-table-component")); @@ -64,16 +64,6 @@ function ReportedRatings() { return `${professor?.lastName}, ${professor?.firstName}`; }, }, - { - name: "Department", - grow: 0.5, - selector: (row: RatingReport) => { - const professor = professors?.find( - (professor) => professor?.id === row.professorId, - ); - return professor?.department ?? ""; - }, - }, { name: "Reason", wrap: true, @@ -181,10 +171,6 @@ function PendingProfessors() { ), }, - { - name: "Department", - selector: (row: Professor) => row.department, - }, { name: "Rating Course", selector: (row: Professor) => Object.keys(row.reviews ?? {})[0], @@ -238,7 +224,6 @@ function PendingProfessorActions({ data: professor }: ExpanderComponentProps -
); } @@ -373,43 +358,6 @@ function ChangeNameAction({ professor }: PendingProfessorAction) { ); } -function ChangeNameDepartment({ professor }: PendingProfessorAction) { - const [department, setDepartment] = useState(professor.department); - - const queryClient = useQueryClient(); - const { - mutate: setProfessorDepartment, - isLoading, - error, - } = trpc.admin.changePendingProfessorDepartment.useMutation({ - onSuccess: () => queryClient.invalidateQueries(bulkInvalidationKey("professor-queue")), - }); - - return ( -
- Change Department -