import React, { useEffect, useState } from 'react'
import Image from 'next/image'
import underline from "../Image/underline.png"
import Link from "next/link"
import { useUser } from '@clerk/clerk-react'
import { ClerkProvider } from '@clerk/nextjs'
import { Github } from 'lucide-react'
import DialogViewer from "../Components/Dialog"
import { FaTrashAlt } from "react-icons/fa";
import { MdEdit } from "react-icons/md";
const FormDisplay = () => {
const { isLoaded, user } = useUser()
console.log(user)
const [formdata, setFormdata] = useState({
name_project: "",
desc_project: "",
url_project: "",
name_comp: "",
date_comp: "",
url_comp: "",
image_url: "",
website_url: ""
})
let name, value;
const handleInput = (e) => {
name = e.target.name;
value = e.target.value;
setFormdata({ ...formdata, [name]: value })
}
const submit = async (e) => {
e.preventDefault()
const { name_project, desc_project, url_project, name_comp, date_comp, url_comp, image_url, website_url } = formdata
const formData = {
"name_project": name_project,
"desc_project": desc_project,
"url_project": url_project,
"prizes": [
{
"name_comp": name_comp,
"date_comp": date_comp,
"url_comp": url_comp
}
],
"image_url": image_url,
"website_url": website_url,
"clerkID": user.id
}
const response = await fetch("/api/addProject", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData)
})
const result = await response.json()
console.log(result)
if (result.success === true) {
window.location.reload()
}
}
return (
<div className='w-auto pl-5'>
<form action="">
<br />
<div className='flex gap-2 text-lg font-bold text-black '><p className='w-56 text-left pl-5'>Title:</p> <input type="text" name="name_project" id="name_project" onChange={handleInput} placeholder='Enter Title...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Description:</p> <textarea name="desc_project" id="desc_project" onChange={handleInput} placeholder='Enter Description...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Project URL:</p> <input type="text" name="url_project" id="url_project" onChange={handleInput} placeholder='Enter Project URL...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Image URL:</p> <input type="text" name="image_url" id="image_url" onChange={handleInput} placeholder='Enter Image URL...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Website URL:</p> <input type="text" name="website_url" id="website_url" onChange={handleInput} placeholder='Enter Website URL...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Name of Competition:</p> <input type="text" name="name_comp" id="name_comp" onChange={handleInput} placeholder='Enter Name of Competition...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Date of Competition:</p> <input type="text" name="date_comp" id="name_comp" onChange={handleInput} placeholder='Enter Date of Competition...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>URL of Competition:</p> <input type="text" name="url_comp" id="url_comp" onChange={handleInput} placeholder='Enter URL of Competition...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<button className='bg-black text-white font-bold px-4 py-2 rounded-md mt-8' onClick={submit}>Submit</button>
</form>
</div>
)
}
const Page = () => {
const [projectData, setprojectData] = useState(null)
const [runned, setRunned] = useState(false)
const { isLoaded, user } = useUser()
const [selectedProjectId, setSelectedProjectId] = useState(null);
const getProjectData = async () => {
if (!runned) {
try {
const response = await fetch("/api/getProject");
const data = await response.json();
setprojectData(data.data);
// console.log("Fetched Data:", data);
setRunned(true);
} catch (error) {
console.error("Cannot fetch data: ", error);
}
}
};
const deleteData = async (item) => {
const _id = item.currentTarget.id
console.log(_id)
const confirmed = window.confirm("Are you sure you want to delete this project?")
if (confirmed == true) {
try {
const response = await fetch("/api/deleteProject", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ _id: _id })
})
const data = await response.json()
console.log(data)
if (data.success === true) {
window.location.reload()
}
} catch (error) {
console.log("Cannot delete the project: ", error)
}
}
}
useEffect(() => {
getProjectData();
}, []);
const Edit_FormDisplay = (item) => {
const [data, setData] = useState()
const [formdata, setFormdata] = useState({
name_project: "",
desc_project: "",
url_project: "",
name_comp: "",
date_comp: "",
url_comp: "",
image_url: "",
website_url: ""
})
useEffect(() => {
const fetchOneProjectData = async () => {
const _id = item.currentTarget.id
console.log(_id)
try {
const response = await fetch("/api/getOneProject", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ _id: _id })
})
const result = await response.json()
console.log(result)
setData(result.data)
} catch (error) {
console.log("Cannot delete the project: ", error)
}
}
fetchOneProjectData()
}, [item])
useEffect(() => {
if (data) {
setFormdata({
name_project: data.name_project || "",
desc_project: data.desc_project || "",
url_project: data.url_project || "",
name_comp: data.prizes?.[0]?.name_comp || "",
date_comp: data.prizes?.[0]?.date_comp || "",
url_comp: data.prizes?.[0]?.url_comp || "",
image_url: data.image_url || "",
website_url: data.website_url || ""
});
}
}, [data]);
const handleInput = (e) => {
const { name, value } = e.target;
setFormdata({ ...formdata, [name]: value });
};
const submit = async (e) => {
e.preventDefault();
const { name_project, desc_project, url_project, name_comp, date_comp, url_comp, image_url, website_url } = formdata;
const formData = {
name_project,
desc_project,
url_project,
prizes: [
{
name_comp,
date_comp,
url_comp
}
],
image_url,
website_url,
};
try {
const response = await fetch("/api/editProject", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData)
});
const result = await response.json();
console.log(result);
if (result.success) {
window.location.reload();
}
} catch (error) {
console.log("Error editing project:", error);
}
}
return (
<div className='w-auto pl-5'>
<form action="">
<br />
<div className='flex gap-2 text-lg font-bold text-black '><p className='w-56 text-left pl-5'>Title:</p> <input type="text" name="name_project" id="name_project" onChange={handleInput} placeholder='Enter Title...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Description:</p> <textarea name="desc_project" id="desc_project" onChange={handleInput} placeholder='Enter Description...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Project URL:</p> <input type="text" name="url_project" id="url_project" onChange={handleInput} placeholder='Enter Project URL...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Image URL:</p> <input type="text" name="image_url" id="image_url" onChange={handleInput} placeholder='Enter Image URL...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Website URL:</p> <input type="text" name="website_url" id="website_url" onChange={handleInput} placeholder='Enter Website URL...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Name of Competition:</p> <input type="text" name="name_comp" id="name_comp" onChange={handleInput} placeholder='Enter Name of Competition...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>Date of Competition:</p> <input type="text" name="date_comp" id="name_comp" onChange={handleInput} placeholder='Enter Date of Competition...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<div className='flex gap-2 text-lg font-bold text-black mt-3'><p className='w-56 text-left pl-5'>URL of Competition:</p> <input type="text" name="url_comp" id="url_comp" onChange={handleInput} placeholder='Enter URL of Competition...' className='bg-white px-2 rounded-md text-box font-normal text-base' /></div>
<button className='bg-black text-white font-bold px-4 py-2 rounded-md mt-8' onClick={submit}>Submit</button>
</form>
</div>
)
}
return (
<div className='bg-black sm:h-auto h-auto w-auto pt-16 text-white border-b-2 border-gray-600 scale-100 '>
<h1 className='cedarville-cursive-regular text-4xl font-extrabold tracking-wide text-center mt-5 mb-14'>My Projects</h1>
<div className='w-auto text-right mr-8'>
{!user ? "" : !user.publicMetadata.role ? "" : user.publicMetadata.role === "admin" ? <DialogViewer trigger_name={"+ Add New Project"} title={"Add a New Project"} description={"Fill the following fields to create/add a new project"} formElement={<FormDisplay />} /> : ""}
</div>
<Image src={underline} width={470} height={50} alt='underline' className='brightness-[100] absolute top-[6.7rem] left-[32rem] scale-75'></Image>
{projectData === null ? (<div> Loading.... </div>) :
(Array.isArray(projectData) && projectData.map((data) => {
return (
<div className='flex bg-gray-600 bg-opacity-50 m-3 rounded-lg h-96 scale-[98%] hover:scale-100 transition-all h-auto' key={data.name_project}>
<div className='w-[50%] p-7'>
<div className="relative w-[500px] h-[300px]" style={{ backgroundImage: `url(${data.image_url})`, backgroundSize: "contain", backgroundRepeat: "no-repeat", backgroundPosition: "center" }}>
{/* <Image
src={data.image_url}
fill // ✅ Makes the image fill the container
className="rounded-lg object-cover"
alt="card-image"
/> */}
</div>
</div>
<div className='w-[70%] p-7'>
<div className="w-[100%] text-right flex gap-3 justify-end ">
{!user ? "" : !user.publicMetadata.role ? "" : user.publicMetadata.role === "admin" ?
<button className='text-red-500 bg-black w-8 h-8 text-center rounded-md pl-2' id={data._id} onClick={deleteData}><FaTrashAlt /></button>
: ""}
{!user ? "" : !user.publicMetadata.role ? "" : user.publicMetadata.role === "admin" ? <button
onClick={Edit_FormDisplay}
id={data._id}
className="bg-black text-green-500 h-8 w-auto font-bold rounded-lg px-2"
><DialogViewer trigger_name={<MdEdit />} title={"Edit an existing Project"} description={"Fill the following fields to edit a new project"} formElement={<Edit_FormDisplay />} /></button> : ""}
</div>
<div className='flex mb-7'>
<div className='w-[65%] border-r-2 border-r-white mr-3'>
<h2 className='text-white text-3xl font-extrabold tracking-wider mb-5 border-b-2 border-r-white mr-3 w-40'>{data.name_project}</h2>
<p>{data.desc_project}</p>
</div>
<div>
<h3 className='text-red-400 text-xl font-extrabold tracking-wide mb-5 border-b-2 border-b-white mr-3 w-20'>Prizes</h3>
<p className=''>
{Array.isArray(data.prizes) && data.prizes.map((data) => {
console.log(data)
return (
<>
<div className='flex' key={data.name_comp}><p>Name: </p><p className='cursor-pointer text-blue-600' >{data.name_comp}</p></div>
<p className='font-bold'>Participated in: {data.date_comp}</p>
</>
)
})}
</p>
</div>
</div>
<Link href={data.url_project} target='_blank'><button className='bg-green-500 text-black h-9 w-44 font-bold rounded-lg'><div className='flex'><Github className="h-5 w-5 pt-1 ml-3" /> View On Github</div></button></Link>
<Link href={data.website_url} target='_blank'><button className='bg-green-500 text-black h-9 w-32 font-bold rounded-lg'>Visit Website</button></Link>
</div>
</div>
)
}))}
</div>
)
}
export default Page
This is the Dialog Viewer
import React from 'react'
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/components/ui/dialog"
const DialogViewer = ({ trigger_name, title, description, formElement }) => {
return (
<div>
<Dialog className="text-black w-96">
{trigger_name === "+ Add New Project"
? (
<DialogTrigger className='bg-green-500 text-black h-9 w-auto font-bold rounded-lg px-2'>
{trigger_name}
</DialogTrigger>
)
: (
<div className="bg-black text-green-500 h-8 w-auto font-bold rounded-lg px-2">
<DialogTrigger>
{trigger_name}
</DialogTrigger>
</div>
)
}
<DialogContent className='text-black'>
<DialogHeader>
<DialogTitle className='text-black text-2xl font-extrabold text-center'>{title}</DialogTitle>
<DialogDescription className='text-lg'>
<p className='text-center'>{description}</p>
{formElement}
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
</div>
)
}
export default DialogViewer
I have been trying to implement a page where I can display all the projects from the MongoDB database and perform all crud operations. The create, read, and delete functions are working fine. But when it comes to the edit part it is becoming a bit complex.
I am also getting this error: –
This error is according to me related to the function EditFormDisplay which is being called by a button. What can be an alternate method for this?
Error message: –
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app
See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.
For Your Info Dialog Viewer is taken from Schad cn UI which I made a separate component and its details are the props that I can pass from any component according to my need where I need to use it.
Please help me solve the problem in the above image
