import { useEffect, useState } from "react"; import { ByteSize, formatBytes } from "~/client/components/bytes-size"; import { Card } from "~/client/components/ui/card"; import { Progress } from "~/client/components/ui/progress"; import { type BackupProgressEvent, useServerEvents } from "~/client/hooks/use-server-events"; import { formatDuration } from "~/utils/utils"; type Props = { scheduleId: number; }; export const BackupProgressCard = ({ scheduleId }: Props) => { const { addEventListener } = useServerEvents(); const [progress, setProgress] = useState(null); useEffect(() => { const unsubscribe = addEventListener("backup:progress", (data) => { const progressData = data as BackupProgressEvent; if (progressData.scheduleId === scheduleId) { setProgress(progressData); } }); const unsubscribeComplete = addEventListener("backup:completed", (data) => { const completedData = data as { scheduleId: number }; if (completedData.scheduleId === scheduleId) { setProgress(null); } }); return () => { unsubscribe(); unsubscribeComplete(); }; }, [addEventListener, scheduleId]); const percentDone = progress ? Math.round(progress.percent_done * 100) : 0; const currentFile = progress?.current_files[0] || ""; const fileName = currentFile.split("/").pop() || currentFile; const speed = progress ? formatBytes(progress.bytes_done / progress.seconds_elapsed) : null; return (
Backup in progress
{progress ? `${percentDone}%` : "—"}

Files

{progress ? ( <> {progress.files_done.toLocaleString()} / {progress.total_files.toLocaleString()} ) : ( "—" )}

Data

{progress ? ( <> / ) : ( "—" )}

Elapsed

{progress ? formatDuration(progress.seconds_elapsed) : "—"}

Speed

{progress ? (progress.seconds_elapsed > 0 ? `${speed?.text} ${speed?.unit}/s` : "Calculating...") : "—"}

Current file

{fileName || "—"}

); };