From 5a09053c73c5c1e554e49b910ac6ca53e8765164 Mon Sep 17 00:00:00 2001 From: Jeff Sieu Date: Fri, 7 Oct 2022 13:50:38 +0800 Subject: [PATCH] [questions][feat] add filter section --- .../questions/ContributeQuestionCard.tsx | 6 +- .../questions/filter/FilterSection.tsx | 62 +++++++ .../questions/ui-patch/Checkbox.tsx | 25 +++ apps/portal/src/pages/questions/index.tsx | 160 +++++++++++++++++- packages/ui/src/Collapsible/Collapsible.tsx | 2 +- 5 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 apps/portal/src/components/questions/filter/FilterSection.tsx create mode 100644 apps/portal/src/components/questions/ui-patch/Checkbox.tsx diff --git a/apps/portal/src/components/questions/ContributeQuestionCard.tsx b/apps/portal/src/components/questions/ContributeQuestionCard.tsx index 683d55f5..4237febb 100644 --- a/apps/portal/src/components/questions/ContributeQuestionCard.tsx +++ b/apps/portal/src/components/questions/ContributeQuestionCard.tsx @@ -57,7 +57,7 @@ export default function ContributeQuestionCard({ {...register('questionContent')} />
-
+
-
+
-
+
void; + options: Array; +} & ( + | { + searchPlaceholder: string; + showAll?: never; + } + | { + searchPlaceholder?: never; + showAll: true; + } +); + +export default function FilterSection({ + label, + options, + searchPlaceholder, + showAll, + onOptionChange, +}: FilterSectionProps) { + return ( +
+ +
+ {!showAll && ( + + )} +
+ {options.map((option) => ( + { + onOptionChange(option.value, checked); + }} + /> + ))} +
+
+
+
+ ); +} diff --git a/apps/portal/src/components/questions/ui-patch/Checkbox.tsx b/apps/portal/src/components/questions/ui-patch/Checkbox.tsx new file mode 100644 index 00000000..413c12fe --- /dev/null +++ b/apps/portal/src/components/questions/ui-patch/Checkbox.tsx @@ -0,0 +1,25 @@ +import { useId } from 'react'; + +export type CheckboxProps = { + checked: boolean; + label: string; + onChange: (checked: boolean) => void; +}; + +export default function Checkbox({ label, checked, onChange }: CheckboxProps) { + const id = useId(); + return ( +
+ onChange(event.target.checked)} + /> + +
+ ); +} diff --git a/apps/portal/src/pages/questions/index.tsx b/apps/portal/src/pages/questions/index.tsx index 6dd2003f..07f8fe86 100644 --- a/apps/portal/src/pages/questions/index.tsx +++ b/apps/portal/src/pages/questions/index.tsx @@ -1,15 +1,168 @@ +import { useMemo, useState } from 'react'; + import ContributeQuestionCard from '~/components/questions/ContributeQuestionCard'; +import type { FilterOptions } from '~/components/questions/filter/FilterSection'; +import FilterSection from '~/components/questions/filter/FilterSection'; import NavBar from '~/components/questions/NavBar'; import QuestionOverviewCard from '~/components/questions/QuestionOverviewCard'; import QuestionSearchBar from '~/components/questions/QuestionSearchBar'; +type FilterChoices = Array>; + +const companies: FilterChoices = [ + { + label: 'Google', + value: 'Google', + }, + { + label: 'Meta', + value: 'meta', + }, +]; + +// Code, design, behavioral +const questionTypes: FilterChoices = [ + { + label: 'Code', + value: 'code', + }, + { + label: 'Design', + value: 'design', + }, + { + label: 'Behavioral', + value: 'behavioral', + }, +]; + +const questionAges: FilterChoices = [ + { + label: 'Last month', + value: 'last-month', + }, + { + label: 'Last 6 months', + value: 'last-6-months', + }, + { + label: 'Last year', + value: 'last-year', + }, +]; + +const locations: FilterChoices = [ + { + label: 'Singapore', + value: 'singapore', + }, +]; + export default function QuestionsHomePage() { + const [selectedCompanies, setSelectedCompanies] = useState>([]); + const [selectedQuestionTypes, setSelectedQuestionTypes] = useState< + Array + >([]); + const [selectedQuestionAges, setSelectedQuestionAges] = useState< + Array + >([]); + const [selectedLocations, setSelectedLocations] = useState>([]); + + const companyFilterOptions = useMemo(() => { + return companies.map((company) => ({ + ...company, + checked: selectedCompanies.includes(company.value), + })); + }, [selectedCompanies]); + + const questionTypeFilterOptions = useMemo(() => { + return questionTypes.map((questionType) => ({ + ...questionType, + checked: selectedQuestionTypes.includes(questionType.value), + })); + }, [selectedQuestionTypes]); + + const questionAgeFilterOptions = useMemo(() => { + return questionAges.map((questionAge) => ({ + ...questionAge, + checked: selectedQuestionAges.includes(questionAge.value), + })); + }, [selectedQuestionAges]); + + const locationFilterOptions = useMemo(() => { + return locations.map((location) => ({ + ...location, + checked: selectedLocations.includes(location.value), + })); + }, [selectedLocations]); + return ( -
+
-
+
+
+

Filter by

+
+ { + if (checked) { + setSelectedCompanies((prev) => [...prev, optionValue]); + } else { + setSelectedCompanies((prev) => + prev.filter((company) => company !== optionValue), + ); + } + }} + /> + { + if (checked) { + setSelectedQuestionTypes((prev) => [...prev, optionValue]); + } else { + setSelectedQuestionTypes((prev) => + prev.filter((questionType) => questionType !== optionValue), + ); + } + }} + /> + { + if (checked) { + setSelectedQuestionAges((prev) => [...prev, optionValue]); + } else { + setSelectedQuestionAges((prev) => + prev.filter((questionAge) => questionAge !== optionValue), + ); + } + }} + /> + { + if (checked) { + setSelectedLocations((prev) => [...prev, optionValue]); + } else { + setSelectedLocations((prev) => + prev.filter((location) => location !== optionValue), + ); + } + }} + /> +
+
{ @@ -40,9 +193,6 @@ export default function QuestionsHomePage() { upvoteCount={0} />
-
-

To do: Filter column

-
); diff --git a/packages/ui/src/Collapsible/Collapsible.tsx b/packages/ui/src/Collapsible/Collapsible.tsx index 93e5ba10..211c54fd 100644 --- a/packages/ui/src/Collapsible/Collapsible.tsx +++ b/packages/ui/src/Collapsible/Collapsible.tsx @@ -23,7 +23,7 @@ export default function Collapsible({ children, defaultOpen, label }: Props) { /> {label} - + {children}