[questions][ui] radio button

pull/346/head
wlren 3 years ago
parent 00f3fdff88
commit 41046b4720

@ -2,37 +2,54 @@ import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { Collapsible, TextInput } from '@tih/ui'; import { Collapsible, TextInput } from '@tih/ui';
import Checkbox from '../ui-patch/Checkbox'; import Checkbox from '../ui-patch/Checkbox';
import RadioGroup from '../ui-patch/RadioGroup';
export type FilterOptions = { export type FilterOption = {
checked: boolean; checked: boolean;
label: string; label: string;
value: string; value: string;
}; };
export type FilterChoices = Array<Omit<FilterOptions, 'checked'>>; export type FilterChoices = Array<Omit<FilterOption, 'checked'>>;
export type FilterSectionProps = { type FilterSectionType<FilterOptions extends Array<FilterOption>> =
label: string;
onOptionChange: (optionValue: string, checked: boolean) => void;
options: Array<FilterOptions>;
} & (
| { | {
searchPlaceholder: string; isSingleSelect: true;
showAll?: never; onOptionChange: (optionValue: FilterOptions[number]['value']) => void;
} }
| { | {
searchPlaceholder?: never; isSingleSelect?: false;
showAll: true; onOptionChange: (
} optionValue: FilterOptions[number]['value'],
); checked: boolean,
) => void;
};
export default function FilterSection({ export type FilterSectionProps<FilterOptions extends Array<FilterOption>> =
FilterSectionType<FilterOptions> & {
label: string;
options: FilterOptions;
} & (
| {
searchPlaceholder: string;
showAll?: never;
}
| {
searchPlaceholder?: never;
showAll: true;
}
);
export default function FilterSection<
FilterOptions extends Array<FilterOption>,
>({
label, label,
options, options,
searchPlaceholder, searchPlaceholder,
showAll, showAll,
onOptionChange, onOptionChange,
}: FilterSectionProps) { isSingleSelect,
}: FilterSectionProps<FilterOptions>) {
return ( return (
<div className="mx-2"> <div className="mx-2">
<Collapsible defaultOpen={true} label={label}> <Collapsible defaultOpen={true} label={label}>
@ -46,17 +63,25 @@ export default function FilterSection({
startAddOnType="icon" startAddOnType="icon"
/> />
)} )}
<div className="mx-1"> {isSingleSelect ? (
{options.map((option) => ( <RadioGroup
<Checkbox radioData={options}
key={option.value} onChange={(value) => {
{...option} onOptionChange(value);
onChange={(checked) => { }}></RadioGroup>
onOptionChange(option.value, checked); ) : (
}} <div className="mx-1">
/> {options.map((option) => (
))} <Checkbox
</div> key={option.value}
{...option}
onChange={(checked) => {
onOptionChange(option.value, checked);
}}
/>
))}
</div>
)}
</div> </div>
</Collapsible> </Collapsible>
</div> </div>

@ -0,0 +1,38 @@
export type RadioProps = {
onChange: (value: string) => void;
radioData: Array<RadioData>;
};
export type RadioData = {
checked: boolean;
label: string;
value: string;
};
export default function RadioGroup({ radioData, onChange }: RadioProps) {
return (
<fieldset
onChange={(event: React.FormEvent<HTMLFieldSetElement>) => {
const target = event.target as HTMLInputElement;
onChange(target.value);
}}>
<div className="mx-1 space-y-2">
{radioData.map((radio) => (
<div key={radio.value} className="flex items-center">
<input
checked={radio.checked}
className="text-primary-600 focus:ring-primary-500 h-4 w-4 border-gray-300"
type="radio"
value={radio.value}
/>
<label
className="ml-3 min-w-0 flex-1 text-gray-700"
htmlFor={radio.value}>
{radio.label}
</label>
</div>
))}
</div>
</fieldset>
);
}

@ -23,9 +23,7 @@ export default function QuestionsHomePage() {
const [selectedQuestionTypes, setSelectedQuestionTypes] = useState< const [selectedQuestionTypes, setSelectedQuestionTypes] = useState<
Array<string> Array<string>
>([]); >([]);
const [selectedQuestionAges, setSelectedQuestionAges] = useState< const [selectedQuestionAge, setSelectedQuestionAge] = useState<string>('all');
Array<string>
>([]);
const [selectedLocations, setSelectedLocations] = useState<Array<string>>([]); const [selectedLocations, setSelectedLocations] = useState<Array<string>>([]);
const [hasLanded, setHasLanded] = useState(false); const [hasLanded, setHasLanded] = useState(false);
@ -46,9 +44,9 @@ export default function QuestionsHomePage() {
const questionAgeFilterOptions = useMemo(() => { const questionAgeFilterOptions = useMemo(() => {
return QUESTION_AGES.map((questionAge) => ({ return QUESTION_AGES.map((questionAge) => ({
...questionAge, ...questionAge,
checked: selectedQuestionAges.includes(questionAge.value), checked: selectedQuestionAge === questionAge.value,
})); }));
}, [selectedQuestionAges]); }, [selectedQuestionAge]);
const locationFilterOptions = useMemo(() => { const locationFilterOptions = useMemo(() => {
return LOCATIONS.map((location) => ({ return LOCATIONS.map((location) => ({
@ -81,14 +79,14 @@ export default function QuestionsHomePage() {
if (router.isReady && !isSearchInitialized) { if (router.isReady && !isSearchInitialized) {
setSelectedCompanies(paramToArray(router.query.companies)); setSelectedCompanies(paramToArray(router.query.companies));
setSelectedQuestionTypes(paramToArray(router.query.questionTypes)); setSelectedQuestionTypes(paramToArray(router.query.questionTypes));
setSelectedQuestionAges(paramToArray(router.query.questionAges)); setSelectedQuestionAge(router.query.questionAge as string);
setSelectedLocations(paramToArray(router.query.locations)); setSelectedLocations(paramToArray(router.query.locations));
setIsSearchInitialized(true); setIsSearchInitialized(true);
const hasFilter = const hasFilter =
router.query.companies || router.query.companies ||
router.query.questionTypes || router.query.questionTypes ||
router.query.questionAges || router.query.questionAge ||
router.query.locations; router.query.locations;
if (hasFilter) { if (hasFilter) {
setHasLanded(true); setHasLanded(true);
@ -101,7 +99,7 @@ export default function QuestionsHomePage() {
hasLanded, hasLanded,
selectedCompanies, selectedCompanies,
selectedQuestionTypes, selectedQuestionTypes,
selectedQuestionAges, selectedQuestionAge,
selectedLocations, selectedLocations,
]); ]);
@ -113,7 +111,7 @@ export default function QuestionsHomePage() {
query: { query: {
companies: selectedCompanies, companies: selectedCompanies,
locations: selectedLocations, locations: selectedLocations,
questionAges: selectedQuestionAges, questionAge: selectedQuestionAge,
questionTypes: selectedQuestionTypes, questionTypes: selectedQuestionTypes,
}, },
}, },
@ -124,7 +122,7 @@ export default function QuestionsHomePage() {
}, [ }, [
selectedCompanies, selectedCompanies,
selectedQuestionTypes, selectedQuestionTypes,
selectedQuestionAges, selectedQuestionAge,
selectedLocations, selectedLocations,
router, router,
router.isReady, router.isReady,
@ -168,17 +166,12 @@ export default function QuestionsHomePage() {
}} }}
/> />
<FilterSection <FilterSection
isSingleSelect={true}
label="Question age" label="Question age"
options={questionAgeFilterOptions} options={questionAgeFilterOptions}
showAll={true} showAll={true}
onOptionChange={(optionValue, checked) => { onOptionChange={(optionValue) => {
if (checked) { setSelectedQuestionAge(optionValue);
setSelectedQuestionAges((prev) => [...prev, optionValue]);
} else {
setSelectedQuestionAges((prev) =>
prev.filter((questionAge) => questionAge !== optionValue),
);
}
}} }}
/> />
<FilterSection <FilterSection

@ -40,6 +40,10 @@ export const QUESTION_AGES: FilterChoices = [
label: 'Last year', label: 'Last year',
value: 'last-year', value: 'last-year',
}, },
{
label: 'All',
value: 'all',
},
]; ];
export const LOCATIONS: FilterChoices = [ export const LOCATIONS: FilterChoices = [

Loading…
Cancel
Save