1- import React , { useEffect } from 'react' ;
1+ import React , { useEffect , useCallback } from 'react' ;
22import { observer } from "mobx-react-lite" ;
33import { useState } from 'react' ;
44import CoursePagePopup from '../views/Components/CoursePagePopup.jsx' ;
55import PrerequisitePresenter from './PrerequisitePresenter.jsx' ;
66import { ReviewPresenter } from "../presenters/ReviewPresenter.jsx" ;
77import SearchbarView from "../views/SearchbarView.jsx" ;
8+ import Fuse from 'fuse.js'
9+ import debounce from 'lodash.debounce' ;
810
911const SearchbarPresenter = observer ( ( { model } ) => {
1012
11- const searchCourses = ( query ) => {
12- //model.filteredCourses is essentially a smaller subset of model.courses, if theres no filters, it should be the same
13- console . log ( "---------------search recalculated" ) ;
14- console . log ( "filtered courses length: " , model . filteredCourses . length ) ;
15- const searchResults = model . filteredCourses . filter ( course =>
16- course . code . toLowerCase ( ) . includes ( query . toLowerCase ( ) ) ||
17- course . name . toLowerCase ( ) . includes ( query . toLowerCase ( ) ) ||
18- course . description ?. toLowerCase ( ) . includes ( query . toLowerCase ( ) )
19- ) ;
20- model . setCurrentSearchText ( query ) ;
21- model . setCurrentSearch ( searchResults ) ;
22- console . log ( model . currentSearch . length ) ;
13+ const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
14+
15+ const fuseOptions = {
16+ keys : [
17+ { name : 'code' , weight : 0.6 } ,
18+ { name : 'name' , weight : 0.3 } ,
19+ { name : 'description' , weight : 0.1 } ,
20+ ] ,
21+ threshold : 0.3 , // adjust this for sensitivity
22+ ignoreLocation : true ,
23+ minMatchCharLength : 2 ,
2324 } ;
2425
26+ // Debounced search function
27+ const searchCourses = useCallback ( debounce ( ( query ) => {
28+ if ( ! query . trim ( ) ) {
29+ model . setCurrentSearch ( model . filteredCourses ) ;
30+ } else {
31+ const fuse = new Fuse ( model . filteredCourses , fuseOptions ) ;
32+ const results = fuse . search ( query ) . map ( ( r ) => r . item ) ;
33+ model . setCurrentSearch ( results ) ;
34+ }
35+ } , 500 ) , [ ] ) ;
36+
2537 const addFavourite = ( course ) => {
2638 model . addFavourite ( course ) ;
2739 } ;
@@ -69,7 +81,7 @@ const SearchbarPresenter = observer(({ model }) => {
6981
7082
7183 if ( model . filtersCalculated ) {
72- searchCourses ( "" ) ;
84+ searchCourses ( searchQuery ) ;
7385 model . filtersCalculated = false ;
7486 }
7587
@@ -84,6 +96,8 @@ const SearchbarPresenter = observer(({ model }) => {
8496 setIsPopupOpen = { setIsPopupOpen }
8597 setSelectedCourse = { setSelectedCourse }
8698 popup = { popup }
99+ setSearchQuery = { setSearchQuery }
100+ searchQuery = { searchQuery } // Add this line
87101 handleFavouriteClick = { handleFavouriteClick }
88102 totalCredits = { creditsSum ( model . favourites ) }
89103 resetScrollPosition = { resetScoll }
0 commit comments