From a88d39c7fe1a74aecee281a30306692f421dc389 Mon Sep 17 00:00:00 2001 From: Mahendra785 Date: Sat, 8 Feb 2025 15:11:51 +0530 Subject: [PATCH 1/5] image --- app/components/mainpage.tsx | 4 +- app/components/organization.tsx | 153 ++++++++++++++++++++++++++++++++ app/components/tooltip.tsx | 66 ++++++++++++++ app/components/upload.tsx | 136 ++++++++++++++++++++++++++++ app/globals.css | 9 ++ app/page.tsx | 1 + app/upload/page.tsx | 128 +++++++++++++++----------- public/expand.svg | 9 ++ public/expanded.svg | 9 ++ public/feat1.svg | 20 +++++ public/feat2.svg | 28 ++++++ public/feat3.svg | 31 +++++++ public/feat4.svg | 22 +++++ public/feat5.svg | 20 +++++ public/feat6.svg | 19 ++++ public/feat7.svg | 23 +++++ public/fonts/Deutschlander.otf | Bin 0 -> 56252 bytes 17 files changed, 624 insertions(+), 54 deletions(-) create mode 100644 app/components/tooltip.tsx create mode 100644 app/components/upload.tsx create mode 100644 public/expand.svg create mode 100644 public/expanded.svg create mode 100644 public/feat1.svg create mode 100644 public/feat2.svg create mode 100644 public/feat3.svg create mode 100644 public/feat4.svg create mode 100644 public/feat5.svg create mode 100644 public/feat6.svg create mode 100644 public/feat7.svg create mode 100644 public/fonts/Deutschlander.otf diff --git a/app/components/mainpage.tsx b/app/components/mainpage.tsx index d0f288a..6745950 100644 --- a/app/components/mainpage.tsx +++ b/app/components/mainpage.tsx @@ -35,9 +35,9 @@ export default function Home() { initial={{ y: 0, opacity: 0 }} animate={{ y: animateText ? "-180%" : "0%", opacity: 1 }} transition={{ duration: 1.5, ease: "easeInOut" }} - className="absolute text-[200px] font-extrabold font-mono text-white leading-[100px]" + className="absolute deutschlander text-[300px] text-white leading-[100px]" > - The Postmen + SORT IQ {/* Animated Button */} diff --git a/app/components/organization.tsx b/app/components/organization.tsx index e69de29..139f617 100644 --- a/app/components/organization.tsx +++ b/app/components/organization.tsx @@ -0,0 +1,153 @@ +"use client"; + +import { useState, useEffect, useRef } from "react"; +import type React from "react"; +import Image from "next/image"; +import bg from "../../public/BG.svg"; +import FileUploadTest from "./upload"; + +const Organization: React.FC = () => { + const [isExpanded, setIsExpanded] = useState(false); + const [activeFeature, setActiveFeature] = useState(null); + const sidebarRef = useRef(null); + + const handleClickOutside = (event: MouseEvent) => { + if ( + sidebarRef.current && + !sidebarRef.current.contains(event.target as Node) + ) { + setIsExpanded(false); + } + }; + + useEffect(() => { + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [sidebarRef]); // Added sidebarRef to dependencies + + const features = [ + { name: "Feature 1", icon: "/feat1.svg", component: }, + { + name: "Feature 2", + icon: "/feat2.svg", + component:
Feature 2 Content
, + }, + { + name: "Feature 3", + icon: "/feat3.svg", + component:
Feature 3 Content
, + }, + { + name: "Feature 4", + icon: "/feat4.svg", + component:
Feature 4 Content
, + }, + { + name: "Feature 5", + icon: "/feat5.svg", + component:
Feature 5 Content
, + }, + { + name: "Feature 6", + icon: "/feat6.svg", + component:
Feature 6 Content
, + }, + { + name: "Feature 7", + icon: "/feat7.svg", + component:
Feature 7 Content
, + }, + ]; + + return ( +
+ CentralHack +
+ Sort IQ +
+
+ {/* Left Box (Sidebar) */} +
+ {isExpanded ? ( +
+
+ expand setIsExpanded(!isExpanded)} + /> +
Features
+
+
+ {features.map((feature, index) => ( +
setActiveFeature(index)} + > + {feature.name} +
{feature.name}
+
+ ))} +
+
+ ) : ( +
+ expand setIsExpanded(!isExpanded)} + /> + {features.map((feature, index) => ( +
setActiveFeature(index)} + > + {feature.name} +
+ ))} +
+ )} +
+ + {/* Right Box */} +
+ {activeFeature !== null && features[activeFeature].component} +
+
+
+ ); +}; + +export default Organization; diff --git a/app/components/tooltip.tsx b/app/components/tooltip.tsx new file mode 100644 index 0000000..cb393e3 --- /dev/null +++ b/app/components/tooltip.tsx @@ -0,0 +1,66 @@ +"use client"; + +import React, { useState, useRef, useEffect } from "react"; + +interface TooltipProps { + content: string; + children: React.ReactNode; +} + +const Tooltip: React.FC = ({ content, children }) => { + const [isVisible, setIsVisible] = useState(false); + const [position, setPosition] = useState({ top: 0, left: 0 }); + const triggerRef = useRef(null); + const tooltipRef = useRef(null); + + useEffect(() => { + if (isVisible && triggerRef.current && tooltipRef.current) { + const triggerRect = triggerRef.current.getBoundingClientRect(); + const tooltipRect = tooltipRef.current.getBoundingClientRect(); + + // Position the tooltip below the icon + setPosition({ + top: triggerRect.bottom + window.scrollY + 10, // 10px below the trigger + left: + triggerRect.left + + window.scrollX + + triggerRect.width / 2 - // Centered horizontally based on the trigger + tooltipRect.width / 2, + }); + } + }, [isVisible]); + + return ( +
setIsVisible(true)} + onMouseLeave={() => setIsVisible(false)} + className="relative inline-block" + > + {children} + {isVisible && ( +
+ {content} +
+
+ )} +
+ ); +}; + +export default Tooltip; diff --git a/app/components/upload.tsx b/app/components/upload.tsx new file mode 100644 index 0000000..92bea98 --- /dev/null +++ b/app/components/upload.tsx @@ -0,0 +1,136 @@ +"use client"; + +import { useState } from "react"; + +export default function FileUploadTest() { + const [file, setFile] = useState(null); + const [uploading, setUploading] = useState(false); + const [uploadedUrl, setUploadedUrl] = useState(null); + const [error, setError] = useState(null); + + const handleFileChange = (e: React.ChangeEvent) => { + if (e.target.files && e.target.files[0]) { + setFile(e.target.files[0]); + setError(null); + setUploadedUrl(null); + } + }; + + const handleUpload = async () => { + if (!file) { + setError("Please select a file first"); + return; + } + + setUploading(true); + setError(null); + + try { + const formData = new FormData(); + formData.append("file", file); + + const response = await fetch("/api/upload", { + method: "POST", + body: formData, + }); + + if (!response.ok) { + throw new Error("Upload failed"); + } + + const data = await response.json(); + setUploadedUrl(data.url); + } catch (err) { + setError("Failed to upload file. Please try again."); + console.error("Upload error:", err); + } finally { + setUploading(false); + } + }; + + return ( +
+
+ {/* File upload container */} +
+
+ + +
+ + {/* Display selected file */} + {file && ( +
+

+ Selected file: {file.name} +

+
+ )} + + {/* Upload button */} + +
+ + {/* Error Message */} + {error && ( +
+
{error}
+
+ )} + + {/* Success Message and Image Preview */} + {uploadedUrl && ( +
+

+ File uploaded successfully! +

+ + {uploadedUrl} + + + {/* Image preview for uploaded images */} + {uploadedUrl && ( +
+ {/* If the uploaded file is an image, show the preview */} + Uploaded preview +
+ )} +
+ )} + + {/* Image preview before uploading (optional feature) */} + {file && file.type.startsWith("image/") && !uploadedUrl && ( +
+ Preview +
+ )} +
+
+ ); +} diff --git a/app/globals.css b/app/globals.css index 6b717ad..d42bbf5 100644 --- a/app/globals.css +++ b/app/globals.css @@ -19,3 +19,12 @@ body { background: var(--background); font-family: Arial, Helvetica, sans-serif; } + +@font-face { + font-family: 'deutschlander'; + src: url('../public/fonts/Deutschlander.otf') format('opentype'); +} + +.deutschlander { + font-family: 'deutschlander', Arial, Helvetica, sans-serif; +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index ad77ed5..c3b399e 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,6 +2,7 @@ import { useSession } from "next-auth/react"; import Home from "./components/mainpage"; +import Organization from "./components/organization"; export default function Page() { const { data: session } = useSession(); // ✅ Get session from NextAuth diff --git a/app/upload/page.tsx b/app/upload/page.tsx index b2dcfd3..1ba3f21 100644 --- a/app/upload/page.tsx +++ b/app/upload/page.tsx @@ -1,83 +1,107 @@ "use client"; + import { useState } from "react"; -import { revalidateUpload } from "../(auth)/authactions/revalidate"; -export default function UploadPage() { + +export default function FileUploadTest() { const [file, setFile] = useState(null); const [uploading, setUploading] = useState(false); - const [progress, setProgress] = useState(0); - const [message, setMessage] = useState(""); + const [uploadedUrl, setUploadedUrl] = useState(null); + const [error, setError] = useState(null); - const handleFileChange = (event: React.ChangeEvent) => { - if (event.target.files && event.target.files.length > 0) { - const selectedFile = event.target.files[0]; - - if (selectedFile.type !== "video/mp4") { - setMessage("Only .mp4 files are allowed."); - return; - } - - setFile(selectedFile); - setMessage(""); + const handleFileChange = (e: React.ChangeEvent) => { + if (e.target.files && e.target.files[0]) { + setFile(e.target.files[0]); + setError(null); + setUploadedUrl(null); } }; const handleUpload = async () => { if (!file) { - setMessage("Please select a .mp4 file first."); + setError("Please select a file first"); return; } setUploading(true); - setMessage(""); - - const formData = new FormData(); - formData.append("file", file); + setError(null); try { - console.log("Uploading file..."); + const formData = new FormData(); + formData.append("file", file); + const response = await fetch("/api/upload", { method: "POST", body: formData, }); - console.log(response); - const result = await response.json(); - console.log(result); - await revalidateUpload(); - if (response.ok) { - setMessage(`Movie uploaded successfully: ${result.filename}`); - } else { - setMessage(`Upload failed: ${result.message}`); + + if (!response.ok) { + throw new Error("Upload failed"); } - } catch (error) { - setMessage("An error occurred while uploading."); + + const data = await response.json(); + setUploadedUrl(data.url); + } catch (err) { + setError("Failed to upload file. Please try again."); + console.error("Upload error:", err); } finally { setUploading(false); } }; return ( -
-
-

Upload a Movie (.mp4)

- - - {progress > 0 && ( -

Upload Progress: {progress}%

+
+
+
+
+ + +
+ + {file && ( +
+

+ Selected file: {file.name} +

+
+ )} + + +
+ + {error && ( +
+
{error}
+
+ )} + + {uploadedUrl && ( +
+

+ File uploaded successfully! +

+ + {uploadedUrl} + +
)} - {message &&

{message}

}
); diff --git a/public/expand.svg b/public/expand.svg new file mode 100644 index 0000000..382e635 --- /dev/null +++ b/public/expand.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/expanded.svg b/public/expanded.svg new file mode 100644 index 0000000..a2f09f1 --- /dev/null +++ b/public/expanded.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/feat1.svg b/public/feat1.svg new file mode 100644 index 0000000..638db82 --- /dev/null +++ b/public/feat1.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/public/feat2.svg b/public/feat2.svg new file mode 100644 index 0000000..4ee22bc --- /dev/null +++ b/public/feat2.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/feat3.svg b/public/feat3.svg new file mode 100644 index 0000000..a6f7883 --- /dev/null +++ b/public/feat3.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/feat4.svg b/public/feat4.svg new file mode 100644 index 0000000..bd1f548 --- /dev/null +++ b/public/feat4.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/feat5.svg b/public/feat5.svg new file mode 100644 index 0000000..99f99b6 --- /dev/null +++ b/public/feat5.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/public/feat6.svg b/public/feat6.svg new file mode 100644 index 0000000..907a058 --- /dev/null +++ b/public/feat6.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/feat7.svg b/public/feat7.svg new file mode 100644 index 0000000..3303317 --- /dev/null +++ b/public/feat7.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/fonts/Deutschlander.otf b/public/fonts/Deutschlander.otf new file mode 100644 index 0000000000000000000000000000000000000000..26191273a4dc8f36e3c06824cb14028efe1aa97d GIT binary patch literal 56252 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 literal 0 HcmV?d00001 From a9862ead9daaddabe1a6c8d27a23bd3619d1333d Mon Sep 17 00:00:00 2001 From: TejasGhatte Date: Sat, 8 Feb 2025 15:12:03 +0530 Subject: [PATCH 2/5] fix: image url --- utils/ml-actions/proccessImage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/ml-actions/proccessImage.ts b/utils/ml-actions/proccessImage.ts index ef33bcf..9ae1418 100644 --- a/utils/ml-actions/proccessImage.ts +++ b/utils/ml-actions/proccessImage.ts @@ -7,7 +7,7 @@ export async function processImage(imageUrl: string, imageId: string, userId: st const response = await fetch(`${process.env.ML_SERVER_URL}/analyze-waste`, { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ imageUrl }), + body: JSON.stringify({ image_url: imageUrl }), }); const data = await response.json(); From 7ac854cf008d8134aa0e6604ddbf037d271f8882 Mon Sep 17 00:00:00 2001 From: Mahendra785 Date: Sat, 8 Feb 2025 15:44:19 +0530 Subject: [PATCH 3/5] hello --- app/actions/getImageId.ts | 17 +++++++++++++++++ app/actions/proccessImage.ts | 3 ++- app/page.tsx | 2 +- package-lock.json | 8 +++++++- package.json | 3 ++- 5 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 app/actions/getImageId.ts diff --git a/app/actions/getImageId.ts b/app/actions/getImageId.ts new file mode 100644 index 0000000..b622efc --- /dev/null +++ b/app/actions/getImageId.ts @@ -0,0 +1,17 @@ + +"use server" +import { prisma } from "@/lib/prisma"; +import { auth } from "@/app/(auth)/auth"; +export async function getImageID(imageUrl: string) { + const Image = await prisma.image.findUnique({ + where: { + imageUrl: imageUrl + } + }); + + return { + status: "success", + message: "Organization created successfully", + data: Image.id + }; +} diff --git a/app/actions/proccessImage.ts b/app/actions/proccessImage.ts index f1095b3..fac8322 100644 --- a/app/actions/proccessImage.ts +++ b/app/actions/proccessImage.ts @@ -1,3 +1,4 @@ +"use server" import { prisma } from "@/lib/prisma"; import { auth } from "@/app/(auth)/auth"; import { processImage } from "@/utils/ml-actions/proccessImage"; @@ -32,6 +33,6 @@ export async function proccessImageAndSave(imageId: string) { status: "success", message: "Image proccessed successfully", proccessImage: processedImageUrl, - analysis: analysis + // analysis: analysis }; } \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 4c46982..c3b399e 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -7,5 +7,5 @@ import Organization from "./components/organization"; export default function Page() { const { data: session } = useSession(); // ✅ Get session from NextAuth - return
{}
; + return
{session ? : }
; } diff --git a/package-lock.json b/package-lock.json index 9724f39..d4a4e7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,8 @@ "next": "15.1.6", "next-auth": "^5.0.0-beta.25", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "tls": "^0.0.1" }, "devDependencies": { "@eslint/eslintrc": "^3", @@ -6655,6 +6656,11 @@ "node": ">=0.8" } }, + "node_modules/tls": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tls/-/tls-0.0.1.tgz", + "integrity": "sha512-GzHpG+hwupY8VMR6rYsnAhTHqT/97zT45PG8WD5eTT1lq+dFE0nN+1PYpsoBcHJgSmTz5ceK2Cv88IkPmIPOtQ==" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/package.json b/package.json index ca8a208..362e3fc 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "next": "15.1.6", "next-auth": "^5.0.0-beta.25", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "tls": "^0.0.1" }, "devDependencies": { "@eslint/eslintrc": "^3", From c7b1673f3dabebb606e7b352bd2b2458b85a26db Mon Sep 17 00:00:00 2001 From: Mahendra785 Date: Sat, 8 Feb 2025 16:38:15 +0530 Subject: [PATCH 4/5] stable --- app/actions/getImageId.ts | 11 +++ app/actions/proccessImage.ts | 3 +- app/components/upload.tsx | 16 +++- app/getImage/page.tsx | 47 ++++++++++ app/upload/page.tsx | 33 ++++++- .../20250208101922_render/migration.sql | 2 + utils/ml-actions/proccessImage.ts | 92 +++++++++---------- 7 files changed, 151 insertions(+), 53 deletions(-) create mode 100644 app/getImage/page.tsx create mode 100644 prisma/migrations/20250208101922_render/migration.sql diff --git a/app/actions/getImageId.ts b/app/actions/getImageId.ts index b622efc..bea697c 100644 --- a/app/actions/getImageId.ts +++ b/app/actions/getImageId.ts @@ -15,3 +15,14 @@ export async function getImageID(imageUrl: string) { data: Image.id }; } + +export async function getImages() { + const images = await prisma.image.findMany({ + }); + + return { + status: "success", + message: "Organization created successfully", + data: images + }; +} diff --git a/app/actions/proccessImage.ts b/app/actions/proccessImage.ts index fac8322..a81aa5b 100644 --- a/app/actions/proccessImage.ts +++ b/app/actions/proccessImage.ts @@ -27,12 +27,11 @@ export async function proccessImageAndSave(imageId: string) { } } - const {processedImageUrl, analysis} = await processImage(imageUrl, imageId, user.id, image.name); + const {processedImageUrl} = await processImage(imageUrl, imageId, user.id, image.name); return { status: "success", message: "Image proccessed successfully", proccessImage: processedImageUrl, - // analysis: analysis }; } \ No newline at end of file diff --git a/app/components/upload.tsx b/app/components/upload.tsx index 92bea98..ea6bcb0 100644 --- a/app/components/upload.tsx +++ b/app/components/upload.tsx @@ -1,13 +1,13 @@ "use client"; import { useState } from "react"; - +import { proccessImageAndSave } from "../actions/proccessImage"; export default function FileUploadTest() { const [file, setFile] = useState(null); const [uploading, setUploading] = useState(false); const [uploadedUrl, setUploadedUrl] = useState(null); const [error, setError] = useState(null); - + const [image, setImage] = useState(null); const handleFileChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files[0]) { setFile(e.target.files[0]); @@ -39,6 +39,9 @@ export default function FileUploadTest() { } const data = await response.json(); + const res = await proccessImageAndSave(data.image.id); + + setImage(res.proccessImage || null); setUploadedUrl(data.url); } catch (err) { setError("Failed to upload file. Please try again."); @@ -130,6 +133,15 @@ export default function FileUploadTest() { />
)} + {image && ( +
+ Preview +
+ )}
); diff --git a/app/getImage/page.tsx b/app/getImage/page.tsx new file mode 100644 index 0000000..5aecb99 --- /dev/null +++ b/app/getImage/page.tsx @@ -0,0 +1,47 @@ +"use client"; +import React, { useState, useEffect } from "react"; +import { getImages } from "../actions/getImageId"; + +interface ImageData { + processedImageUrl: string; +} + +const ImageList = () => { + const [images, setImages] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetchImages(); + }, []); + + const fetchImages = async () => { + try { + const images = await getImages(); + setImages(images.data); + } catch (err) { + console.error("Failed to fetch images:", err); + } finally { + setLoading(false); + } + }; + + return ( +
+ {loading ? ( +

Loading...

+ ) : ( +
    + {images.map((image, index) => + image.processedImageUrl ? ( +
  • + {`Image +
  • + ) : null + )} +
+ )} +
+ ); +}; + +export default ImageList; diff --git a/app/upload/page.tsx b/app/upload/page.tsx index 1ba3f21..0baa292 100644 --- a/app/upload/page.tsx +++ b/app/upload/page.tsx @@ -1,7 +1,8 @@ "use client"; -import { useState } from "react"; - +import { useState, useEffect } from "react"; +import { getImages } from "../actions/getImageId"; +import { console } from "inspector"; export default function FileUploadTest() { const [file, setFile] = useState(null); const [uploading, setUploading] = useState(false); @@ -47,6 +48,16 @@ export default function FileUploadTest() { setUploading(false); } }; + const [images, setImages] = useState([]); + + useEffect(() => { + const fetchImages = async () => { + const result = await getImages(); + console.log(result); + setImages(result.data || []); + }; + fetchImages(); + }, []); return (
)} + {/* Image Gallery */} +
+

Uploaded Images

+
+ {images?.map((image, index) => ( +
+ {`Uploaded +
+ ))} +
+
); diff --git a/prisma/migrations/20250208101922_render/migration.sql b/prisma/migrations/20250208101922_render/migration.sql new file mode 100644 index 0000000..a0c12bd --- /dev/null +++ b/prisma/migrations/20250208101922_render/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "Image_name_key"; diff --git a/utils/ml-actions/proccessImage.ts b/utils/ml-actions/proccessImage.ts index 9ae1418..fdaca10 100644 --- a/utils/ml-actions/proccessImage.ts +++ b/utils/ml-actions/proccessImage.ts @@ -3,7 +3,7 @@ import { projectClient } from '@/lib/bucket-client'; export async function processImage(imageUrl: string, imageId: string, userId: string, imageName: string) { try { - // Send the image to ML server + const response = await fetch(`${process.env.ML_SERVER_URL}/analyze-waste`, { method: "POST", headers: { "Content-Type": "application/json" }, @@ -11,59 +11,58 @@ export async function processImage(imageUrl: string, imageId: string, userId: st }); const data = await response.json(); + console.log(data); - // Convert base64 to buffer - const base64Image = data.visualisation.replace(/^data:image\/\w+;base64,/, ''); + + const base64Image = data.visualization.replace(/^data:image\/\w+;base64,/, ''); const buffer = Buffer.from(base64Image, 'base64'); - - // Upload processed image to bucket + const processedImageFileName = `${Date.now()}-${userId}-processed-${imageName}.png`; const processedImageUrl = await projectClient.uploadFile( buffer, processedImageFileName ); - // Save analysis results to database - const analysis = await prisma.wasteAnalysis.create({ - data: { - imageId, - totalWeightKg: data.total_stats.total_weight_kg, - wasteCoverage: data.total_stats.waste_coverage, - distributionEvenness: data.total_stats.distribution_evenness, - compositions: { - create: [ - { - type: 'RIGID_PLASTIC', - present: data.waste_composition.rigid_plastic.present, - pixelCount: data.waste_composition.rigid_plastic.pixel_count, - areaPercentage: data.waste_composition.rigid_plastic.area_percentage, - estimatedWeightKg: data.waste_composition.rigid_plastic.estimated_weight_kg, - }, - { - type: 'CARDBOARD', - present: data.waste_composition.cardboard.present, - pixelCount: data.waste_composition.cardboard.pixel_count, - areaPercentage: data.waste_composition.cardboard.area_percentage, - estimatedWeightKg: data.waste_composition.cardboard.estimated_weight_kg, - }, - { - type: 'METAL', - present: data.waste_composition.metal.present, - pixelCount: data.waste_composition.metal.pixel_count, - areaPercentage: data.waste_composition.metal.area_percentage, - estimatedWeightKg: data.waste_composition.metal.estimated_weight_kg, - }, - { - type: 'SOFT_PLASTIC', - present: data.waste_composition.soft_plastic.present, - pixelCount: data.waste_composition.soft_plastic.pixel_count, - areaPercentage: data.waste_composition.soft_plastic.area_percentage, - estimatedWeightKg: data.waste_composition.soft_plastic.estimated_weight_kg, - }, - ], - }, - }, - }); + // const analysis = await prisma.wasteAnalysis.create({ + // data: { + // imageId, + // totalWeightKg: data.total_stats.total_weight_kg, + // wasteCoverage: data.total_stats.waste_coverage, + // distributionEvenness: data.total_stats.distribution_evenness, + // compositions: { + // create: [ + // { + // type: 'RIGID_PLASTIC', + // present: data.waste_composition.rigid_plastic.present, + // pixelCount: data.waste_composition.rigid_plastic.pixel_count, + // areaPercentage: data.waste_composition.rigid_plastic.area_percentage, + // estimatedWeightKg: data.waste_composition.rigid_plastic.estimated_weight_kg, + // }, + // { + // type: 'CARDBOARD', + // present: data.waste_composition.cardboard.present, + // pixelCount: data.waste_composition.cardboard.pixel_count, + // areaPercentage: data.waste_composition.cardboard.area_percentage, + // estimatedWeightKg: data.waste_composition.cardboard.estimated_weight_kg, + // }, + // { + // type: 'METAL', + // present: data.waste_composition.metal.present, + // pixelCount: data.waste_composition.metal.pixel_count, + // areaPercentage: data.waste_composition.metal.area_percentage, + // estimatedWeightKg: data.waste_composition.metal.estimated_weight_kg, + // }, + // { + // type: 'SOFT_PLASTIC', + // present: data.waste_composition.soft_plastic.present, + // pixelCount: data.waste_composition.soft_plastic.pixel_count, + // areaPercentage: data.waste_composition.soft_plastic.area_percentage, + // estimatedWeightKg: data.waste_composition.soft_plastic.estimated_weight_kg, + // }, + // ], + // }, + // }, + // }); await prisma.image.update({ where: { id: imageId }, @@ -72,7 +71,6 @@ export async function processImage(imageUrl: string, imageId: string, userId: st return { processedImageUrl, - analysis }; } catch (error) { console.error("Error analyzing waste:", error); From 97566963f78534cbb48272aa86fbcbdc90f33243 Mon Sep 17 00:00:00 2001 From: Mahendra785 Date: Sat, 8 Feb 2025 17:23:39 +0530 Subject: [PATCH 5/5] stable --- app/actions/orgActions.ts | 5 -- app/components/mainpage.tsx | 10 +-- app/components/organization.tsx | 113 +++++++++++++++++++++----------- app/components/tooltip.tsx | 66 ------------------- app/components/upload.tsx | 17 +---- app/page.tsx | 2 +- app/signout/page.tsx | 24 +++++++ package-lock.json | 10 +++ package.json | 1 + 9 files changed, 114 insertions(+), 134 deletions(-) delete mode 100644 app/components/tooltip.tsx create mode 100644 app/signout/page.tsx diff --git a/app/actions/orgActions.ts b/app/actions/orgActions.ts index 80ef80c..6aacb73 100644 --- a/app/actions/orgActions.ts +++ b/app/actions/orgActions.ts @@ -3,11 +3,6 @@ import { auth } from "@/app/(auth)/auth"; import { CreateOrganizationType } from "@/lib/validation/schema"; export async function createOrg(body: CreateOrganizationType) { - const session = await auth(); - const user = session?.user; - if (!user) { - //do something - } const org = await prisma.organization.create({ data: { name: body.name, diff --git a/app/components/mainpage.tsx b/app/components/mainpage.tsx index 6745950..2238df5 100644 --- a/app/components/mainpage.tsx +++ b/app/components/mainpage.tsx @@ -9,7 +9,7 @@ export default function Home() { const [showButton, setShowButton] = useState(false); const handleSignIn = async () => { try { - await Signin(); // ✅ Redirects to /upload after signing in + await Signin(); } catch (error) { console.error("Error during sign-in:", error); } finally { @@ -17,8 +17,8 @@ export default function Home() { }; useEffect(() => { - setTimeout(() => setAnimateText(true), 500); // Delay animation start - setTimeout(() => setShowButton(true), 2000); // Show button after text animation + setTimeout(() => setAnimateText(true), 500); + setTimeout(() => setShowButton(true), 2000); }, []); return ( @@ -29,8 +29,6 @@ export default function Home() { fill className="object-cover opacity-50" /> - - {/* Animated Text */} SORT IQ - - {/* Animated Button */} {showButton && ( { const [isExpanded, setIsExpanded] = useState(false); const [activeFeature, setActiveFeature] = useState(null); + const [isMobile, setIsMobile] = useState(false); const sidebarRef = useRef(null); + // Handle screen resize + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth < 768); + if (window.innerWidth < 768) { + setIsExpanded(false); + } + }; + + handleResize(); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + const handleClickOutside = (event: MouseEvent) => { if ( sidebarRef.current && @@ -25,64 +40,71 @@ const Organization: React.FC = () => { return () => { document.removeEventListener("mousedown", handleClickOutside); }; - }, [sidebarRef]); // Added sidebarRef to dependencies + }, [sidebarRef]); const features = [ - { name: "Feature 1", icon: "/feat1.svg", component: }, { - name: "Feature 2", + name: "Live Video Stream", + icon: "/feat1.svg", + component: , + }, + { + name: "History ", icon: "/feat2.svg", - component:
Feature 2 Content
, + component:
History
, }, { - name: "Feature 3", + name: "Analytics", icon: "/feat3.svg", - component:
Feature 3 Content
, + component:
Analytics
, }, { - name: "Feature 4", + name: "Organization", icon: "/feat4.svg", - component:
Feature 4 Content
, + component:
Organization
, }, { - name: "Feature 5", + name: "ESG Reports", icon: "/feat5.svg", - component:
Feature 5 Content
, + component:
ESG Reports
, }, { - name: "Feature 6", + name: "Custom Reports ", icon: "/feat6.svg", - component:
Feature 6 Content
, + component:
Custom Reports
, }, { - name: "Feature 7", + name: "Performance Reports", icon: "/feat7.svg", - component:
Feature 7 Content
, + component:
Performance Reports
, }, ]; return ( -
+
CentralHack -
+
Sort IQ
-
- {/* Left Box (Sidebar) */} +
+ {/* Sidebar */}
- {isExpanded ? ( -
-
+ {isExpanded && !isMobile ? ( +
+
expand { className="hover:scale-[1.04] cursor-pointer" onClick={() => setIsExpanded(!isExpanded)} /> -
Features
+
+ Features +
-
+
{features.map((feature, index) => (
setActiveFeature(index)} > { height={70} className="hover:scale-[1.04]" /> -
{feature.name}
+
{feature.name}
))}
) : ( -
- expand setIsExpanded(!isExpanded)} - /> +
+ {!isMobile && ( + expand setIsExpanded(!isExpanded)} + /> + )} {features.map((feature, index) => (
{ {feature.name} + {isMobile && ( +
{feature.name}
+ )}
))}
)}
- {/* Right Box */} -
+ {/* Main Content */} +
{activeFeature !== null && features[activeFeature].component}
diff --git a/app/components/tooltip.tsx b/app/components/tooltip.tsx deleted file mode 100644 index cb393e3..0000000 --- a/app/components/tooltip.tsx +++ /dev/null @@ -1,66 +0,0 @@ -"use client"; - -import React, { useState, useRef, useEffect } from "react"; - -interface TooltipProps { - content: string; - children: React.ReactNode; -} - -const Tooltip: React.FC = ({ content, children }) => { - const [isVisible, setIsVisible] = useState(false); - const [position, setPosition] = useState({ top: 0, left: 0 }); - const triggerRef = useRef(null); - const tooltipRef = useRef(null); - - useEffect(() => { - if (isVisible && triggerRef.current && tooltipRef.current) { - const triggerRect = triggerRef.current.getBoundingClientRect(); - const tooltipRect = tooltipRef.current.getBoundingClientRect(); - - // Position the tooltip below the icon - setPosition({ - top: triggerRect.bottom + window.scrollY + 10, // 10px below the trigger - left: - triggerRect.left + - window.scrollX + - triggerRect.width / 2 - // Centered horizontally based on the trigger - tooltipRect.width / 2, - }); - } - }, [isVisible]); - - return ( -
setIsVisible(true)} - onMouseLeave={() => setIsVisible(false)} - className="relative inline-block" - > - {children} - {isVisible && ( -
- {content} -
-
- )} -
- ); -}; - -export default Tooltip; diff --git a/app/components/upload.tsx b/app/components/upload.tsx index ea6bcb0..83b6eda 100644 --- a/app/components/upload.tsx +++ b/app/components/upload.tsx @@ -53,8 +53,7 @@ export default function FileUploadTest() { return (
-
- {/* File upload container */} +
- - {/* Display selected file */} {file && (

@@ -76,8 +73,6 @@ export default function FileUploadTest() {

)} - - {/* Upload button */}
- - {/* Error Message */} {error && (
{error}
)} - - {/* Success Message and Image Preview */} {uploadedUrl && (

@@ -109,10 +100,8 @@ export default function FileUploadTest() { {uploadedUrl} - {/* Image preview for uploaded images */} {uploadedUrl && (

- {/* If the uploaded file is an image, show the preview */} Uploaded preview )} - - {/* Image preview before uploading (optional feature) */} {file && file.type.startsWith("image/") && !uploadedUrl && (
)} {image && ( -
+
Preview{session ? : }
; } diff --git a/app/signout/page.tsx b/app/signout/page.tsx new file mode 100644 index 0000000..21a4390 --- /dev/null +++ b/app/signout/page.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import SignOut from "../(auth)/authactions/signout"; + +export default function SignOutPage() { + const router = useRouter(); + + const handleSignOut = async () => { + await SignOut(); + router.push("/"); + }; + + return ( +
+ +
+ ); +} diff --git a/package-lock.json b/package-lock.json index d4a4e7d..299e825 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@types/multer": "^1.4.12", "formidable": "^3.5.2", "framer-motion": "^12.4.1", + "lucide-react": "^0.475.0", "multer": "^1.4.5-lts.1", "next": "15.1.6", "next-auth": "^5.0.0-beta.25", @@ -4715,6 +4716,15 @@ "dev": true, "license": "ISC" }, + "node_modules/lucide-react": { + "version": "0.475.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.475.0.tgz", + "integrity": "sha512-NJzvVu1HwFVeZ+Gwq2q00KygM1aBhy/ZrhY9FsAgJtpB+E4R7uxRk9M2iKvHa6/vNxZydIB59htha4c2vvwvVg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", diff --git a/package.json b/package.json index 362e3fc..42543d8 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@types/multer": "^1.4.12", "formidable": "^3.5.2", "framer-motion": "^12.4.1", + "lucide-react": "^0.475.0", "multer": "^1.4.5-lts.1", "next": "15.1.6", "next-auth": "^5.0.0-beta.25",