about view done, projects mostly done, some minor styling left!
1
src/assets/icons/socials/globe.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M352 256c0 22.2-1.2 43.6-3.3 64l-185.3 0c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64l185.3 0c2.2 20.4 3.3 41.8 3.3 64zm28.8-64l123.1 0c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64l-123.1 0c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64zm112.6-32l-116.7 0c-10-63.9-29.8-117.4-55.3-151.6c78.3 20.7 142 77.5 171.9 151.6zm-149.1 0l-176.6 0c6.1-36.4 15.5-68.6 27-94.7c10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5c11.6 26 20.9 58.2 27 94.7zm-209 0L18.6 160C48.6 85.9 112.2 29.1 190.6 8.4C165.1 42.6 145.3 96.1 135.3 160zM8.1 192l123.1 0c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64L8.1 320C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64zM194.7 446.6c-11.6-26-20.9-58.2-27-94.6l176.6 0c-6.1 36.4-15.5 68.6-27 94.6c-10.5 23.6-22.2 40.7-33.5 51.5C272.6 508.8 263.3 512 256 512s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6C112.2 482.9 48.6 426.1 18.6 352l116.7 0zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6c25.5-34.2 45.2-87.7 55.3-151.6l116.7 0z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/img/projects/animedb1.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
src/assets/img/projects/animedb2.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
src/assets/img/projects/animedb3.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
src/assets/img/projects/deb.png
Normal file
|
After Width: | Height: | Size: 456 KiB |
BIN
src/assets/img/projects/inkspire.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
src/assets/img/projects/strogaso.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
@@ -8,7 +8,7 @@ const LangSelect = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`langSelect container animate__animated ${animation}`}
|
className={`langSelect container animate__animated ${animation}`}
|
||||||
onMouseEnter={() => onMouseEnter(setAnimation)}
|
/* onMouseEnter={() => onMouseEnter(setAnimation)} */
|
||||||
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
||||||
>
|
>
|
||||||
<div className="eng">🇬🇧</div>
|
<div className="eng">🇬🇧</div>
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import "../css/Mail.css";
|
import "../css/Mail.css";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import EnvelopeIcon from "../assets/icons/navIcons/envelope.svg?react";
|
||||||
|
|
||||||
const Mail = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
|
const Mail = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
|
||||||
const [animation, setAnimation] = useState(initialAnimation);
|
const [animation, setAnimation] = useState(initialAnimation);
|
||||||
|
const emailUser = "yousif.paulus";
|
||||||
|
const domain = "hotmail.de";
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`eMail container animate__animated ${animation}`}
|
className={`eMail container animate__animated ${animation}`}
|
||||||
onMouseEnter={() => onMouseEnter(setAnimation)}
|
/* onMouseEnter={() => onMouseEnter(setAnimation)} */
|
||||||
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
||||||
>
|
>
|
||||||
Mail
|
<a
|
||||||
|
className="emailAnchor"
|
||||||
|
href="mailto:yousif.paulus@hotmail.de"
|
||||||
|
>{`${emailUser}@${domain}`}</a>
|
||||||
|
<p className="copyright">© 2025 | Yousif Paulus</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import "animate.css";
|
|||||||
const Switch = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
|
const Switch = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
|
||||||
const [animation, setAnimation] = useState(initialAnimation);
|
const [animation, setAnimation] = useState(initialAnimation);
|
||||||
return (
|
return (
|
||||||
<div className={`switch container animate__animated ${animation}`}>
|
<div
|
||||||
|
className={`switch container animate__animated ${animation}`}
|
||||||
|
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
||||||
|
>
|
||||||
switch
|
switch
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import "animate.css";
|
|||||||
|
|
||||||
const TechStack = ({
|
const TechStack = ({
|
||||||
initialAnimation,
|
initialAnimation,
|
||||||
onMouseEnter,
|
/* onMouseEnter, */
|
||||||
onAnimationEnd,
|
onAnimationEnd,
|
||||||
isExpanded,
|
isExpanded,
|
||||||
onExpandToggle, // Receive the handler as a prop
|
onExpandToggle, // Receive the handler as a prop
|
||||||
@@ -105,7 +105,7 @@ const TechStack = ({
|
|||||||
animation,
|
animation,
|
||||||
{ expanded: isExpanded } // Conditional class
|
{ expanded: isExpanded } // Conditional class
|
||||||
)}
|
)}
|
||||||
onMouseEnter={() => onMouseEnter(setAnimation)}
|
/* onMouseEnter={() => onMouseEnter(setAnimation)} */
|
||||||
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
||||||
>
|
>
|
||||||
<h2>Tech Stack</h2>
|
<h2>Tech Stack</h2>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const About = () => {
|
|||||||
/>
|
/>
|
||||||
<LangSelect />
|
<LangSelect />
|
||||||
<Mail />
|
<Mail />
|
||||||
<Switch isOn={false} handleToggle={toggleSwitch} />
|
<Switch/>
|
||||||
<Navigation
|
<Navigation
|
||||||
/* initialAnimation="animate__bounceInDown"
|
/* initialAnimation="animate__bounceInDown"
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
|
|||||||
@@ -1,9 +1,107 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
|
import "../../css/Home.css";
|
||||||
|
import "animate.css";
|
||||||
|
import "../../css/GridContainer.css";
|
||||||
|
import LangSelect from "../LangSelect";
|
||||||
|
import Mail from "../Mail";
|
||||||
|
import Switch from "../Switch";
|
||||||
|
import Navigation from "../Navigation";
|
||||||
|
import LinkedInIcon from "../../assets/icons/socials/linkedin.svg?react";
|
||||||
|
import GitHubIcon from "../../assets/icons/socials/square-github.svg?react";
|
||||||
|
import Location from "../Location";
|
||||||
|
import { useState } from "react";
|
||||||
|
import ProjectsMain from "../subComponents/Projects/ProjectsMain";
|
||||||
|
import inkspireImg from "../../assets/img/projects/inkspire.png";
|
||||||
|
import debImg from "../../assets/img/projects/deb.png";
|
||||||
|
import animedbImg1 from "../../assets/img/projects/animedb1.png";
|
||||||
|
import animedbImg2 from "../../assets/img/projects/animedb2.png";
|
||||||
|
import animedbImg3 from "../../assets/img/projects/animedb3.png";
|
||||||
|
import strogasoImg from "../../assets/img/projects/strogaso.png";
|
||||||
|
|
||||||
const Projects = () => {
|
const Projects = () => {
|
||||||
return (
|
const projectArr = [
|
||||||
<div>Projects</div>
|
{
|
||||||
)
|
name: "inkspire.",
|
||||||
}
|
urls: { ghUrl: "https://github.com/yousifpa98/inkspire" },
|
||||||
|
year: "2024",
|
||||||
|
job: "freelance",
|
||||||
|
imgs: [inkspireImg],
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Client Website",
|
||||||
|
urls: {
|
||||||
|
ghUrl: "N/A",
|
||||||
|
liveUrl: "https://druckerei-eberwein.de/",
|
||||||
|
},
|
||||||
|
year: "2024",
|
||||||
|
job: "freelance",
|
||||||
|
imgs: [debImg],
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Otaku Critics",
|
||||||
|
urls: {
|
||||||
|
ghUrl: "https://github.com/yousifpa98/animeDB-react",
|
||||||
|
liveUrl: "https://otakucritics.netlify.app/",
|
||||||
|
},
|
||||||
|
year: "2024",
|
||||||
|
job: "personal project",
|
||||||
|
imgs: [animedbImg1, animedbImg2, animedbImg3],
|
||||||
|
id: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "strogaso",
|
||||||
|
urls: {
|
||||||
|
ghUrl: "https://github.com/yousifpa98/strogaso-react",
|
||||||
|
liveUrl: "https://www.strogaso.de",
|
||||||
|
},
|
||||||
|
year: "2023/24",
|
||||||
|
job: "Salescape",
|
||||||
|
imgs: [strogasoImg],
|
||||||
|
id: 4,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export default Projects
|
const social = (url) => () => {
|
||||||
|
window.open(url, "_blank", "noopener,noreferrer");
|
||||||
|
};
|
||||||
|
const [hoverAnimation, setHoverAnimation] = useState("animate__headShake");
|
||||||
|
|
||||||
|
const handleMouseEnter = (setAnimation) => {
|
||||||
|
setAnimation(hoverAnimation); // Trigger hover animation
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAnimationEnd = (setAnimation) => {
|
||||||
|
setAnimation(""); // Clear animation to prevent re-triggering
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="gridContainer">
|
||||||
|
<Navigation />
|
||||||
|
<Location />
|
||||||
|
<div
|
||||||
|
className="linkedIn container"
|
||||||
|
onClick={social("https://www.linkedin.com/in/yousifpaulus/")}
|
||||||
|
>
|
||||||
|
<LinkedInIcon className="linkedInIcon" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="github container"
|
||||||
|
onClick={social("https://github.com/yousifpa98")}
|
||||||
|
>
|
||||||
|
<GitHubIcon className="githubIcon" />
|
||||||
|
</div>
|
||||||
|
<Switch />
|
||||||
|
<Mail />
|
||||||
|
<LangSelect />
|
||||||
|
<ProjectsMain
|
||||||
|
projects={projectArr}
|
||||||
|
initialAnimation="animate__bounceInDown"
|
||||||
|
onMouseEnter={handleMouseEnter}
|
||||||
|
onAnimationEnd={handleAnimationEnd}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Projects;
|
||||||
|
|||||||
52
src/components/subComponents/Projects/ProjectCard.jsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import React from "react";
|
||||||
|
import "../../../css/ProjectCard.css";
|
||||||
|
import GitHubIcon from "../../../assets/icons/socials/square-github.svg?react";
|
||||||
|
import GlobeIcon from "../../../assets/icons/socials/globe.svg?react";
|
||||||
|
|
||||||
|
const ProjectCard = ({ project }) => {
|
||||||
|
return (
|
||||||
|
<div className="projectCard">
|
||||||
|
<div className={project.imgs.length > 1 ? "imgs" : "img"}>
|
||||||
|
{project.imgs.map((img, index) => (
|
||||||
|
<img
|
||||||
|
key={index}
|
||||||
|
src={img}
|
||||||
|
alt={`${project.name} screenshot ${index + 1}`}
|
||||||
|
style={
|
||||||
|
project.imgs.length > 1
|
||||||
|
? { width: `${100 / project.imgs.length}%` }
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="projectInfo">
|
||||||
|
<h3>
|
||||||
|
{project.name} <span>({project.year})</span>
|
||||||
|
</h3>
|
||||||
|
<p className="projectJob">{project.job}</p>
|
||||||
|
<div className="projectLinks">
|
||||||
|
{Object.entries(project.urls).map(([key, value]) => {
|
||||||
|
// Determine the correct icon to render based on the key
|
||||||
|
const Icon = key === "ghUrl" ? GitHubIcon : GlobeIcon;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={key}
|
||||||
|
className="socialIconAnchor"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={value}
|
||||||
|
>
|
||||||
|
<Icon className="socialIcon"/>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectCard;
|
||||||
30
src/components/subComponents/Projects/ProjectsMain.jsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import React from "react";
|
||||||
|
import "../../../css/ProjectsMain.css";
|
||||||
|
import { useState } from "react";
|
||||||
|
import ProjectCard from "./ProjectCard";
|
||||||
|
|
||||||
|
const ProjectsMain = ({
|
||||||
|
initialAnimation,
|
||||||
|
onMouseEnter,
|
||||||
|
onAnimationEnd,
|
||||||
|
projects,
|
||||||
|
}) => {
|
||||||
|
const [animation, setAnimation] = useState(initialAnimation);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`projectsMain container animate__animated ${animation}`}
|
||||||
|
/* onMouseEnter={() => onMouseEnter(setAnimation)} */
|
||||||
|
onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
||||||
|
>
|
||||||
|
<h2>Some of my latest projects:</h2>
|
||||||
|
<div className="projectsDiv">
|
||||||
|
{projects.map((project) => (
|
||||||
|
<ProjectCard key={project.id} project={project} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectsMain;
|
||||||
@@ -1,3 +1,19 @@
|
|||||||
.eMail {
|
.eMail {
|
||||||
grid-area: 9 / 1 / 10 / 4;
|
grid-area: 9 / 1 / 10 / 4;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emailAnchor {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
color: rgb(151, 151, 151);
|
||||||
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|||||||
53
src/css/ProjectCard.css
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
.projectCard {
|
||||||
|
width: 33%;
|
||||||
|
/* height: 200px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgs,
|
||||||
|
.img {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img img,
|
||||||
|
.imgs img {
|
||||||
|
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
margin-bottom: 0.245rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectInfo h3 {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectInfo h3 span {
|
||||||
|
color: rgb(151, 151, 151);
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectJob {
|
||||||
|
color: rgb(151, 151, 151);
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socialIcon {
|
||||||
|
width: 1.5rem;
|
||||||
|
height: auto;
|
||||||
|
fill: white;
|
||||||
|
transition: fill 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socialIcon:hover {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectLinks {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
17
src/css/ProjectsMain.css
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
.projectsMain {
|
||||||
|
grid-area: 1 / 1 / 8 / 9;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projectsDiv {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
@@ -23,6 +23,10 @@
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.funFactList li::marker {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.funFactList li p {
|
.funFactList li p {
|
||||||
color: rgb(151, 151, 151);
|
color: rgb(151, 151, 151);
|
||||||
}
|
}
|
||||||
|
|||||||