Files
Portfolio/src/components/ProjectDetails/ProjectDetails.jsx
T

119 lines
8.2 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import "./ProjectDetails.css"
import SkillCard from "../SkillCard/SkillCard.jsx";
import React, {useEffect, useState} from "react";
import NavBar from "../NavBar/NavBar.jsx";
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import {useNavigate} from "react-router-dom";
function ProjectDetails({project}) {
const [mdTitle, setMdTitle] = useState([]);
const navigate = useNavigate();
useEffect(() =>{
if (!project.long_description) return;
const matches = [...project.long_description.matchAll(/^## (?!#)(.+)$/gm)];
setMdTitle(matches.map(match => match[1].trim()));
}, [project.long_description])
const handleSummaryClick = (event, anchor) => {
event.preventDefault();
const element = document.getElementById(anchor);
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
};
return (
<div>
<button className="return-button" onClick={() => navigate(-1)}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="currentColor">
<path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/>
</svg>
</button>
<div className="nav-bar">
<NavBar/>
</div>
<div className="project-details">
<div className="project-details-header">
<h1>
<div className="project-details-header-left">
{project.title}
{project.school ? (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="#D95F46" width="1em" height="1em">
<path d="M80 259.8L289.2 345.9C299 349.9 309.4 352 320 352C330.6 352 341 349.9 350.8 345.9L593.2 246.1C602.2 242.4 608 233.7 608 224C608 214.3 602.2 205.6 593.2 201.9L350.8 102.1C341 98.1 330.6 96 320 96C309.4 96 299 98.1 289.2 102.1L46.8 201.9C37.8 205.6 32 214.3 32 224L32 520C32 533.3 42.7 544 56 544C69.3 544 80 533.3 80 520L80 259.8zM128 331.5L128 448C128 501 214 544 320 544C426 544 512 501 512 448L512 331.4L369.1 390.3C353.5 396.7 336.9 400 320 400C303.1 400 286.5 396.7 270.9 390.3L128 331.4z"/>
</svg>
) : null}
</div>
{typeof project.repo_link === "string" && project.repo_link.length > 0 ? (
<a href={project.repo_link} className="repo_link">
{project.repo_link.includes("github") ? (
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" fill="currentColor" width="1em" height="1em">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
) : (
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" fill="currentColor" width="1em" height="1em">
<path d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z"/>
</svg>
)}
</a>
) : null}
</h1>
{project.end_year === null ? (
<p className="project-details-years">{project.beginning_year + ' – in progress'}</p>
) : project.beginning_year === project.end_year ? (
<p className="project-details-years">{project.beginning_year}</p>
) : (
<p className="project-details-years">{project.beginning_year + ' – ' + project.end_year}</p>
)}
<p className="project-details-short-description">{project.short_description}</p>
<ul>
{project.skills && project.skills.map((skill) => (
<li>
<SkillCard text={skill} />
</li>
))}
</ul>
</div>
<div className="project-details-container">
<div className="project-details-content">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
h2({node, ...props}) {
const id = String(props.children).toLowerCase().replace(/\s+/g, "-");
return <h2 id={id} {...props} />;
}
}}
>
{project.long_description}
</ReactMarkdown>
{[...Array(project.nb_image)].map((_, i) => (
<img src={`/assets/images/projects/${project.image_name}/${project.image_name}_${i+1}.png`} alt={project.image_name} className="project-details-image"/>
))}
</div>
<aside>
<ul>
{mdTitle.map(title => {
const anchor = title.toLowerCase().replace(/\s+/g, "-");
return (
<li key={anchor}>
<a href={`#${anchor}`} onClick={(e) => handleSummaryClick(e, anchor)}>
{title}
</a>
</li>
);
})}
</ul>
</aside>
</div>
</div>
</div>
);
}
export default ProjectDetails