Improved the Country selector

This commit is contained in:
Tiago Ribeiro
2023-09-19 21:58:03 +01:00
parent 395afbb4ee
commit 0ca2649040
5 changed files with 84 additions and 32 deletions

View File

@@ -9,6 +9,7 @@ import {BsArrowRepeat} from "react-icons/bs";
import axios from "axios";
import {toast} from "react-toastify";
import {KeyedMutator} from "swr";
import CountrySelect from "./Low/CountrySelect";
interface Props {
mutateUser: KeyedMutator<User>;
@@ -54,22 +55,7 @@ export default function DemographicInformationInput({mutateUser}: Props) {
<form className="flex flex-col items-center justify-items-center gap-6 w-full h-full -lg:px-8 lg:w-1/2 mb-32" onSubmit={save}>
<div className="relative flex flex-col gap-3 w-full">
<label className="font-normal text-base text-mti-gray-dim">Country *</label>
<select
name="country"
className="px-8 py-6 text-sm font-normal placeholder:text-mti-gray-cool bg-white rounded-full border border-mti-gray-platinum focus:outline-none"
onChange={(e) => {
setCountry(e.target.value);
}}
defaultValue={country}>
<option value={undefined} disabled selected>
Select a country
</option>
{countryCodes.all().map((x) => (
<option key={x.countryCode} value={x.countryCode}>
{x.flag} {x.countryNameLocal}
</option>
))}
</select>
<CountrySelect value={country} onChange={setCountry} />
</div>
<Input type="tel" name="phone" label="Phone number" onChange={(e) => setPhone(e)} placeholder="Enter phone number" required />
<div className="relative flex flex-col gap-3 w-full">

View File

@@ -0,0 +1,73 @@
import {countries, TCountries} from "countries-list";
import {Fragment, useState} from "react";
import {Combobox, Transition} from "@headlessui/react";
import {BsChevronExpand} from "react-icons/bs";
interface Props {
value?: string;
onChange: (value: string) => void;
}
const mapCountries = (codes: string[]) => {
return codes.map((code) => ({
label: countries[code as unknown as keyof TCountries].name,
code,
}));
};
export default function CountrySelect({value, onChange}: Props) {
const [query, setQuery] = useState("");
const filteredCountries =
query === ""
? mapCountries(Object.keys(countries))
: mapCountries(
Object.keys(countries).filter((x) =>
countries[x as unknown as keyof TCountries].name.toLowerCase().includes(query.toLowerCase()),
),
);
return (
<>
<Combobox value={value} onChange={onChange}>
<div className="relative mt-1">
<div className="relative w-full cursor-default overflow-hidden ">
<Combobox.Input
className="py-6 w-full px-8 text-sm font-normal placeholder:text-mti-gray-cool bg-white rounded-full border border-mti-gray-platinum focus:outline-none"
onChange={(e) => setQuery(e.target.value)}
displayValue={(code: string) => countries[code as unknown as keyof TCountries].name}
/>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-8">
<BsChevronExpand />
</Combobox.Button>
</div>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
afterLeave={() => setQuery("")}>
<Combobox.Options className="absolute z-20 mt-1 max-h-60 w-full overflow-auto rounded-xl bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{filteredCountries.length === 0 && query !== "" ? (
<div className="relative cursor-default select-none py-2 px-4 text-gray-700">Nothing found.</div>
) : (
filteredCountries.map((country) => (
<Combobox.Option
key={country.code}
value={country.code}
className={({active}) =>
`relative cursor-default select-none py-2 pl-10 pr-4 ${
active ? "bg-mti-purple-light text-white" : "text-gray-900"
}`
}>
{country.label}
</Combobox.Option>
))
)}
</Combobox.Options>
</Transition>
</div>
</Combobox>
</>
);
}

View File

@@ -15,6 +15,8 @@ import {RadioGroup} from "@headlessui/react";
import clsx from "clsx";
import {EmploymentStatus, EMPLOYMENT_STATUS, Gender, User} from "@/interfaces/user";
import countryCodes from "country-codes-list";
import {countries, TCountries} from "countries-list";
import CountrySelect from "@/components/Low/CountrySelect";
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
@@ -186,22 +188,7 @@ export default function Home() {
<div className="flex flex-row gap-8 w-full">
<div className="flex flex-col gap-3 w-full">
<label className="font-normal text-base text-mti-gray-dim">Country *</label>
<select
name="country"
className="py-6 w-full px-8 text-sm font-normal placeholder:text-mti-gray-cool bg-white rounded-full border border-mti-gray-platinum focus:outline-none"
onChange={(e) => {
setCountry(e.target.value);
}}
value={country}>
<option value={undefined} disabled selected>
Select a country
</option>
{countryCodes.all().map((x) => (
<option key={x.countryCode} value={x.countryCode}>
{x.flag} {x.countryNameLocal}
</option>
))}
</select>
<CountrySelect value={country} onChange={setCountry} />
</div>
<Input
type="tel"