Skip to content

Commit

Permalink
refactor: move search state to context
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinWu098 committed Dec 5, 2024
1 parent b84b215 commit 0e50a61
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 151 deletions.
5 changes: 5 additions & 0 deletions src/app/search/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SearchContextProvider } from "@/contexts/search-context/search-context";

export default function Layout({ children }: { children: React.ReactNode }) {
return <SearchContextProvider>{children}</SearchContextProvider>;
}
90 changes: 10 additions & 80 deletions src/components/search/Search.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
"use client";

import React, { useCallback, useEffect, useState } from "react";
import React, { useCallback } from "react";
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 { SearchResults } from "@/components/search/search-results";
import type {
CourseObject,
FilterValues,
} from "@/components/search/search.types";
import type { CourseObject } from "@/components/search/search.types";
import { useSearchContext } from "@/contexts/search-context/search-context";
import { UNIVERSITY_GE } from "@/lib/constants";
import { useQueryState } from "nuqs";

Expand All @@ -27,6 +25,8 @@ export function Search({
courses: CourseObject[];
lastUpdated: number;
}) {
const { filterValues } = useSearchContext();

const [university, setUniversity] = useQueryState("uni", {
defaultValue: _university,
shallow: false,
Expand All @@ -38,53 +38,6 @@ export function Search({
clearOnDefault: false,
});

const [format, setFormat] = useState([true, true]);
const [enrollment, setEnrollment] = useState([true]);
const [available, setAvailable] = useState([true]);
const [start, setStart] = useState<Date>();
const [end, setEnd] = useState<Date>();
const [institution, setInstitution] = useState("Any Institution");
const [min, setMin] = useState(0);
const [max, setMax] = useState(20);

const [sort, setSort] = useState("Default Sort");

const [filterValues, setFilterValues] = useState<FilterValues>({
format: format,
enrollment: enrollment,
available: available,
start: start,
end: end,
institution: institution,
min: min,
max: max,
sort: sort,
});

useEffect(() => {
setFilterValues({
format,
enrollment,
available,
start,
end,
institution,
min,
max,
sort,
});
}, [
format,
enrollment,
available,
start,
end,
institution,
min,
max,
sort,
]);

const handleUniversityChange = useCallback(
(university: string) => {
setUniversity(university);
Expand All @@ -100,6 +53,8 @@ export function Search({
[setGE]
);

const results = filterData(courses, filterValues);

return (
<div className="wrapper mb-8 min-h-[calc(100vh-96px)] px-4 md:mb-16 lg:px-28 xl:px-36">
<div className="flex flex-wrap text-6xl font-bold">
Expand All @@ -126,46 +81,21 @@ export function Search({
<SearchBlurb
filterData={filterData}
courses={courses}
filterValues={filterValues}
lastUpdated={lastUpdated}
/>

<div className="mt-4 flex flex-row gap-4 md:mt-8 md:gap-8">
<div className="hidden h-fit xl:flex xl:flex-col">
<SearchFilter
setFormat={setFormat}
setEnrollment={setEnrollment}
setAvailable={setAvailable}
setStart={setStart}
setEnd={setEnd}
setInstitution={setInstitution}
setMin={setMin}
setMax={setMax}
filterValues={filterValues}
courses={courses}
/>
<SearchFilter courses={courses} />
</div>

<div className="w-full xl:w-[65%]">
<div className="mb-8 flex flex-wrap items-center justify-between gap-y-4 xl:justify-end">
<SearchFilterDialog>
<SearchFilter
setFormat={setFormat}
setEnrollment={setEnrollment}
setAvailable={setAvailable}
setStart={setStart}
setEnd={setEnd}
setInstitution={setInstitution}
setMin={setMin}
setMax={setMax}
filterValues={filterValues}
courses={courses}
/>
<SearchFilter courses={courses} />
</SearchFilterDialog>

<SearchFilterSortDropdown
value={sort}
onChange={setSort}
data={[
"Default Sort",
"Alphabetical",
Expand All @@ -176,7 +106,7 @@ export function Search({
</div>

<SearchResults
results={filterData(courses, filterValues)}
results={results}
university={university}
ge={ge}
/>
Expand Down
42 changes: 20 additions & 22 deletions src/components/search/filter/search-filter-date-select.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
import { useCallback } from "react";
import { Calendar } from "@/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { useSearchContext } from "@/contexts/search-context/search-context";
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() {
const { start, setStart, end, setEnd } = useSearchContext();

export function SearchFilterDateSelect({
onStartChange,
onEndChange,
start,
end,
}: SearchFilterDateSelectProps) {
const handleStartChange = (date: Date | undefined) => {
if (!date) {
console.error("No start date selected");
return;
}
const handleStartChange = useCallback(
(date: Date | undefined) => {
if (!date) {
console.error("No start date selected");
return;
}

onStartChange(date);
};
setStart(date);
},
[setStart]
);

const handleEndChange = (date: Date | undefined) => {
onEndChange(date);
};
const handleEndChange = useCallback(
(date: Date | undefined) => {
setEnd(date);
},
[setEnd]
);

return (
<div className="relative flex flex-col">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useSearchContext } from "@/contexts/search-context/search-context";

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 { institution, setInstitution } = useSearchContext();

const uniqueColleges =
institution == "Any Institution" ? [] : [institution];

const sendingInstitutions = courses?.map(
(course: CourseObject) => course.sendingInstitution
Expand All @@ -40,8 +40,8 @@ export function SearchFilterInstitutionDropdown({
Teaching Institution
</div>
<Select
value={value}
onValueChange={onChange}
value={institution}
onValueChange={setInstitution}
>
<SelectTrigger className="text-regular min-h-full w-full max-w-[368px] rounded-lg border-[1px] border-gray">
<SelectValue placeholder="Teaching Institution" />
Expand Down
11 changes: 5 additions & 6 deletions src/components/search/filter/search-filter-sort-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,23 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useSearchContext } from "@/contexts/search-context/search-context";

interface SearchFilterSortDropdownProps {
value: string;
onChange: (input: string) => void;
data: string[];
}

export function SearchFilterSortDropdown({
value,
data,
onChange,
}: SearchFilterSortDropdownProps) {
const { sort, setSort } = useSearchContext();

return (
<div className="flex items-center gap-4 md:flex-row">
<div className="hidden text-gray sm:flex">Sort By:</div>
<Select
value={value}
onValueChange={onChange}
value={sort}
onValueChange={setSort}
>
<SelectTrigger className="text-regular min-h-full w-40 rounded-lg border-[1px] border-gray">
<SelectValue />
Expand Down
42 changes: 8 additions & 34 deletions src/components/search/filter/search-filter.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,15 @@
import { Dispatch, SetStateAction } from "react";
import { SearchFilterCheckbox } from "@/components/search/filter/search-filter-checkbox";
import { SearchFilterDateSelect } from "@/components/search/filter/search-filter-date-select";
import { SearchFilterInstitutionDropdown } from "@/components/search/filter/search-filter-institution-dropdown";
import { CourseObject, FilterValues } from "@/components/search/search.types";
import { CourseObject } from "@/components/search/search.types";
import { useSearchContext } from "@/contexts/search-context/search-context";

interface SearchFilterProps {
setFormat: Dispatch<SetStateAction<boolean[]>>;
setEnrollment: Dispatch<SetStateAction<boolean[]>>;
setAvailable: Dispatch<SetStateAction<boolean[]>>;
setStart: Dispatch<React.SetStateAction<Date | undefined>>;
setEnd: Dispatch<SetStateAction<Date | undefined>>;
setInstitution: Dispatch<SetStateAction<string>>;
setMin: Dispatch<SetStateAction<number>>;
setMax: Dispatch<SetStateAction<number>>;
filterValues: FilterValues;
courses: CourseObject[] | undefined;
}

export const SearchFilter = (props: SearchFilterProps) => {
const {
setFormat,
setAvailable,
setStart,
setEnd,
setInstitution,
filterValues,
courses,
} = props;
export const SearchFilter = ({ courses }: SearchFilterProps) => {
const { format, setFormat, available, setAvailable } = useSearchContext();

return (
<div className="space-y-8 rounded-lg bg-bg_secondary p-8 text-left">
Expand All @@ -37,27 +20,18 @@ export const SearchFilter = (props: SearchFilterProps) => {
<div className="flex flex-col gap-4">
<SearchFilterCheckbox
title="Online Format"
value={filterValues.format}
value={format}
onChange={setFormat}
categories={["Asynchronous", "Synchronous"]}
/>
<SearchFilterCheckbox
title="Available Seats"
value={filterValues.available}
value={available}
onChange={setAvailable}
categories={["Only show courses with available seats"]}
/>
<SearchFilterDateSelect
onStartChange={setStart}
onEndChange={setEnd}
start={filterValues.start}
end={filterValues.end}
/>
<SearchFilterInstitutionDropdown
value={filterValues.institution}
onChange={setInstitution}
courses={courses}
/>
<SearchFilterDateSelect />
<SearchFilterInstitutionDropdown courses={courses} />
</div>
</div>
);
Expand Down
5 changes: 3 additions & 2 deletions src/components/search/search-blurb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
CourseObject,
FilterValues,
} from "@/components/search/search.types";
import { useSearchContext } from "@/contexts/search-context/search-context";

interface SearchBlurbProps {
filterData: (
Expand All @@ -11,15 +12,15 @@ interface SearchBlurbProps {
) => CourseObject[];
courses: CourseObject[] | undefined;
lastUpdated: number | undefined;
filterValues: FilterValues;
}

export const SearchBlurb = ({
filterData,
courses,
lastUpdated,
filterValues,
}: SearchBlurbProps) => {
const { filterValues } = useSearchContext();

const [timeAgo, setTimeAgo] = useState("");

const getTimeAgo = useCallback((date: number) => {
Expand Down
Loading

0 comments on commit 0e50a61

Please sign in to comment.