Files
Investidor-V2/tools/portal-internal-designation-ui.tsx
T
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

74 lines
6.6 KiB
TypeScript

type OperatorOrganization = { id: string; name: string; nuit: string; contact: string; director: string };
function OperatorOrganizationForm() {
const [operationKey] = useState(createOperationKey);
const [name, setName] = useState('Tempo Lda');
const [nuit, setNuit] = useState('400993114');
const [contact, setContact] = useState('+258868010880');
const [director, setDirector] = useState('Osmane Nala');
const [source, setSource] = useState('Dados e designação interna confirmados pelo responsável da Tempo em 11/10/2026.');
const [busy, setBusy] = useState(false);
const [message, setMessage] = useState('');
async function save() {
setBusy(true);
try {
const result = await profileJson('/perfis/organizacao-operadora', { operation_key: operationKey, name, nuit, contact, director, function: 'portal_owner_operator', source_reference: source });
setMessage(result.message); router.reload();
} catch (error) { setMessage(error instanceof Error ? error.message : 'Resposta indisponível.'); }
finally { setBusy(false); }
}
return <section className="space-y-3" aria-label="Organização operadora">
<h2 className="text-xl font-semibold">Organização proprietária e operadora</h2>
<p>Reutiliza o cadastro mestre e conserva o histórico. Estes dados não atribuem representação empresarial nem papéis às contas.</p>
<form className="max-w-2xl space-y-3" onSubmit={e => { e.preventDefault(); void save(); }}>
<label className="block">Denominação<input required className={control} value={name} onChange={e => setName(e.target.value)} /></label>
<label className="block">NUIT<input required className={control} value={nuit} onChange={e => setNuit(e.target.value)} pattern="[0-9]{9}" /></label>
<label className="block">Contacto<input required type="tel" className={control} value={contact} onChange={e => setContact(e.target.value)} /></label>
<label className="block">Director Geral<input required className={control} value={director} onChange={e => setDirector(e.target.value)} /></label>
<label className="block">Origem dos dados<textarea required minLength={20} maxLength={1000} className={control} value={source} onChange={e => setSource(e.target.value)} /></label>
<button className={button} disabled={busy}>Guardar organização operadora</button>
<p role="status">{message}</p>
</form>
</section>;
}
function InternalStaffGrant({ types, organizations, operators }: { types: string[]; organizations: { id: string; name: string }[]; operators: OperatorOrganization[] }) {
const [operationKey, setOperationKey] = useState(createOperationKey);
const [subject, setSubject] = useState('');
const [role, setRole] = useState('promoter');
const [operator, setOperator] = useState('');
const [scope, setScope] = useState('');
const [selected, setSelected] = useState<string[]>([]);
const [confirmed, setConfirmed] = useState(false);
const [reason, setReason] = useState('');
const [busy, setBusy] = useState(false);
const [message, setMessage] = useState('');
async function save() {
setBusy(true);
try {
await profileJson('/perfis/atribuicoes', { internal_designation: true, operation_key: operationKey,
user_id: Number(subject), role, operator_organization_id: operator,
organization_id: role === 'promoter' ? operator : scope || null,
opportunity_types: selected, responsibilities: [], reason, confirmed_internal_designation: confirmed });
setMessage('Designação interna atribuída e auditada.'); router.reload();
} catch (error) { setMessage(error instanceof Error ? error.message : 'Resposta indisponível.'); }
finally { setBusy(false); }
}
return <section className="space-y-3" aria-label="Designação interna">
<h2 className="text-xl font-semibold">Atribuir função interna do portal</h2>
<p>A proprietária define as funções da sua equipa. Esta atribuição não exige comprovativos de Promotor externo nem concede gestão empresarial. Cada oportunidade conserva o promotor real e a autorização de divulgação.</p>
<form className="max-w-2xl space-y-3" onSubmit={e => { e.preventDefault(); void save(); }}>
<label className="block">Conta da pessoa designada<input required type="number" min={1} className={control} value={subject} onChange={e => setSubject(e.target.value)} /></label>
<label className="block">Função interna<select required className={control} value={role} onChange={e => setRole(e.target.value)}>{['promoter', 'validator', 'publisher'].map(v => <option key={v} value={v}>{v}</option>)}</select></label>
<label className="block">Vínculo à organização operadora<select required className={control} value={operator} onChange={e => setOperator(e.target.value)}><option value="">Selecionar organização</option>{operators.map(o => <option key={o.id} value={o.id}>{o.name} — NUIT {o.nuit}</option>)}</select></label>
{role !== 'promoter' && <label className="block">Âmbito da função interna<select className={control} value={scope} onChange={e => setScope(e.target.value)}><option value="">Todas as organizações para as categorias selecionadas</option>{organizations.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}</select></label>}
<fieldset><legend>Categorias da função interna</legend>{types.map(v => <label className="block" key={v}><input type="checkbox" checked={selected.includes(v)} onChange={() => setSelected(old => old.includes(v) ? old.filter(x => x !== v) : [...old, v])} /> {v}</label>)}</fieldset>
<label className="block"><input type="checkbox" required checked={confirmed} onChange={e => setConfirmed(e.target.checked)} /> Confirmo a designação interna expressa pelo responsável da organização operadora.</label>
<label className="block">Fundamento da designação interna<textarea required minLength={20} maxLength={1000} className={control} value={reason} onChange={e => setReason(e.target.value)} /></label>
<button className={button} disabled={busy}>Atribuir função interna com auditoria</button>
<button type="button" className={button} disabled={busy} onClick={() => { setOperationKey(createOperationKey()); setSubject(''); setConfirmed(false); setMessage('Nova atribuição preparada.'); }}>Preparar outra atribuição</button>
<p role="status">{message}</p>
</form>
</section>;
}