Skip to content

Commit 8bf4770

Browse files
authored
Merge pull request #48 from Code-the-Dream-School/final-PR
final PR, with issues 5,6,7
2 parents aa247ce + 0fbcd28 commit 8bf4770

File tree

5 files changed

+167
-45
lines changed

5 files changed

+167
-45
lines changed

src/components/Details.jsx

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React from "react";
2+
import { Box, VStack, Text, Button } from "@chakra-ui/react";
3+
import {
4+
DialogRoot,
5+
DialogTrigger,
6+
DialogContent,
7+
DialogBody,
8+
DialogCloseTrigger,
9+
} from "./ui/dialog";
10+
11+
const Details = ({ project }) => {
12+
return (
13+
<DialogRoot placement="center" initialFocusEl={() => null}>
14+
<DialogTrigger>
15+
<Button id="details-trigger" style={{ display: "none" }}>
16+
Open Details
17+
</Button>
18+
</DialogTrigger>
19+
20+
<DialogContent
21+
width={["90%", "80%", "500px"]}
22+
height="400px"
23+
className="dialog-container"
24+
backdropFilter="blur(10px)"
25+
borderRadius="8px"
26+
>
27+
<DialogBody
28+
width="auto"
29+
height="100%"
30+
display="flex"
31+
flexDirection="column"
32+
marginTop="16px"
33+
>
34+
{/* Close Button */}
35+
<DialogCloseTrigger>
36+
<Button color="black" size="2xs" bg="wheat">
37+
X
38+
</Button>
39+
</DialogCloseTrigger>
40+
41+
{/* Project Details */}
42+
<Box
43+
flex="1"
44+
borderRadius="md"
45+
overflowY="auto" // Enable vertical scrolling
46+
paddingRight="4"
47+
paddingLeft="4"
48+
paddingTop='24px'
49+
marginBottom="8px"
50+
paddingBottom='24px'
51+
color="black"
52+
53+
>
54+
<VStack spacing="4" align="start" color='white' gap='28px' wordBreak="break-word">
55+
<Text fontWeight="bold" mx='auto' fontSize='40px' lineHeight='40px' textAlign='center'>
56+
{project.name}
57+
</Text>
58+
<Text>
59+
<strong>Description:</strong> {project.description}
60+
</Text>
61+
<Text>
62+
<strong>Frameworks/Languages:</strong> {project.tags.join(", ")}
63+
</Text>
64+
{project.github_link && (
65+
<Text>
66+
<strong>GitHub:</strong>{" "}
67+
<a href={project.github_link} target="_blank" rel="noopener noreferrer">
68+
{project.github_link}
69+
</a>
70+
</Text>
71+
)}
72+
{project.youtube_video_link && (
73+
<Text>
74+
<strong>Live Demo:</strong>{" "}
75+
<a href={project.youtube_video_link} target="_blank" rel="noopener noreferrer">
76+
{project.youtube_video_link}
77+
</a>
78+
</Text>
79+
)}
80+
</VStack>
81+
</Box>
82+
</DialogBody>
83+
</DialogContent>
84+
</DialogRoot>
85+
);
86+
};
87+
88+
export default Details;

src/components/Navbar.jsx

+2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ const Navbar = () => {
9696
return (
9797
<div className="navbar">
9898
<div className="navbar-container">
99+
<a href='/home'>
99100
<img src="./images/logo.png" className="logo" alt="Logo" />
101+
</a>
100102
<div className="hamburger-menu">
101103
<MenuRoot>
102104
<MenuTrigger asChild>

src/styles/ExploreProjects.css

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
border-color: rgba(255, 255, 255, 0.24);
2323
border-width: 0.1em;
2424
position: relative;
25+
box-shadow: 4px 4px 10px rgba(99, 233, 238, 0.5); /* Horizontal, Vertical, Blur, Spread */
26+
transition: transform 0.5s ease;
27+
}
28+
.project-tile:hover {
29+
transform: scale(1.04); /* Zoom in */
2530
}
2631
.project-details {
2732
padding: 59px 16px 80px 16px;

src/views/ExploreProjects.jsx

+46-2
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,23 @@ import {
1010
} from "../components/ui/menu";
1111
import { StatRoot, StatValueText } from "../components/ui/stat"
1212
import Comments from "../components/Comments";
13+
import Details from "../components/Details"
1314
import { Toaster, toaster } from "../components/ui/toaster";
1415
import { jwtDecode } from "jwt-decode";
1516

1617
const ExploreProjects = () => {
1718
const [projects, setProjects] = useState([]);
1819
const [activeProjectId, setActiveProjectId] = useState(null);
1920
const [activeProjectOwnerId, setActiveProjectOwnerId] = useState(null);
21+
const [activeProjectDetails, setActiveProjectDetails] = useState(null);
22+
2023
const token = JSON.parse(localStorage.getItem("auth"));
2124
const rawToken = localStorage.getItem("auth");
2225
const { user_id: userId, username } = rawToken ? jwtDecode(rawToken) : {};
2326

27+
const truncateTitle = (title, maxLength) => {
28+
return title.length > maxLength ? `${title.slice(0, maxLength)}...` : title;
29+
};
2430
// Fetch all projects on component mount
2531
useEffect(() => {
2632
const fetchProjects = async () => {
@@ -90,6 +96,18 @@ const ExploreProjects = () => {
9096
}, 0);
9197
};
9298

99+
const openDetailsModal = (project) => {
100+
setActiveProjectDetails(project);
101+
102+
// Trigger the Details Dialog
103+
setTimeout(() => {
104+
const triggerButton = document.getElementById("details-trigger");
105+
if (triggerButton) {
106+
triggerButton.click();
107+
}
108+
}, 0);
109+
};
110+
93111
const handleDelete = async (projectId) => {
94112
try {
95113
const response = await fetch(
@@ -227,6 +245,9 @@ const ExploreProjects = () => {
227245
></img>
228246
</MenuTrigger>
229247
<MenuContent className="menu-content">
248+
<MenuItem onClick={() => openDetailsModal(project)}>
249+
Details
250+
</MenuItem>
230251
{Number(userId) === Number(project.created_by) && (
231252
<>
232253
<MenuItem
@@ -239,7 +260,20 @@ const ExploreProjects = () => {
239260
<MenuSeparator />
240261
</>
241262
)}
242-
<MenuItem value="new-txt2" as="a">
263+
<MenuItem
264+
value="new-txt2"
265+
as="a"
266+
onClick={() => {
267+
toaster.create({
268+
title: "Project reported to admin!",
269+
description: "Thank you for bringing this to our attention.",
270+
type: "info",
271+
duration: 4000,
272+
action: {
273+
label: "x",
274+
},
275+
});
276+
}}>
243277
Report ⚠️
244278
</MenuItem>
245279
</MenuContent>
@@ -295,7 +329,7 @@ const ExploreProjects = () => {
295329
day: "numeric",
296330
})}
297331
</p>
298-
<p className="project-name">{project.name}</p>
332+
<p className="project-name">{truncateTitle(project.name, 16)}</p>
299333
<p className="ep-username">{project.users.username}</p>
300334
<div className="framework-badges">
301335
{project.tags
@@ -350,6 +384,15 @@ const ExploreProjects = () => {
350384
className="git-link-button"
351385
variant="solid"
352386
type="submit"
387+
onClick={() => {
388+
const url =
389+
project.github_link.startsWith("http://") ||
390+
project.github_link.startsWith("https://")
391+
? project.github_link
392+
: `https://${project.github_link}`;
393+
console.log("Opening Github Repository URL:", url);
394+
window.open(url, "_blank");
395+
}}
353396
>
354397
View on Github
355398
<img
@@ -373,6 +416,7 @@ const ExploreProjects = () => {
373416
projectOwnerId={activeProjectOwnerId}
374417
/>
375418
)}
419+
{activeProjectDetails && <Details project={activeProjectDetails} />}
376420
<Toaster />
377421
</div>
378422
<footer>

src/views/ShareAProject.jsx

+26-43
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
Textarea,
88
Button,
99
Link,
10-
Stack,
10+
VStack,
1111
} from "@chakra-ui/react";
1212
import { LuExternalLink } from "react-icons/lu";
1313
import { Field } from "../components/ui/field";
@@ -23,15 +23,12 @@ const ShareAProject = () => {
2323
youtube_video_link: "",
2424
tags: [],
2525
});
26-
const [errors, setErrors] = useState({
27-
github_link: "",
28-
youtube_video_link: "",
29-
});
3026

3127
const validateUrl = (url) => {
3228
const urlPattern = /^(https?:\/\/)?([\w-]+(\.[\w-]+)+)(\/[\w-.]*)*(\?.+)?$/;
3329
return urlPattern.test(url);
3430
};
31+
3532
const handleSubmit = async (e) => {
3633
e.preventDefault();
3734
if (newProject.tags.length === 0) {
@@ -43,51 +40,38 @@ const ShareAProject = () => {
4340
label: "x",
4441
},
4542
});
46-
//console.log("Please select at least one framework/language.");
4743
return;
4844
}
49-
const newErrors = {};
5045

5146
// Validate GitHub URL (Required)
5247
if (!newProject.github_link || !validateUrl(newProject.github_link)) {
53-
newErrors.github_link = "Please provide a valid GitHub repository URL.";
48+
toaster.create({
49+
title: "Please provide a valid GitHub repository URL.",
50+
type: "warning",
51+
duration: 4000,
52+
action: {
53+
label: "x",
54+
},
55+
});
56+
return;
5457
}
5558

5659
// Validate Live Demo URL (Optional, only if provided)
5760
if (
5861
newProject.youtube_video_link &&
5962
!validateUrl(newProject.youtube_video_link)
6063
) {
61-
newErrors.youtube_video_link = "Please provide a valid Live Demo URL.";
62-
}
63-
console.log(Object.keys(newErrors).length);
64-
if (Object.keys(newErrors).length > 0) {
65-
setErrors(newErrors); // Display errors
66-
67-
if (errors.github_link) {
68-
console.log(errors.github_link);
69-
toaster.create({
70-
title: errors.github_link,
71-
type: "warning",
72-
duration: 4000,
73-
action: {
74-
label: "x",
75-
},
76-
});
77-
}
78-
if (errors.youtube_video_link) {
79-
console.log(errors.youtube_video_link);
80-
toaster.create({
81-
title: errors.youtube_video_link,
82-
type: "warning",
83-
duration: 4000,
84-
action: {
85-
label: "x",
86-
},
87-
});
88-
}
64+
toaster.create({
65+
title: "Please provide a valid Live Demo URL.",
66+
type: "warning",
67+
duration: 4000,
68+
action: {
69+
label: "x",
70+
},
71+
});
8972
return;
9073
}
74+
9175
try {
9276
const response = await fetch("http://localhost:8001/api/v1/addProject", {
9377
method: "POST",
@@ -99,7 +83,7 @@ const ShareAProject = () => {
9983
});
10084
if (response.ok) {
10185
toaster.create({
102-
title: "Project submitted succesfully!",
86+
title: "Project submitted successfully!",
10387
type: "success",
10488
duration: 8000,
10589
action: {
@@ -115,7 +99,6 @@ const ShareAProject = () => {
11599
});
116100
} else {
117101
console.error("Failed to add project:", response.statusText);
118-
//console.error("Failed to submit project");
119102
}
120103
} catch (error) {
121104
toaster.create({
@@ -137,7 +120,7 @@ const ShareAProject = () => {
137120
: [...prev.tags, value],
138121
}));
139122
};
140-
//const isSubmitEnabled = newProject.tags.length > 0;
123+
141124
return (
142125
<form onSubmit={handleSubmit}>
143126
<div className="share-project-container">
@@ -317,8 +300,8 @@ const ShareAProject = () => {
317300
}
318301
/>
319302
</Field>
320-
<Field marginBottom={"20%"} marginTop={10}>
321-
<Stack direction="row" h="20">
303+
<Field marginBottom={"20%"} marginTop={10} display='flex' alignItems='center'>
304+
<VStack direction="row" h="20" justifyContent="center" alignItems="center">
322305
<Button
323306
className="sp-button"
324307
variant="solid"
@@ -328,12 +311,12 @@ const ShareAProject = () => {
328311
SUBMIT PROJECT
329312
</Button>
330313
<Link
331-
style={{ fontSize: "20px", color: "#63E9EE", padding: "40px" }}
314+
style={{ fontSize: "20px", color: "#63E9EE", alignItems: "center", display: 'flex' }}
332315
href="/explore-project"
333316
>
334317
Go to explore projects <LuExternalLink />
335318
</Link>
336-
</Stack>
319+
</VStack>
337320
</Field>
338321
<Toaster />
339322
</div>

0 commit comments

Comments
 (0)