chore: stylistic changes

This commit is contained in:
Nicolas Meienberger 2026-04-02 22:20:19 +02:00 committed by Nico
parent 1b780ed127
commit 19e0a950fd
4 changed files with 61 additions and 72 deletions

View file

@ -64,7 +64,7 @@ export function CompressionStatsChart({ repositoryShortId, initialStats }: Props
const hasStats = !!stats && (storedSize > 0 || uncompressedSize > 0 || snapshotsCount > 0); const hasStats = !!stats && (storedSize > 0 || uncompressedSize > 0 || snapshotsCount > 0);
const storedPercent = uncompressedSize > 0 ? (storedSize / uncompressedSize) * 100 : 0; const storedPercent = Math.min(100, Math.max(0, uncompressedSize > 0 ? (storedSize / uncompressedSize) * 100 : 0));
return ( return (
<Card className="flex flex-col px-6 py-6"> <Card className="flex flex-col px-6 py-6">

View file

@ -1,5 +1,5 @@
import { useMutation, useSuspenseQuery } from "@tanstack/react-query"; import { useMutation, useSuspenseQuery } from "@tanstack/react-query";
import { Suspense, useState } from "react"; import { useState } from "react";
import { useNavigate, useSearch } from "@tanstack/react-router"; import { useNavigate, useSearch } from "@tanstack/react-router";
import { toast } from "sonner"; import { toast } from "sonner";
import { ChevronDown, Database, Pencil, Square, Stethoscope, Trash2, Unlock } from "lucide-react"; import { ChevronDown, Database, Pencil, Square, Stethoscope, Trash2, Unlock } from "lucide-react";
@ -134,7 +134,7 @@ export default function RepositoryDetailsPage({
{repository.provisioningId && <Badge variant="secondary">Managed</Badge>} {repository.provisioningId && <Badge variant="secondary">Managed</Badge>}
</div> </div>
<p className="text-sm text-muted-foreground mt-0.5"> <p className="text-sm text-muted-foreground mt-0.5">
Created {formatDateTime(repository.createdAt)} &middot; Last checked{" "} Created {formatDateTime(repository.createdAt)} &middot; Last checked&nbsp;
{formatTimeAgo(repository.lastChecked)} {formatTimeAgo(repository.lastChecked)}
</p> </p>
</div> </div>
@ -222,13 +222,11 @@ export default function RepositoryDetailsPage({
<RepositoryInfoTabContent repository={repository} initialStats={initialStats} /> <RepositoryInfoTabContent repository={repository} initialStats={initialStats} />
</TabsContent> </TabsContent>
<TabsContent value="snapshots"> <TabsContent value="snapshots">
<Suspense> <RepositorySnapshotsTabContent
<RepositorySnapshotsTabContent repository={repository}
repository={repository} initialSnapshots={initialSnapshots}
initialSnapshots={initialSnapshots} initialBackupSchedules={initialBackupSchedules}
initialBackupSchedules={initialBackupSchedules} />
/>
</Suspense>
</TabsContent> </TabsContent>
</Tabs> </Tabs>
</div> </div>

View file

@ -140,36 +140,35 @@ export function VolumeDetails({ volumeId }: { volumeId: string }) {
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{isMounted ? ( <Button
<Button className={cn({ hidden: !isMounted })}
variant="secondary" variant="secondary"
onClick={() => onClick={() =>
toast.promise(unmountVol.mutateAsync({ path: { shortId: volume.shortId } }), { toast.promise(unmountVol.mutateAsync({ path: { shortId: volume.shortId } }), {
loading: "Unmounting volume...", loading: "Unmounting volume...",
success: "Volume unmounted successfully", success: "Volume unmounted successfully",
error: (error) => parseError(error)?.message || "Failed to unmount volume", error: (error) => parseError(error)?.message || "Failed to unmount volume",
}) })
} }
loading={unmountVol.isPending} loading={unmountVol.isPending}
> >
<Unplug className="h-4 w-4 mr-2" /> <Unplug className="h-4 w-4 mr-2" />
Unmount Unmount
</Button> </Button>
) : ( <Button
<Button className={cn({ hidden: isMounted })}
onClick={() => onClick={() =>
toast.promise(mountVol.mutateAsync({ path: { shortId: volume.shortId } }), { toast.promise(mountVol.mutateAsync({ path: { shortId: volume.shortId } }), {
loading: "Mounting volume...", loading: "Mounting volume...",
success: "Volume mounted successfully", success: "Volume mounted successfully",
error: (error) => parseError(error)?.message || "Failed to mount volume", error: (error) => parseError(error)?.message || "Failed to mount volume",
}) })
} }
loading={mountVol.isPending} loading={mountVol.isPending}
> >
<Plug className="h-4 w-4 mr-2" /> <Plug className="h-4 w-4 mr-2" />
Mount Mount
</Button> </Button>
)}
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button variant="outline"> <Button variant="outline">
@ -203,19 +202,18 @@ export function VolumeDetails({ volumeId }: { volumeId: string }) {
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<HeartIcon className="h-4 w-4 text-muted-foreground" /> <HeartIcon className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">Health</span> <span className="text-sm font-medium">Health</span>
{isError ? ( <Badge variant="destructive" className={cn("ml-1", { hidden: !isError })}>
<Badge variant="destructive" className="ml-1"> Error
Error </Badge>
</Badge> <Badge
) : isMounted ? ( variant="outline"
<Badge variant="outline" className="text-success border-success/30 bg-success/10 ml-1"> className={cn("text-success border-success/30 bg-success/10 ml-1", { hidden: !isMounted })}
Healthy >
</Badge> Healthy
) : ( </Badge>
<Badge variant="secondary" className="ml-1"> <Badge variant="secondary" className={cn("ml-1", { hidden: isMounted || isError })}>
Unmounted Unmounted
</Badge> </Badge>
)}
</div> </div>
<Separator orientation="vertical" className="h-4 hidden @lg:block" /> <Separator orientation="vertical" className="h-4 hidden @lg:block" />
<span className="text-sm text-muted-foreground">Checked {formatTimeAgo(volume.lastHealthCheck)}</span> <span className="text-sm text-muted-foreground">Checked {formatTimeAgo(volume.lastHealthCheck)}</span>
@ -248,14 +246,12 @@ export function VolumeDetails({ volumeId }: { volumeId: string }) {
</div> </div>
</Card> </Card>
{volume.lastError && ( <Card className={cn("px-6 py-6", { hidden: !volume.lastError })}>
<Card className="px-6 py-6"> <div className="space-y-2">
<div className="space-y-2"> <p className="text-sm font-medium text-destructive">Last Error</p>
<p className="text-sm font-medium text-destructive">Last Error</p> <p className="text-sm text-muted-foreground wrap-break-word">{volume.lastError}</p>
<p className="text-sm text-muted-foreground wrap-break-word">{volume.lastError}</p> </div>
</div> </Card>
</Card>
)}
<Tabs value={activeTab} onValueChange={(value) => navigate({ to: ".", search: () => ({ tab: value }) })}> <Tabs value={activeTab} onValueChange={(value) => navigate({ to: ".", search: () => ({ tab: value }) })}>
<TabsList className="mb-2"> <TabsList className="mb-2">

View file

@ -3,7 +3,7 @@ import { FolderOpen, HardDrive, Settings, Unplug } from "lucide-react";
import { Label, Pie, PieChart } from "recharts"; import { Label, Pie, PieChart } from "recharts";
import { ByteSize } from "~/client/components/bytes-size"; import { ByteSize } from "~/client/components/bytes-size";
import { Card, CardTitle } from "~/client/components/ui/card"; import { Card, CardTitle } from "~/client/components/ui/card";
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from "~/client/components/ui/chart"; import { ChartContainer, ChartTooltip, ChartTooltipContent } from "~/client/components/ui/chart";
import type { StatFs, Volume } from "~/client/lib/types"; import type { StatFs, Volume } from "~/client/lib/types";
import { cn } from "~/client/lib/utils"; import { cn } from "~/client/lib/utils";
@ -21,17 +21,14 @@ const backendLabels: Record<Volume["type"], string> = {
sftp: "SFTP", sftp: "SFTP",
}; };
function ConfigRow({ type ConfigRowProps = {
icon,
label,
value,
mono,
}: {
icon: React.ReactNode; icon: React.ReactNode;
label: string; label: string;
value: string; value: string;
mono?: boolean; mono?: boolean;
}) { };
function ConfigRow({ icon, label, value, mono }: ConfigRowProps) {
return ( return (
<div className="flex items-center gap-3 py-3 first:pt-0 last:pb-0"> <div className="flex items-center gap-3 py-3 first:pt-0 last:pb-0">
<span className="text-muted-foreground shrink-0">{icon}</span> <span className="text-muted-foreground shrink-0">{icon}</span>
@ -95,14 +92,12 @@ function DonutChart({ statfs }: { statfs: StatFs }) {
[statfs], [statfs],
); );
const chartConfig = {} satisfies ChartConfig;
const usagePercentage = useMemo(() => { const usagePercentage = useMemo(() => {
return Math.round((statfs.used / statfs.total) * 100); return Math.round((statfs.used / statfs.total) * 100);
}, [statfs]); }, [statfs]);
return ( return (
<ChartContainer config={chartConfig} className="mx-auto aspect-square max-h-[200px]"> <ChartContainer config={{}} className="mx-auto aspect-square max-h-[200px]">
<PieChart> <PieChart>
<ChartTooltip <ChartTooltip
cursor={false} cursor={false}