code-share/pages/project/@slug/components/createfile-dialog.tsx

102 lines
2.8 KiB
TypeScript
Raw Permalink Normal View History

2024-02-20 18:03:43 +07:00
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "../../../../components/ui/dialog";
2024-02-22 12:14:58 +00:00
import { UseDiscloseReturn } from "~/hooks/useDisclose";
2024-02-23 19:36:10 +07:00
import { BaseInput } from "../../../../components/ui/input";
2024-02-20 18:03:43 +07:00
import { Button } from "../../../../components/ui/button";
2024-02-22 12:14:58 +00:00
import { useForm } from "~/hooks/useForm";
2024-02-20 06:52:39 +00:00
import { z } from "zod";
2024-02-20 18:03:43 +07:00
import FormErrorMessage from "../../../../components/ui/form-error-message";
2024-02-22 12:14:58 +00:00
import trpc from "~/lib/trpc";
import type { FileSchema } from "~/server/db/schema/file";
2024-02-20 18:03:43 +07:00
import { useWatch } from "react-hook-form";
2024-02-26 10:48:17 +00:00
import { useProjectContext } from "../context/project";
2024-02-20 06:52:39 +00:00
type Props = {
2024-02-20 18:03:43 +07:00
disclose: UseDiscloseReturn<CreateFileSchema>;
2024-02-20 06:52:39 +00:00
onSuccess?: (file: FileSchema, type: "create" | "update") => void;
};
const fileSchema = z.object({
id: z.number().optional(),
2024-02-20 18:03:43 +07:00
parentId: z.number().optional().nullable(),
2024-02-20 06:52:39 +00:00
filename: z.string().min(1),
2024-02-20 18:03:43 +07:00
isDirectory: z.boolean().optional(),
2024-02-20 06:52:39 +00:00
});
2024-02-20 18:03:43 +07:00
export type CreateFileSchema = z.infer<typeof fileSchema>;
2024-02-20 06:52:39 +00:00
const defaultValues: z.infer<typeof fileSchema> = {
filename: "",
};
const CreateFileDialog = ({ disclose, onSuccess }: Props) => {
2024-02-26 10:48:17 +00:00
const { project } = useProjectContext();
2024-02-20 06:52:39 +00:00
const form = useForm(fileSchema, disclose.data || defaultValues);
2024-02-20 18:03:43 +07:00
const isDir = useWatch({ name: "isDirectory", control: form.control });
2024-02-20 06:52:39 +00:00
const create = trpc.file.create.useMutation({
onSuccess(data) {
if (onSuccess) onSuccess(data, "create");
disclose.onClose();
},
});
const update = trpc.file.update.useMutation({
onSuccess(data) {
if (onSuccess) onSuccess(data, "update");
disclose.onClose();
},
});
const onSubmit = form.handleSubmit((values) => {
if (update.isPending || create.isPending) {
return;
}
if (values.id) {
2024-02-26 10:48:17 +00:00
update.mutate({ ...values, id: values.id!, projectId: project.id });
2024-02-20 06:52:39 +00:00
} else {
2024-02-26 10:48:17 +00:00
create.mutate({ ...values, projectId: project.id });
2024-02-20 06:52:39 +00:00
}
});
return (
<Dialog open={disclose.isOpen} onOpenChange={disclose.onChange}>
<DialogContent>
<DialogHeader>
2024-02-20 18:03:43 +07:00
<DialogTitle>
{[
!disclose.data?.id ? "Create" : "Rename",
isDir ? "Directory" : "File",
].join(" ")}
</DialogTitle>
2024-02-20 06:52:39 +00:00
</DialogHeader>
<form onSubmit={onSubmit}>
<FormErrorMessage form={form} />
2024-02-23 19:36:10 +07:00
<BaseInput
2024-02-20 18:03:43 +07:00
placeholder={isDir ? "Directory Name" : "Filename"}
2024-02-20 06:52:39 +00:00
autoFocus
{...form.register("filename")}
/>
<div className="flex justify-end gap-4 mt-4">
2024-02-20 18:03:43 +07:00
<Button size="sm" variant="ghost" onClick={disclose.onClose}>
2024-02-20 06:52:39 +00:00
Cancel
</Button>
<Button type="submit" size="sm">
Submit
</Button>
</div>
</form>
</DialogContent>
</Dialog>
);
};
export default CreateFileDialog;