113 lines
3.8 KiB
TypeScript
113 lines
3.8 KiB
TypeScript
import { useState } from 'react';
|
|
import { api } from '@/pages/investment/shared';
|
|
|
|
export type ParkInstallationPlan = {
|
|
installed: boolean;
|
|
ready: boolean;
|
|
hash: string;
|
|
migration: string;
|
|
reasons: string[];
|
|
target: { database: string; port: number };
|
|
};
|
|
export default function InvestmentZoneInstallation({
|
|
initial,
|
|
endpoint = '/management/investment/zones/profile-install',
|
|
title = 'Preparação privada da ficha de parques',
|
|
summary = 'Uma coluna privada; sem importação ou publicação de dados.',
|
|
}: {
|
|
initial: ParkInstallationPlan;
|
|
endpoint?: string;
|
|
title?: string;
|
|
summary?: string;
|
|
}) {
|
|
const [plan, setPlan] = useState(initial);
|
|
const [busy, setBusy] = useState(false);
|
|
const [message, setMessage] = useState('');
|
|
async function refresh() {
|
|
const response = await fetch(endpoint, {
|
|
headers: { Accept: 'application/json' },
|
|
});
|
|
if (!response.ok)
|
|
throw new Error(
|
|
'Não foi possível carregar a prévia da instalação.',
|
|
);
|
|
const value = await response.json();
|
|
setPlan(value.plan);
|
|
return value.plan as ParkInstallationPlan;
|
|
}
|
|
return (
|
|
<section
|
|
className="space-y-3 rounded border p-4"
|
|
aria-label="Instalação da ficha de parques"
|
|
>
|
|
<h2 className="font-semibold">{title}</h2>
|
|
<p>
|
|
{plan.installed
|
|
? 'Esquema instalado. Não importa nem publica fichas.'
|
|
: summary}
|
|
</p>
|
|
<p>
|
|
Alvo: {plan.target.database}:{plan.target.port} ·{' '}
|
|
{plan.migration}
|
|
</p>
|
|
{plan.reasons.map((reason) => (
|
|
<p key={reason} role="status">
|
|
{reason}
|
|
</p>
|
|
))}
|
|
<button
|
|
type="button"
|
|
className="rounded border p-2"
|
|
disabled={busy}
|
|
onClick={async () => {
|
|
setBusy(true);
|
|
try {
|
|
await refresh();
|
|
setMessage('Prévia atualizada, sem escrita.');
|
|
} catch (e) {
|
|
setMessage(
|
|
e instanceof Error
|
|
? e.message
|
|
: 'Falha ao carregar.',
|
|
);
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}}
|
|
>
|
|
Atualizar prévia
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="rounded border p-2"
|
|
disabled={busy || !plan.ready || plan.installed}
|
|
onClick={async () => {
|
|
setBusy(true);
|
|
try {
|
|
await api(endpoint, {
|
|
hash: plan.hash,
|
|
idempotency_key: crypto.randomUUID(),
|
|
confirm: true,
|
|
});
|
|
await refresh();
|
|
setMessage(
|
|
'Instalação nominal verificada; nenhuma ficha publicada.',
|
|
);
|
|
} catch (e) {
|
|
setMessage(
|
|
e instanceof Error
|
|
? e.message
|
|
: 'Falha ao instalar.',
|
|
);
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}}
|
|
>
|
|
Instalar apenas o esquema indicado
|
|
</button>
|
|
{message && <p role="alert">{message}</p>}
|
|
</section>
|
|
);
|
|
}
|