contact
This commit is contained in:
@@ -1,9 +1,60 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
|
import "../../css/Home.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 "animate.css";
|
||||||
|
import { useState } from "react";
|
||||||
|
import "../../css/GridContainer.css";
|
||||||
|
import ContactTile from "../subComponents/Contact/ContactTile";
|
||||||
|
|
||||||
const Contact = () => {
|
const Contact = () => {
|
||||||
return (
|
const social = (url) => () => {
|
||||||
<div>Contact</div>
|
window.open(url, "_blank", "noopener,noreferrer");
|
||||||
)
|
};
|
||||||
}
|
const [hoverAnimation, setHoverAnimation] = useState("animate__headShake");
|
||||||
|
|
||||||
export default Contact
|
const handleMouseEnter = (setAnimation) => {
|
||||||
|
setAnimation(hoverAnimation); // Trigger hover animation
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAnimationEnd = (setAnimation) => {
|
||||||
|
setAnimation(""); // Clear animation to prevent re-triggering
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="gridContainer">
|
||||||
|
<LangSelect />
|
||||||
|
<Mail />
|
||||||
|
<Switch />
|
||||||
|
<Navigation
|
||||||
|
/* initialAnimation="animate__bounceInDown"
|
||||||
|
onMouseEnter={handleMouseEnter}
|
||||||
|
onAnimationEnd={handleAnimationEnd} */
|
||||||
|
/>
|
||||||
|
<ContactTile
|
||||||
|
initialAnimation="animate__bounceInDown"
|
||||||
|
onMouseEnter={handleMouseEnter}
|
||||||
|
onAnimationEnd={handleAnimationEnd}
|
||||||
|
/>
|
||||||
|
<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>
|
||||||
|
<Location />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Contact;
|
||||||
|
|||||||
98
src/components/subComponents/Contact/ContactTile.jsx
Normal file
98
src/components/subComponents/Contact/ContactTile.jsx
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import "../../../css/ContactTile.css";
|
||||||
|
import { useTheme } from "../../../Context/ThemeContext";
|
||||||
|
import { useLang } from "../../../Context/LangContext";
|
||||||
|
|
||||||
|
const ContactTileTiltFlip = ({
|
||||||
|
initialAnimation,
|
||||||
|
onMouseEnter,
|
||||||
|
onAnimationEnd,
|
||||||
|
}) => {
|
||||||
|
const [animation, setAnimation] = useState(initialAnimation);
|
||||||
|
const { colormode } = useTheme();
|
||||||
|
const { language } = useLang();
|
||||||
|
const [isFlipped, setIsFlipped] = useState(false);
|
||||||
|
const [tiltStyle, setTiltStyle] = useState({});
|
||||||
|
|
||||||
|
const handleMouseMove = (e) => {
|
||||||
|
const rect = e.currentTarget.getBoundingClientRect();
|
||||||
|
const x = e.clientX - rect.left - rect.width / 2;
|
||||||
|
const y = e.clientY - rect.top - rect.height / 2;
|
||||||
|
const tiltX = (y / rect.height) * 40; // Harter Tilt
|
||||||
|
const tiltY = -(x / rect.width) * 40;
|
||||||
|
|
||||||
|
setTiltStyle({
|
||||||
|
transform: `rotateX(${tiltX}deg) rotateY(${tiltY}deg)`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
setTiltStyle({ transform: "rotateX(0deg) rotateY(0deg)" });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
setIsFlipped(!isFlipped);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`container contactTile ${colormode} animate__animated ${animation}`}
|
||||||
|
/* onMouseEnter={() => onMouseEnter(setAnimation)}
|
||||||
|
*/ onAnimationEnd={() => onAnimationEnd(setAnimation)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`card ${isFlipped ? "flipped" : ""}`}
|
||||||
|
onClick={handleClick}
|
||||||
|
onMouseMove={handleMouseMove}
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
|
style={{
|
||||||
|
transform: `${tiltStyle.transform || "rotateX(0deg) rotateY(0deg)"} ${
|
||||||
|
isFlipped ? "rotateY(180deg)" : ""
|
||||||
|
}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="card-inner">
|
||||||
|
<div className={`card-front ${colormode}`}>
|
||||||
|
<h2>Yousif Paulus</h2>
|
||||||
|
<p>React | Node.js | TypeScript</p>
|
||||||
|
<p>
|
||||||
|
{language === "en-GB"
|
||||||
|
? "Full-Stack Developer"
|
||||||
|
: "Full-Stack Entwickler"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={`card-back ${colormode}`}>
|
||||||
|
<p>
|
||||||
|
📧 {/* Email: */}{" "}
|
||||||
|
<a href="mailto:yousif.paulus@hotmail.de">
|
||||||
|
yousif.paulus@hotmail.de
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
📞{" "}
|
||||||
|
{/* {language === "en-GB" ? "Phone:" : "Tel:"} */}
|
||||||
|
<a href="tel:+4915150717623">
|
||||||
|
{language === "en-GB"
|
||||||
|
? "+49 151 50717623"
|
||||||
|
: "0151 50717623"}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
🌐 {/* Portfolio: */}{" "}
|
||||||
|
<a href="http://www.yousifpaulus.dev">www.yousifpaulus.dev</a>
|
||||||
|
</p>
|
||||||
|
{/* <p>
|
||||||
|
💬{" "}
|
||||||
|
{language === "en-GB"
|
||||||
|
? "Let’s Build Something Great."
|
||||||
|
: "Tel: +49 151 50717623"}
|
||||||
|
</p> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ContactTileTiltFlip;
|
||||||
163
src/css/ContactTile.css
Normal file
163
src/css/ContactTile.css
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
.contactTile {
|
||||||
|
grid-area: 1 / 1 / 8 / 9;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.contactTile {
|
||||||
|
perspective: 1500px; /* Für 3D-Effekt */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 340px; /* Visitenkartenformat */
|
||||||
|
height: 200px;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.5s ease-out; /* Smooth Flip Transition */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.flipped {
|
||||||
|
transform: rotateY(180deg); /* Rückseite anzeigen */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-inner {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-front.dark h2 {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-front,
|
||||||
|
.card-back {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: linear-gradient(145deg, #d9d9d9, #f2f2f2); /* Helles Silber */
|
||||||
|
box-shadow: inset 0 4px 8px rgba(255, 255, 255, 0.5),
|
||||||
|
inset 0 -4px 8px rgba(0, 0, 0, 0.1), 0 6px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
overflow: hidden; /* Für Glanzeffekt-Beschneidung */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rückseite - dunkler Silber-Look */
|
||||||
|
.card-back {
|
||||||
|
background: linear-gradient(145deg, #999999, #b3b3b3);
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-back p {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0rem 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-back p a {
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Glanzeffekt nur innerhalb der Karte */
|
||||||
|
.card-front::before
|
||||||
|
/*, .card-back::before */ {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 150%;
|
||||||
|
height: 150%;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at 50% 50%,
|
||||||
|
rgba(255, 255, 255, 0.4),
|
||||||
|
rgba(255, 255, 255, 0) 70%
|
||||||
|
);
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg);
|
||||||
|
animation: subtle-glow 3s ease-in-out infinite;
|
||||||
|
pointer-events: none;
|
||||||
|
filter: blur(4px);
|
||||||
|
mix-blend-mode: screen; /* Lichtdurchlässigkeit */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subtile Animation des Glanzes */
|
||||||
|
@keyframes subtle-glow {
|
||||||
|
0% {
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg) scale(1.1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg) scale(1.3);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg) scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light Mode Styles */
|
||||||
|
.card-front.light,
|
||||||
|
.card-back.light {
|
||||||
|
background: linear-gradient(
|
||||||
|
145deg,
|
||||||
|
#fdfdfd,
|
||||||
|
#e6e6e6
|
||||||
|
); /* Heller, weicher Silber-Look */
|
||||||
|
box-shadow: inset 0 4px 8px rgba(255, 255, 255, 0.6),
|
||||||
|
inset 0 -4px 8px rgba(0, 0, 0, 0.1), 0 6px 10px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Vorderseite Light Mode */
|
||||||
|
.card-front.light {
|
||||||
|
border: 1px solid #ddd; /* Leichte Kontur für hellen Look */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rückseite Light Mode */
|
||||||
|
.card-back.light {
|
||||||
|
border: 1px solid #ccc; /* Etwas dunklere Kontur für Kontrast */
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
color: #333; /* Dunkler Text für bessere Lesbarkeit */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Glanzeffekt für Light Mode */
|
||||||
|
.card-front.light::before,
|
||||||
|
.card-back.light::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 150%;
|
||||||
|
height: 150%;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at 50% 50%,
|
||||||
|
rgba(255, 255, 255, 0.5),
|
||||||
|
rgba(255, 255, 255, 0) 70%
|
||||||
|
);
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg);
|
||||||
|
animation: subtle-glow-light 3s ease-in-out infinite;
|
||||||
|
pointer-events: none;
|
||||||
|
filter: blur(3px);
|
||||||
|
mix-blend-mode: overlay; /* Leicht transparenter Glanz */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Glanz-Animation für Light Mode */
|
||||||
|
@keyframes subtle-glow-light {
|
||||||
|
0% {
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg) scale(1.05);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg) scale(1.2);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(-25%, -25%) rotate(30deg) scale(1.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user