[questions][ui] radio button

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

@ -2,20 +2,34 @@ import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { Collapsible, TextInput } from '@tih/ui';
import Checkbox from '../ui-patch/Checkbox';
import RadioGroup from '../ui-patch/RadioGroup';
export type FilterOptions = {
export type FilterOption = {
checked: boolean;
label: 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>> =
| {
isSingleSelect: true;
onOptionChange: (optionValue: FilterOptions[number]['value']) => void;
}
| {
isSingleSelect?: false;
onOptionChange: (
optionValue: FilterOptions[number]['value'],
checked: boolean,
) => void;
};
export type FilterSectionProps<FilterOptions extends Array<FilterOption>> =
FilterSectionType<FilterOptions> & {
label: string;
onOptionChange: (optionValue: string, checked: boolean) => void;
options: Array<FilterOptions>;
} & (
options: FilterOptions;
} & (
| {
searchPlaceholder: string;
showAll?: never;
@ -24,15 +38,18 @@ export type FilterSectionProps = {
searchPlaceholder?: never;
showAll: true;
}
);
);
export default function FilterSection({
export default function FilterSection<
FilterOptions extends Array<FilterOption>,
>({
label,
options,
searchPlaceholder,
showAll,
onOptionChange,
}: FilterSectionProps) {
isSingleSelect,
}: FilterSectionProps<FilterOptions>) {
return (
<div className="mx-2">
<Collapsible defaultOpen={true} label={label}>
@ -46,6 +63,13 @@ export default function FilterSection({
startAddOnType="icon"
/>
)}
{isSingleSelect ? (
<RadioGroup
radioData={options}
onChange={(value) => {
onOptionChange(value);
}}></RadioGroup>
) : (
<div className="mx-1">
{options.map((option) => (
<Checkbox
@ -57,6 +81,7 @@ export default function FilterSection({
/>
))}
</div>
)}
</div>
</Collapsible>
</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<
Array<string>
>([]);
const [selectedQuestionAges, setSelectedQuestionAges] = useState<
Array<string>
>([]);
const [selectedQuestionAge, setSelectedQuestionAge] = useState<string>('all');
const [selectedLocations, setSelectedLocations] = useState<Array<string>>([]);
const [hasLanded, setHasLanded] = useState(false);
@ -46,9 +44,9 @@ export default function QuestionsHomePage() {
const questionAgeFilterOptions = useMemo(() => {
return QUESTION_AGES.map((questionAge) => ({
...questionAge,
checked: selectedQuestionAges.includes(questionAge.value),
checked: selectedQuestionAge === questionAge.value,
}));
}, [selectedQuestionAges]);
}, [selectedQuestionAge]);
const locationFilterOptions = useMemo(() => {
return LOCATIONS.map((location) => ({
@ -81,14 +79,14 @@ export default function QuestionsHomePage() {
if (router.isReady && !isSearchInitialized) {
setSelectedCompanies(paramToArray(router.query.companies));
setSelectedQuestionTypes(paramToArray(router.query.questionTypes));
setSelectedQuestionAges(paramToArray(router.query.questionAges));
setSelectedQuestionAge(router.query.questionAge as string);
setSelectedLocations(paramToArray(router.query.locations));
setIsSearchInitialized(true);
const hasFilter =
router.query.companies ||
router.query.questionTypes ||
router.query.questionAges ||
router.query.questionAge ||
router.query.locations;
if (hasFilter) {
setHasLanded(true);
@ -101,7 +99,7 @@ export default function QuestionsHomePage() {
hasLanded,
selectedCompanies,
selectedQuestionTypes,
selectedQuestionAges,
selectedQuestionAge,
selectedLocations,
]);
@ -113,7 +111,7 @@ export default function QuestionsHomePage() {
query: {
companies: selectedCompanies,
locations: selectedLocations,
questionAges: selectedQuestionAges,
questionAge: selectedQuestionAge,
questionTypes: selectedQuestionTypes,
},
},
@ -124,7 +122,7 @@ export default function QuestionsHomePage() {
}, [
selectedCompanies,
selectedQuestionTypes,
selectedQuestionAges,
selectedQuestionAge,
selectedLocations,
router,
router.isReady,
@ -168,17 +166,12 @@ export default function QuestionsHomePage() {
}}
/>
<FilterSection
isSingleSelect={true}
label="Question age"
options={questionAgeFilterOptions}
showAll={true}
onOptionChange={(optionValue, checked) => {
if (checked) {
setSelectedQuestionAges((prev) => [...prev, optionValue]);
} else {
setSelectedQuestionAges((prev) =>
prev.filter((questionAge) => questionAge !== optionValue),
);
}
onOptionChange={(optionValue) => {
setSelectedQuestionAge(optionValue);
}}
/>
<FilterSection

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

Loading…
Cancel
Save