Files
Investidor-V2/resources/js/components/country-select.tsx
T
2026-11-02 20:31:15 +02:00

100 lines
3.2 KiB
TypeScript

import { useId, useState } from 'react';
export type Country = { code: string; name: string; name_en: string };
export default function CountrySelect({
countries,
value,
onChange,
id,
disabled = false,
label = 'País',
required = false,
allowLegacyValue = false,
error,
}: {
countries: Country[];
value: string;
onChange: (value: string) => void;
id?: string;
disabled?: boolean;
label?: string;
required?: boolean;
allowLegacyValue?: boolean;
error?: string;
}) {
const generatedId = useId();
const [search, setSearch] = useState('');
const matches = countries.filter(
(country) =>
country.code === value ||
`${country.name} ${country.name_en} ${country.code}`
.normalize('NFD')
.replace(/\p{Diacritic}/gu, '')
.toLowerCase()
.includes(
search
.normalize('NFD')
.replace(/\p{Diacritic}/gu, '')
.toLowerCase(),
),
);
return (
<div className="space-y-2">
<input
disabled={disabled}
className="w-full rounded border p-2"
aria-label={`Pesquisar ${label.toLowerCase()}`}
maxLength={100}
value={search}
onChange={(event) => setSearch(event.target.value)}
placeholder="Pesquisar nome ou código do país"
/>
{search.trim() && (
<p role="status" aria-live="polite">
Países:{' '}
{matches.length
? `${matches.length} opções disponíveis`
: 'Nenhuma opção encontrada'}
</p>
)}
<select
disabled={disabled}
id={id ?? generatedId}
aria-label={label}
aria-invalid={!!error}
aria-describedby={
error ? (id ?? generatedId) + '-error' : undefined
}
required={required}
className="w-full rounded border p-2"
value={value}
onChange={(event) => onChange(event.target.value)}
>
<option value="">Não informado</option>
{allowLegacyValue &&
value &&
!countries.some((country) => country.code === value) && (
<option value={value}>
{value} (valor anterior conservado)
</option>
)}
{matches.map((country) => (
<option key={country.code} value={country.code}>
{country.name} ({country.code})
</option>
))}
</select>
{error && (
<p
id={(id ?? generatedId) + '-error'}
role="alert"
className="text-red-700"
>
{error}
</p>
)}
</div>
);
}