Files
Investidor-V2/resources/js/pages/profiles/request.tsx
T
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

196 lines
7.4 KiB
TypeScript

import { createOperationKey } from '@/lib/operation-key';
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(() => createOperationKey());
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(createOperationKey());
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>
);
}