Skip to content

Commit 554be61

Browse files
authored
Merge pull request #86 from mortal22soul/feat/get-project-by-id
Get Project by ID Page
2 parents d83bafe + 537e11e commit 554be61

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

app/project/[id]/page.tsx

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/* eslint-disable react-hooks/exhaustive-deps */
2+
"use client";
3+
4+
import api from "@/api";
5+
import ProjectCard from "@/components/project/ProjectCard";
6+
import ProjectInformation from "@/components/project/ProjectInformation";
7+
import Button from "@/components/ui/Button";
8+
import FooterSection from "@/components/ui/FooterSection";
9+
import HeaderComponent from "@/components/ui/HeaderComponent";
10+
import Link from "next/link";
11+
import { useRouter } from "next/navigation";
12+
import React, { useState, useEffect, use } from "react";
13+
import { useAuth } from "@/context/AuthContext";
14+
import axios from "axios";
15+
16+
interface Evaluation {
17+
id: string;
18+
createdAt: string;
19+
updatedAt: string;
20+
projectId: string;
21+
score: number;
22+
}
23+
24+
interface Team {
25+
id: string;
26+
createdAt: string;
27+
updatedAt: string;
28+
name: string;
29+
imageId: string;
30+
}
31+
32+
interface Project {
33+
id: string;
34+
createdAt: string;
35+
updatedAt: string;
36+
name: string;
37+
description: string;
38+
imageId: string;
39+
teamId: string;
40+
team: Team;
41+
evaluations: Evaluation[];
42+
}
43+
44+
interface Params {
45+
params: Promise<{
46+
id: string;
47+
}>;
48+
}
49+
50+
const Profile = ({ params }: Params) => {
51+
const { user, loading, getUser } = useAuth();
52+
const [project, setProject] = useState<Project | null>(null);
53+
const [error, setError] = useState<string | null>(null);
54+
const router = useRouter();
55+
56+
const id = use(params).id;
57+
const getProject = async () => {
58+
if (id) {
59+
try {
60+
const response = await api.get(`/project/${id}`);
61+
if (response.status === 200) {
62+
setProject(response.data);
63+
}
64+
65+
if (!response.data) {
66+
router.push("/");
67+
}
68+
} catch (err: unknown) {
69+
if (axios.isAxiosError(err) && err.response) {
70+
switch (err.response.status) {
71+
case 403:
72+
setError("Forbidden. User does not have sufficient permissions.");
73+
break;
74+
case 404:
75+
setError("Project not found.");
76+
break;
77+
case 500:
78+
setError("Unexpected Server Error.");
79+
break;
80+
default:
81+
setError("An unexpected error occurred. Please try again later.");
82+
}
83+
} else {
84+
setError("An unexpected error occurred. Please try again later.");
85+
}
86+
}
87+
}
88+
};
89+
90+
useEffect(() => {
91+
if (!user) {
92+
getUser();
93+
}
94+
}, [user]);
95+
96+
useEffect(() => {
97+
getProject();
98+
}, [id]);
99+
100+
const formatDate = (dateString: string) => {
101+
const date = new Date(dateString);
102+
return date.toLocaleDateString("en-US", {
103+
year: "numeric",
104+
month: "long",
105+
day: "numeric",
106+
});
107+
};
108+
109+
if (loading) {
110+
return (
111+
<div className="flex justify-center items-center h-screen bg-[#121212]">
112+
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-gray-400" />
113+
</div>
114+
);
115+
}
116+
117+
if (error) {
118+
return (
119+
<div className="flex flex-col items-center justify-center min-h-screen bg-[#09090b] text-red-400">
120+
<div className="bg-red-800 text-white px-4 py-3 rounded border border-red-500">
121+
<strong className="font-bold">Error: </strong>
122+
<span className="block sm:inline">{error}</span>
123+
</div>
124+
</div>
125+
);
126+
}
127+
128+
return (
129+
<div className="flex flex-col items-center justify-center min-h-screen bg-[#09090b] text-white">
130+
<HeaderComponent />
131+
<div className="flex flex-grow flex-row w-[80%] mx-auto align-center justify-center mt-10">
132+
<ProjectCard
133+
createdAt={
134+
project?.createdAt
135+
? formatDate(project.createdAt)
136+
: formatDate(new Date().toISOString())
137+
}
138+
updatedAt={
139+
project?.updatedAt
140+
? formatDate(project.updatedAt)
141+
: formatDate(new Date().toISOString())
142+
}
143+
name={project?.name || ""}
144+
imageId={project?.imageId || ""}
145+
evaluations={project?.evaluations || []}
146+
teamName={project?.team?.name || ""}
147+
customStyle="w-[1/4]"
148+
/>
149+
<div className="ml-8 my-auto">
150+
<ProjectInformation
151+
teamName={project?.team?.name || "Not in a team"}
152+
description={project?.description || "No description"}
153+
customStyle="w-[3/4]"
154+
/>
155+
{user?.isLeader && (
156+
<Link href="/updateProject">
157+
<Button
158+
buttonText="Update Project"
159+
customStyle="mt-6 bg-blue-600 hover:bg-blue-500 text-white w-full"
160+
onClick={() => {}}
161+
/>
162+
</Link>
163+
)}
164+
</div>
165+
</div>
166+
<FooterSection />
167+
</div>
168+
);
169+
};
170+
171+
export default Profile;

0 commit comments

Comments
 (0)