skilld-frontend/src/components/geolocation.tsx

162 lines
4.1 KiB
TypeScript

"use client";
import { CaretSortIcon, CheckIcon } from "@radix-ui/react-icons";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { FC, useEffect, useState } from "react";
import Geonames from "geonames.js";
import { FormControl } from "./ui/form";
const frameworks = [
{
value: "next.js",
label: "Next.js",
},
{
value: "sveltekit",
label: "SvelteKit",
},
{
value: "nuxt.js",
label: "Nuxt.js",
},
{
value: "remix",
label: "Remix",
},
{
value: "astro",
label: "Astro",
},
];
// @ts-ignore
const geonames = new Geonames({
username: "thalesandrade",
lan: "en",
encoding: "JSON",
});
interface Props {
geoId: number | null;
onChange: (country: string, geoId: number) => void;
isCountry: boolean;
placeholderText: string;
searchPlaceholder: string;
emptyPlaceholder: string;
isDisabled: boolean;
}
const Geolocation: FC<Props> = ({
geoId,
onChange,
isCountry,
placeholderText,
searchPlaceholder,
emptyPlaceholder,
isDisabled,
}) => {
const [open, setOpen] = useState(false);
const [currentValue, setCurrentValue] = useState<null | number>(null);
const [options, setOptions] = useState<
{ countryName: string; geonameId: number; name: string }[]
>([]);
useEffect(() => {
try {
const data = () => {
isCountry
? geonames.countryInfo({}).then((res: any) => {
console.log(res);
setOptions(res.geonames);
})
: geonames.children({ geonameId: geoId }).then((res: any) => {
if (res.totalResultsCount) setOptions(res.geonames);
});
};
data();
} catch (err) {
console.error(err);
}
}, [geoId, isCountry]);
const currentPlaceholderText =
currentValue && isCountry
? options.find((option: any) => option.geonameId === currentValue)
?.countryName
: currentValue
? options.find((option: any) => option.geonameId === currentValue)?.name
: placeholderText;
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild disabled={isDisabled}>
<FormControl>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-full justify-between"
>
{currentPlaceholderText}
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[200px] md:w-[400px] p-0">
<Command>
<CommandList>
<CommandInput placeholder={searchPlaceholder} className="h-9" />
<CommandEmpty>{emptyPlaceholder}</CommandEmpty>
<CommandGroup>
{options.map((v: any, index) => (
<CommandItem
key={index}
value={v.geonameId}
onSelect={() => {
setCurrentValue(
v.geonameId === currentValue ? null : v.geonameId,
);
const name = isCountry ? v.countryName : v.name;
onChange(
v.geonameId === currentValue ? "" : name,
v.geonameId === currentValue ? null : v.geonameId,
);
setOpen(false);
}}
>
{isCountry ? v.countryName : v.name}
<CheckIcon
className={cn(
"ml-auto h-4 w-4",
currentValue === v.geonameId
? "opacity-100"
: "opacity-0",
)}
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
};
export default Geolocation;