refactor(create-volume): from dialog to page

This commit is contained in:
Nicolas Meienberger
2025-11-14 21:23:52 +01:00
parent c898e1ce07
commit cfeff643c4
6 changed files with 96 additions and 72 deletions

View File

@@ -0,0 +1,83 @@
import { useMutation } from "@tanstack/react-query";
import { HardDrive } from "lucide-react";
import { useId } from "react";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import { createVolumeMutation } from "~/client/api-client/@tanstack/react-query.gen";
import { CreateVolumeForm, type FormValues } from "~/client/components/create-volume-form";
import { Button } from "~/client/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/client/components/ui/card";
import { parseError } from "~/client/lib/errors";
import type { Route } from "./+types/create-volume";
import { Alert, AlertDescription } from "~/client/components/ui/alert";
export const handle = {
breadcrumb: () => [{ label: "Volumes", href: "/volumes" }, { label: "Create" }],
};
export function meta(_: Route.MetaArgs) {
return [
{ title: "Create Volume" },
{
name: "description",
content: "Create a new storage volume with automatic mounting and health checks.",
},
];
}
export default function CreateVolume() {
const navigate = useNavigate();
const formId = useId();
const createVolume = useMutation({
...createVolumeMutation(),
onSuccess: (data) => {
toast.success("Volume created successfully");
navigate(`/volumes/${data.name}`);
},
});
const handleSubmit = (values: FormValues) => {
createVolume.mutate({
body: {
config: values,
name: values.name,
},
});
};
return (
<div className="container mx-auto space-y-6">
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<div className="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<HardDrive className="w-5 h-5 text-primary" />
</div>
<CardTitle>Create Volume</CardTitle>
</div>
</CardHeader>
<CardContent className="space-y-6">
{createVolume.isError && (
<Alert variant="destructive">
<AlertDescription>
<strong>Failed to create volume:</strong>
<br />
{parseError(createVolume.error)?.message}
</AlertDescription>
</Alert>
)}
<CreateVolumeForm mode="create" formId={formId} onSubmit={handleSubmit} loading={createVolume.isPending} />
<div className="flex justify-end gap-2 pt-4 border-t">
<Button type="button" variant="secondary" onClick={() => navigate("/volumes")}>
Cancel
</Button>
<Button type="submit" form={formId} loading={createVolume.isPending}>
Create Volume
</Button>
</div>
</CardContent>
</Card>
</div>
);
}

View File

@@ -1,8 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import { HardDrive, RotateCcw } from "lucide-react";
import { HardDrive, Plus, RotateCcw } from "lucide-react";
import { useState } from "react";
import { useNavigate } from "react-router";
import { CreateVolumeDialog } from "~/client/components/create-volume-dialog";
import { EmptyState } from "~/client/components/empty-state";
import { StatusDot } from "~/client/components/status-dot";
import { Button } from "~/client/components/ui/button";
@@ -36,7 +35,6 @@ export const clientLoader = async () => {
};
export default function Volumes({ loaderData }: Route.ComponentProps) {
const [createVolumeOpen, setCreateVolumeOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [statusFilter, setStatusFilter] = useState("");
const [backendFilter, setBackendFilter] = useState("");
@@ -73,7 +71,12 @@ export default function Volumes({ loaderData }: Route.ComponentProps) {
icon={HardDrive}
title="No volume"
description="Manage and monitor all your storage backends in one place with advanced features like automatic mounting and health checks."
button={<CreateVolumeDialog open={createVolumeOpen} setOpen={setCreateVolumeOpen} />}
button={
<Button onClick={() => navigate("/volumes/create")}>
<Plus size={16} className="mr-2" />
Create Volume
</Button>
}
/>
);
}
@@ -115,7 +118,10 @@ export default function Volumes({ loaderData }: Route.ComponentProps) {
</Button>
)}
</span>
<CreateVolumeDialog open={createVolumeOpen} setOpen={setCreateVolumeOpen} />
<Button onClick={() => navigate("/volumes/create")}>
<Plus size={16} className="mr-2" />
Create Volume
</Button>
</div>
<div className="overflow-x-auto">
<Table className="border-t">