import { useQuery } from "@tanstack/react-query"; import { CalendarClock, Database, HardDrive, Plus } from "lucide-react"; import { Link } from "react-router"; import { BackupStatusDot } from "../components/backup-status-dot"; import { EmptyState } from "~/client/components/empty-state"; import { Button } from "~/client/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card"; import type { Route } from "./+types/backups"; import { listBackupSchedules } from "~/client/api-client"; import { listBackupSchedulesOptions } from "~/client/api-client/@tanstack/react-query.gen"; export const handle = { breadcrumb: () => [{ label: "Backups" }], }; export function meta(_: Route.MetaArgs) { return [ { title: "Zerobyte - Backup Jobs" }, { name: "description", content: "Automate volume backups with scheduled jobs and retention policies.", }, ]; } export const clientLoader = async () => { const jobs = await listBackupSchedules(); if (jobs.data) return jobs.data; return []; }; export default function Backups({ loaderData }: Route.ComponentProps) { const { data: schedules, isLoading } = useQuery({ ...listBackupSchedulesOptions(), initialData: loaderData, refetchInterval: 10000, refetchOnWindowFocus: true, }); if (isLoading) { return (

Loading backup schedules...

); } if (!schedules || schedules.length === 0) { return ( Create a backup job } /> ); } return (
{schedules.map((schedule) => (
Volume {schedule.volume.name}
{schedule.repository.name}
Schedule {schedule.cronExpression}
Last backup {schedule.lastBackupAt ? new Date(schedule.lastBackupAt).toLocaleDateString() : "Never"}
Next backup {schedule.nextBackupAt ? new Date(schedule.nextBackupAt).toLocaleDateString() : "N/A"}
))} Create a backup job
); }