113 lines
4.2 KiB
TypeScript
113 lines
4.2 KiB
TypeScript
import { useState } from 'react';
|
|
|
|
export default function ProfileProofPicker({
|
|
documents,
|
|
value,
|
|
onChange,
|
|
disabled = false,
|
|
}: {
|
|
documents: { id: string; file_name: string }[];
|
|
value: string[];
|
|
onChange: (ids: string[]) => void;
|
|
disabled?: boolean;
|
|
}) {
|
|
const [query, setQuery] = useState('');
|
|
const [showAll, setShowAll] = useState(false);
|
|
const [limit, setLimit] = useState(10);
|
|
const normalize = (text: string) =>
|
|
text
|
|
.normalize('NFD')
|
|
.replace(/\p{Diacritic}/gu, '')
|
|
.toLocaleLowerCase();
|
|
const matches = documents.filter((document) =>
|
|
normalize(document.file_name).includes(normalize(query)),
|
|
);
|
|
const toggle = (id: string) =>
|
|
onChange(
|
|
value.includes(id)
|
|
? value.filter((item) => item !== id)
|
|
: [...value, id],
|
|
);
|
|
return (
|
|
<fieldset disabled={disabled} className="space-y-3 rounded border p-4">
|
|
<legend>Escolher comprovativos</legend>
|
|
<p className="text-sm">
|
|
Escolha os seus documentos que sustentam este pedido. A lista
|
|
contém ficheiros próprios com análise antimalware concluída; não
|
|
confirma a sua adequação como comprovativo.
|
|
</p>
|
|
<p role="status">{value.length} comprovativos escolhidos</p>
|
|
{value.map((id) => (
|
|
<div
|
|
key={id}
|
|
className="flex items-start justify-between gap-3 rounded border p-2"
|
|
>
|
|
<span className="min-w-0 break-words">
|
|
{documents.find((document) => document.id === id)
|
|
?.file_name ??
|
|
'Ficheiro seleccionado indisponível nesta consulta'}
|
|
</span>
|
|
<button
|
|
type="button"
|
|
className="underline"
|
|
onClick={() => toggle(id)}
|
|
>
|
|
Retirar
|
|
</button>
|
|
</div>
|
|
))}
|
|
<label className="block">
|
|
Pesquisar nos meus ficheiros
|
|
<input
|
|
type="search"
|
|
className="mt-1 w-full rounded border p-2"
|
|
value={query}
|
|
onChange={(event) => {
|
|
setQuery(event.target.value);
|
|
setLimit(10);
|
|
}}
|
|
/>
|
|
</label>
|
|
<button
|
|
type="button"
|
|
className="underline"
|
|
onClick={() => setShowAll(!showAll)}
|
|
>
|
|
{showAll ? 'Fechar lista' : 'Ver ficheiros disponíveis'}
|
|
</button>
|
|
{(query || showAll) && (
|
|
<div className="space-y-2">
|
|
<p role="status">
|
|
{matches.length} ficheiros encontrados · a mostrar até{' '}
|
|
{Math.min(limit, matches.length)}
|
|
</p>
|
|
{matches.slice(0, limit).map((document) => (
|
|
<label
|
|
key={document.id}
|
|
className="flex gap-2 rounded border p-2"
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
checked={value.includes(document.id)}
|
|
onChange={() => toggle(document.id)}
|
|
/>
|
|
<span className="min-w-0 break-words">
|
|
{document.file_name}
|
|
</span>
|
|
</label>
|
|
))}
|
|
{matches.length > limit && (
|
|
<button
|
|
type="button"
|
|
className="underline"
|
|
onClick={() => setLimit(limit + 10)}
|
|
>
|
|
Mostrar mais ficheiros
|
|
</button>
|
|
)}
|
|
</div>
|
|
)}
|
|
</fieldset>
|
|
);
|
|
}
|