diff --git a/apps/portal/src/components/questions/filter/FilterSection.tsx b/apps/portal/src/components/questions/filter/FilterSection.tsx index 312122c3..20af0f7b 100644 --- a/apps/portal/src/components/questions/filter/FilterSection.tsx +++ b/apps/portal/src/components/questions/filter/FilterSection.tsx @@ -1,8 +1,11 @@ -import { MagnifyingGlassIcon } from '@heroicons/react/24/outline'; -import { CheckboxInput, Collapsible, RadioList, TextInput } from '@tih/ui'; +import { useMemo } from 'react'; +import type { UseFormRegisterReturn } from 'react-hook-form'; +import { useForm } from 'react-hook-form'; +import { CheckboxInput, Collapsible, RadioList } from '@tih/ui'; export type FilterOption = { checked: boolean; + id: string; label: string; value: V; }; @@ -30,37 +33,66 @@ export type FilterSectionProps> = options: FilterOptions; } & ( | { - searchPlaceholder: string; + renderInput: (props: { + field: UseFormRegisterReturn<'search'>; + onOptionChange: FilterSectionType['onOptionChange']; + options: FilterOptions; + }) => React.ReactNode; showAll?: never; } | { - searchPlaceholder?: never; + renderInput?: never; showAll: true; } ); +export type FilterSectionFormData = { + search: string; +}; + export default function FilterSection< FilterOptions extends Array, >({ label, options, - searchPlaceholder, showAll, onOptionChange, isSingleSelect, + renderInput, }: FilterSectionProps) { + const { register, reset } = useForm(); + + const registerSearch = register('search'); + + const field: UseFormRegisterReturn<'search'> = { + ...registerSearch, + onChange: async (event) => { + await registerSearch.onChange(event); + reset(); + }, + }; + + const autocompleteOptions = useMemo(() => { + return options.filter((option) => !option.checked) as FilterOptions; + }, [options]); + return (
{!showAll && ( - +
+ {renderInput({ + field, + onOptionChange: async ( + optionValue: FilterOptions[number]['value'], + ) => { + reset(); + return onOptionChange(optionValue, true); + }, + options: autocompleteOptions, + })} +
)} {isSingleSelect ? (
@@ -81,16 +113,18 @@ export default function FilterSection<
) : (
- {options.map((option) => ( - { - onOptionChange(option.value, checked); - }} - /> - ))} + {options + .filter((option) => showAll || option.checked) + .map((option) => ( + { + onOptionChange(option.value, checked); + }} + /> + ))}
)}
diff --git a/apps/portal/src/pages/questions/index.tsx b/apps/portal/src/pages/questions/index.tsx index eed5464f..7105b7ea 100644 --- a/apps/portal/src/pages/questions/index.tsx +++ b/apps/portal/src/pages/questions/index.tsx @@ -3,7 +3,7 @@ import Router, { useRouter } from 'next/router'; import { useEffect, useMemo, useState } from 'react'; import { NoSymbolIcon } from '@heroicons/react/24/outline'; import type { QuestionsQuestionType } from '@prisma/client'; -import { SlideOut } from '@tih/ui'; +import { SlideOut, Typeahead } from '@tih/ui'; import QuestionOverviewCard from '~/components/questions/card/QuestionOverviewCard'; import ContributeQuestionCard from '~/components/questions/ContributeQuestionCard'; @@ -188,7 +188,18 @@ export default function QuestionsHomePage() { ( + {}} + onSelect={({ value }) => { + onOptionChange(value, true); + }} + /> + )} onOptionChange={(optionValue, checked) => { if (checked) { setSelectedCompanies([...selectedCompanies, optionValue]); @@ -227,7 +238,18 @@ export default function QuestionsHomePage() { ( + {}} + onSelect={({ value }) => { + onOptionChange(value, true); + }} + /> + )} onOptionChange={(optionValue, checked) => { if (checked) { setSelectedLocations([...selectedLocations, optionValue]); diff --git a/apps/portal/src/utils/questions/constants.ts b/apps/portal/src/utils/questions/constants.ts index 357b6f55..70e04fdc 100644 --- a/apps/portal/src/utils/questions/constants.ts +++ b/apps/portal/src/utils/questions/constants.ts @@ -4,10 +4,12 @@ import type { FilterChoices } from '~/components/questions/filter/FilterSection' export const COMPANIES: FilterChoices = [ { + id: 'Google', label: 'Google', value: 'Google', }, { + id: 'Meta', label: 'Meta', value: 'Meta', }, @@ -16,14 +18,17 @@ export const COMPANIES: FilterChoices = [ // Code, design, behavioral export const QUESTION_TYPES: FilterChoices = [ { + id: 'CODING', label: 'Coding', value: 'CODING', }, { + id: 'SYSTEM_DESIGN', label: 'Design', value: 'SYSTEM_DESIGN', }, { + id: 'BEHAVIORAL', label: 'Behavioral', value: 'BEHAVIORAL', }, @@ -33,18 +38,22 @@ export type QuestionAge = 'all' | 'last-6-months' | 'last-month' | 'last-year'; export const QUESTION_AGES: FilterChoices = [ { + id: 'last-month', label: 'Last month', value: 'last-month', }, { + id: 'last-6-months', label: 'Last 6 months', value: 'last-6-months', }, { + id: 'last-year', label: 'Last year', value: 'last-year', }, { + id: 'all', label: 'All', value: 'all', }, @@ -52,22 +61,27 @@ export const QUESTION_AGES: FilterChoices = [ export const LOCATIONS: FilterChoices = [ { + id: 'Singapore', label: 'Singapore', value: 'Singapore', }, { + id: 'Menlo Park', label: 'Menlo Park', value: 'Menlo Park', }, { + id: 'california', label: 'California', value: 'california', }, { + id: 'california', label: 'Hong Kong', value: 'Hong Kong', }, { + id: 'Taiwan', label: 'Taiwan', value: 'Taiwan', },