22
33import { cn } from "@/lib/utils" ;
44import { redirect } from "next/navigation" ;
5- import { useEffect , useState } from "react" ;
5+ import { useEffect , useRef , useState } from "react" ;
66import {
77 Command ,
88 CommandEmpty ,
@@ -16,36 +16,57 @@ import { useAutocomplete } from "@/hooks/autocomplete";
1616export default function SearchBar ( { header } : { header ?: boolean } ) {
1717 const [ query , setQuery ] = useState ( "" ) ;
1818 const [ results , sendQuery ] = useAutocomplete ( ) ;
19+ const [ isOpen , setIsOpen ] = useState ( false ) ;
20+ const commandRef = useRef < HTMLDivElement > ( null ) ;
1921
2022 useEffect ( ( ) => {
2123 sendQuery ( query ) ;
2224 } , [ query ] ) ;
2325
26+ useEffect ( ( ) => {
27+ const handleClickOutside = ( event : MouseEvent ) => {
28+ if ( commandRef . current && ! commandRef . current . contains ( event . target as Node ) ) {
29+ setIsOpen ( false ) ;
30+ }
31+ } ;
32+
33+ document . addEventListener ( "mousedown" , handleClickOutside ) ;
34+ return ( ) => {
35+ document . removeEventListener ( "mousedown" , handleClickOutside ) ;
36+ } ;
37+ } , [ ] ) ;
38+
2439 return (
2540 < div className = { cn ( "flex" , "flex-col" , "w-[600px]" , header && "ml-3" ) } >
2641 < Command
42+ ref = { commandRef }
2743 shouldFilter = { false }
2844 className = { cn ( "h-[36px]" , header && "bg-background" ) }
2945 >
3046 < CommandInput
3147 placeholder = "Search for a class or professor..."
3248 value = { query }
33- onValueChange = { setQuery }
49+ onValueChange = { ( value ) => {
50+ setQuery ( value ) ;
51+ setIsOpen ( value . length > 0 ) ;
52+ } }
3453 className = { cn ( "h-[36px]" , header && "bg-background" ) }
3554 />
3655 < CommandList >
37- { results &&
56+ { results && isOpen &&
3857 results . courses . length === 0 &&
3958 results . departments . length === 0 &&
4059 results . instructors . length === 0 && (
4160 < CommandEmpty > No results found</ CommandEmpty >
4261 ) }
43- { results && results . departments . length > 0 && (
62+ { results && isOpen && results . departments . length > 0 && (
4463 < CommandGroup heading = "Departments" >
4564 { results ?. departments . map ( ( dept ) => (
4665 < CommandItem
4766 key = { dept . item . url }
67+ // onSelect={handleSelect(dept.item.url)}
4868 onSelect = { ( ) => {
69+ setIsOpen ( false ) ;
4970 redirect ( `/review${ dept . item . url } ` ) ;
5071 } }
5172 >
@@ -54,12 +75,14 @@ export default function SearchBar({ header }: { header?: boolean }) {
5475 ) ) }
5576 </ CommandGroup >
5677 ) }
57- { results && results . courses . length > 0 && (
78+ { results && isOpen && results . courses . length > 0 && (
5879 < CommandGroup heading = "Courses" >
5980 { results ?. courses . map ( ( course ) => (
6081 < CommandItem
6182 key = { course . item . url }
83+ // onSelect={handleSelect(course.item.url)}
6284 onSelect = { ( ) => {
85+ setIsOpen ( false ) ;
6386 redirect ( `/review${ course . item . url } ` ) ;
6487 } }
6588 >
@@ -68,12 +91,14 @@ export default function SearchBar({ header }: { header?: boolean }) {
6891 ) ) }
6992 </ CommandGroup >
7093 ) }
71- { results && results . instructors . length > 0 && (
94+ { results && isOpen && results . instructors . length > 0 && (
7295 < CommandGroup heading = "Instructors" >
7396 { results ?. instructors . map ( ( ins ) => (
7497 < CommandItem
7598 key = { ins . item . url }
99+ // onSelect={handleSelect(ins.item.url)}
76100 onSelect = { ( ) => {
101+ setIsOpen ( false ) ;
77102 redirect ( `/review${ ins . item . url } ` ) ;
78103 } }
79104 >
0 commit comments