"use client"; import { redirect } from "next/navigation"; import { useCallback, useEffect, useRef, useState } from "react"; import { FileWithPath } from "react-dropzone"; import { Mii } from "@prisma/client"; import { nameSchema, tagsSchema } from "@/lib/schemas"; import TagSelector from "../tag-selector"; import ImageList from "./image-list"; import LikeButton from "../like-button"; import Carousel from "../carousel"; import SubmitButton from "../submit-button"; import Dropzone from "../dropzone"; interface Props { mii: Mii; likes: number; } export default function EditForm({ mii, likes }: Props) { const [files, setFiles] = useState([]); const handleDrop = useCallback( (acceptedFiles: FileWithPath[]) => { if (files.length >= 3) return; hasFilesChanged.current = true; setFiles((prev) => [...prev, ...acceptedFiles]); }, [files.length] ); const [error, setError] = useState(undefined); const [name, setName] = useState(mii.name); const [tags, setTags] = useState(mii.tags); const [description, setDescription] = useState(mii.description); const hasFilesChanged = useRef(false); const handleSubmit = async () => { // Validate before sending request const nameValidation = nameSchema.safeParse(name); if (!nameValidation.success) { setError(nameValidation.error.issues[0].message); return; } const tagsValidation = tagsSchema.safeParse(tags); if (!tagsValidation.success) { setError(tagsValidation.error.issues[0].message); return; } // Send request to server const formData = new FormData(); if (name != mii.name) formData.append("name", name); if (tags != mii.tags) formData.append("tags", JSON.stringify(tags)); if (description && description != mii.description) formData.append("description", description); if (hasFilesChanged.current) { files.forEach((file, index) => { // image1, image2, etc. formData.append(`image${index + 1}`, file); }); } const response = await fetch(`/api/mii/${mii.id}/edit`, { method: "PATCH", body: formData, }); const { error } = await response.json(); if (!response.ok) { setError(error); return; } redirect(`/mii/${mii.id}`); }; // Load existing images - converts image URLs to File objects useEffect(() => { const loadExistingImages = async () => { try { const existing = await Promise.all( Array.from({ length: mii.imageCount }, async (_, index) => { const path = `/mii/${mii.id}/image?type=image${index}`; const response = await fetch(path); const blob = await response.blob(); return Object.assign(new File([blob], `image${index}.webp`, { type: "image/webp" }), { path }); }) ); setFiles(existing); } catch (error) { console.error("Error loading existing images:", error); } }; loadExistingImages(); }, [mii.id, mii.imageCount]); return (
URL.createObjectURL(file))]} />

{name || "Mii name"}

{tags.length == 0 && tag} {tags.map((tag) => ( {tag} ))}

Edit your Mii

Make changes to your existing Mii.

{/* Separator */}

Info
setName(e.target.value)} />