import { MariadbIcon, MongodbIcon, MysqlIcon, PostgresqlIcon, RedisIcon, } from "@/components/icons/data-tools-icons"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Textarea } from "@/components/ui/textarea"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; import { Database } from "lucide-react"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; type DbType = typeof mySchema._type.type; // TODO: Change to a real docker images const dockerImageDefaultPlaceholder: Record = { mongo: "mongo:6", mariadb: "mariadb:11", mysql: "mysql:8", postgres: "postgres:15", redis: "redis:7", }; const databasesUserDefaultPlaceholder: Record< Exclude, string > = { mongo: "mongo", mariadb: "mariadb", mysql: "mysql", postgres: "postgres", }; const baseDatabaseSchema = z.object({ name: z.string().min(1, "Name required"), databasePassword: z.string(), dockerImage: z.string(), description: z.string().nullable(), }); const mySchema = z.discriminatedUnion("type", [ z .object({ type: z.literal("postgres"), databaseName: z.string().min(1, "Database name required"), databaseUser: z.string().default("postgres"), }) .merge(baseDatabaseSchema), z .object({ type: z.literal("mongo"), databaseUser: z.string().default("mongo"), }) .merge(baseDatabaseSchema), z .object({ type: z.literal("redis"), }) .merge(baseDatabaseSchema), z .object({ type: z.literal("mysql"), databaseRootPassword: z.string().default(""), databaseUser: z.string().default("mysql"), databaseName: z.string().min(1, "Database name required"), }) .merge(baseDatabaseSchema), z .object({ type: z.literal("mariadb"), dockerImage: z.string().default("mariadb:4"), databaseRootPassword: z.string().default(""), databaseUser: z.string().default("mariadb"), databaseName: z.string().min(1, "Database name required"), }) .merge(baseDatabaseSchema), ]); type AddDatabase = z.infer; interface Props { projectId: string; } export const AddDatabase = ({ projectId }: Props) => { const utils = api.useUtils(); const { mutateAsync: createPostgresql } = api.postgres.create.useMutation(); const { mutateAsync: createMongo } = api.mongo.create.useMutation(); const { mutateAsync: createRedis } = api.redis.create.useMutation(); const { mutateAsync: createMariadb } = api.mariadb.create.useMutation(); const { mutateAsync: createMysql } = api.mysql.create.useMutation(); const form = useForm({ defaultValues: { type: "postgres", dockerImage: "", name: "", databasePassword: "", description: "", databaseName: "", databaseUser: "", }, resolver: zodResolver(mySchema), }); const type = form.watch("type"); useEffect(() => { form.reset({ type: "postgres", dockerImage: "", name: "", databasePassword: "", description: "", databaseName: "", databaseUser: "", }); }, [form, form.reset, form.formState.isSubmitSuccessful]); const onSubmit = async (data: AddDatabase) => { const defaultDockerImage = data.dockerImage || dockerImageDefaultPlaceholder[data.type]; let promise: Promise | null = null; if (data.type === "postgres") { promise = createPostgresql({ name: data.name, dockerImage: defaultDockerImage, databasePassword: data.databasePassword, databaseName: data.databaseName, databaseUser: data.databaseUser || databasesUserDefaultPlaceholder[data.type], projectId, description: data.description, }); } else if (data.type === "mongo") { promise = createMongo({ name: data.name, dockerImage: defaultDockerImage, databasePassword: data.databasePassword, databaseUser: data.databaseUser || databasesUserDefaultPlaceholder[data.type], projectId, description: data.description, }); } else if (data.type === "redis") { promise = createRedis({ name: data.name, dockerImage: defaultDockerImage, databasePassword: data.databasePassword, projectId, description: data.description, }); } else if (data.type === "mariadb") { promise = createMariadb({ name: data.name, dockerImage: defaultDockerImage, databasePassword: data.databasePassword, projectId, databaseRootPassword: data.databaseRootPassword, databaseName: data.databaseName, databaseUser: data.databaseUser || databasesUserDefaultPlaceholder[data.type], description: data.description, }); } else if (data.type === "mysql") { promise = createMysql({ name: data.name, dockerImage: defaultDockerImage, databasePassword: data.databasePassword, databaseName: data.databaseName, databaseUser: data.databaseUser || databasesUserDefaultPlaceholder[data.type], projectId, databaseRootPassword: data.databaseRootPassword, description: data.description, }); } if (promise) { await promise .then(async () => { toast.success("Database Created"); await utils.project.one.invalidate({ projectId, }); }) .catch(() => { toast.error("Error to create a database"); }); } }; return ( e.preventDefault()} > Database Databases {/* {isError && (
{error?.message}
)} */}
( Select a database
)} />
Fill the next fields.
( Name )} /> ( Description