Files
Investidor-V2/resources/js/pages/profiles/request.tsx
T
nala 01405cbf8a
tests / ci (push) Canceled after 0s
oportunidades 5
2026-10-10 14:15:28 +02:00

49 lines
4.3 KiB
TypeScript

import { Head, Link, router } from '@inertiajs/react';
import { useState } from 'react';
import ProfileNavigation from '@/components/profile-navigation';
import { profileJson } from '@/lib/profile-json';
import { button, control } from '@/pages/management/shared';
type RequestEntry = { id: string; status: string; reason: string; decision_reason: string | null; created_at: string };
export default function RequestProfile({ requests, types, organizations, documents }: {
requests: RequestEntry[]; types: string[]; organizations: {id: string; name: string}[]; documents: {id: string; file_name: string}[];
}) {
const [representation, setRepresentation] = useState('individual');
const [organization, setOrganization] = useState('');
const [selected, setSelected] = useState<string[]>([]);
const [proofs, setProofs] = useState<string[]>([]);
const [reason, setReason] = useState('');
const [key, setKey] = useState(() => crypto.randomUUID());
const [message, setMessage] = useState('');
const [busy, setBusy] = useState(false);
async function send() {
setBusy(true); setMessage('');
try {
const result = await profileJson('/perfil/promotor', { creation_key: key, representation_type: representation, organization_id: representation === 'individual' ? null : organization,
opportunity_types: selected, document_ids: proofs, reason });
setMessage(result.message); setKey(crypto.randomUUID()); router.reload();
} catch (error) { setMessage(error instanceof Error ? error.message : 'Resposta indisponível. Confira o acompanhamento antes de repetir.'); }
finally { setBusy(false); }
}
const toggle = (values: string[], id: string) => values.includes(id) ? values.filter(v => v !== id) : [...values, id];
return <main className="space-y-6 p-6"><Head title="Perfil de Promotor" /><ProfileNavigation />
<h1 className="text-2xl font-semibold">Solicitar perfil de Promotor</h1>
<p>A aprovação confirma identidade, representação e comprovativos. Só os tipos aprovados ficam disponíveis; o pedido não ativa o perfil.</p>
<form className="max-w-2xl space-y-4" onSubmit={e => { e.preventDefault(); void send(); }}>
<label className="block">Representação<select className={control} value={representation} onChange={e => setRepresentation(e.target.value)}>
{['individual','company','public_entity','association','partner'].map(v => <option key={v}>{v}</option>)}
</select></label>
{representation !== 'individual' && <label className="block">Organização representada<select required className={control} value={organization} onChange={e => setOrganization(e.target.value)}>
<option value="">Selecionar</option>{organizations.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}
</select></label>}
<fieldset><legend>Tipos pretendidos</legend>{types.map(type => <label key={type} className="block"><input type="checkbox" checked={selected.includes(type)} onChange={() => setSelected(toggle(selected,type))} /> {type}</label>)}</fieldset>
<fieldset><legend>Comprovativos próprios analisados</legend>{documents.map(d => <label key={d.id} className="block"><input type="checkbox" checked={proofs.includes(d.id)} onChange={() => setProofs(toggle(proofs,d.id))} /> {d.file_name}</label>)}</fieldset>
{!documents.length && <p>Sem comprovativos próprios disponíveis. Pode anexar ao seu dossier no <Link className="underline" href="/balcao-virtual/painel">Balcão</Link>; o ficheiro precisa de análise antimalware concluída.</p>}
<label className="block">Fundamentação<textarea required minLength={20} maxLength={1000} className={control} value={reason} onChange={e => setReason(e.target.value)} /></label>
<button disabled={busy} className={button}>Submeter pedido de perfil</button>
</form>
<p role="status" aria-live="polite">{message}</p>
<section><h2 className="text-xl font-semibold">Acompanhamento dos meus pedidos</h2>{requests.map(r => <article key={r.id} className="border-b py-3"><p>{r.id} — {r.status}</p><p>{r.decision_reason ?? 'Aguarda revisão independente.'}</p></article>)}{!requests.length && <p>Nenhum pedido recebido.</p>}</section>
</main>;
}