From 857afa076748cc04dd24a7363d13955dae355578 Mon Sep 17 00:00:00 2001
From: Ahmed Furkhan <108826853+Ahmedfurkhan@users.noreply.github.com>
Date: Fri, 26 Jun 2026 23:13:04 -0400
Subject: [PATCH] fix: remove client-supplied rating, dead code, and
deletePrompt rollback
---
backend.js | 2 ++
frontend/css/prompts.css | 45 +++++++++++++++++++++++++++++++++++++
frontend/js/prompts.js | 48 ++++++++++++++++++++++++++++++++++++++++
routes/generate_image.js | 38 +++++++++++++++++++++++++++++++
4 files changed, 133 insertions(+)
create mode 100644 routes/generate_image.js
diff --git a/backend.js b/backend.js
index a43b137..106e019 100644
--- a/backend.js
+++ b/backend.js
@@ -6,6 +6,7 @@ import express from "express";
import promptsRouter from "./routes/prompts.js";
import rateRouter from "./routes/rate.js";
import deleteRouter from "./routes/delete.js";
+import generateImageRouter from "./routes/generate_image.js";
/* CREATE PAGE */
import createRouter from "./routes/create.js";
@@ -28,6 +29,7 @@ app.use(express.static("frontend"));
app.use("/api", promptsRouter);
app.use("/api", rateRouter);
app.use("/api", deleteRouter);
+app.use("/api", generateImageRouter);
/* CREATE PAGE */
app.use("/api", createRouter);
diff --git a/frontend/css/prompts.css b/frontend/css/prompts.css
index daa26a4..4fede48 100644
--- a/frontend/css/prompts.css
+++ b/frontend/css/prompts.css
@@ -315,3 +315,48 @@
background: #6f42c1;
color: #fff;
}
+
+/* Image Preview */
+.preview-btn {
+ background: transparent;
+ border: 1.5px solid #a78bfa;
+ color: #a78bfa;
+ border-radius: 9999px;
+ padding: 0.3rem 1rem;
+ font-size: 0.8rem;
+ cursor: pointer;
+ transition: background 0.2s, color 0.2s;
+}
+
+.preview-btn:hover:not(:disabled) {
+ background: #a78bfa;
+ color: #fff;
+}
+
+.preview-btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.image-preview-container {
+ margin-top: 0.75rem;
+}
+
+.preview-img {
+ max-width: 100%;
+ max-height: 320px;
+ border-radius: 8px;
+ border: 1px solid #a78bfa44;
+ display: block;
+}
+
+.preview-loading {
+ font-size: 0.85rem;
+ color: #a78bfa;
+ font-style: italic;
+}
+
+.preview-error {
+ font-size: 0.85rem;
+ color: #f87171;
+}
diff --git a/frontend/js/prompts.js b/frontend/js/prompts.js
index f2bd54d..7c69c5a 100644
--- a/frontend/js/prompts.js
+++ b/frontend/js/prompts.js
@@ -241,6 +241,44 @@ function openDeleteModal(promptId) {
document.body.appendChild(overlay);
}
+async function generatePreview(promptText, btn, container) {
+ if (container.querySelector(".preview-img")) {
+ container.innerHTML = "";
+ btn.textContent = "Preview Image";
+ return;
+ }
+
+ btn.disabled = true;
+ btn.textContent = "Generating...";
+ container.innerHTML = 'Generating image, please wait...';
+
+ try {
+ const res = await fetch("/api/generate-image", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ prompt: promptText }),
+ });
+
+ const data = await res.json();
+
+ if (!res.ok || data.error) {
+ container.innerHTML = `Could not generate image: ${data.error}`;
+ } else {
+ container.innerHTML = "";
+ const img = document.createElement("img");
+ img.src = data.image;
+ img.alt = "AI generated preview";
+ img.className = "preview-img";
+ container.appendChild(img);
+ btn.textContent = "Hide Preview";
+ }
+ } catch (err) {
+ container.innerHTML = `Error: ${err.message}`;
+ } finally {
+ btn.disabled = false;
+ }
+}
+
function buildPromptRow(prompt) {
const row = document.createElement("div");
row.className = "prompt-row";
@@ -295,14 +333,24 @@ function buildPromptRow(prompt) {
tags.appendChild(tag);
}
+ const previewBtn = document.createElement("button");
+ previewBtn.className = "preview-btn";
+ previewBtn.textContent = "Preview Image";
+ previewBtn.addEventListener("click", () => generatePreview(prompt.prompt, previewBtn, imageContainer));
+
+ const imageContainer = document.createElement("div");
+ imageContainer.className = "image-preview-container";
+
actions.appendChild(rateLabel);
actions.appendChild(stars);
actions.appendChild(submitBtn);
+ actions.appendChild(previewBtn);
actions.appendChild(deleteBtn);
actions.appendChild(tags);
contentCol.appendChild(text);
contentCol.appendChild(actions);
+ contentCol.appendChild(imageContainer);
row.appendChild(ratingCol);
row.appendChild(contentCol);
diff --git a/routes/generate_image.js b/routes/generate_image.js
new file mode 100644
index 0000000..88c1095
--- /dev/null
+++ b/routes/generate_image.js
@@ -0,0 +1,38 @@
+import express from "express";
+
+const router = express.Router();
+
+router.post("/generate-image", async (req, res) => {
+ const { prompt } = req.body;
+ if (!prompt) return res.status(400).json({ error: "prompt required" });
+
+ const token = process.env.HF_TOKEN;
+ if (!token) return res.status(500).json({ error: "HF_TOKEN not set" });
+
+ try {
+ const hfRes = await fetch(
+ "https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-schnell",
+ {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${token}`,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ inputs: prompt }),
+ },
+ );
+
+ if (!hfRes.ok) {
+ const msg = await hfRes.text();
+ return res.status(hfRes.status).json({ error: msg });
+ }
+
+ const buffer = await hfRes.arrayBuffer();
+ const base64 = Buffer.from(buffer).toString("base64");
+ res.json({ image: `data:image/jpeg;base64,${base64}` });
+ } catch (err) {
+ res.status(500).json({ error: err.message });
+ }
+});
+
+export default router;