diff --git a/client/src/modules/Globals/Navbar.tsx b/client/src/modules/Globals/Navbar.tsx
index 6afa82056..1c713ff3d 100644
--- a/client/src/modules/Globals/Navbar.tsx
+++ b/client/src/modules/Globals/Navbar.tsx
@@ -78,6 +78,9 @@ export default function Navbar({ userInput }: NavbarProps) {
userInput={userInput}
contrastingResultsBackground={true}
isInNavbar={true}
+ imgSrc={netId}
+ signOut={signOut}
+ isLoggedIn={isLoggedIn}
/>
{displayButton()}
diff --git a/client/src/modules/Home/Components/Home.tsx b/client/src/modules/Home/Components/Home.tsx
index 753ef8d1c..ad74bc9e7 100644
--- a/client/src/modules/Home/Components/Home.tsx
+++ b/client/src/modules/Home/Components/Home.tsx
@@ -11,15 +11,15 @@ import DTIWhiteLogo from '../../../assets/img/dti-text-white-logo.png'
import '../home.css'
/**
- Home Page.
-
+ Home Page.
+
Uppermost View component in the component tree, the first element of the HTML body tag grabbed by index.html.
@returns the application homepage with a navbar and searchbar, popular
classes and recent reviews components.
@param imgSrc for search bar
-
+
*/
export const Home = (imgSrc: any) => {
const [isLoggedIn, token, netId, signIn, signOut] = useAuthOptionalLogin()
@@ -113,6 +113,7 @@ export const Home = (imgSrc: any) => {
imgSrc={`${String(imgSrc.imgSrc)}`}
signOut={signOut}
isLoggedIn={isLoggedIn}
+ isInNavbar={false}
/>
diff --git a/client/src/modules/SearchBar/Components/Course.tsx b/client/src/modules/SearchBar/Components/Course.tsx
index 8cfb928f2..9ba043a18 100644
--- a/client/src/modules/SearchBar/Components/Course.tsx
+++ b/client/src/modules/SearchBar/Components/Course.tsx
@@ -21,7 +21,6 @@ type Props = {
active: boolean
enter: number
mouse: number
- handler: Function
key?: string
}
diff --git a/client/src/modules/SearchBar/Components/SearchBar.jsx b/client/src/modules/SearchBar/Components/SearchBar.jsx
deleted file mode 100644
index 318b14d65..000000000
--- a/client/src/modules/SearchBar/Components/SearchBar.jsx
+++ /dev/null
@@ -1,425 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-
-import ProfileDropdown from '../../Globals/ProfileDropdown'
-
-import { Redirect } from 'react-router'
-import axios from 'axios'
-import { Session } from '../../../session-store'
-
-import '../Styles/SearchBar.css'
-import Course from './Course'
-import SubjectResult from './SubjectResult'
-import ProfessorResult from './ProfessorResult'
-
-/*
- SearchBar Component.
-
- Simple Styling Component that renders a searchbar as an input element with a list of
- results that match the user's query.
-
- The component does not control the input element - it is instead controlled by
- this componet's parent, which saves the value of the query each time it changes.
- It takes in this query and requests a list of relevant classes from the local
- meteor database and displays them.
-*/
-
-let newSearchState = { selected: false, mouse: 0, enter: 0, index: 0 }
-
-const initState = {
- showDropdown: true,
- index: 0, //the initial state is the first element
- enter: 0, //to keep track of the initial state of enter as false
- mouse: 0, //keep track of the initial state of mouse hovering in the list cells as false
- selected: false, //whether or not user has clicked yet,
- query: '', //user's query,
- allCourses: [],
- allSubjects: [],
- allProfessors: [],
-}
-
-export class SearchBar extends Component {
- static DEBOUNCE_TIME = 200
- controller
- searchTimeout
-
- constructor(props) {
- super(props)
-
- this.state = initState
- this.updateQuery = this.updateQuery.bind(this)
- this.checkForCourseMatch = this.checkForCourseMatch.bind(this)
- }
-
- // Set the local state variable 'query' to the current value of the input (given by user)
- // Passed as a prop to SearchBar component, which calls this when user changes their query.
- updateQuery = (event) => {
- // Reset index, enter, mouse, and selected
- this.setState(newSearchState)
- // trim the query to remove trailing spaces
- let query = event.target.value.trim()
-
- // This is used to make "cs2110" and "cs 2110" equivalent
- if (query && query.split(' ').length === 1) {
- query = query.match(/[a-z]+|[^a-z]+/gi).join(' ')
- }
-
- if (this.checkForCourseMatch(query)) {
- // If query is exact match to a class,
- // highlight this class by setting index to index of this class
- // in search results dropdown
- this.setState({ index: this.state.allSubjects.length + 1 })
- }
- this.setState({ query: query })
-
- Session.setPersistent({ 'last-search': query })
- }
-
- /**
- * Compares classes based on score, then class number, then alphabetically by
- * subject.
- * @param {Class} a
- * @param {Class} b
- * @returns -1, 0, or 1
- */
- sortCourses(a, b) {
- const sortByAlphabet = (a, b) => {
- const aSub = a.classSub.toLowerCase()
- const bSub = b.classSub.toLowerCase()
- if (aSub < bSub) {
- return -1
- } else if (aSub > bSub) {
- return 1
- } else {
- return 0
- }
- }
-
- return b.score - a.score || a.classNum - b.classNum || sortByAlphabet(a, b)
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (
- this.state.query.toLowerCase() !== '' &&
- (this.state.query.toLowerCase() !== prevState.query.toLowerCase() ||
- this.props !== prevProps)
- ) {
- if (this.controller) this.controller.abort()
- this.controller = new AbortController()
- clearTimeout(this.searchTimeout)
-
- this.searchTimeout = setTimeout(() => {
- axios
- .post(
- `/v2/getClassesByQuery`,
- { query: this.state.query },
- { signal: this.controller.signal }
- )
- .then((response) => {
- const queryCourseList = response.data.result
- if (queryCourseList.length !== 0) {
- this.setState({
- allCourses: queryCourseList.sort(this.sortCourses),
- })
- } else {
- this.setState({
- allCourses: [],
- })
- }
- })
- .catch((e) => console.log('Getting courses failed!'))
-
- axios
- .post(
- `/v2/getSubjectsByQuery`,
- { query: this.state.query },
- { signal: this.controller.signal }
- )
- .then((response) => {
- const subjectList = response.data.result
- if (subjectList && subjectList.length !== 0) {
- // Save the list of Subject objects that matches the request
- this.setState({
- allSubjects: subjectList,
- })
- } else {
- this.setState({
- allSubjects: [],
- })
- }
- })
- .catch((e) => console.log('Getting subjects failed!'))
-
- axios
- .post(
- `/v2/getProfessorsByQuery`,
- { query: this.state.query },
- { signal: this.controller.signal }
- )
- .then((response) => {
- const professorList = response.data.result
- if (professorList && professorList.length !== 0) {
- // Save the list of Subject objects that matches the request
- this.setState({
- allProfessors: professorList,
- })
- } else {
- this.setState({
- allProfessors: [],
- })
- }
- })
- .catch((e) => console.log('Getting professors failed!'))
- }, this.DEBOUNCE_TIME)
- }
- }
-
- handleKeyPress = (e) => {
- //detect some arrow key movement (up, down, or enter)
- if (e.key === 'ArrowDown') {
- //if the down arrow was detected, increase the index value by 1 to highlight the next element
- this.setState((prevState) => ({
- index: prevState.index + 1,
- }))
- } else if (e.key === 'ArrowUp') {
- //if the up arrow key was detected, decrease the index value by 1 to highlight the prev element
- //never index below 0 (the first element)
- this.setState((prevState) => ({
- index: Math.max(prevState.index - 1, 0),
- }))
- } else if (e.key === 'Enter') {
- //if the enter key was detected, change the state of enter to 1 (true)
- this.setState({
- enter: 1,
- })
- } else {
- this.updateQuery(e)
- }
- }
-
- mouseHover = () => {
- this.setState({
- mouse: 1,
- })
- }
-
- mouseLeave = () => {
- this.setState({
- mouse: 0,
- })
- this.setState({
- index: 0, //resets the index to the first element
- })
- }
-
- showDropdown = () => {
- this.setState({ showDropdown: true })
- }
-
- hideDropdown = () => {
- this.setState({ showDropdown: false })
- }
-
- checkForCourseMatch(query) {
- let isMatch = false
- let querySplit = query.toLowerCase().split(' ')
- let queryNum = ''
- let querySub = ''
- if (querySplit.length === 2) {
- querySub = querySplit[0]
- queryNum = querySplit[1]
- }
- this.state.allCourses.forEach((course) => {
- let classNum = course.classNum.toLowerCase()
- let classSub = course.classSub.toLowerCase()
- if (classNum === queryNum && classSub === querySub) {
- isMatch = true
- }
- })
-
- return isMatch
- }
-
- // Convert the class amd major objects that satisfy this query into a styled list of search results.
- // Each one will act as a button, such that clicking a course will take the user
- // to that class's ClassView. The name of the class will have underline and bold
- // where it matches the query.
- // Clicking a major will take the user to the results page for that major's Classes
- renderResults() {
- if (this.state.query !== '' && !this.state.selected) {
- let results = []
-
- // Used for "enter" key on 'Search: "query" ' button for exact search
- // Sends user to /results/keyword/query+query
- if (this.state.index === 0 && this.state.enter === 1) {
- this.setState(initState)
- return (
- {'Search: "' + this.state.query + '"'}
{'Search: "' + query + '"'}
+ + ) + + results.push(exact_search) + + let subjectList: JSX.Element[] = [] + + subjectList = subjects.slice(0, 3).map((subject, i) => ( + //create a new class "button" that will set the selected class to this class when it is clicked. +