I am trying to use a replicate model that takes image and text as a prompt , but I can't make the file upload work here is my page.tsx:
"use client";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import axios from "axios";
import { Home } from "lucide-react";
import { useRouter } from "next/navigation";
import { useForm } from "react-hook-form";
import { useState } from "react";
import { useRef } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Card, CardFooter } from "@/components/ui/card";
import { Form, FormControl, FormField, FormItem } from "@/components/ui/form";
import downloadPhoto from "@/public/downolad";
import appendNewToName from "@/public/newname";
import { formSchema } from "@/app/(dashboard)/(routes)/product/constants";
import Heading from "@/components/heading";
import { Empty } from "@/components/empty";
import { Loader } from "@/components/loader";
const ProductPage = () => {
const router = useRouter();
const [images, setImages] = useState<string[]>([]);
const InputRef = useRef(null);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
prompt: "",
},
});
const isLoading = form.formState.isSubmitting;
const onSubmit = async (values: z.infer<typeof formSchema>) => {
try {
setImages([]);
const prompt= values.prompt
const formdata = new FormData
formdata.append("prompt", prompt)
formdata.append('inputimage', InputRef.current.files[0])
const response = await axios.post("/api/product", formData);
console.log(response.data);
setImages(response.data);
form.reset();
} catch (error) {
console.log(error);
} finally {
router.refresh();
}
};
return (
<div>
<Heading
title="Interior"
description="Generate Interior Design with AI"
icon={Home}
iconColor="text-emerald-300"
/>
<div className="px-4 lg:px-8">
<div>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="rouned-lg border w-full p-4 px-3 md:px-6 focus-within:shadow-sm grid grid-cols-12 gap-2"
>
<FormField
name="prompt"
render={({ field }) => (
<FormItem className="col-span-12 lg:col-span-10">
<FormControl className="m-0 p-0">
<Input
className="border-0 outline-none focus-visible:ring-0 focus-visible:ring-transparent"
disabled={isLoading}
placeholder="A dark bathroom"
{...field}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
name="image"
render={({ field }) => (
<FormItem className="col-span-12 lg:col-span-10">
<FormControl className="m-0 p-0">
<Input
className="border-0 outline-none focus-visible:ring-0 focus-visible:ring-transparent"
disabled={isLoading}
{...field}
type="file"
ref={InputRef}
accept="image/*"
/>
</FormControl>
</FormItem>
)}
/>
<Button
className="col-span-12 lg:col-span-2 w-full"
disabled={isLoading}
>
Generate
</Button>
</form>
</Form>
</div>
<div className="space-y-4 mt-4">
{isLoading && (
<div className="p-20">
<Loader />
</div>
)}
{images.length === 0 && !isLoading && (
<Empty label="No images generated" />
)}
<div className=" flex items-center">
{images.map((src) => (
<Card key={src} className="rounded-lg block m-auto">
<div className="relative aspect-square">
<img alt="image" src={src} width={300} height={300} />
</div>
<CardFooter className="p-2">
<Button
variant="secondary"
className="w-50 border-black border-2 block m-auto hover:bg-slate-600 hover:text-white"
onClick={() => downloadPhoto(src, appendNewToName(src))}
>
<h1 className="block m-auto w-20 ">DOWNLOAD</h1>
</Button>
</CardFooter>
</Card>
))}
</div>
</div>
</div>
</div>
);
};
export default ProductPage;
My constants.ts with zod:
import * as z from "zod";
export const formSchema = z.object({
prompt: z.string().min(1, {
message: "Image Prompt is required",
}),
file: z.instanceof(File)
});
And my route.ts:
import { NextResponse } from 'next/server';
import { auth } from '@clerk/nextjs';
import Replicate from "replicate";
const replicate = new Replicate({
auth: process.env.REPLICATE_API_TOKEN!,
});
export async function POST(req: Request) {
try {
const { userId } = auth();
const body = await req.json();
const prompt = body.prompt;
const inputImage = body.inputimage; // Change from body.prompt to body.inputimage
if (!userId) {
return new NextResponse('Unauthorized', { status: 401 });
}
if (!prompt) {
return new NextResponse('Prompt is required', { status: 400 });
}
if (!inputImage) {
return new NextResponse('Input image is required', { status: 400 });
}
const response = await replicate.run(
"logerzhu/ad-inpaint:b1c17d148455c1fda435ababe9ab1e03bc0d917cc3cf4251916f22c45c83c7df",
{
input: {
image_path: inputImage,
prompt: prompt,
}
}
);
return NextResponse.json(await response);
} catch (error) {
console.error('[VIDEO ERROR]', error);
return new NextResponse('Internal error', { status: 500 });
}
}
I had tried so many ways but none of them work so please somebody help me?Please if somebody helps me to use zod because that is my way to show the loader.I know that my code has many errors