Files
jobtrackingapp/job-tracker-ui/src/components/BackupCard.tsx
T
2026-03-21 11:55:27 +01:00

52 lines
1.7 KiB
TypeScript

import React, { useState } from "react";
import { Box, Button, Paper, Typography } from "@mui/material";
import { api } from "../api";
import { useToast } from "../toast";
export default function BackupCard() {
const { toast } = useToast();
const [downloading, setDownloading] = useState(false);
const downloadEncrypted = async () => {
setDownloading(true);
try {
const res = await api.post("/backup/encrypted", null, { responseType: "blob" });
const blob: Blob = res.data;
const url = URL.createObjectURL(blob);
const cd = (res.headers?.["content-disposition"] as string) || "";
const m = /filename="?([^";]+)"?/i.exec(cd);
const filename = m?.[1] ?? `jobtracker_backup_${new Date().toISOString().slice(0, 10)}.jtbackup`;
const link = document.createElement("a");
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
link.remove();
window.setTimeout(() => URL.revokeObjectURL(url), 5000);
toast("Backup downloaded.", "success");
} catch {
toast("Backup failed.", "error");
} finally {
setDownloading(false);
}
};
return (
<Paper sx={{ mt: 2, p: 2 }}>
<Typography variant="h6" sx={{ mb: 1 }}>
Data Safety
</Typography>
<Typography sx={{ color: "text.secondary", mb: 1 }}>
One-click encrypted backup (Windows DPAPI).
</Typography>
<Box sx={{ display: "flex", gap: 1, flexWrap: "wrap" }}>
<Button variant="contained" onClick={downloadEncrypted} disabled={downloading}>
{downloading ? "Preparing..." : "Download Encrypted Backup"}
</Button>
</Box>
</Paper>
);
}