import { createOperationKey } from '@/lib/operation-key'; import { useState } from 'react'; import { Management, button, control } from '@/pages/management/shared'; import { profileJson } from '@/lib/profile-json'; type Plan = { installed: boolean; consistent: boolean; ready: boolean; target: { database: string; port: number }; hash: string; dependencies: Record; changes: string[]; backupDate: string | null; rollback: string; bootstrap: { initialized: boolean; holders: number[]; version: number | null; rule: string; pending: {approval_id:string;confirmation_url:string;expires_at:string} | null; }; }; export default function Installation(initial: Plan) { const [plan, setPlan] = useState(initial); const [reason, setReason] = useState(''); const [confirmed, setConfirmed] = useState(false); const [first, setFirst] = useState(''); const [second, setSecond] = useState(''); const [busy, setBusy] = useState(false); const [message, setMessage] = useState(''); const [confirmationUrl, setConfirmationUrl] = useState(null); const [installationKey] = useState(createOperationKey); const [bootstrapKey] = useState(createOperationKey); async function run(bootstrap = false) { setBusy(true); setMessage(''); try { const result = await profileJson( '/management/profile-install' + (bootstrap ? '/bootstrap' : ''), { hash: plan.hash, confirm: confirmed, reason, idempotency_key: bootstrap ? bootstrapKey : installationKey, ...(bootstrap ? { first_user_id: Number(first), second_user_id: Number(second), } : {}), }, ); setMessage( bootstrap ? 'Pedido registado, sem atribuir privilégios. O segundo titular deve autenticar-se com MFA e confirmar pelo endereço abaixo.' : result.changed ? 'Schema instalado. Perfis ainda não disponibilizados; nenhuma conta ou atribuição criada.' : 'Schema já instalado. Nenhuma reinstalação ou duplicação.', ); if (bootstrap) setConfirmationUrl(result.confirmation_url as string); if (!bootstrap) setPlan( (await profileJson( '/management/profile-install', {}, 'GET', )) as Plan, ); setConfirmed(false); } catch (error) { setMessage( error instanceof Error ? error.message : 'Resposta indisponível; consulte o estado antes de repetir.', ); } finally { setBusy(false); } } return (

Base {plan.target.database}:{plan.target.port} ·{' '} {plan.installed ? 'Schema instalado' : 'Schema por instalar'}

Preparação:{' '} {plan.ready ? 'Provas atuais verificadas' : 'Dependências ou provas por completar'} . Preparação não significa instalação ou disponibilização dos perfis.

{!plan.consistent && (

Ledger e schema divergem. Recuperar a consistência antes de instalar.

)}
    {Object.entries(plan.dependencies).map(([key, ok]) => (
  • {key}: {ok ? 'presente' : 'pendente'}
  • ))}
    {plan.changes.map((c) => (
  • {c}
  • ))}

Backup/restauro: {plan.backupDate ?? 'Prova atual pendente'}

{plan.rollback}