From db0b220056b6d1555b11cb724d88f1f20f0129ab Mon Sep 17 00:00:00 2001 From: ronit-ghosh Date: Sun, 2 Mar 2025 22:24:21 +0530 Subject: [PATCH 1/2] image loader added in generate image --- apps/backend/index.ts | 3 + apps/backend/routes/getimage.routes.ts | 24 ++++++++ apps/web/components/GenerateImage.tsx | 82 +++++++++++++++++++++++--- 3 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 apps/backend/routes/getimage.routes.ts diff --git a/apps/backend/index.ts b/apps/backend/index.ts index 0ddf71d..22e4cae 100644 --- a/apps/backend/index.ts +++ b/apps/backend/index.ts @@ -14,6 +14,7 @@ import dotenv from "dotenv"; import paymentRoutes from "./routes/payment.routes"; import { router as webhookRouter } from "./routes/webhook.routes"; +import { router as imageRouter } from "./routes/getimage.routes"; const IMAGE_GEN_CREDITS = 1; const TRAIN_MODEL_CREDITS = 20; @@ -155,6 +156,7 @@ app.post("/ai/generate", authMiddleware, async (req, res) => { res.json({ imageId: data.id, + falReqId: request_id }); }); @@ -443,6 +445,7 @@ app.get("/model/status/:modelId", authMiddleware, async (req, res) => { app.use("/payment", paymentRoutes); app.use("/api/webhook", webhookRouter); +app.use("/api/image/", imageRouter); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); diff --git a/apps/backend/routes/getimage.routes.ts b/apps/backend/routes/getimage.routes.ts new file mode 100644 index 0000000..a3b1dec --- /dev/null +++ b/apps/backend/routes/getimage.routes.ts @@ -0,0 +1,24 @@ +import { prismaClient } from "db"; +import { Router } from "express" + +export const router = Router() + +router.post('/status/:falreqid', async (req, res) => { + const falReqId = req.params.falreqid; + try { + const image = await prismaClient.outputImages.findFirst({ + where: { + AND: [{ falAiRequestId: falReqId }, { userId: req.userId }] + }, + select: { + imageUrl: true, + status: true + } + }) + + res.json({ imageUrl: "https://v3.fal.media/files/elephant/VBTGCYry98QgJJPGBlkX6_ee4245ec81814803b3c0ca6da0e50eb4.jpg", status: image?.status }) + } catch (error) { + console.error(error) + res.status(403).json({ msg: "Error while fetching image" }) + } +}) \ No newline at end of file diff --git a/apps/web/components/GenerateImage.tsx b/apps/web/components/GenerateImage.tsx index 7343f06..7ecb449 100644 --- a/apps/web/components/GenerateImage.tsx +++ b/apps/web/components/GenerateImage.tsx @@ -1,6 +1,6 @@ "use client" import { useAuth } from "@clerk/nextjs" -import { useState } from "react" +import { useEffect, useState } from "react" import { Button } from "./ui/button" import { Textarea } from "@/components/ui/textarea" import axios from "axios" @@ -11,10 +11,19 @@ import { motion } from "framer-motion" import { Sparkles } from "lucide-react" import { useCredits } from "@/hooks/use-credits" import { useRouter } from "next/navigation" +import { Card } from "./ui/card" +import { Badge } from "./ui/badge" +import { Dialog, DialogTrigger } from "./ui/dialog" +import Image from "next/image" +import { Skeleton } from "./ui/skeleton" export function GenerateImage() { const [prompt, setPrompt] = useState("") const [selectedModel, setSelectedModel] = useState() const [isGenerating, setIsGenerating] = useState(false) + const [falReqId, setFalReqId] = useState("e05658a5-4904-49fd-bc4d-bf67d32511fa") + const [imageStatus, setImageStatus] = useState<"Pending" | "Generated" | "Failed">("Pending") + const [imageUrl, setImageUrl] = useState() + const [, setImageLoading] = useState(true) const { getToken } = useAuth() const { credits } = useCredits(); const router = useRouter() @@ -26,11 +35,11 @@ export function GenerateImage() { router.push("/pricing") return } - + setIsGenerating(true) try { const token = await getToken() - await axios.post(`${BACKEND_URL}/ai/generate`, { + const response = await axios.post(`${BACKEND_URL}/ai/generate`, { prompt, modelId: selectedModel, num: 1 @@ -39,6 +48,7 @@ export function GenerateImage() { }) toast.success("Image generation started!") setPrompt("") + setFalReqId(response.data.falReqId) } catch (error) { toast.error("Failed to generate image") } finally { @@ -46,15 +56,44 @@ export function GenerateImage() { } } + async function fetchImage() { + try { + setImageStatus('Pending') + const res = await axios.post(`${BACKEND_URL}/api/image/status/${falReqId}`) + if (res.data.status == 'Failed') { + setImageLoading(false) + setImageStatus('Failed') + return + } + setImageStatus(res.data.status) + if (res.data.imageUrl) setImageUrl(res.data.imageUrl) + } catch (error) { + setImageStatus('Failed') + setImageLoading(false) + console.error(error) + } + } + + useEffect(() => { + if (!falReqId || imageUrl) return; + + const interval = setInterval(() => { + fetchImage(); + }, 2000); + + return () => clearInterval(interval); + + }, [falReqId, imageUrl]) + return ( - -
+
-
+ { + isGenerating && +
+
+
+

Result

+ {imageStatus} +
+ + + { + !imageUrl ? + : + image + } + + +
+

Your request will cost 1 credit per operation.

+
+
+
+ } ) } \ No newline at end of file From 8ac9b9b50a4685de90adebf8b1bd81ebcd011ef5 Mon Sep 17 00:00:00 2001 From: ronit-ghosh Date: Mon, 3 Mar 2025 00:38:40 +0530 Subject: [PATCH 2/2] recent image card added with download feature --- apps/backend/routes/getimage.routes.ts | 2 +- apps/web/components/GenerateImage.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/backend/routes/getimage.routes.ts b/apps/backend/routes/getimage.routes.ts index a3b1dec..16ece50 100644 --- a/apps/backend/routes/getimage.routes.ts +++ b/apps/backend/routes/getimage.routes.ts @@ -16,7 +16,7 @@ router.post('/status/:falreqid', async (req, res) => { } }) - res.json({ imageUrl: "https://v3.fal.media/files/elephant/VBTGCYry98QgJJPGBlkX6_ee4245ec81814803b3c0ca6da0e50eb4.jpg", status: image?.status }) + res.json({ imageUrl: image?.imageUrl, status: image?.status }) } catch (error) { console.error(error) res.status(403).json({ msg: "Error while fetching image" }) diff --git a/apps/web/components/GenerateImage.tsx b/apps/web/components/GenerateImage.tsx index 7ecb449..9fb2501 100644 --- a/apps/web/components/GenerateImage.tsx +++ b/apps/web/components/GenerateImage.tsx @@ -11,7 +11,6 @@ import { motion } from "framer-motion" import { Sparkles } from "lucide-react" import { useCredits } from "@/hooks/use-credits" import { useRouter } from "next/navigation" -import { Card } from "./ui/card" import { Badge } from "./ui/badge" import { Dialog, DialogTrigger } from "./ui/dialog" import Image from "next/image"