feat: add emergency backup restoration page for new installs

This commit is contained in:
Erik
2026-03-07 22:58:01 -03:00
parent febe5437ff
commit 75e1977fe5

View File

@@ -0,0 +1,91 @@
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
export default function EmergencyBackupPage() {
const [file, setFile] = useState<File | null>(null);
const [status, setStatus] = useState<'idle' | 'uploading' | 'success' | 'error'>('idle');
const [message, setMessage] = useState('');
const router = useRouter();
const handleUpload = async () => {
if (!file) return;
setStatus('uploading');
setMessage('Restaurando sistema de emergência... Por favor, aguarde.');
const formData = new FormData();
formData.append('file', file);
try {
const res = await fetch('/api/admin/backup/full', {
method: 'POST',
body: formData,
});
if (res.ok) {
setStatus('success');
setMessage('Sistema restaurado com sucesso! Redirecionando para o login...');
setTimeout(() => router.push('/admin/login'), 3000);
} else {
const errorData = await res.json();
setStatus('error');
setMessage(errorData.error || 'Erro ao restaurar backup.');
}
} catch (err) {
setStatus('error');
setMessage('Erro de conexão ao restaurar backup.');
}
};
return (
<div className="min-h-screen bg-slate-900 flex items-center justify-center p-4">
<div className="max-w-md w-full bg-slate-800 rounded-2xl shadow-2xl p-8 border border-white/10">
<h1 className="text-2xl font-bold text-white mb-2">🔑 Chave Mestra de Restauração</h1>
<p className="text-slate-400 mb-8">Use esta página para restaurar seu backup ZIP em um banco de dados novo.</p>
<div className="space-y-6">
<div className="border-2 border-dashed border-slate-600 rounded-xl p-8 text-center hover:border-blue-500 transition-colors cursor-pointer relative">
<input
type="file"
accept=".zip"
className="absolute inset-0 opacity-0 cursor-pointer"
onChange={(e) => setFile(e.target.files?.[0] || null)}
/>
<div className="text-slate-300">
{file ? (
<span className="text-blue-400 font-medium">{file.name}</span>
) : (
'Clique ou arraste o arquivo .zip de backup aqui'
)}
</div>
</div>
<button
onClick={handleUpload}
disabled={!file || status === 'uploading'}
className="w-full bg-blue-600 hover:bg-blue-500 disabled:bg-slate-700 text-white font-bold py-4 rounded-xl transition-all shadow-lg flex items-center justify-center gap-3"
>
{status === 'uploading' ? (
<>
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin"></div>
Restaurando...
</>
) : (
'Restaurar Sistema Agora'
)}
</button>
{message && (
<div className={`p-4 rounded-lg text-center text-sm font-medium ${status === 'success' ? 'bg-emerald-500/20 text-emerald-400 border border-emerald-500/30' :
status === 'error' ? 'bg-rose-500/20 text-rose-400 border border-rose-500/30' :
'bg-blue-500/10 text-blue-400 border border-blue-500/20'
}`}>
{message}
</div>
)}
</div>
</div>
</div>
);
}