feat: add restore functionality to backup manager
This commit is contained in:
@@ -21,6 +21,7 @@ interface BackupsListResponse {
|
||||
|
||||
export function BackupManager() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [restoreLoading, setRestoreLoading] = useState<string | null>(null);
|
||||
const [backups, setBackups] = useState<BackupInfo[]>([]);
|
||||
const [listLoading, setListLoading] = useState(true);
|
||||
const { success, error: showError } = useToast();
|
||||
@@ -33,12 +34,9 @@ export function BackupManager() {
|
||||
const fetchBackups = async () => {
|
||||
try {
|
||||
setListLoading(true);
|
||||
const token = localStorage.getItem('auth_token') || '';
|
||||
|
||||
const response = await fetch('/api/backup', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
@@ -57,12 +55,10 @@ export function BackupManager() {
|
||||
const createBackup = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const token = localStorage.getItem('auth_token') || '';
|
||||
|
||||
const response = await fetch('/api/backup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
@@ -90,13 +86,8 @@ export function BackupManager() {
|
||||
}
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('auth_token') || '';
|
||||
|
||||
const response = await fetch(`/api/backup?id=${backupId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
@@ -114,13 +105,7 @@ export function BackupManager() {
|
||||
|
||||
const downloadBackup = async (filename: string) => {
|
||||
try {
|
||||
const token = localStorage.getItem('auth_token') || '';
|
||||
|
||||
const response = await fetch(`/api/backup/download?file=${filename}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
const response = await fetch(`/api/backup/download?file=${filename}`);
|
||||
|
||||
if (response.ok) {
|
||||
const blob = await response.blob();
|
||||
@@ -140,6 +125,32 @@ export function BackupManager() {
|
||||
}
|
||||
};
|
||||
|
||||
const restoreBackup = async (filename: string) => {
|
||||
if (!window.confirm('⚠️ AVISO: A restauração substituirá todo o banco de dados!\n\nTem certeza que deseja restaurar este backup?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setRestoreLoading(filename);
|
||||
|
||||
const response = await fetch(`/api/backup/restore?file=${filename}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
success('Backup restaurado com sucesso! Por favor, recarregue a página.');
|
||||
} else {
|
||||
showError(data.error || 'Erro ao restaurar backup');
|
||||
}
|
||||
} catch (err) {
|
||||
showError('Erro ao restaurar backup: ' + (err as Error).message);
|
||||
} finally {
|
||||
setRestoreLoading(null);
|
||||
}
|
||||
};
|
||||
|
||||
const formatSize = (bytes: number) => {
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
@@ -236,6 +247,18 @@ export function BackupManager() {
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<button
|
||||
onClick={() => restoreBackup(backup.filename)}
|
||||
disabled={restoreLoading === backup.filename}
|
||||
title="Restaurar backup"
|
||||
className="p-2 hover:bg-amber-100 dark:hover:bg-amber-900/20 rounded-lg transition-colors text-amber-600 dark:text-amber-400 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{restoreLoading === backup.filename ? (
|
||||
<i className="ri-loader-4-line animate-spin text-xl"></i>
|
||||
) : (
|
||||
<i className="ri-restart-line text-xl"></i>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => downloadBackup(backup.filename)}
|
||||
title="Baixar backup"
|
||||
|
||||
Reference in New Issue
Block a user