💬

【Convex】NextJs14 と Convex【#28 Convex Rename Form】

2024/05/29に公開

【#28 Convex Rename Form】

YouTube: https://youtu.be/yiZrdCjThl4
https://youtu.be/yiZrdCjThl4

今回はモーダルにフォームを追加します。
フォームのデフォルトバリューの設定はいろいろやり方はあるのですが
今回はuseEffectを使ってさっくりと実装しています。

components/modals/rename-card-modal.tsx
"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";

import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogDescription,
  DialogClose,
  DialogFooter,
  DialogTitle,
} from "@/components/ui/dialog";
import { Form, FormControl, FormField } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";

import { useRenameCardModal } from "@/store/use-rename-card-modal";
import { useApiMutation } from "@/hooks/use-api-mutation";
import { api } from "@/convex/_generated/api";
import { toast } from "sonner";
import { useEffect } from "react";

const formSchema = z.object({
  title: z
    .string()
    .min(2, { message: "Title must be at least 2 characters." })
    .max(50, { message: "Title must be less than 50 characters." }),
});

export const RenameCardModal = () => {
  const { isOpen, onClose, initialValues } = useRenameCardModal();
  const { pending, mutate } = useApiMutation(api.card.updateCard);

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      title: "",
    },
  });

  const onSubmit = (values: z.infer<typeof formSchema>) => {
    mutate({
      id: initialValues.id,
      title: values.title,
    })
      .then(() => {
        toast.success("Card updated");
        onClose();
      })
      .catch((error) => {
        toast.error("Failed to rename title");
        console.log(error);
      });
  };

  useEffect(() => {
    form.setValue("title", initialValues.title);
  }, [initialValues.title]);

  return (
    <Dialog open={isOpen} onOpenChange={onClose}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Rename card title</DialogTitle>
          <DialogDescription>Enter a new card title.</DialogDescription>
          <Form {...form}>
            <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
              <FormField
                control={form.control}
                name="title"
                render={({ field }) => <Input {...field} disabled={pending} />}
              />
              <DialogFooter>
                <DialogClose asChild>
                  <Button type="button" variant="outline">
                    Cancel
                  </Button>
                </DialogClose>
                <Button type="submit" disabled={pending}>
                  Save
                </Button>
              </DialogFooter>
            </form>
          </Form>
        </DialogHeader>
      </DialogContent>
    </Dialog>
  );
};

Discussion