Files
Investidor-V2/resources/js/pages/desk/install.tsx
T
nala 6ddafc95ba
tests / ci (push) Canceled after 0s
oportunidades 4
2026-10-10 07:03:59 +02:00

221 lines
8.6 KiB
TypeScript

import { Link, useForm } from '@inertiajs/react';
import { Frame, card, button, input } from '@/pages/investment/shared';
export default function Install({
hash,
installed,
backupVerified,
qaVerified,
changes,
target,
pendingMigrations,
compatibilityVerified,
backupDate,
scanner,
rollback,
databaseReady,
baseDeskInstalled,
pathInstalled,
pathEnabled,
pathQaVerified,
}: {
hash: string;
installed: boolean;
backupVerified: boolean;
qaVerified: boolean;
changes: string[];
target: { database: string; port: number };
pendingMigrations: string[];
compatibilityVerified: boolean;
backupDate: string | null;
scanner: { available: boolean; reason_code: string | null };
rollback: string;
databaseReady: boolean;
baseDeskInstalled: boolean;
pathInstalled: boolean;
pathEnabled: boolean;
pathQaVerified: boolean;
}) {
const form = useForm({ hash, confirm: false });
const service = useForm({ code: 'project-preparation', confirm: false });
return (
<Frame title="Instalação autenticada do Balcão e acompanhamento">
<Link href="/balcao-virtual" className="mr-4 underline">
Voltar ao Balcão
</Link>
<Link href="/management/balcao/fontes" className="underline">
Consultar inventário privado e exemplares de formulários
</Link>
<section className={card}>
<p>
Destino: {target.database}, porta {target.port}.
Backup/restauro: {backupDate ?? 'Pendente'}.
</p>
<h2 className="mt-3 text-lg font-semibold">
Alterações de esquema ainda necessárias
</h2>
<ul>
{pendingMigrations.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
<p>
Balcão existente:{' '}
{baseDeskInstalled ? 'Instalado' : 'Pendente'}. Apenas as
migrations ausentes serão executadas; nenhuma instalação já
registada será repetida.
</p>
<p>
Extensão do percurso:{' '}
{pathInstalled ? 'Instalada' : 'Pendente'}.
Disponibilização:{' '}
{pathEnabled ? 'Configurada' : 'Desativada'}. Instalar não
disponibiliza o percurso, não converte dossiers antigos nem
apaga dados ou publica serviços.
</p>
<ul>
{changes.map((c) => (
<li key={c}>{c}</li>
))}
</ul>
<p>
Backup/restauro verificado:{' '}
{backupVerified ? 'Sim' : 'Pendente'} · QA desta versão:{' '}
{qaVerified ? 'Sim' : 'Pendente'}.
</p>
<p>
Compatibilidade e reversão em cópia restaurada:{' '}
{compatibilityVerified ? 'Verificadas' : 'Pendentes'}.
</p>
<p>
Percursos A/B completos na interface desta versão:{' '}
{pathQaVerified
? 'Demonstrados'
: 'Pendentes — API ou build não substituem a demonstração visual'}
.
</p>
<p>
Permissões da conexão para criar o esquema e estender
tarefas:{' '}
{databaseReady
? 'Disponíveis'
: 'Insuficientes — intervenção autorizada necessária'}
.
</p>
<p>
ClamD real:{' '}
{scanner.available
? 'Disponível'
: `Indisponível (${scanner.reason_code ?? 'sem evidência'})`}
. Ficheiros sem scan conclusivo continuam pendentes para
utilização segura; guardar rascunhos e preparar pedidos
mantém-se disponível.
</p>
<p>{rollback}</p>
<p>
Confirmação inclui o restauro isolado da base e a
integridade dos ficheiros privados. O histórico e os pedidos
existentes são preservados.
</p>
</section>
{!installed && (
<form
onSubmit={(e) => {
e.preventDefault();
form.post('/management/balcao-install');
}}
>
<label className="flex gap-2">
<input
type="checkbox"
checked={form.data.confirm}
onChange={(e) =>
form.setData('confirm', e.target.checked)
}
/>
Confirmo aplicar exactamente as alterações
pré-visualizadas.
</label>
<button
className={button}
disabled={
form.processing ||
!form.data.confirm ||
!backupVerified ||
!qaVerified ||
!compatibilityVerified ||
!pathQaVerified ||
!databaseReady
}
>
Aplicar instalação autenticada
</button>
{Object.entries(form.errors).map(([k, v]) => (
<p role="alert" key={k}>
{v}
</p>
))}
</form>
)}
{baseDeskInstalled && (
<form
className={card + ' space-y-3'}
onSubmit={(e) => {
e.preventDefault();
service.post('/management/balcao/servicos');
}}
>
<h2 className="text-xl font-bold">
Publicar serviço de preparação interna
</h2>
<p>
Publicação do catálogo é uma acção separada; não submete
pedidos nem homologa um formulário oficial.
</p>
<label>
Serviço
<select
className={input}
value={service.data.code}
onChange={(e) =>
service.setData('code', e.target.value)
}
>
<option value="project-preparation">
Preparação de projecto
</option>
<option value="project-change">
Alteração de projecto
</option>
<option value="project-follow-up">
Acompanhamento de investimento
</option>
</select>
</label>
<label className="flex gap-2">
<input
type="checkbox"
checked={service.data.confirm}
onChange={(e) =>
service.setData('confirm', e.target.checked)
}
/>
Confirmo disponibilizar este serviço de preparação
interna.
</label>
<button
className={button}
disabled={service.processing || !service.data.confirm}
>
Publicar este serviço
</button>
{Object.entries(service.errors).map(([k, v]) => (
<p role="alert" key={k}>
{v}
</p>
))}
</form>
)}
</Frame>
);
}