diff --git a/src/components/search/Search.tsx b/src/components/search/Search.tsx index f502f1e..2770af9 100644 --- a/src/components/search/Search.tsx +++ b/src/components/search/Search.tsx @@ -4,6 +4,7 @@ import React, { useEffect, useState } from "react"; import Link from "next/link"; import { useRouter, useSearchParams } from "next/navigation"; import { SearchFilterDialog } from "@/components/search/filter/search-filter-dialog"; +import { SearchFilterSortDropdown } from "@/components/search/filter/search-filter-sort-dropdown"; import { SearchBlurb } from "@/components/search/search-blurb"; import { analyticsEnum, logAnalytics } from "@/lib/analytics"; import { UNIVERSITY_GE } from "@/lib/constants"; @@ -13,7 +14,6 @@ import { filterData } from "../../lib/utils/filter"; import { queryDatabase } from "../../lib/utils/query-db"; import { ToastAction } from "../ui/toast"; import { useToast } from "../ui/use-toast"; -import { SortDropdown } from "./filter/FilterComponents"; import { SearchFilter } from "./filter/search-filter"; import ScrollToTop from "./ScrollToTop"; import SearchResults from "./SearchResults"; @@ -103,7 +103,7 @@ const Search = () => { const [format, setFormat] = useState([true, true]); const [enrollment, setEnrollment] = useState([true]); - const [available, setAvailable] = useState([false]); + const [available, setAvailable] = useState([true]); const [start, setStart] = useState(); const [end, setEnd] = useState(); const [institution, setInstitution] = useState("Any Institution"); @@ -305,15 +305,15 @@ const Search = () => { /> - diff --git a/src/components/search/filter/FilterComponents.tsx b/src/components/search/filter/FilterComponents.tsx deleted file mode 100644 index f69ba53..0000000 --- a/src/components/search/filter/FilterComponents.tsx +++ /dev/null @@ -1,340 +0,0 @@ -"use client"; - -import React, { ChangeEvent, Dispatch, SetStateAction, useState } from "react"; -import { Calendar } from "@/components/ui/calendar"; -import { Checkbox } from "@/components/ui/checkbox"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { cn } from "@/lib/utils"; -import { format } from "date-fns"; -import { CalendarIcon } from "lucide-react"; - -import { Button } from "../../ui/button"; -import { CourseObject } from "../Search"; - -interface FilterCheckboxProps { - title: string; - categories: string[]; - onChange: Dispatch>; - defaultValue: boolean[]; -} - -export const CustomFilterCheckbox = (props: FilterCheckboxProps) => { - const { title, categories, onChange, defaultValue } = props; - - // Initialize an array of boolean values to represent the checked state of each category - const [categoryStates, setCategoryStates] = useState( - categories.map((_, index) => defaultValue[index]) - ); - - // Function to toggle the checked state of a category - const toggleCategory = (index: number) => { - const newCategoryStates = [...categoryStates]; - newCategoryStates[index] = !categoryStates[index]; - - onChange(newCategoryStates); - setCategoryStates(newCategoryStates); - }; - - return ( -
-
{title}
-
- {categories.map((category, index) => ( -
- toggleCategory(index)} - /> - -
- ))} -
-
-
- ); -}; - -interface CalendarFilterProps { - onStartChange: Dispatch>; - onEndChange: Dispatch>; - defaultStart: Date | undefined; - defaultEnd: Date | undefined; -} - -export const CalendarFilter = (props: CalendarFilterProps) => { - const { onStartChange, onEndChange, defaultStart, defaultEnd } = props; - - const [startDate, setStartDate] = useState(defaultStart); - const [endDate, setEndDate] = useState(defaultEnd); - - const handleStartChange = (date: Date | undefined) => { - if (!date) { - console.error("No start date selected"); - return; - } - - onStartChange(date); - setStartDate(date); - }; - - const handleEndChange = (date: Date | undefined) => { - onEndChange(date); - setEndDate(date); - }; - - return ( -
-
Timeframe
-
-
- -
- - - - - - - - -
-
-
- -
- - - - - - - - -
-
-
-
-
- ); -}; - -interface InstitutionDropdownProps { - defaultValue: string; - courses: CourseObject[] | undefined; - onChange: Dispatch>; -} - -export const InstitutionDropdown = (props: InstitutionDropdownProps) => { - const { defaultValue, courses, onChange } = props; - - const [value, setValue] = useState(defaultValue); - - const handleChange = (value: string) => { - onChange(value); - setValue(value); - }; - - const uniqueColleges = - defaultValue == "Any Institution" ? [] : [defaultValue]; - - const sendingInstitutions = courses?.map( - (course: CourseObject) => course.sendingInstitution - ); - - if (sendingInstitutions) { - for (const college of sendingInstitutions) { - if (!uniqueColleges.includes(college)) { - uniqueColleges.push(college); - } - } - - uniqueColleges.sort(); - } - - return ( -
-
- Teaching Institution -
- -
-
- ); -}; - -interface UnitsFilterProps { - onMinChange: Dispatch>; - onMaxChange: Dispatch>; - defaultMin: number; - defaultMax: number; -} - -export const UnitsFilter = (props: UnitsFilterProps) => { - const { onMinChange, onMaxChange, defaultMin, defaultMax } = props; - - const [min, setMin] = useState(defaultMin); - const [max, setMax] = useState(defaultMax); - - const handleMinChange = (e: ChangeEvent) => { - onMinChange(e.target.value ? parseInt(e.target.value) : 0); - setMin(parseInt(e.target.value)); - }; - - const handleMaxChange = (e: ChangeEvent) => { - onMaxChange(e.target.value ? parseInt(e.target.value) : 0); - setMax(parseInt(e.target.value)); - }; - - return ( -
-
Units
-
-
- -
- -
-
-
- -
- -
-
-
-
-
- ); -}; - -interface SortDropdownProps { - defaultValue: string; - data: string[]; - onChange: Dispatch>; -} - -export const SortDropdown = (props: SortDropdownProps) => { - const { defaultValue, data, onChange } = props; - - const [value, setValue] = useState(defaultValue); - - const handleChange = (value: string) => { - onChange(value); - setValue(value); - }; - - return ( -
-
Sort By:
- -
- ); -}; diff --git a/src/components/search/filter/search-filter-checkbox.tsx b/src/components/search/filter/search-filter-checkbox.tsx new file mode 100644 index 0000000..cff2b06 --- /dev/null +++ b/src/components/search/filter/search-filter-checkbox.tsx @@ -0,0 +1,50 @@ +import { Checkbox } from "@/components/ui/checkbox"; + +interface SearchFilterCheckboxProps { + title: string; + value: boolean[]; + onChange: (input: boolean[]) => void; + categories: string[]; +} + +export const SearchFilterCheckbox = ({ + title, + categories, + onChange, + value, +}: SearchFilterCheckboxProps) => { + const toggleCategory = (index: number) => { + const newCategoryStates = [...value]; + newCategoryStates[index] = !value[index]; + + onChange(newCategoryStates); + }; + + return ( +
+
{title}
+
+ {categories.map((category, index) => ( +
+ toggleCategory(index)} + /> + +
+ ))} +
+
+
+ ); +}; diff --git a/src/components/search/filter/search-filter-date-select.tsx b/src/components/search/filter/search-filter-date-select.tsx new file mode 100644 index 0000000..eb747d3 --- /dev/null +++ b/src/components/search/filter/search-filter-date-select.tsx @@ -0,0 +1,114 @@ +import { Calendar } from "@/components/ui/calendar"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { cn } from "@/lib/utils"; +import { format } from "date-fns"; +import { CalendarIcon } from "lucide-react"; + +import { Button } from "../../ui/button"; + +interface SearchFilterDateSelectProps { + onStartChange: (input: Date | undefined) => void; + onEndChange: (input: Date | undefined) => void; + start: Date | undefined; + end: Date | undefined; +} + +export function SearchFilterDateSelect({ + onStartChange, + onEndChange, + start, + end, +}: SearchFilterDateSelectProps) { + const handleStartChange = (date: Date | undefined) => { + if (!date) { + console.error("No start date selected"); + return; + } + + onStartChange(date); + }; + + const handleEndChange = (date: Date | undefined) => { + onEndChange(date); + }; + + return ( +
+
Timeframe
+
+
+ +
+ + + + + + + + +
+
+ +
+ +
+ + + + + + + + +
+
+
+
+
+ ); +} diff --git a/src/components/search/filter/search-filter-institution-dropdown.tsx b/src/components/search/filter/search-filter-institution-dropdown.tsx new file mode 100644 index 0000000..8a9bd5d --- /dev/null +++ b/src/components/search/filter/search-filter-institution-dropdown.tsx @@ -0,0 +1,66 @@ +import { CourseObject } from "@/components/search/Search"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +interface SearchFilterInstitutionDropdownProps { + value: string; + onChange: (input: string) => void; + courses: CourseObject[] | undefined; +} + +export function SearchFilterInstitutionDropdown({ + value, + onChange, + courses, +}: SearchFilterInstitutionDropdownProps) { + const uniqueColleges = value == "Any Institution" ? [] : [value]; + + const sendingInstitutions = courses?.map( + (course: CourseObject) => course.sendingInstitution + ); + + if (sendingInstitutions) { + for (const college of sendingInstitutions) { + if (!uniqueColleges.includes(college)) { + uniqueColleges.push(college); + } + } + + uniqueColleges.sort(); + } + + return ( +
+
+ Teaching Institution +
+ +
+
+ ); +} diff --git a/src/components/search/filter/search-filter-sort-dropdown.tsx b/src/components/search/filter/search-filter-sort-dropdown.tsx new file mode 100644 index 0000000..968d631 --- /dev/null +++ b/src/components/search/filter/search-filter-sort-dropdown.tsx @@ -0,0 +1,43 @@ +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +interface SearchFilterSortDropdownProps { + value: string; + onChange: (input: string) => void; + data: string[]; +} + +export function SearchFilterSortDropdown({ + value, + data, + onChange, +}: SearchFilterSortDropdownProps) { + return ( +
+
Sort By:
+ +
+ ); +} diff --git a/src/components/search/filter/search-filter.tsx b/src/components/search/filter/search-filter.tsx index 7fd06f4..0db1a14 100644 --- a/src/components/search/filter/search-filter.tsx +++ b/src/components/search/filter/search-filter.tsx @@ -1,11 +1,9 @@ import { Dispatch, SetStateAction } from "react"; +import { SearchFilterDateSelect } from "@/components/search/filter/search-filter-date-select"; +import { SearchFilterInstitutionDropdown } from "@/components/search/filter/search-filter-institution-dropdown"; import { CourseObject, FilterValues } from "../Search"; -import { - CalendarFilter, - CustomFilterCheckbox, - InstitutionDropdown, -} from "./FilterComponents"; +import { SearchFilterCheckbox } from "./search-filter-checkbox"; interface SearchFilterProps { setFormat: Dispatch>; @@ -38,26 +36,26 @@ export const SearchFilter = (props: SearchFilterProps) => {
- - - -