From 72d485e265b4435a12e49c5631d251db1690ca26 Mon Sep 17 00:00:00 2001 From: Prajyot Tayde Date: Tue, 25 Mar 2025 11:51:15 +0530 Subject: [PATCH 1/8] route --- app/api/user/[id]/route.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/api/user/[id]/route.ts b/app/api/user/[id]/route.ts index c17900e..6e3e8a7 100644 --- a/app/api/user/[id]/route.ts +++ b/app/api/user/[id]/route.ts @@ -4,11 +4,11 @@ import User from "@/app/models/User"; import { auth } from "@/app/auth"; export async function GET(req: NextRequest, context: any) { - const session = await auth(); + // const session = await auth(); - if (!session) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } + // if (!session) { + // return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + // } const {params} = context; const id = (await params).id; From 2ec91481064e31a8bf436ae27364e52c15b2d1fc Mon Sep 17 00:00:00 2001 From: Prajyot Tayde Date: Thu, 25 Sep 2025 19:15:36 +0530 Subject: [PATCH 2/8] minor bug fixes --- app/(root)/application/page.tsx | 3 +- app/(root)/components/Hero.tsx | 2 +- app/(root)/leaderboard/c/page.tsx | 14 +++--- app/(root)/project/ProjectList.tsx | 44 +++------------- app/(root)/project/[id]/Detail.tsx | 50 +++---------------- app/(root)/project/[id]/Sidebar2.tsx | 5 +- app/(root)/project/create/[id]/page.tsx | 2 +- app/actions/requestActions.ts | 45 +++++++++++++++++ .../join/[user_id]/[project_id]/route.ts | 10 ++-- .../request/[user_id]/[project_id]/route.ts | 4 +- app/api/list/all/route.ts | 2 +- app/api/list/request/[project_id]/route.ts | 4 +- app/models/JionRequest.ts | 24 --------- app/models/JoinRequest.ts | 28 +++++++++++ app/types/projects.ts | 11 ++++ app/utils/userActions.ts | 3 +- 16 files changed, 121 insertions(+), 130 deletions(-) create mode 100644 app/actions/requestActions.ts delete mode 100644 app/models/JionRequest.ts create mode 100644 app/models/JoinRequest.ts create mode 100644 app/types/projects.ts diff --git a/app/(root)/application/page.tsx b/app/(root)/application/page.tsx index b1f867f..fdaa7d8 100644 --- a/app/(root)/application/page.tsx +++ b/app/(root)/application/page.tsx @@ -10,7 +10,8 @@ const tabContents = [ , ]; -const Page = () => { +const Page = async () => { + // const requests = await fetchJoinRequests() const tabTitles = ["Submitted(56)", "Bookmarks(23)", "Rejected(23)"]; return (
diff --git a/app/(root)/components/Hero.tsx b/app/(root)/components/Hero.tsx index ad06802..80404cc 100644 --- a/app/(root)/components/Hero.tsx +++ b/app/(root)/components/Hero.tsx @@ -20,7 +20,7 @@ const Hero: React.FC = () => { const [exiting, setExiting] = useState(false); const [textEditing, setTextEditing] = useState(false); - console.log(textEditing); + console.log("", textEditing); const handleButtonClick = useCallback( (index: number): void => { diff --git a/app/(root)/leaderboard/c/page.tsx b/app/(root)/leaderboard/c/page.tsx index bc50987..620a58b 100644 --- a/app/(root)/leaderboard/c/page.tsx +++ b/app/(root)/leaderboard/c/page.tsx @@ -4,9 +4,9 @@ const page = () => { const data = [ { rank: "#1", - name: "Pranav Ramane", + name: "Mayur Tummewar", institute: "Pimpri Chinchwad College of Engineering & Research", - points: 3000, + points: 69420, }, { rank: "#2", @@ -28,19 +28,19 @@ const page = () => { }, { rank: "#5", - name: "Mayur Tummewar", + name: "Pranav Ramane", institute: "Pimpri Chinchwad College of Engineering & Research", points: 3000, }, { - rank: "#2", - name: "Adarsh Thakare", + rank: "#6", + name: "Udit Padhye", institute: "Pimpri Chinchwad College of Engineering & Research", points: 3000, }, { - rank: "#3", - name: "Prajyot Tayde", + rank: "#7", + name: "Vansh Khakule", institute: "Pimpri Chinchwad College of Engineering & Research", points: 3000, }, diff --git a/app/(root)/project/ProjectList.tsx b/app/(root)/project/ProjectList.tsx index bcc9ea8..184608a 100644 --- a/app/(root)/project/ProjectList.tsx +++ b/app/(root)/project/ProjectList.tsx @@ -5,49 +5,16 @@ import React, { useState, useEffect } from "react"; import Link from "next/link"; import { IoLocationOutline } from "react-icons/io5"; import axios from "axios"; -// const projects = [ -// { -// id: 1, -// title: "E-Commerce Website", -// domain: "Web Development", -// location: "Pccoer Ravet", -// description: -// "A full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features an admin panel for managing inventory, orders, and user accounts, along with search and filtering capabilities for an enhanced shopping experienceA full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features A full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features an admin panel for managing inventory, orders, and user accounts, along with search and filtering capabilities for an enhanced shopping experienceA full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features A full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features an admin panel for managing inventory, orders, and user accounts, along with search and filtering capabilities for an enhanced shopping experienceA full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features ", -// }, -// { -// id: 2, -// title: "AI Chatbot", -// domain: "Machine Learning", -// location: "MIT Pune", -// description: -// "A chatbot powered by AI to assist with customer queries and automate responses. It uses NLP to understand user intent, providing instant and accurate replies. The chatbot integrates with multiple platforms like websites and messaging apps, helping businesses reduce response time and improve customer engagement through continuous learning and smart recommendations.", -// }, -// { -// id: 3, -// title: "IoT Smart Home", -// domain: "Internet of Things", -// location: "COEP Pune", -// description: -// "An IoT-based smart home system to control and monitor devices remotely. It enables users to automate lighting, security cameras, and appliances using a mobile app. With real-time data analytics and voice assistant integration, the system enhances convenience, energy efficiency, and security while allowing remote access and control from anywhere in the world.", -// }, -// ]; - -interface Project { - _id: number; - title: string; - domain: string; - location: string; - description: string; - instituteName?: string; -} +import { Project } from "@/app/types/projects"; const ProjectList = () => { const [projects, setProjects] = useState([]); const getData = async () => { try { - const response = await axios.get(`http://localhost:3000/api/list/all`); - console.log(response.data); + const response = await axios.get( + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/list/all` + ); setProjects(response.data); } catch (error) { console.error("Error fetching projects:", error); @@ -102,10 +69,11 @@ const ProjectList = () => {
{project.title}
+
{project.link}
Domains :{" "} - {project.domain} + {project.domains}
diff --git a/app/(root)/project/[id]/Detail.tsx b/app/(root)/project/[id]/Detail.tsx index 006e37e..1e032e5 100644 --- a/app/(root)/project/[id]/Detail.tsx +++ b/app/(root)/project/[id]/Detail.tsx @@ -3,56 +3,20 @@ import React, { useState, useEffect, useCallback } from "react"; import { IoShareSocialSharp } from "react-icons/io5"; import { FaRegBookmark } from "react-icons/fa"; import axios from "axios"; -// const projects = [ -// { -// id: 1, -// title: "E-Commerce Website", -// domain: "Web Development", -// location: "Pccoer Ravet", -// description: -// "A full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features an admin panel for managing inventory, orders, and user accounts, along with search and filtering capabilities for an enhanced shopping experienceA full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features A full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features an admin panel for managing inventory, orders, and user accounts, along with search and filtering capabilities for an enhanced shopping experienceA full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features A full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features an admin panel for managing inventory, orders, and user accounts, along with search and filtering capabilities for an enhanced shopping experienceA full-stack e-commerce website with authentication and payment integration. Users can browse products, add them to a cart, and securely complete purchases using various payment methods. The platform features ", -// }, -// { -// id: 2, -// title: "AI Chatbot", -// domain: "Machine Learning", -// location: "MIT Pune", -// description: -// "A chatbot powered by AI to assist with customer queries and automate responses. It uses NLP to understand user intent, providing instant and accurate replies. The chatbot integrates with multiple platforms like websites and messaging apps, helping businesses reduce response time and improve customer engagement through continuous learning and smart recommendations.", -// }, -// { -// id: 3, -// title: "IoT Smart Home", -// domain: "Internet of Things", -// location: "COEP Pune", -// description: -// "An IoT-based smart home system to control and monitor devices remotely. It enables users to automate lighting, security cameras, and appliances using a mobile app. With real-time data analytics and voice assistant integration, the system enhances convenience, energy efficiency, and security while allowing remote access and control from anywhere in the world.", -// }, -// ]; +import { Project } from "@/app/types/projects"; + type DetailProps = { id: string; }; -interface Project { - id: number; - title: string; - domain: string; - location: string; - description: string; - requirements: string; - responsibilities: string; - instituteName?: string; -} - const Detail = ({ id }: DetailProps) => { const [project, setProject] = useState(); const getData = useCallback(async () => { try { const response = await axios.get( - `http://localhost:3000/api/project/project_id/${id}` + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/project/project_id/${id}` ); - console.log(response.data); setProject(response.data); } catch (error) { console.error("Error fetching projects:", error); @@ -69,7 +33,7 @@ const Detail = ({ id }: DetailProps) => { return (
@@ -114,7 +78,7 @@ const Detail = ({ id }: DetailProps) => {
Domains : - {project.domain} + {project.domains}
{project.location}
@@ -146,7 +110,7 @@ const Detail = ({ id }: DetailProps) => {
{/* Attachments */} -
+ {/*
Attachments:
@@ -157,7 +121,7 @@ const Detail = ({ id }: DetailProps) => {
Untitled Document
-
+
*/}
); diff --git a/app/(root)/project/[id]/Sidebar2.tsx b/app/(root)/project/[id]/Sidebar2.tsx index 806ecc2..eb4914c 100644 --- a/app/(root)/project/[id]/Sidebar2.tsx +++ b/app/(root)/project/[id]/Sidebar2.tsx @@ -31,7 +31,6 @@ const Sidebar2 = ({ id }: DetailProps) => { const email = "email"; const dta = ["Rohit", "Adarsh"]; - console.log("Teammates:", teammates); //get current user data const getUserData = async () => { try { @@ -39,7 +38,6 @@ const Sidebar2 = ({ id }: DetailProps) => { `${process.env.NEXT_PUBLIC_API_URL}/api/user/${email}` ); setCurrentUser(response.data); - console.log(response.data); } catch (error) { console.error("Error fetching user data:", error); } @@ -50,12 +48,11 @@ const Sidebar2 = ({ id }: DetailProps) => { const response = await axios.get( `${process.env.NEXT_PUBLIC_API_URL}/api/project/project_id/${id}` ); - console.log(response.data); setProject(response.data); } catch (error) { console.error("Error fetching projects:", error); } - }, [id]); // <-- dependencies used inside getData + }, [id]); const getTeammates = useCallback(async () => { if (!project?.team) return; diff --git a/app/(root)/project/create/[id]/page.tsx b/app/(root)/project/create/[id]/page.tsx index 1ed9444..f851f35 100644 --- a/app/(root)/project/create/[id]/page.tsx +++ b/app/(root)/project/create/[id]/page.tsx @@ -40,7 +40,7 @@ const CreatePage = () => { console.log("id: ", id); const res = await axios.post( - `http://localhost:3000/api/project/user_id/${id}`, + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/project/user_id/${id}`, formData, { headers: { diff --git a/app/actions/requestActions.ts b/app/actions/requestActions.ts new file mode 100644 index 0000000..3a0de0c --- /dev/null +++ b/app/actions/requestActions.ts @@ -0,0 +1,45 @@ +"use server"; + +import axios from "axios"; +import { auth } from "../auth"; // Adjust the path to your auth file if needed + +/** + * Fetches all join requests for a given project ID. + * Requires the user to be authenticated. + * @param {string} projectId - The ID of the project to fetch requests for. + * @returns {Promise>} A promise that resolves to an array of join requests. + * @throws {Error} If the user is not authenticated or if the fetch fails. + */ +export async function fetchJoinRequestsForProject(projectId: string) { + const session = await auth(); + if (!session?.user) { + // Throws an error if the user is not logged in. + throw new Error( + "Unauthorized: User must be signed in to fetch join requests." + ); + } + + try { + // NOTE: The API path '/api/join-requests/' is inferred from your model name "JoinRequest". + // Please adjust this path if your actual API route is different. + const { data: requests } = await axios.get( + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/list/requests/${projectId}` + ); + + return requests; + } catch (error) { + if (axios.isAxiosError(error)) { + // Handles specific Axios errors (e.g., 404 Not Found, 500 Server Error) + console.error( + "Axios Error fetching join requests:", + error.response?.data || error.message + ); + } else { + // Handles other types of errors + console.error("Unexpected error fetching join requests:", error); + } + + // Throws a new, standardized error to the component that called this action. + throw new Error("Failed to fetch join requests."); + } +} diff --git a/app/api/linkage/join/[user_id]/[project_id]/route.ts b/app/api/linkage/join/[user_id]/[project_id]/route.ts index 5777666..b18e8c0 100644 --- a/app/api/linkage/join/[user_id]/[project_id]/route.ts +++ b/app/api/linkage/join/[user_id]/[project_id]/route.ts @@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server"; import { connectDB } from "@/app/lib/db"; import Projects from "@/app/models/Projects"; import User from "@/app/models/User"; -import JionRequest from "@/app/models/JionRequest"; +import JoinRequest from "@/app/models/JoinRequest"; export async function POST( req: NextRequest, @@ -43,11 +43,11 @@ export async function POST( project.team.push(user_id); await project.save(); - const jionRequest = await JionRequest.findOneAndDelete({ + const JoinRequest = await JoinRequest.findOneAndDelete({ user: user_id, project: project_id, }); - if (!jionRequest) { + if (!JoinRequest) { return NextResponse.json( { message: "Request not found" }, { status: 404 } @@ -59,11 +59,11 @@ export async function POST( { status: 200 } ); } else { - const jionRequest = await JionRequest.findOneAndDelete({ + const JoinRequest = await JoinRequest.findOneAndDelete({ user: user_id, project: project_id, }); - if (!jionRequest) { + if (!JoinRequest) { return NextResponse.json( { message: "Request not found" }, { status: 404 } diff --git a/app/api/linkage/request/[user_id]/[project_id]/route.ts b/app/api/linkage/request/[user_id]/[project_id]/route.ts index 48fce54..78a1bd0 100644 --- a/app/api/linkage/request/[user_id]/[project_id]/route.ts +++ b/app/api/linkage/request/[user_id]/[project_id]/route.ts @@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server"; import { connectDB } from "@/app/lib/db"; import Projects from "@/app/models/Projects"; import User from "@/app/models/User"; -import JionRequest from "@/app/models/JionRequest"; +import JoinRequest from "@/app/models/JoinRequest"; //request to join export async function POST( req: NextRequest, @@ -45,7 +45,7 @@ export async function POST( ); } - const joinRequest = await JionRequest.create({ + const joinRequest = await JoinRequest.create({ project: project_id, user: user_id, }); diff --git a/app/api/list/all/route.ts b/app/api/list/all/route.ts index ee5fbbd..3ab3209 100644 --- a/app/api/list/all/route.ts +++ b/app/api/list/all/route.ts @@ -12,7 +12,7 @@ export async function GET() { try { await connectDB(); - const list = await Projects.find({}).select("-team -owner"); + const list = (await Projects.find({}).select("-team -owner")).reverse(); return NextResponse.json(list, { status: 200 }); } catch (error) { return NextResponse.json( diff --git a/app/api/list/request/[project_id]/route.ts b/app/api/list/request/[project_id]/route.ts index df9b163..3858ed9 100644 --- a/app/api/list/request/[project_id]/route.ts +++ b/app/api/list/request/[project_id]/route.ts @@ -1,5 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; -import JionRequest from "@/app/models/JionRequest"; +import JoinRequest from "@/app/models/JoinRequest"; //get all the requests export async function GET( @@ -13,7 +13,7 @@ export async function GET( try { const { params } = context; const id = (await params).project_id; - const list = await JionRequest.find({ project: id }).populate( + const list = await JoinRequest.find({ project: id }).populate( "user", "name image" ); diff --git a/app/models/JionRequest.ts b/app/models/JionRequest.ts deleted file mode 100644 index a55f4c7..0000000 --- a/app/models/JionRequest.ts +++ /dev/null @@ -1,24 +0,0 @@ -import mongoose from "mongoose"; - -const JoinRequestSchema = new mongoose.Schema({ - project: { - type: mongoose.Schema.Types.ObjectId, - ref: "Project", - required: true, - }, - user:{ - type: mongoose.Schema.Types.ObjectId, - ref: "User", - required: true, - }, - attachment:{ - type: String, - }, - status:{ - type: String, - enum: ["pending", "accepted", "rejected"], - default: "pending", - }, -},{ timestamps: true }); - -export default mongoose.models.JoinRequest || mongoose.model("JoinRequest", JoinRequestSchema); \ No newline at end of file diff --git a/app/models/JoinRequest.ts b/app/models/JoinRequest.ts new file mode 100644 index 0000000..6abb54b --- /dev/null +++ b/app/models/JoinRequest.ts @@ -0,0 +1,28 @@ +import mongoose from "mongoose"; + +const JoinRequestSchema = new mongoose.Schema( + { + project: { + type: mongoose.Schema.Types.ObjectId, + ref: "Project", + required: true, + }, + user: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + required: true, + }, + attachment: { + type: String, + }, + status: { + type: String, + enum: ["pending", "accepted", "rejected"], + default: "pending", + }, + }, + { timestamps: true } +); + +export default mongoose.models.JoinRequest || + mongoose.model("JoinRequest", JoinRequestSchema); diff --git a/app/types/projects.ts b/app/types/projects.ts new file mode 100644 index 0000000..32e7d99 --- /dev/null +++ b/app/types/projects.ts @@ -0,0 +1,11 @@ +export interface Project { + _id: number; + title: string; + domains: string[]; + location: string; + description: string; + instituteName?: string; + link: string; + requirements: string; + responsibilities: string; +} diff --git a/app/utils/userActions.ts b/app/utils/userActions.ts index 2d3d827..3ef0cd7 100644 --- a/app/utils/userActions.ts +++ b/app/utils/userActions.ts @@ -7,8 +7,9 @@ export async function fetchUserData() { if (session?.user) { try { const { data: user } = await axios.get( - `http://localhost:3000/api/user/${session.user.id}` + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/user/${session.user.id}` ); + console.log("USER: ", user); return user; } catch (error) { if (axios.isAxiosError(error)) { From 1df4e6f3d66378fbed27f3a2a5c87e9ca4189ee5 Mon Sep 17 00:00:00 2001 From: Prajyot Tayde Date: Thu, 25 Sep 2025 23:36:06 +0530 Subject: [PATCH 3/8] add joining applications page and minor improvements --- app/(root)/components/SignInButton.tsx | 17 +- app/(root)/components/SignOutButton.tsx | 17 +- app/(root)/layout.tsx | 59 +++-- app/(root)/project/ProjectList.tsx | 42 +++- app/(root)/project/Sidebar1.tsx | 2 +- app/(root)/project/[id]/Detail.tsx | 56 ++--- app/(root)/project/[id]/Sidebar2.tsx | 204 ++++++++---------- app/(root)/project/[id]/requests/page.tsx | 121 +++++++++++ app/(root)/project/create/[id]/page.tsx | 100 +++------ app/api/linkage/accept/[request_id]/route.ts | 50 +++++ .../join/[user_id]/[project_id]/route.ts | 84 ++------ app/api/linkage/reject/[request_id]/route.ts | 45 ++++ app/api/list/all/route.ts | 9 +- app/api/list/request/[project_id]/route.ts | 47 ++-- .../project/project_id/[project_id]/route.ts | 131 ++--------- app/api/project/user_id/[user_id]/route.ts | 83 +++---- app/auth.ts | 8 + package-lock.json | 11 + package.json | 1 + 19 files changed, 584 insertions(+), 503 deletions(-) create mode 100644 app/(root)/project/[id]/requests/page.tsx create mode 100644 app/api/linkage/accept/[request_id]/route.ts create mode 100644 app/api/linkage/reject/[request_id]/route.ts diff --git a/app/(root)/components/SignInButton.tsx b/app/(root)/components/SignInButton.tsx index 5a95139..84ef738 100644 --- a/app/(root)/components/SignInButton.tsx +++ b/app/(root)/components/SignInButton.tsx @@ -1,10 +1,25 @@ "use client"; import { signIn } from "next-auth/react"; +import { useSession } from "next-auth/react"; export default function SignInButton() { + const { status } = useSession(); + + if (status === "loading") { + return ( + + ); + } + + if (status === "authenticated") { + return null; + } + return ( + ); + } + + if (status === "unauthenticated") { + return null; + } + return ( - {user ? : } + {user ? ( +
+ + User Profile + + +
+ ) : ( + + )}
diff --git a/app/(root)/project/ProjectList.tsx b/app/(root)/project/ProjectList.tsx index 184608a..70da385 100644 --- a/app/(root)/project/ProjectList.tsx +++ b/app/(root)/project/ProjectList.tsx @@ -6,23 +6,42 @@ import Link from "next/link"; import { IoLocationOutline } from "react-icons/io5"; import axios from "axios"; import { Project } from "@/app/types/projects"; +import { useSession } from "next-auth/react"; +import { useRouter } from "next/navigation"; const ProjectList = () => { + const { data: session, status } = useSession(); + const router = useRouter(); const [projects, setProjects] = useState([]); - const getData = async () => { - try { - const response = await axios.get( - `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/list/all` - ); - setProjects(response.data); - } catch (error) { - console.error("Error fetching projects:", error); - } - }; useEffect(() => { + if (status === "unauthenticated") { + router.push("/home"); + } + + const getData = async () => { + if (status === "authenticated") { + try { + const response = await axios.get( + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/list/all` + ); + setProjects(response.data); + } catch (error) { + console.error("Error fetching projects:", error); + } + } + }; + getData(); - }, []); + }, [session, status, router]); + + if (status === "loading") { + return
Loading...
; + } + + if (!session) { + return null; + } return (
@@ -104,3 +123,4 @@ const ProjectList = () => { }; export default ProjectList; + diff --git a/app/(root)/project/Sidebar1.tsx b/app/(root)/project/Sidebar1.tsx index 7ed00ff..d792f33 100644 --- a/app/(root)/project/Sidebar1.tsx +++ b/app/(root)/project/Sidebar1.tsx @@ -64,7 +64,7 @@ const Sidebar1 = () => { >
- 2000project found{" "} + 8project found{" "}
clear filter diff --git a/app/(root)/project/[id]/Detail.tsx b/app/(root)/project/[id]/Detail.tsx index 1e032e5..dd318f8 100644 --- a/app/(root)/project/[id]/Detail.tsx +++ b/app/(root)/project/[id]/Detail.tsx @@ -4,12 +4,15 @@ import { IoShareSocialSharp } from "react-icons/io5"; import { FaRegBookmark } from "react-icons/fa"; import axios from "axios"; import { Project } from "@/app/types/projects"; +import { useSession } from "next-auth/react"; +import Link from "next/link"; type DetailProps = { id: string; }; const Detail = ({ id }: DetailProps) => { + const { data: session } = useSession(); const [project, setProject] = useState(); const getData = useCallback(async () => { @@ -19,19 +22,22 @@ const Detail = ({ id }: DetailProps) => { ); setProject(response.data); } catch (error) { - console.error("Error fetching projects:", error); + console.error("Error fetching project:", error); } - }, [id, setProject]); // dependencies used inside getData + }, [id]); useEffect(() => { getData(); }, [getData]); if (!project) { - return
Project not found
; + return
Loading project details...
; } + + const isOwner = session?.user?.id === project.owner._id; + return ( -
+
{
{project.title}
- Domains : - {project.domains} + Domains: + {project.domains.join(", ")}
{project.location}
-
- - +
+ {isOwner && ( + + View Requests + + )} + +

Description:
-

+

{project.description}

-
Minimum Requirements :
-

+

Minimum Requirements:
+

{project.requirements}

-
Possible Responsibilities :
-

+

Possible Responsibilities:
+

{project.responsibilities}

- - {/* Attachments */} - {/*
-
Attachments:
-
-
- Untitled Document -
-
- Untitled Document -
-
Untitled Document
-
-
*/}
); diff --git a/app/(root)/project/[id]/Sidebar2.tsx b/app/(root)/project/[id]/Sidebar2.tsx index eb4914c..81a860e 100644 --- a/app/(root)/project/[id]/Sidebar2.tsx +++ b/app/(root)/project/[id]/Sidebar2.tsx @@ -1,101 +1,84 @@ "use client"; -import React, { useState, useRef, useEffect, useCallback } from "react"; +import React, { useState, useRef, useEffect } from "react"; import Link from "next/link"; import axios from "axios"; import { IoMdArrowDropdown } from "react-icons/io"; import { FaUser } from "react-icons/fa"; +import { useSession } from "next-auth/react"; +import { toast } from "sonner"; + type DetailProps = { id: string; }; -interface Project { - owner: string; - team: string[]; -} interface User { _id: string; - name: string; + firstName: string; + lastName: string; + email: string; +} + +interface Project { + owner: string; + team: User[]; } const Sidebar2 = ({ id }: DetailProps) => { + const { data: session } = useSession(); const [isDropdownOpen, setIsDropdownOpen] = useState(false); - const [isModalOpen, setIsModalOpen] = useState(false); // Modal state - const [formData, setFormData] = useState(""); // Form data + const [isModalOpen, setIsModalOpen] = useState(false); + const [formData, setFormData] = useState(""); const [isChecked, setIsChecked] = useState(false); - const [isSidebarOpen, setIsSidebarOpen] = useState(false); // Sidebar state + const [isSidebarOpen, setIsSidebarOpen] = useState(false); const sidebarRef = useRef(null); - const [currentUser, setCurrentUser] = useState(); - const [teammates, setTeammates] = useState([]); - const [project, setProject] = useState(); - const email = "email"; - const dta = ["Rohit", "Adarsh"]; - - //get current user data - const getUserData = async () => { - try { - const response = await axios.get( - `${process.env.NEXT_PUBLIC_API_URL}/api/user/${email}` - ); - setCurrentUser(response.data); - } catch (error) { - console.error("Error fetching user data:", error); - } - }; - //get project data - const getData = useCallback(async () => { - try { - const response = await axios.get( - `${process.env.NEXT_PUBLIC_API_URL}/api/project/project_id/${id}` - ); - setProject(response.data); - } catch (error) { - console.error("Error fetching projects:", error); - } - }, [id]); + const [project, setProject] = useState(null); + const [isSubmitting, setIsSubmitting] = useState(false); - const getTeammates = useCallback(async () => { - if (!project?.team) return; - - try { - const teammateData = await Promise.all( - project.team.map(async (item) => { - const response = await axios.get( - `${process.env.NEXT_PUBLIC_API_URL}/api/user/${item}` - ); - return response.data; - }) - ); + useEffect(() => { + const getData = async () => { + try { + const response = await axios.get( + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/project/project_id/${id}` + ); + setProject(response.data); + } catch (error) { + console.error("Error fetching project:", error); + toast.error("Failed to load project details."); + } + }; - setTeammates(teammateData); - console.log(teammateData); - } catch (error) { - console.error("Error fetching user data:", error); + if (id) { + getData(); } - }, [project]); - - useEffect(() => { - getUserData(); - getData(); - getTeammates(); - }, [getData, getTeammates]); + }, [id]); - //send the request to join the project const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); + if (!session?.user?.id) { + toast.error("You must be logged in to apply."); + return; + } + setIsSubmitting(true); + const toastId = toast.loading("Submitting application..."); + try { - const response = await axios.post( - `${process.env.NEXT_PUBLIC_API_URL}/api/linkage/join/${currentUser?._id}/${id}`, - formData + await axios.post( + `${process.env.NEXT_PUBLIC_CLIENT_URL}/api/linkage/join/${session.user.id}/${id}`, + { attachment: formData } ); - console.log("Response:", response.data); + toast.success("Application submitted successfully!", { id: toastId }); + setIsModalOpen(false); + setFormData(""); + setIsChecked(false); } catch (error) { - console.error("Error fetching projects:", error); + toast.error("Failed to submit application.", { id: toastId }); + console.error("Error sending join request:", error); + } finally { + setIsSubmitting(false); } - setIsModalOpen(false); }; - // Close sidebar on outside click (only for mobile screens) useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( @@ -109,101 +92,96 @@ const Sidebar2 = ({ id }: DetailProps) => { if (isSidebarOpen) { document.addEventListener("mousedown", handleClickOutside); - } else { - document.removeEventListener("mousedown", handleClickOutside); } - - return () => document.removeEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; }, [isSidebarOpen]); return ( <> - {/* Toggle Sidebar Button for Small Screens */} - {/* Sidebar Wrapper */}
+
- +
Back

- {/* Team-mates Dropdown */}
setIsDropdownOpen(!isDropdownOpen)} >
Team-mates
{isDropdownOpen && ( -
    - {dta?.length > 0 ? ( - dta.map((teammate, index) => ( +
      + {project?.team && project.team.length > 0 ? ( + project.team.map((teammate) => (
    • -
      {teammate}
      +
      {`${teammate.firstName} ${teammate.lastName}`}
    • )) ) : ( -
    • No results found
    • +
    • No teammates yet
    • )}
    )}
    - {/* Open Modal Button */}
    setIsModalOpen(true)} >
    Apply
    - +

- {/* Modal */} {isModalOpen && ( -
+

Application Form


- {/* Input Field */}
- - - - - - - - - - - - - - -
- - - - -
- - - -
- )} - + + + ))}
- ) -} + )} +
+ ); +}; -export default UserProject +export default UserProject; diff --git a/app/(root)/dashboard/page.tsx b/app/(root)/dashboard/page.tsx index bc6f797..a6b2c5c 100644 --- a/app/(root)/dashboard/page.tsx +++ b/app/(root)/dashboard/page.tsx @@ -1,50 +1,62 @@ +"use client"; import React from "react"; import TabsComponent2 from "../TabsComponent2"; import TableComponent from "../TableComponent"; import UserProject from "./UserProject"; -import Image from "next/image"; +import useAuthStore from "@/app/store/useAuthStore"; +import { motion } from "framer-motion"; +import { LayoutDashboard, Sparkles } from "lucide-react"; -// Tab contents with table components const tabContents = [ - , - , + , + , ]; -const page = () => { - const tabTitles = ["Announcements (10)", "Projects(02)"]; +const Page = () => { + const { user } = useAuthStore(); + const tabTitles = ["Announcements", "Projects"]; + return ( -
-
Hello, Rohit!
-
-
-

Welcome to User Dashboard.

-

- Here, you can stay up-to-date with all the latest notifications and - announcements related to your selected projects. Get real-time - updates, important alerts, and stay informed about key developments - and opportunities. Keep everything at your fingertips and never miss - an important detail about your ongoing collaborations. +

+ + Hello, {user?.firstName || "Developer"}! + + + +
+
+ +

Welcome to your Dashboard

+
+

+ Stay up-to-date with notifications and announcements for your projects. + Get real-time updates, important alerts, and never miss key developments.

-
- +
+
-
+
-
Dashboard
- + +

Dashboard

+ +
); }; -export default page; +export default Page; diff --git a/app/(root)/feedback/page.tsx b/app/(root)/feedback/page.tsx index f19662a..aab362e 100644 --- a/app/(root)/feedback/page.tsx +++ b/app/(root)/feedback/page.tsx @@ -1,63 +1,104 @@ -import Image from "next/image"; -import React from "react"; +"use client"; +import React, { useState } from "react"; +import useAuthStore from "@/app/store/useAuthStore"; +import { motion } from "framer-motion"; +import { MessageSquare, Send, Sparkles } from "lucide-react"; +import { toast } from "sonner"; const Page = () => { + const { user } = useAuthStore(); + const [feedback, setFeedback] = useState(""); + const [isChecked, setIsChecked] = useState(false); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + toast.success("Feedback submitted! Thank you for your input."); + setFeedback(""); + setIsChecked(false); + }; + return ( -
-
Hello, Rohit!
-
-
-

Welcome to Feedback Page.

-

- Your feedback is important to us! Share your thoughts, suggestions, - or any ideas for improvement. Help us make the website better by - letting us know how we can enhance your experience. We value your - input! +

+ + Hello, {user?.firstName || "Developer"}! + + + +
+
+ +

Share Your Feedback

+
+

+ Your feedback helps us improve! Share your thoughts, suggestions, or ideas + to make DevGuild better for everyone.

-
- +
+
-
+
-
Submit Your Feedback
-
-
- {/* Input Field */} -
-