{"version":3,"file":"index.e1bc1027.js","sources":["../../vite/modulepreload-polyfill","../../src/assets/home-header.webp","../../src/assets/home-curve-transition.svg","../../src/assets/star.svg","../../src/assets/worst-of-worst-background.webp","../../src/App.config.ts","../../src/services/auth.service.ts","../../src/services/http.service.ts","../../src/services/review.service.ts","../../src/utils/getRandomSubarray.ts","../../src/utils/intersectingDbEntities.ts","../../src/services/teacher.service.ts","../../src/services/index.ts","../../src/components/Backdrop.tsx","../../src/hooks/useObservable.ts","../../src/hooks/useService.ts","../../src/hooks/useAuth.ts","../../src/hooks/useProtectedRoute.ts","../../src/hooks/useQuery.ts","../../src/hooks/useWindowSize.ts","../../src/hooks/useTailwindBreakpoints.ts","../../src/constants/departments.ts","../../src/components/EvaluateTeacherForm.tsx","../../src/assets/Logo.png","../../src/components/SearchBar.tsx","../../src/components/Navbar.tsx","../../src/components/NewTeacherForm.tsx","../../src/components/TeacherCard.tsx","../../src/components/TwoPosSlider.tsx","../../src/pages/Home.tsx","../../src/pages/Login.tsx","../../src/pages/NewTeacher.tsx","../../src/pages/Search.tsx","../../src/pages/Teacher.tsx","../../src/App.tsx","../../src/main.tsx"],"sourcesContent":["const p = function polyfill() {\n const relList = document.createElement('link').relList;\n if (relList && relList.supports && relList.supports('modulepreload')) {\n return;\n }\n for (const link of document.querySelectorAll('link[rel=\"modulepreload\"]')) {\n processPreload(link);\n }\n new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type !== 'childList') {\n continue;\n }\n for (const node of mutation.addedNodes) {\n if (node.tagName === 'LINK' && node.rel === 'modulepreload')\n processPreload(node);\n }\n }\n }).observe(document, { childList: true, subtree: true });\n function getFetchOpts(script) {\n const fetchOpts = {};\n if (script.integrity)\n fetchOpts.integrity = script.integrity;\n if (script.referrerpolicy)\n fetchOpts.referrerPolicy = script.referrerpolicy;\n if (script.crossorigin === 'use-credentials')\n fetchOpts.credentials = 'include';\n else if (script.crossorigin === 'anonymous')\n fetchOpts.credentials = 'omit';\n else\n fetchOpts.credentials = 'same-origin';\n return fetchOpts;\n }\n function processPreload(link) {\n if (link.ep)\n // ep marker = processed\n return;\n link.ep = true;\n // prepopulate the load record\n const fetchOpts = getFetchOpts(link);\n fetch(link.href, fetchOpts);\n }\n};__VITE_IS_MODERN__&&p();","export default \"__VITE_ASSET__6c92036b__\"","export default \"__VITE_ASSET__e73e0055__\"","export default \"__VITE_ASSET__7e79bd14__\"","export default \"__VITE_ASSET__3f2466ee__\"","interface AppConfiguration {\n remoteUrl:string,\n base:string\n}\n\nconst devConfig:AppConfiguration = {\n remoteUrl:'https://api.addison-polyratings.workers.dev',\n base:'/'\n}\n\nconst prodConfig:AppConfiguration = {\n remoteUrl:'https://api.addison-polyratings.workers.dev',\n base:'/'\n}\n\nconst githubPagesConfig:AppConfiguration = {\n remoteUrl:'https://api.addison-polyratings.workers.dev',\n base:'/polyratings-revamp/'\n}\n\nconst regularConfig = process.env.NODE_ENV === 'development' ? devConfig : prodConfig; \n\nexport const config = window.location.href.includes('github.io') ? githubPagesConfig : regularConfig","import { BehaviorSubject } from \"rxjs\"\nimport { config } from \"../App.config\"\nimport { JwtAuthResponse } from \"@polyratings/shared\"\nimport { User } from \"@polyratings/shared\"\nimport jwt_decode from \"jwt-decode\";\n\nconst USER_LOCAL_STORAGE_KEY = 'user'\n\nexport class AuthService {\n\n private jwtToken:string | null = null\n public isAuthenticatedSubject = new BehaviorSubject(null)\n\n constructor(\n private storage:Storage,\n private fetch: typeof window.fetch\n ) {\n const jwt = storage.getItem(USER_LOCAL_STORAGE_KEY) as string | null\n if(jwt) {\n this.setAuthState(jwt)\n }\n }\n\n public getJwt(): string | null {\n return this.jwtToken\n }\n\n public getUser(): User | null {\n return this.jwtToken ? jwt_decode(this.jwtToken) : null\n }\n\n public async login(calPolyUsername:string, password:string):Promise {\n const loginRes = await this.fetch(\n `${config.remoteUrl}/auth/login`,\n {\n method:'POST', \n headers:{\n 'Content-Type':'application/json'\n },\n body:JSON.stringify({email:`${calPolyUsername}@calpoly.edu`, password})\n }\n )\n if(loginRes.status != 200 && loginRes.status != 201) {\n const error = await loginRes.json()\n throw error.message\n }\n const loginBody = await loginRes.json() as JwtAuthResponse\n const jwt = loginBody.access_token\n \n // We know that this is a valid user since we just got a jwt\n return this.setAuthState(jwt) as User\n }\n\n public signOut() {\n this.setAuthState(null)\n }\n\n private setAuthState(jwtToken:string | null):User | null {\n this.jwtToken = jwtToken\n const user = this.getUser()\n this.isAuthenticatedSubject.next(user)\n if(jwtToken) {\n this.storage.setItem(USER_LOCAL_STORAGE_KEY, jwtToken)\n } else {\n this.storage.removeItem(USER_LOCAL_STORAGE_KEY)\n }\n return user\n }\n}","import { AuthService } from \"./auth.service\";\n\nexport class HttpService {\n constructor(\n private authService:AuthService,\n private globalFetch: typeof window.fetch\n ){}\n\n async fetch(input: string, init?: RequestInit | undefined):Promise {\n init = init || {}\n init.headers = init.headers || {}\n const jwt = this.authService.getJwt()\n if(jwt) {\n // @ts-expect-error error since can't normally index header object. The way that its going to be used will be fine though\n init.headers['Authorization'] = `Bearer ${jwt}`\n }\n const res = await this.globalFetch(input, init)\n if(res.status == 401) {\n // TODO: Find a way to do this cleaner\n this.authService.signOut()\n const LOGIN_ROUTE = '/login'\n if(window.location.pathname != LOGIN_ROUTE) {\n window.location.replace(LOGIN_ROUTE)\n }\n }\n return res\n }\n \n}","import { TeacherEntry, AddReview } from \"@polyratings/shared\";\nimport { config } from \"../App.config\";\nimport { HttpService } from \"./http.service\";\n\nexport class ReviewService {\n constructor(\n private httpService:HttpService\n ){}\n\n async uploadReview(newReview:AddReview): Promise {\n const res = await this.httpService.fetch(\n `${config.remoteUrl}/review`,\n {\n method:'POST',\n headers:{\n 'Content-Type':'application/json'\n },\n body:JSON.stringify(newReview)\n }\n )\n this.throwIfNot200(res)\n return res.json()\n }\n \n private throwIfNot200(res:Response) {\n if(res.status != 200 && res.status != 201) {\n throw res.statusText\n }\n }\n}\n","export function getRandomSubarray(arr:T[], size:number):T[] {\n var shuffled = arr.slice(0), i = arr.length, min = i - size, temp, index;\n while (i-- > min) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(min);\n}","import { DbEntryProperties } from '@polyratings/shared'\n\nexport function intersectingDbEntities(arrays:T[][]): {intersect: T[], nonIntersect:T[]} {\n if(arrays.length == 1) {\n return {\n intersect:arrays[0],\n nonIntersect:[]\n }\n }\n const idToEntity = arrays.flat().reduce((acc:{[id:string]: T},curr) => {\n acc[curr.id] = curr\n return acc\n }, {})\n const idArrays = arrays.map(arr => arr.map(x => x.id))\n let intersectionSet = new Set(idArrays[0])\n for(let array of idArrays.slice(1)) {\n const compareSet = new Set(array);\n intersectionSet = new Set([...intersectionSet].filter(x => compareSet.has(x)));\n }\n const nonIntersect = arrays.flat().filter(x => !intersectionSet.has(x.id))\n\n return {\n intersect: Array.from(intersectionSet).map(id => idToEntity[id]),\n nonIntersect\n }\n}","import { TeacherEntry, Teacher, TeacherIdResponse } from \"@polyratings/shared\"\nimport { config } from \"../App.config\";\nimport { getRandomSubarray, intersectingDbEntities } from \"../utils\";\nimport { HttpService } from \"./http.service\";\n\nconst TEN_MINUTES = 1000 * 60 * 10\nconst ALL_TEACHER_CACHE_KEY = 'ALL_TEACHERS'\nconst INDIVIDUAL_TEACHER_CACHE_KEY = 'TEACHERS'\n\ninterface TeacherCacheEntry {\n exp:Date\n teacher:TeacherEntry\n}\n\nexport type TeacherSearchType = 'name' | 'department' | 'class'\n\nexport class TeacherService {\n\n private allTeachers:Promise\n private teacherCache:{[id:string]:TeacherCacheEntry}\n\n constructor(\n private httpService:HttpService,\n private storage:Storage,\n ){\n\n const individualTeacherCacheStr = this.storage.getItem(INDIVIDUAL_TEACHER_CACHE_KEY)\n this.teacherCache = individualTeacherCacheStr ? JSON.parse(individualTeacherCacheStr) : {}\n\n const cachedAllTeacherCacheStr = this.storage.getItem(ALL_TEACHER_CACHE_KEY)\n if(cachedAllTeacherCacheStr) {\n const allTeacherCache:{exp:Date, data:TeacherEntry[]} = JSON.parse(cachedAllTeacherCacheStr)\n if(allTeacherCache.exp < new Date()) {\n // List has not expired\n this.allTeachers = Promise.resolve(allTeacherCache.data)\n // Return early no need to fetch the teacher list\n return\n }\n }\n\n this.allTeachers = new Promise(async resolve => {\n const res = await this.httpService.fetch(`${config.remoteUrl}/all`)\n this.throwIfNot200(res)\n const data = await res.json()\n this.storage.setItem(ALL_TEACHER_CACHE_KEY, JSON.stringify({\n exp:new Date(Date.now() + TEN_MINUTES),\n data\n }))\n resolve(data)\n })\n }\n\n async getRandomBestTeacher(): Promise {\n const allTeachers = await this.allTeachers\n const rankedTeachers = allTeachers\n .filter(t => t.numEvals > 10)\n .sort((a,b) => b.overallRating - a.overallRating)\n return getRandomSubarray(rankedTeachers.slice(0,30), 1)[0]\n }\n\n async getRandomWorstTeachers(): Promise {\n const allTeachers = await this.allTeachers\n const rankedTeachers = allTeachers\n .filter(t => t.numEvals > 10)\n .sort((a,b) => a.overallRating - b.overallRating)\n return getRandomSubarray(rankedTeachers.slice(0,30), 6)\n }\n\n async getTeacher(id:string): Promise {\n if(this.teacherCache[id]) {\n if(this.teacherCache[id].exp > new Date()) {\n return this.teacherCache[id].teacher\n }\n this.removeTeacherFromCache(id)\n }\n\n const res = await this.httpService.fetch(`${config.remoteUrl}/${id}`)\n this.throwIfNot200(res)\n\n const teacher:TeacherEntry = await res.json()\n // Make sure reviews are in dated order\n Object.values(teacher.reviews!).forEach(reviewArr => reviewArr.sort((a,b) => Date.parse(b.postDate) - Date.parse(a.postDate)))\n this.addTeacherToCache(teacher)\n return teacher\n }\n\n async searchForTeacher(type:TeacherSearchType ,value:string): Promise {\n const allTeachers = await this.allTeachers\n\n switch(type) {\n case 'name':\n const tokens = value.toLowerCase().split(' ')\n const tokenMatches = tokens\n .map(token => allTeachers.filter(teacher => `${teacher.lastName}, ${teacher.firstName}`.toLowerCase().includes(token)))\n const {intersect, nonIntersect} = intersectingDbEntities(tokenMatches)\n return [...intersect, ...nonIntersect]\n case 'class':\n const courseName = value.toUpperCase()\n // use includes to possibly be more lenient\n return allTeachers.filter(teacher => teacher.courses.find(course => course.includes(courseName)))\n case 'department':\n const department = value.toUpperCase()\n // Use starts with since most times with department you are looking for an exact match\n return allTeachers.filter(teacher => teacher.department.startsWith(department))\n default:\n throw `Invalid Search Type: ${type}`\n }\n\n }\n\n async getAllTeachers(): Promise {\n return this.allTeachers\n }\n\n async addNewTeacher(newTeacher:Teacher): Promise {\n const res = await this.httpService.fetch(\n `${config.remoteUrl}/teacher`,\n {\n method:'POST',\n headers:{\n 'Content-Type':'application/json'\n },\n body:JSON.stringify(newTeacher)\n }\n )\n const teacherIdResponse = await res.json() as TeacherIdResponse\n return teacherIdResponse.teacherId\n }\n \n private throwIfNot200(res:Response) {\n if(res.status != 200) {\n throw res.statusText\n }\n }\n\n private addTeacherToCache(teacher:TeacherEntry) {\n this.teacherCache[teacher.id] = {\n teacher,\n exp: new Date(Date.now() + TEN_MINUTES)\n }\n this.storage.setItem(INDIVIDUAL_TEACHER_CACHE_KEY, JSON.stringify(this.teacherCache))\n }\n\n private removeTeacherFromCache(id:string) {\n delete this.teacherCache[id]\n this.storage.setItem(INDIVIDUAL_TEACHER_CACHE_KEY, JSON.stringify(this.teacherCache))\n }\n}","import { DependencyInjector, InjectionToken, makeInjector } from \"@mindspace-io/react\";\nimport { AuthService } from \"./auth.service\";\nimport { HttpService } from \"./http.service\";\nimport { ReviewService } from \"./review.service\";\nimport { TeacherService } from \"./teacher.service\";\n\nconst LOCAL_STORAGE = new InjectionToken('local-storage')\nconst FETCH = new InjectionToken('fetch')\n\nexport const injector:DependencyInjector = makeInjector([\n { provide: LOCAL_STORAGE, useValue:window.localStorage },\n { provide: FETCH, useFactory:() => window.fetch.bind(window) },\n { provide: AuthService, useClass:AuthService, deps:[LOCAL_STORAGE, FETCH] },\n { provide: HttpService, useClass: HttpService, deps:[AuthService, FETCH] },\n { provide: TeacherService, useClass: TeacherService, deps:[HttpService, LOCAL_STORAGE] },\n { provide: ReviewService, useClass: ReviewService, deps:[HttpService] }\n])\n\nexport { AuthService, HttpService, TeacherService, ReviewService }\n","import { ReactNode, useEffect } from \"react\";\n\nexport function Backdrop({children}:{children:ReactNode}) {\n // Fix scroll position \n useEffect(() => {\n document.body.style.overflowY = \"hidden\"\n return () => {\n document.body.style.overflowY = \"auto\"\n }\n },[])\n \n return (\n
\n {children}\n
\n )\n}","import { useEffect, useState } from \"react\"\nimport { Observable } from \"rxjs\"\n\nexport function useObservable(observable:Observable, initial:T) {\n let [value, setValue] = useState(initial)\n useEffect(() => {\n const sub = observable.subscribe(setValue)\n return () => {\n sub.unsubscribe()\n }\n },[])\n return value\n}","import { DependencyInjector, HookTuple, useInjectorHook } from \"@mindspace-io/react\";\nimport { injector } from \"../services\";\n\ntype Constructs = (new (...args: any[]) => T)\n\nexport function useService(token:Constructs):HookTuple {\n return useInjectorHook(token, injector)\n}","import { useObservable } from \"./useObservable\";\nimport { AuthService } from \"../services\";\nimport { useService } from \"./useService\";\n\nexport function useAuth() {\n let [authService] = useService(AuthService)\n let isAuthenticated = useObservable(authService.isAuthenticatedSubject, authService.getUser())\n return isAuthenticated\n}","import { useEffect } from \"react\"\nimport { useHistory } from \"react-router-dom\"\nimport { toast } from \"react-toastify\"\nimport { User } from \"@polyratings/shared\"\nimport { useAuth } from \"./useAuth\"\n\nexport function useProtectedRoute(\n authenticated:B,\n redirect:string,\n toastMessage?:(user: B extends false ? User : null) => string\n) {\n // Redirect to home if logged in\n let user = useAuth()\n let history = useHistory()\n useEffect(() => {\n if(authenticated == !user) {\n if(toastMessage) {\n toast.info(toastMessage(user as any))\n }\n history.replace(redirect)\n }\n },[user])\n}","import { useMemo } from \"react\";\nimport { useLocation } from \"react-router-dom\";\n\n// From: https://v5.reactrouter.com/web/example/query-parameters\n// A custom hook that builds on useLocation to parse\n// the query string for you.\nexport function useQuery() {\n const { search } = useLocation();\n \n return useMemo(() => new URLSearchParams(search), [search]);\n}","import { useState, useEffect } from \"react\";\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n// From https://usehooks.com/useWindowSize/ used to bind to the window size\nexport function useWindowSize(): Size {\n const [windowSize, setWindowSize] = useState({\n width: 0,\n height: 0,\n });\n\n useEffect(() => {\n\n function handleResize() {\n setWindowSize({\n width: window.innerWidth,\n height: window.innerHeight,\n });\n }\n\n // Add event listener\n window.addEventListener(\"resize\", handleResize);\n\n // Call handler right away so state gets updated with initial window size\n handleResize();\n\n // Remove event listener on cleanup\n return () => window.removeEventListener(\"resize\", handleResize);\n\n }, []);\n\n return windowSize;\n}","import { useEffect, useState } from \"react\"\nimport { useWindowSize } from \"./useWindowSize\"\n\nexport interface TailwindBreakpoints {\n sm?:T\n md?:T,\n lg?:T,\n xl?:T\n '2xl'?:T\n}\n\nconst breakpointRanges:TailwindBreakpoints<[number,number]> = {\n sm: [640, 768],\n md: [768, 1024],\n lg: [1024, 1280],\n xl: [1280, 1536],\n '2xl': [1536, Infinity]\n}\n\n\nexport function useTailwindBreakpoint(breakpoints:TailwindBreakpoints, defaultValue:T):T {\n const windowSize = useWindowSize()\n const [outputValue, setOutputValue] = useState(defaultValue)\n const internalValues:TailwindBreakpoints = {}\n internalValues.sm = breakpoints.sm ?? defaultValue\n internalValues.md = breakpoints.md ?? internalValues.sm\n internalValues.lg = breakpoints.lg ?? internalValues.md\n internalValues.xl = breakpoints.xl ?? internalValues.lg\n internalValues['2xl'] = breakpoints['2xl'] ?? internalValues.xl\n\n useEffect(() => {\n const windowWidth = window.innerWidth\n for(let [key, [lower, upper]] of Object.entries(breakpointRanges) as [keyof TailwindBreakpoints, [number,number]][]) {\n if(windowWidth >= lower && windowWidth < upper) {\n // Always defined\n setOutputValue(internalValues[key] as T)\n return\n }\n }\n setOutputValue(defaultValue)\n },[windowSize.width])\n\n return outputValue\n}","export const departments = [\n \"AERO\",\n \"BIO\",\n \"IT\",\n \"CHEM\",\n \"MATH\",\n \"ARCH\",\n \"ENGL\",\n \"PHIL\",\n \"AGB\",\n \"ASCI\",\n \"ART\",\n \"EE\",\n \"BUS\",\n \"PHYS\",\n \"SOC\",\n \"CSC\",\n \"JOUR\",\n \"FSN\",\n \"IME\",\n \"DSCI\",\n \"POLS\",\n \"SS\",\n \"CE\",\n \"TH\",\n \"ARCE\",\n \"LA\",\n \"MU\",\n \"ME\",\n \"COMS\",\n \"NRM\",\n \"STAT\",\n \"ECON\",\n \"EDUC\",\n \"HIST\",\n \"CPE\",\n \"CRSC\",\n \"PSY\",\n \"WGS\",\n \"CRP\",\n \"ES\",\n \"MSC\",\n \"EHS\",\n \"AGED\",\n \"HUM\",\n \"BRAE\",\n \"GRC\",\n \"MATE\",\n \"LS\",\n \"CM\",\n \"PE\",\n \"ENGR\",\n \"BMED\",\n \"SCI\",\n \"GBA\",\n \"WS\"\n].sort()","import { useState, useEffect } from \"react\";\nimport { useService } from \"../hooks\";\nimport { departments } from \"../constants\";\nimport { useForm, SubmitHandler } from \"react-hook-form\";\nimport { ErrorMessage } from '@hookform/error-message'\nimport { ReviewService } from \"../services\";\nimport { toast } from \"react-toastify\";\nimport { TeacherEntry, AddReview } from \"@polyratings/shared\";\nimport ClipLoader from \"react-spinners/ClipLoader\";\n\ninterface EvaluateTeacherFormInputs {\n knownClass:string\n overallRating:number\n recognizesStudentDifficulties:number\n presentsMaterialClearly:number\n reviewText:string\n unknownClassDepartment:string\n unknownClassNumber:number\n year:string\n grade:string\n reasonForTaking:string\n}\n\ninterface EvaluateTeacherFormProps {\n teacher:TeacherEntry | null\n setTeacher:(teacher:TeacherEntry) => void\n closeForm:() => void,\n overrideSubmitHandler?:(review: AddReview) => void | Promise\n innerRef?:any\n}\nexport function EvaluateTeacherForm({teacher, setTeacher, closeForm, overrideSubmitHandler, innerRef}:EvaluateTeacherFormProps) {\n\n const { register, handleSubmit, watch, formState: { errors } } = useForm({\n defaultValues:{\n knownClass: Object.keys(teacher?.reviews || {})[0]\n }\n });\n const knownClassValue = watch('knownClass')\n const [reviewService] = useService(ReviewService)\n const [networkErrorText, setNetworkErrorText] = useState('')\n const [loading, setLoading] = useState(false)\n\n const onSubmit:SubmitHandler = async formResult => {\n setLoading(true)\n const newReview:AddReview = {\n overallRating:formResult.overallRating,\n recognizesStudentDifficulties:formResult.recognizesStudentDifficulties,\n presentsMaterialClearly:formResult.presentsMaterialClearly,\n // Purposely set null as any due to use case where when teacher == null teacherId is not used\n teacherId: teacher?.id || null as any,\n classIdOrName: formResult.knownClass || `${formResult.unknownClassDepartment} ${formResult.unknownClassNumber}`,\n review: {\n gradeLevel:formResult.year,\n grade:formResult.grade,\n courseType: formResult.reasonForTaking,\n rating:formResult.reviewText,\n profferer:teacher?.id ?? '',\n postDate:(new Date()).toString(),\n department:formResult.knownClass.split(' ')[0] ?? formResult.unknownClassDepartment,\n courseNum:formResult.knownClass.split(' ')[1] ?? formResult.unknownClassNumber \n }\n }\n if(overrideSubmitHandler) {\n overrideSubmitHandler(newReview)\n } else {\n try {\n const newTeacherData = await reviewService.uploadReview(newReview)\n setTeacher(newTeacherData)\n toast.success('Thank you for your review')\n closeForm()\n } catch(e) {\n setNetworkErrorText(e as string)\n }\n }\n setLoading(false)\n }\n \n const numericalRatings:{label:string, inputName:keyof EvaluateTeacherFormInputs}[] = [\n { label: 'Overall Rating', inputName:'overallRating'},\n { label: 'Recognizes Student Difficulties', inputName:'recognizesStudentDifficulties'},\n { label: 'Presents Material Clearly', inputName:'presentsMaterialClearly'},\n ]\n \n const classInformation:{label:string, inputName:keyof EvaluateTeacherFormInputs, options:string[]}[] = [\n { label: 'Year', inputName:'year', options:['Freshman', 'Sophomore', 'Junior', 'Senior', 'Grad']},\n { label: 'Grade Achieved', inputName:'grade', options:['A', 'A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-', 'D+', 'D', 'D-', 'F', 'CR', 'NC']},\n { label: 'Reason For Taking', inputName:'reasonForTaking', options:['Required (Major)', 'Required (Support)', 'Elective']},\n ]\n\n return(\n
\n {teacher &&\n \n }\n {teacher &&\n \n }\n\n

Class

\n
\n {teacher &&\n \n }\n\n
\n \n \n
\n
\n \n
\n {numericalRatings.map(rating =>\n
\n
\n

{rating.label}

\n
\n \n {[0,1,2,3,4].map(n =>\n \n )}\n
\n
\n \n
\n )}\n
\n
\n {classInformation.map(dropdown =>\n
\n
\n

{dropdown.label}

\n \n
\n
\n )}\n
\n

Review:

\n \n \n
\n {teacher &&\n
\n \n {/* Exact size for no layer shift */}\n \n
\n }\n
\n
{networkErrorText}
\n \n )\n}","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAkCAYAAADsHujfAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAVuSURBVHgBvVdrbBRVFL5zZnZ3dmd2t13a7ra1lZaCvF82+AMQNQYSMUKCDSYaQ+IP/ePjh4kxJkg0phEEE2PU4B+DiYnWRIzPYJSHiRUMxlJaWhYECl3a3Xbbnd3Znded69xZFpdlaPpY9ksmO/ex9373O+eec4ZBd0DHWytWLFw+/phf1DoEMdPCexSeEDQrMAxCJmGQpvDSRLL66OiY8N1Hh9Z/g459phTmsE5/fPyN9nWbt0Y/jUSkpwKBTBMwhtci4bKGZv1YXFw8b4jzajIrImF544KmhDasbhhIRaM2GaaEA7z2ZXPnosWjzxNTDRpG/jTlBlVWEIBcuxb8/vVXHn0S9Xdptyiy/e3VmzZsvHSAmFoA47tDgoKuizFhqkP6ApefOdV3JB69SWRH56o1WzZf+AQRpZmSuNugqhCTQGNDtnkUNpyAwsDiRfGtbk9umWmiioGa3sXhhQ9tirZxN/oYQdSfAcbkkANzsOhyLGBF45PEZLJW34yMBgDWlrkIxxm+4puXN70yr6U1VmNv/PQHbX5BGG5yMglrGc9l+fzgYPhgetJzJJnypNAMYehuvHzlyPvNTYm1qnrrGMMQwvOY2EROHl/S9PDGiz4nIhzHKv39Dfv27ry6G80Bq36qdewnVnzJZQDZPuLzayEWnKNVVvZe6Bus/RbNAVWrd1UJQjZc6n+2w2JOTUmiaivS0paoYiA/UAzOGs2kYfTKJTFe6Nuxd/XClffFX+YF5UET294yZby1Tsx4+a/Dgl8Oa9qtIYG+E+Ay44lA2iYSCUlB4nBbqJNqOsiN947JZ2/0rVk5/E5LS3KbpmI3JT4drzVJ/oY4xSVsgDomCXlFqkK5uoIixZOpo2Zk19iZWKsVhvtRR+eqna0tPR2ZzO3qzRYEQTYW82cBdXSwqsGE6aaljKkiisxNXD/Yrix9bktozdrL23W9fCTAPryZ1k02A/cg5PYLuRonR6KbMiw7hNAes/3+obWhkLE+l0NlAyVirSfNjyQlaGuMejweHHQ6Je3DGOy4EQ4ll7Cg1pcz/1Aius5qvb1hDUSBCF5BD5TGELohfc721Cdo2x/QliIGc6iMoO6QU/jJmDE/C7GR2gALbKDUNIWTx1N+if7qOl/ncpXJOdD/F0PXYXj0c0WB+oakD8AUnIhoGqDxEd+I3UakppxmKSg+2NfYjVAXhpo6medY4in1EZuI6lbal52foG1gy3dbKGiwlGV3+p++1j/t9esjksAwWCydSO2nqK7Jw+OCbRpDZ6VyKkJz2MV/w+9e7uqyFQeMSBBYIpROzNuPy6GDp3Xa9nrlEV2fOxOqqs+HUGI88Mvg+cihm8QMlW1mAPuQQ4jXDddo4T0t8T31kYxmEMM9G2UoAaqyzwtaPBE89uqb2561qvjJwjh4vFi0HPG2a0mDGcvoiUJ7YKCh28D8ALXtTH2FxgtBoEQ4M3qh/uPjvzW/WEyCguPdWjVySKD01ErOfTPrHt7992klt+6FJ7affc8qNQUyXTaEMU2MpJ7euqPnzkR+/HX/H38hNHzbNA5jd5DjTERTdAkVpBggF/f83HmqO2s8sEsUTAFNE0aOIQjz0hHxkato/x7jTvM4BkETgNMQQ6wlrpf2nth3MopmhRNTjkJpQVuAgVlF8BkjqEIAr08JOX9CcLIswRiqEKgiQSciJgZ1Ih1QUYUAPK/ciYgcjwlZVCEAAyZyyjMmMdINDekZf8PMmohTDZ5PeCBfvVJdOUVYDkGxIvTd5bLrhImhofAEqhAglxXPi0W5l+cpO3fq9+7FB3q/+KFiRNja5W0xq1RsdHmUOksNI5USz0WjdR8eemnPV1bBUsYKZGr8BzFtYlLqZ8alAAAAAElFTkSuQmCC\"","import { useEffect, useState } from \"react\";\nimport { useHistory } from \"react-router-dom\"\nimport { TeacherSearchType } from \"../services/teacher.service\";\n\nexport interface SearchState {\n type:TeacherSearchType\n searchValue:string\n}\n\ninterface SearchBarProps {\n showOnlyInput:boolean,\n initialState?:SearchState\n onChange?:(value: SearchState) => void | Promise\n}\nexport function SearchBar({initialState, onChange, showOnlyInput: showOnlyInput}:SearchBarProps) {\n const [searchValue, setSearchValue] = useState(initialState?.searchValue ?? '');\n const [searchType, setSearchType] = useState(initialState?.type ??'name')\n\n useEffect(() => {\n if(onChange) {\n onChange({type:searchType, searchValue})\n }\n }, [searchValue, searchType])\n\n const history = useHistory()\n const onFormSubmit = (e:React.FormEvent) => {\n e.preventDefault()\n history.push(`/search/${searchType}?term=${encodeURIComponent(searchValue)}`)\n\n }\n return (\n
\n
\n {showOnlyInput && \n \n }\n \n
\n \n \n \n
\n setSearchValue(e.target.value)}\n />\n
\n {showOnlyInput &&\n \n }\n
\n )\n}","import { Link, useLocation } from \"react-router-dom\"\nimport Logo from '../assets/Logo.png'\nimport '../styles/hamburgers.css'\nimport AnimateHeight from 'react-animate-height';\nimport { useEffect, useState } from \"react\";\nimport { AuthService } from \"../services\";\nimport { useService, useAuth } from \"../hooks\";\nimport { SearchBar } from \"./SearchBar\";\n\nconst HIDE_SEARCH_BAR_ROUTES = ['/', '/search/name', '/search/class', '/search/department']\n\nexport function Navbar() {\n let [mobileNavOpen, setMobileNav] = useState(false)\n const triggerMobileNav = () => setMobileNav(!mobileNavOpen)\n let isAuthenticated = useAuth()\n const [authService] = useService(AuthService)\n const location = useLocation()\n const [showInputBar, setShowInputBar] = useState(true)\n \n useEffect(() => {\n const matchingRoute = HIDE_SEARCH_BAR_ROUTES.find(route => location.pathname == route)\n setShowInputBar(!matchingRoute)\n }, [location])\n\n return (\n
\n setMobileNav(false)}>\n \"Polyratings\n \n\n\n
\n
\n
\n
\n
\n\n {/* Mobile hamburger dropdown */}\n \n
\n Home\n Add a Teacher\n Professor List\n {/* Contact */}\n {isAuthenticated &&\n
{\n authService.signOut()\n triggerMobileNav()\n }} \n >\n Sign Out\n
\n }\n
\n
\n\n \n
\n )\n}","import { useState, useRef } from \"react\";\nimport { useService } from \"../hooks\";\nimport { departments } from \"../constants\";\nimport { useForm } from \"react-hook-form\";\nimport { ErrorMessage } from '@hookform/error-message'\nimport { TeacherService } from \"../services\";\n// import { EvaluateTeacherForm } from \"./EvaluateTeacherForm\";\nimport ClipLoader from \"react-spinners/ClipLoader\";\nimport { Teacher, AddReview } from \"@polyratings/shared\";\nimport { toast } from \"react-toastify\";\nimport { useHistory } from \"react-router\";\n\ninterface NewTeacherFormInputs {\n teacherFirstName:string\n teacherLastName:string\n teacherDepartment:string\n}\n\nexport const NEW_TEACHER_FORM_WIDTH = 475\n\nexport function NewTeacherForm() {\n\n const { register, handleSubmit, formState: { errors } } = useForm();\n const [teacherService] = useService(TeacherService)\n const [networkErrorText, setNetworkErrorText] = useState('')\n const [loading, setLoading] = useState(false)\n const reviewFormRef = useRef(null)\n const teacherFormRef = useRef(null)\n const history = useHistory()\n\n // This is needed to synchronize the two forms\n const kickOffSubmit = () => {\n // @ts-expect-error Ignore ts error for onSubmit handler\n teacherFormRef.current!.onsubmit = handleSubmit(()=>{})\n // Double submit form to get error messages\n teacherFormRef.current?.requestSubmit()\n reviewFormRef.current?.requestSubmit()\n }\n\n // Use closure in order to access the data from the two forms\n const reviewFormSubmitOverride = (reviewOverrideData:AddReview) => {\n // @ts-expect-error Ignore ts error for onSubmit handler\n teacherFormRef.current!.onsubmit = handleSubmit(async teacherData => {\n setLoading(true)\n const newTeacher:Teacher = {\n firstName:teacherData.teacherFirstName,\n lastName:teacherData.teacherLastName,\n department:teacherData.teacherDepartment,\n numEvals:1,\n overallRating: reviewOverrideData.overallRating,\n studentDifficulties: reviewOverrideData.recognizesStudentDifficulties,\n materialClear: reviewOverrideData.presentsMaterialClearly,\n courses:[reviewOverrideData.classIdOrName],\n reviews: {\n [reviewOverrideData.classIdOrName]: [reviewOverrideData.review]\n }\n }\n \n try {\n const newTeacherId = await teacherService.addNewTeacher(newTeacher)\n toast.success('Thank you for adding a teacher')\n history.push(`/teacher/${newTeacherId}`)\n } catch(e) {\n setNetworkErrorText(e as string)\n }\n setLoading(false)\n })\n teacherFormRef.current?.requestSubmit()\n }\n\n return(\n
\n
{})} ref={teacherFormRef}>\n

Teacher

\n
\n

Department

\n \n
\n
\n

First Name

\n \n
\n
\n

Last Name

\n \n
\n \n \n \n

Review

\n {/* {}} closeForm={() => {}} innerRef={reviewFormRef} overrideSubmitHandler={reviewFormSubmitOverride}/> */}\n \n
\n \n Submit\n \n {/* Exact size for no layer shift when replacing button */}\n \n
\n
{networkErrorText}
\n
\n \n )\n}","import { TeacherEntry } from \"@polyratings/shared\";\nimport star from '../assets/star.svg'\nimport { useHistory } from \"react-router-dom\"\nimport { useService } from \"../hooks\";\nimport { TeacherService } from \"../services\";\n\ninterface TeacherCardProps {\n teacher:TeacherEntry,\n beforeNavigation?:() => void | (() => Promise)\n}\n\nexport const TEACHER_CARD_HEIGHT = 160\n\nexport function TeacherCard({teacher, beforeNavigation}:TeacherCardProps) {\n const history = useHistory()\n const [teacherService] = useService(TeacherService)\n\n const onClick = async () => {\n // await the pre-navigation handler passed into the component\n if(beforeNavigation) {\n await Promise.resolve(beforeNavigation())\n }\n // Load teacher into the local teacher card for next page to load immediately\n await teacherService.getTeacher(teacher.id)\n history.push(`/teacher/${teacher.id}`)\n }\n\n return(\n
\n
\n

{teacher.lastName}, {teacher.firstName}

\n
\n
{teacher.department}
\n
{teacher.overallRating}
\n
\"\"{teacher.numEvals} evals
\n
\n
\n
\n\n )\n}","import Slider, { createSliderWithTooltip } from 'rc-slider'\nimport 'rc-slider/assets/index.css';\n\nconst Range = createSliderWithTooltip(Slider.Range);\n\ninterface MinMaxSliderProps {\n domain:[number,number],\n value:[number,number]\n onchange:(pos:[number, number]) => void\n resolution?:number\n}\n\nconst overrideHoverCss = `\n.rc-slider-handle-dragging.rc-slider-handle-dragging.rc-slider-handle-dragging {\n border-color: #1F4715;\n box-shadow: 0 0 0 5px rgb(31, 71, 21, 0.5);\n}\n`\n\nexport function MinMaxSlider({domain:[min,max], value, onchange, resolution}:MinMaxSliderProps) {\n resolution = resolution || (max-min) / 20\n const marks = {} as any\n marks[min] = min\n marks[max] = max\n\n const handleStyles = {borderColor:'#1F4715'}\n return(\n
\n \n `${value}` as any}\n />\n
\n )\n}","import homeHeader from '../assets/home-header.webp'\nimport homeCurveTransition from '../assets/home-curve-transition.svg'\nimport star from '../assets/star.svg'\nimport worstOfWorstBackground from '../assets/worst-of-worst-background.webp'\nimport { useEffect, useState } from 'react'\nimport { TeacherEntry } from '@polyratings/shared'\nimport { TeacherService } from '../services'\nimport { SearchBar, TeacherCard } from '../components'\nimport { useService } from '../hooks'\n\nexport function Home() {\n let [bestTeacher, setBestTeacher] = useState({} as any)\n let [worstTeachers, setWorstTeachers] = useState([])\n const[teacherService] = useService(TeacherService)\n\n useEffect(() => {\n async function retrieveHomeData() {\n let [bestTeacher, worstTeachers] = await Promise.all([teacherService.getRandomBestTeacher(), teacherService.getRandomWorstTeachers()])\n setBestTeacher(bestTeacher)\n setWorstTeachers(worstTeachers)\n }\n retrieveHomeData()\n }, [])\n\n return (\n
\n
\n
\n

Polyratings

\n
\n \n
\n
\n {/* Use -1 to make sure background image does not shine through bottom */}\n \n
\n \n
\n

Worst of the Worst

\n
\n {worstTeachers.map((teacher, i) => )}\n
\n
\n
\n )\n}\n\n","import { useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport loginBackground from '../assets/home-header.webp'\nimport { useService,useProtectedRoute } from \"../hooks\";\nimport { AuthService } from \"../services\";\n\nexport function Login() {\n let [calPolyUsername, setCalPolyUsername] = useState('')\n let [password, setPassword] = useState('')\n let [errorText, setErrorText] = useState('')\n let [authService] = useService(AuthService)\n\n const logUserIn = async (event:React.FormEvent) => {\n event.preventDefault()\n try {\n await authService.login(calPolyUsername, password)\n } catch(e) {\n setErrorText(e as string)\n }\n }\n\n // Redirect to homepage if in authenticated state\n useProtectedRoute(false, '/', (user) => `Welcome ${user.email.replace('@calpoly.edu','')}`)\n\n\n return(\n
\n
\n
\n

Sign In

\n
logUserIn(e)}>\n

Cal Poly Username

\n
\n setCalPolyUsername(e.target.value)}\n />\n
\n
@calpoly.edu
\n
\n
\n \n
\n

Password

\n Forgot Password?\n
\n
\n setPassword(e.target.value)}\n />\n

{errorText}

\n
\n \n
Don't have an account? Register
\n
\n
\n
\n \n
\n )\n}","import loginBackground from '../assets/home-header.webp'\nimport { NewTeacherForm } from '../components'\n\n\nexport function NewTeacher() {\n // Redirect to homepage if in authenticated state\n return(\n
\n \n
\n \n
\n
\n )\n}","import { useHistory, useLocation, useParams } from \"react-router-dom\";\nimport { useState, useEffect, useRef, forwardRef, useImperativeHandle, ElementRef } from \"react\";\nimport { TeacherEntry } from \"@polyratings/shared\";\nimport { TeacherService } from \"../services\";\nimport { TeacherCard, TEACHER_CARD_HEIGHT, MinMaxSlider, SearchBar, SearchState } from \"../components\";\nimport { WindowScroller } from 'fish-react-virtualized/dist/es/WindowScroller';\nimport { List } from 'fish-react-virtualized/dist/es/List'\nimport { useService, useQuery, useTailwindBreakpoint } from \"../hooks\";\nimport {Location} from 'history'\nimport { TeacherSearchType } from \"../services/teacher.service\";\n\ninterface SearchPageState {\n searchTerm:SearchState\n}\n\ninterface SearchPageProps {\n location:Location\n}\n\nexport function Search({location}: SearchPageProps) {\n const previousState = location.state as SearchPageState | undefined\n const query = useQuery()\n\n const navigatedSearchTerm = query.get('term')\n const { searchType } = useParams<{searchType:TeacherSearchType}>();\n \n const [teacherService] = useService(TeacherService)\n\n const [searchState, setSearchState] = useState(previousState?.searchTerm ?? {type:searchType, searchValue:navigatedSearchTerm ?? ''})\n const [searchResults, setSearchResults] = useState([])\n const [mobileFiltersOpened, setMobileFiltersOpened] = useState(false)\n\n const [filteredTeachers, setFilteredTeachers] = useState([])\n const ref = useRef>(null)\n\n const history = useHistory()\n // This saves the current state of the filters by replacing the current route\n // with one with the state object to recreate if it gets popped off the history stack\n const saveState = () => {\n const rootRelativePath = window.location.href.replace(window.location.origin, '')\n const currentState:SearchPageState & FilterState = {\n searchTerm: searchState,\n // the ref will have to be defined at this state\n ...ref.current!.getState()\n }\n history.replace(rootRelativePath, currentState)\n }\n\n const listWidth = useTailwindBreakpoint({\n sm:600,\n md:672,\n lg:600,\n '2xl':672\n },window.innerWidth - 20)\n\n // If we remove the filters from the dom we can use one ref and simplify the process of restoring state when re-visiting route\n const mobileFilterBreakpoint = useTailwindBreakpoint({xl:false}, true)\n\n useEffect(() => {\n async function retrieveSearchData() {\n try {\n let result:TeacherEntry[] = []\n if(!searchState) {\n result = await teacherService.getAllTeachers()\n } else {\n result = await teacherService.searchForTeacher(searchState.type, searchState.searchValue)\n }\n setSearchResults(result)\n } catch(e) {\n console.error(`Failed to search for teacher with term: ${searchState}`,e)\n const history = useHistory()\n history.push('/')\n }\n }\n retrieveSearchData()\n }, [searchState])\n\n\n return(\n
\n \n {(!searchResults.length || !filteredTeachers.length) &&\n

No Results Found

\n }\n {Boolean(searchResults.length) &&\n
\n {!mobileFilterBreakpoint &&\n
\n }\n
\n )\n}\n\ntype SortingOptions = 'relevant' | 'alphabetical' | 'overallRating' | 'recognizesStudentDifficulties' | 'presentsMaterialClearly'\n\ninterface FilterProps {\n teachers:TeacherEntry[]\n onUpdate:(teachers:TeacherEntry[]) => void\n className?:string,\n}\n\ninterface FilterHandle {\n getState: () => FilterState\n}\n\ninterface FilterState {\n departmentFilters: {name:string, state:boolean}[]\n avgRatingFilter: [number, number]\n studentDifficultyFilter: [number, number]\n materialClearFilter: [number, number]\n sortBy: SortingOptions\n numberOfEvaluationsFilter: [number, number]\n reverseFilter: boolean\n}\n\nconst FilterRenderFunction:React.ForwardRefRenderFunction = ({teachers, onUpdate, className}, ref) => {\n // Set default for className\n className = className || ''\n\n const location = useLocation()\n const previousState = location.state as FilterState | undefined\n // Component State\n let [departmentFilters, setDepartmentFilters] = useState<{name:string, state:boolean}[]>(previousState?.departmentFilters ?? [])\n let [avgRatingFilter, setAvgRatingFilter] = useState<[number, number]>(previousState?.avgRatingFilter ?? [0,4])\n let [studentDifficultyFilter, setStudentDifficultyFilter] = useState<[number, number]>(previousState?.studentDifficultyFilter ?? [0,4])\n let [materialClearFilter, setMaterialClearFilter] = useState<[number, number]>(previousState?.materialClearFilter ?? [0,4])\n let [numberOfEvaluationsFilter, setNumberOfEvaluationsFilter] = useState<[number, number]>(previousState?.numberOfEvaluationsFilter ?? [1,2])\n let [reverseFilter, setReverseFilter] = useState(previousState?.reverseFilter ?? false)\n let [sortBy, setSortBy] = useState(previousState?.sortBy ?? 'relevant')\n\n // Internal duplicate of result\n const [preDepartmentFilters, setPreDepartmentFilters] = useState([])\n // On change duplicate result to the outside world\n useEffect(() => {\n const depFilters = departmentFilters.filter(({state}) => state).map(({name}) => name)\n const teachersToEmit = preDepartmentFilters.filter((teacher) => depFilters.length == 0 || depFilters.includes(teacher.department))\n onUpdate(teachersToEmit)\n }, [preDepartmentFilters, departmentFilters])\n \n\n const getState:() => FilterState = () => ({\n departmentFilters,\n avgRatingFilter,\n studentDifficultyFilter,\n materialClearFilter,\n sortBy,\n numberOfEvaluationsFilter,\n reverseFilter\n })\n\n useImperativeHandle(ref, () => ({\n getState\n }))\n\n const getEvaluationDomain:(data:TeacherEntry[]) => [number,number] = (data:TeacherEntry[]) => [\n data.reduce((acc,curr) => curr.numEvals < acc ? curr.numEvals : acc, Infinity),\n data.reduce((acc,curr) => curr.numEvals > acc ? curr.numEvals : acc, -Infinity)\n ]\n\n const generateDepartmentFilters = (list:TeacherEntry[]) => {\n const departments = [...(new Set(list.map(t => t.department)))]\n const previousSelectedMap = departmentFilters.reduce((acc:{[name:string]:boolean}, {name, state}) => {\n acc[name] = state\n return acc\n },{})\n const initialDepartmentList = departments\n .filter(dep => !!dep)\n .sort()\n .map(dep => ({name:dep, state:!!previousSelectedMap[dep]}))\n setDepartmentFilters(initialDepartmentList)\n }\n \n\n useEffect(() => {\n generateDepartmentFilters(teachers)\n const initialEvaluationRange = getEvaluationDomain(teachers)\n setNumberOfEvaluationsFilter(initialEvaluationRange)\n },[teachers])\n\n const teacherFilterFunctions:((teacher:TeacherEntry) => boolean)[] = [ \n (teacher) => teacher.overallRating >= avgRatingFilter[0] && \n teacher.overallRating <= avgRatingFilter[1],\n\n (teacher) => teacher.studentDifficulties >= studentDifficultyFilter[0] && \n teacher.studentDifficulties <= studentDifficultyFilter[1],\n\n (teacher) => teacher.materialClear >= materialClearFilter[0] &&\n teacher.materialClear <= materialClearFilter[1],\n\n (teacher) => teacher.numEvals >= numberOfEvaluationsFilter[0] &&\n teacher.numEvals <= numberOfEvaluationsFilter[1]\n ]\n\n const sortingMap:{[key in SortingOptions]:(a: TeacherEntry, b: TeacherEntry) => number} = {\n alphabetical:(a,b) => {\n const aName = `${a.lastName}, ${a.firstName}`\n const bName = `${b.lastName}, ${b.firstName}`\n if(aName < bName) {\n return -1; \n }\n if(aName > bName) {\n return 1; \n }\n return 0;\n\n },\n relevant: () => {throw 'not a sort'},\n overallRating:(a,b) => b.overallRating - a.overallRating,\n recognizesStudentDifficulties:(a,b) => b.studentDifficulties - a.studentDifficulties,\n presentsMaterialClearly: (a,b) => b.materialClear - a.materialClear,\n }\n\n\n\n let filterCalculationDependencies = getState()\n delete (filterCalculationDependencies as any)['departmentFilters']\n useEffect(() => {\n const filteredResult = teachers.filter(teacher => {\n for(let filterFn of teacherFilterFunctions) {\n if(!filterFn(teacher)) {\n return false\n }\n }\n return true\n })\n\n // relevant is no sort applied\n if(sortBy != 'relevant') {\n filteredResult.sort(sortingMap[sortBy])\n }\n\n if(reverseFilter) {\n filteredResult.reverse()\n }\n\n setPreDepartmentFilters(filteredResult)\n generateDepartmentFilters(filteredResult) \n\n }, Object.values(filterCalculationDependencies))\n\n\n return(\n
\n

Sort by:

\n
\n \n {/* Sorting Arrow */}\n setReverseFilter(!reverseFilter)}\n >\n \n \n
\n\n\n

Filters:

\n\n
\n

Department:

\n \n
\n\n {[\n { name:'Overall Rating:', filter:setAvgRatingFilter, value:avgRatingFilter},\n { name:'Recognizes Student Difficulties:', filter:setStudentDifficultyFilter, value:studentDifficultyFilter },\n { name:'Presents Material Clearly:', filter:setMaterialClearFilter, value:materialClearFilter }\n ].map(({name, filter, value}) => \n
\n

{name}

\n
\n \n
\n
\n )}\n
\n

Number of Reviews:

\n
\n \n
\n
\n\n
\n

Department:

\n
\n {departmentFilters.map(({name,state}, i) => \n \n )}\n
\n\n
\n
\n )\n}\n\nconst Filters = forwardRef(FilterRenderFunction)","import { useState, useEffect } from \"react\";\nimport { useHistory, useParams } from \"react-router-dom\";\nimport { TeacherEntry, ReviewEntry } from \"@polyratings/shared\";\nimport { TeacherService } from \"../services\";\nimport AnimateHeight from 'react-animate-height';\nimport AnchorLink from 'react-anchor-link-smooth-scroll'\nimport StarRatings from 'react-star-ratings';\nimport { Backdrop, EvaluateTeacherForm } from '../components'\nimport { useService } from \"../hooks\";\n\nexport function Teacher() {\n let { id } = useParams<{id:string}>();\n\n let [teacherData, setTeacherData] = useState({} as any)\n\n const history = useHistory()\n let [teacherService] = useService(TeacherService)\n let [teacherEvaluationShownDesktop, setTeacherEvaluationShownDesktop] = useState(false)\n let [teacherEvaluationShownMobile, setTeacherEvaluationShownMobile] = useState(false)\n\n useEffect(() => {\n async function retrieveTeacherData() {\n try {\n const result = await teacherService.getTeacher(id)\n setTeacherData(result)\n } catch(e) {\n console.error(`Failed to load teacher with id: ${id}`,e)\n history.push('/')\n } \n }\n retrieveTeacherData()\n }, [])\n\n const ClassScroll = ({outerClassName, innerClassName}: {outerClassName:string, innerClassName:string}) => (\n
\n {\n Object.keys(teacherData?.reviews || {}).map(\n taughtClass => {taughtClass}\n )\n }\n
\n )\n\n return(\n
\n {\n teacherEvaluationShownDesktop &&\n \n
\n setTeacherEvaluationShownDesktop(false)}/>\n
\n
\n }\n\n \n\n
\n

{teacherData.lastName}, {teacherData.firstName}

\n

{teacherData.department}

\n

Overall Rating: {teacherData.overallRating} / 4.00

\n

Recognizes Student Difficulties: {teacherData.studentDifficulties}

\n

Presents Material Clearly: {teacherData.materialClear}

\n \n
\n\n
\n \n
\n setTeacherEvaluationShownMobile(false)}/>\n
\n
\n\n {\n Object.entries(teacherData.reviews || {}).map(\n ([taughtClass, reviews]) => \n )\n }\n \n {/* Mobile class scroll needs room to see all reviews */}\n
\n \n
\n )\n}\n\n\nfunction ClassSection({reviews, taughtClass}:{reviews:ReviewEntry[], taughtClass:string}) {\n let [expanded, setExpanded] = useState(false)\n const UNEXPANDED_LIMIT = 2\n const unexpandedReviews =reviews.slice(0, UNEXPANDED_LIMIT)\n const expandedReviews = reviews.slice(UNEXPANDED_LIMIT)\n return (\n
\n

{taughtClass}

\n
\n {unexpandedReviews.map(review => )}\n
\n\n UNEXPANDED_LIMIT ? 25: 0} \n className={`transition-all ${expanded ? '' : `opacity-25`}`}\n >\n
\n {expandedReviews.map(review => )}\n
\n
\n {reviews.length > UNEXPANDED_LIMIT && !expanded &&\n
setExpanded(!expanded)}\n >\n Show More\n
}\n {expanded && \n
\n setTimeout(() => setExpanded(!expanded), 300)}\n href={`#${taughtClass}`}\n >\n Show Less\n \n
\n }\n
\n\n )\n}\n\n\nfunction ReviewCard({review}:{review:ReviewEntry}) {\n return(\n
\n
\n
{review.gradeLevel}
\n
{review.grade}
\n
{review.courseType}
\n
{new Date(review.postDate).toLocaleString('en-US', {year: 'numeric', month: 'short'})}
\n
\n
\n
{review.rating}
\n
\n )\n}","import { Home, Teacher, Search, Login, NewTeacher } from './pages';\nimport {\n BrowserRouter,\n Switch,\n Route,\n} from \"react-router-dom\";\nimport { Navbar } from './components';\nimport 'react-toastify/dist/ReactToastify.css';\nimport { ToastContainer } from 'react-toastify';\nimport { config } from './App.config';\n\nfunction App() {\n return(\n \n \n \n \n \n \n \n \n \n \n \n )\n}\n\nexport default App\n","import React from 'react'\nimport ReactDOM from 'react-dom'\nimport './index.css'\nimport App from './App'\n// Polyfill for Safari\nimport 'form-request-submit-polyfill'\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n)\n"],"names":["prodConfig","remoteUrl","base","githubPagesConfig","regularConfig","config","window","location","href","includes","USER_LOCAL_STORAGE_KEY","constructor","storage","fetch","jwtToken","isAuthenticatedSubject","BehaviorSubject","jwt","getItem","setAuthState","getJwt","getUser","jwt_decode","login","calPolyUsername","password","loginRes","method","headers","body","JSON","stringify","email","status","error","json","message","loginBody","access_token","signOut","user","next","setItem","removeItem","authService","globalFetch","input","init","res","LOGIN_ROUTE","pathname","replace","httpService","uploadReview","newReview","throwIfNot200","statusText","arr","size","shuffled","slice","i","length","min","temp","index","Math","floor","random","arrays","intersect","nonIntersect","idToEntity","flat","reduce","acc","curr","id","idArrays","map","x","intersectionSet","Set","array","compareSet","filter","has","Array","from","TEN_MINUTES","ALL_TEACHER_CACHE_KEY","INDIVIDUAL_TEACHER_CACHE_KEY","allTeachers","teacherCache","individualTeacherCacheStr","parse","cachedAllTeacherCacheStr","allTeacherCache","exp","Date","Promise","resolve","data","now","getRandomBestTeacher","rankedTeachers","t","numEvals","sort","a","b","overallRating","getRandomSubarray","getRandomWorstTeachers","getTeacher","teacher","removeTeacherFromCache","values","reviews","forEach","reviewArr","postDate","addTeacherToCache","searchForTeacher","type","value","tokenMatches","tokens","toLowerCase","split","token","lastName","firstName","intersectingDbEntities","courseName","toUpperCase","courses","find","course","department","startsWith","getAllTeachers","addNewTeacher","newTeacher","teacherIdResponse","teacherId","LOCAL_STORAGE","InjectionToken","FETCH","injector","makeInjector","provide","useValue","localStorage","useFactory","bind","AuthService","useClass","deps","HttpService","TeacherService","ReviewService","children","style","overflowY","top","pageYOffset","observable","initial","setValue","useState","sub","subscribe","unsubscribe","useInjectorHook","useService","useObservable","authenticated","redirect","toastMessage","useAuth","history","useHistory","info","search","useLocation","useMemo","URLSearchParams","windowSize","setWindowSize","width","height","innerWidth","innerHeight","addEventListener","handleResize","removeEventListener","breakpointRanges","sm","md","lg","xl","Infinity","breakpoints","defaultValue","useWindowSize","outputValue","setOutputValue","internalValues","windowWidth","key","lower","upper","Object","entries","departments","setTeacher","closeForm","overrideSubmitHandler","innerRef","register","handleSubmit","watch","formState","errors","useForm","defaultValues","knownClass","keys","knownClassValue","reviewService","networkErrorText","setNetworkErrorText","loading","setLoading","onSubmit","formResult","recognizesStudentDifficulties","presentsMaterialClearly","classIdOrName","unknownClassDepartment","unknownClassNumber","review","gradeLevel","year","grade","courseType","reasonForTaking","rating","reviewText","profferer","toString","courseNum","newTeacherData","success","e","numericalRatings","label","inputName","classInformation","options","c","display","d","required","ErrorMessage","n","dropdown","option","ClipLoader","initialState","onChange","showOnlyInput","searchValue","setSearchValue","searchType","setSearchType","preventDefault","push","encodeURIComponent","target","HIDE_SEARCH_BAR_ROUTES","mobileNavOpen","setMobileNav","triggerMobileNav","isAuthenticated","showInputBar","setShowInputBar","matchingRoute","route","Logo","AnimateHeight","reviewFormRef","useRef","teacherFormRef","kickOffSubmit","current","onsubmit","requestSubmit","TEACHER_CARD_HEIGHT","beforeNavigation","teacherService","borderRadius","star","Range","createSliderWithTooltip","Slider","overrideHoverCss","domain","max","onchange","resolution","marks","handleStyles","borderColor","backgroundColor","bestTeacher","setBestTeacher","worstTeachers","setWorstTeachers","all","backgroundImage","homeHeader","backgroundRepeat","backgroundPosition","backgroundSize","homeCurveTransition","_","worstOfWorstBackground","minHeight","clipPath","setCalPolyUsername","setPassword","errorText","setErrorText","logUserIn","event","loginBackground","color","previousState","state","navigatedSearchTerm","query","useQuery","get","useParams","searchState","setSearchState","searchTerm","searchResults","setSearchResults","mobileFiltersOpened","setMobileFiltersOpened","filteredTeachers","setFilteredTeachers","ref","saveState","rootRelativePath","origin","currentState","getState","listWidth","useTailwindBreakpoint","mobileFilterBreakpoint","result","Boolean","isScrolling","onChildScroll","scrollTop","FilterRenderFunction","teachers","onUpdate","className","departmentFilters","setDepartmentFilters","avgRatingFilter","setAvgRatingFilter","studentDifficultyFilter","setStudentDifficultyFilter","materialClearFilter","setMaterialClearFilter","numberOfEvaluationsFilter","setNumberOfEvaluationsFilter","reverseFilter","setReverseFilter","sortBy","setSortBy","preDepartmentFilters","setPreDepartmentFilters","depFilters","name","teachersToEmit","getEvaluationDomain","generateDepartmentFilters","list","previousSelectedMap","initialDepartmentList","dep","initialEvaluationRange","teacherFilterFunctions","studentDifficulties","materialClear","sortingMap","alphabetical","aName","bName","relevant","filterCalculationDependencies","filteredResult","filterFn","reverse","parseInt","newDepartmentFilters","updatedDepartmentFilters","checked","Filters","forwardRef","teacherData","setTeacherData","teacherEvaluationShownDesktop","setTeacherEvaluationShownDesktop","teacherEvaluationShownMobile","setTeacherEvaluationShownMobile","ClassScroll","outerClassName","innerClassName","taughtClass","StarRatings","expanded","setExpanded","UNEXPANDED_LIMIT","unexpandedReviews","expandedReviews","setTimeout","toLocaleString","month","Teacher","Search","Login","NewTeacher","Home","ReactDOM","render","document","getElementById"],"mappings":"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"}