diff --git a/app/client/components/create-repository-dialog.tsx b/app/client/components/create-repository-dialog.tsx deleted file mode 100644 index 8a04e44..0000000 --- a/app/client/components/create-repository-dialog.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { useMutation } from "@tanstack/react-query"; -import { Plus } from "lucide-react"; -import { useId } from "react"; -import { toast } from "sonner"; -import { parseError } from "~/client/lib/errors"; -import { CreateRepositoryForm } from "./create-repository-form"; -import { Button } from "./ui/button"; -import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog"; -import { ScrollArea } from "./ui/scroll-area"; -import { createRepositoryMutation } from "../api-client/@tanstack/react-query.gen"; - -type Props = { - open: boolean; - setOpen: (open: boolean) => void; -}; - -export const CreateRepositoryDialog = ({ open, setOpen }: Props) => { - const formId = useId(); - - const create = useMutation({ - ...createRepositoryMutation(), - onSuccess: () => { - toast.success("Repository created successfully"); - setOpen(false); - }, - onError: (error) => { - toast.error("Failed to create repository", { - description: parseError(error)?.message, - }); - }, - }); - - return ( - - - - - - - - Create repository - - { - create.mutate({ body: { config: values, name: values.name, compressionMode: values.compressionMode } }); - }} - /> - - - - - - - - ); -}; diff --git a/app/client/modules/repositories/routes/create-repository.tsx b/app/client/modules/repositories/routes/create-repository.tsx new file mode 100644 index 0000000..5c30eda --- /dev/null +++ b/app/client/modules/repositories/routes/create-repository.tsx @@ -0,0 +1,89 @@ +import { useMutation } from "@tanstack/react-query"; +import { Database } from "lucide-react"; +import { useId } from "react"; +import { useNavigate } from "react-router"; +import { toast } from "sonner"; +import { createRepositoryMutation } from "~/client/api-client/@tanstack/react-query.gen"; +import { CreateRepositoryForm, type RepositoryFormValues } from "~/client/components/create-repository-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-repository"; +import { Alert, AlertDescription } from "~/client/components/ui/alert"; + +export const handle = { + breadcrumb: () => [{ label: "Repositories", href: "/repositories" }, { label: "Create" }], +}; + +export function meta(_: Route.MetaArgs) { + return [ + { title: "Create Repository" }, + { + name: "description", + content: "Create a new backup repository with encryption and compression.", + }, + ]; +} + +export default function CreateRepository() { + const navigate = useNavigate(); + const formId = useId(); + + const createRepository = useMutation({ + ...createRepositoryMutation(), + onSuccess: (data) => { + toast.success("Repository created successfully"); + navigate(`/repositories/${data.repository.name}`); + }, + }); + + const handleSubmit = (values: RepositoryFormValues) => { + createRepository.mutate({ + body: { + config: values, + name: values.name, + compressionMode: values.compressionMode, + }, + }); + }; + + return ( +
+ + +
+
+ +
+ Create Repository +
+
+ + {createRepository.isError && ( + + + Failed to create repository: +
+ {parseError(createRepository.error)?.message} +
+
+ )} + +
+ + +
+
+
+
+ ); +} diff --git a/app/client/modules/repositories/routes/repositories.tsx b/app/client/modules/repositories/routes/repositories.tsx index be2485e..ecb0114 100644 --- a/app/client/modules/repositories/routes/repositories.tsx +++ b/app/client/modules/repositories/routes/repositories.tsx @@ -1,10 +1,9 @@ import { useQuery } from "@tanstack/react-query"; -import { Database, RotateCcw } from "lucide-react"; +import { Database, Plus, RotateCcw } from "lucide-react"; import { useState } from "react"; import { useNavigate } from "react-router"; import { listRepositories } from "~/client/api-client/sdk.gen"; import { listRepositoriesOptions } from "~/client/api-client/@tanstack/react-query.gen"; -import { CreateRepositoryDialog } from "~/client/components/create-repository-dialog"; import { RepositoryIcon } from "~/client/components/repository-icon"; import { Button } from "~/client/components/ui/button"; import { Card } from "~/client/components/ui/card"; @@ -39,7 +38,6 @@ export default function Repositories({ loaderData }: Route.ComponentProps) { const [searchQuery, setSearchQuery] = useState(""); const [statusFilter, setStatusFilter] = useState(""); const [backendFilter, setBackendFilter] = useState(""); - const [createRepositoryOpen, setCreateRepositoryOpen] = useState(false); const clearFilters = () => { setSearchQuery(""); @@ -73,7 +71,12 @@ export default function Repositories({ loaderData }: Route.ComponentProps) { icon={Database} title="No repository" description="Repositories are remote storage locations where you can backup your volumes securely. Encrypted and optimized for storage efficiency." - button={} + button={ + + } /> ); } @@ -116,7 +119,10 @@ export default function Repositories({ loaderData }: Route.ComponentProps) { )} - +
diff --git a/app/routes.ts b/app/routes.ts index 8e034a6..f126a35 100644 --- a/app/routes.ts +++ b/app/routes.ts @@ -12,6 +12,7 @@ export default [ route("backups/create", "./client/modules/backups/routes/create-backup.tsx"), route("backups/:id", "./client/modules/backups/routes/backup-details.tsx"), route("repositories", "./client/modules/repositories/routes/repositories.tsx"), + route("repositories/create", "./client/modules/repositories/routes/create-repository.tsx"), route("repositories/:name", "./client/modules/repositories/routes/repository-details.tsx"), route("repositories/:name/:snapshotId", "./client/modules/repositories/routes/snapshot-details.tsx"), route("settings", "./client/modules/settings/routes/settings.tsx"),