-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
721 additions
and
424 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
frontend/src/app/Explore/Placeholder/Placeholder.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.root { | ||
color: var(--slate-500); | ||
position: absolute; | ||
top: 50%; | ||
left: 16px; | ||
transform: translateY(-50%); | ||
pointer-events: none; | ||
font-size: 16px; | ||
line-height: 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { useEffect, useRef, useState } from "react"; | ||
|
||
import classNames from "classnames"; | ||
|
||
import styles from "./Placeholder.module.scss"; | ||
|
||
const values = [ | ||
"Explore courses...", | ||
"Computational methods for science and engineering", | ||
"Environmental policy and resource management", | ||
"Bioinformatics and computational biology", | ||
"Quantum mechanics and mathematical physics", | ||
"Public health epidemiology and data analysis", | ||
]; | ||
|
||
interface PlaceholderProps { | ||
className?: string; | ||
} | ||
|
||
export default function Placeholder({ className }: PlaceholderProps) { | ||
const [text, setText] = useState(values[0]); | ||
const positionRef = useRef(values[0].length - 1); | ||
const indexRef = useRef(0); | ||
|
||
useEffect(() => { | ||
let timeoutId: ReturnType<typeof setTimeout>; | ||
|
||
const update = () => { | ||
let position = positionRef.current + 1; | ||
|
||
if (position === values[indexRef.current].length * 2) { | ||
indexRef.current = (indexRef.current + 1) % values.length; | ||
|
||
position = 0; | ||
} | ||
|
||
positionRef.current = position; | ||
|
||
const value = values[indexRef.current]; | ||
|
||
const end = | ||
position > value.length ? -(position % value.length) : position; | ||
|
||
const _text = values[indexRef.current].slice(0, end); | ||
|
||
setText(_text); | ||
|
||
timeoutId = setTimeout(update, _text.length === value.length ? 1000 : 75); | ||
}; | ||
|
||
timeoutId = setTimeout(update, 100); | ||
|
||
return () => clearInterval(timeoutId); | ||
}, []); | ||
|
||
return <p className={classNames(styles.root, className)}>{text}</p>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { FormEvent, useState } from "react"; | ||
|
||
import { useApolloClient } from "@apollo/client"; | ||
import { ArrowRight, Calendar } from "iconoir-react"; | ||
|
||
import AverageGrade from "@/components/AverageGrade"; | ||
import Button from "@/components/Button"; | ||
import Container from "@/components/Container"; | ||
import Footer from "@/components/Footer"; | ||
import NavigationBar from "@/components/NavigationBar"; | ||
import Units from "@/components/Units"; | ||
import { GET_COURSE, ICourse, Semester } from "@/lib/api"; | ||
|
||
import styles from "./Explore.module.scss"; | ||
import Placeholder from "./Placeholder"; | ||
|
||
export default function Explore() { | ||
const [input, setInput] = useState(""); | ||
const [courses, setCourses] = useState<ICourse[]>([]); | ||
const apolloClient = useApolloClient(); | ||
|
||
const getCourse = async (name: string) => { | ||
const [subject, courseNumber] = name.split(" "); | ||
|
||
const { data } = await apolloClient.query<{ course: ICourse }>({ | ||
query: GET_COURSE, | ||
variables: { subject, courseNumber }, | ||
}); | ||
|
||
if (!data) return; | ||
|
||
return data.course; | ||
}; | ||
|
||
const handleSubmit = async (event: FormEvent) => { | ||
event.preventDefault(); | ||
|
||
const response = await fetch( | ||
`http://localhost:3002/query?input=${encodeURIComponent(input)}&topK=24` | ||
); | ||
|
||
if (!response.ok) return; | ||
|
||
const { matches } = (await response.json()) as { | ||
matches: { id: string }[]; | ||
}; | ||
|
||
const courses = await Promise.all( | ||
matches.map(({ id: name }) => getCourse(name)) | ||
); | ||
|
||
setCourses( | ||
courses.filter( | ||
(course) => course && course.classes.length !== 0 | ||
) as ICourse[] | ||
); | ||
}; | ||
|
||
return ( | ||
<div className={styles.root}> | ||
<div className={styles.header}> | ||
<NavigationBar invert /> | ||
<div className={styles.container}> | ||
<form className={styles.form} onSubmit={handleSubmit}> | ||
<input | ||
className={styles.input} | ||
value={input} | ||
// Required to display the placeholder conditionally | ||
placeholder="" | ||
onChange={(event) => setInput(event.target.value)} | ||
/> | ||
<Placeholder className={styles.placeholder} /> | ||
<Button className={styles.button}> | ||
Search | ||
<ArrowRight /> | ||
</Button> | ||
</form> | ||
</div> | ||
</div> | ||
<Container> | ||
<div className={styles.body}> | ||
<div className={styles.sideBar}></div> | ||
<div className={styles.view}> | ||
{courses | ||
.sort((a, b) => { | ||
const score = { | ||
[Semester.Fall]: 3, | ||
[Semester.Summer]: 2, | ||
[Semester.Spring]: 1, | ||
}; | ||
|
||
const getTerm = (course: ICourse) => { | ||
return [...course.classes].sort( | ||
(a, b) => | ||
a.year - b.year || score[a.semester] - score[b.semester] | ||
)[0]; | ||
}; | ||
|
||
return ( | ||
getTerm(b).year - getTerm(a).year || | ||
score[getTerm(b).semester] - score[getTerm(a).semester] | ||
); | ||
}) | ||
.map((course) => { | ||
const score = { | ||
[Semester.Fall]: 3, | ||
[Semester.Summer]: 2, | ||
[Semester.Spring]: 1, | ||
}; | ||
|
||
const { year, semester } = [...course.classes].sort( | ||
(a, b) => | ||
a.year - b.year || score[a.semester] - score[b.semester] | ||
)[0]; | ||
|
||
const { unitsMax, unitsMin } = course.classes.reduce( | ||
(acc, { unitsMax, unitsMin }) => ({ | ||
unitsMax: Math.max(acc.unitsMax, unitsMax), | ||
unitsMin: Math.min(acc.unitsMin, unitsMin), | ||
}), | ||
{ unitsMax: 0, unitsMin: 0 } | ||
); | ||
|
||
return ( | ||
<div className={styles.course} key={course.number}> | ||
<p className={styles.title}> | ||
{course.subject} {course.number} | ||
</p> | ||
<p className={styles.description}>{course.title}</p> | ||
<div className={styles.row}> | ||
<AverageGrade gradeAverage={course.gradeAverage} /> | ||
<div className={styles.badge}> | ||
<Calendar /> | ||
{semester} {year} | ||
</div> | ||
<Units unitsMax={unitsMax} unitsMin={unitsMin} /> | ||
</div> | ||
</div> | ||
); | ||
})} | ||
</div> | ||
</div> | ||
</Container> | ||
<Footer /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.