Overhaul of About Page

This commit is contained in:
IM23a-spirgif
2025-03-27 09:49:36 +01:00
parent 74194989b9
commit 650d8e5594
+201 -202
View File
@@ -1,221 +1,220 @@
"use client"; "use client"
import {useRef, useState, useEffect} from "react";
import { useRef, useState, useEffect } from "react";
export default function About() { export default function About() {
// Timeline data const timelineData = [
const timelineData = [ {
{ date: "2018",
date: "2018", title: "First Contact with Coding",
title: "First Contact with Coding", content: "I discovered my passion for technology by experimenting with Scratch and creating some simple Games."
content: },
"I discovered my passion for technology by experimenting with Scratch and creating some simple Games.", {
}, date: "2022",
{ title: "Exploring Web Development",
date: "2020", content: "Started creating my first website and got into HTML and CSS."
title: "Exploring Web & Scripting", },
content: {
"Started creating small websites and got into JavaScript, CSS, and working with various scripting languages.", date: "2023",
}, title: "Diving into Informatics",
{ content: "Started with Python and basic exploration of 'real' programming."
date: "2022", },
title: "Diving into Game Development", {
content: date: "2024",
"Tried Unity and C#, building small 2D and 3D prototypes to expand my skill set.", title: "Full Stack & Beyond",
}, content: "Ventured into backend (SQL, Python) and frontend using Javascript"
{ }
date: "2024", ];
title: "Full Stack & Beyond",
content:
"Ventured into backend (SQL, Python) and continued refining my frontend abilities, always exploring new challenges.",
},
];
// Disable lint for calling hooks in a loop const sectionRefs = timelineData.map(() => useRef(null));
// eslint-disable-next-line react-hooks/rules-of-hooks const aboutMeRef = useRef(null);
const sectionRefs = timelineData.map(() => useRef(null)); const [currentSection, setCurrentSection] = useState(0);
const [timelineFinished, setTimelineFinished] = useState(false);
const [isManualScroll, setIsManualScroll] = useState(false); // Track user scrolling
const scrollContainerRef = useRef(null);
const [currentSection, setCurrentSection] = useState(0); useEffect(() => {
setCurrentSection(0); // Reset timeline
setTimelineFinished(false);
// Keep track if the user has reached the last section in the timeline // Ensure 'About Me' is visible on reload
const [timelineFinished, setTimelineFinished] = useState(false); setTimeout(() => {
aboutMeRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
}, 100);
}, []);
// Keyboard navigation (left / right arrow keys) // Handle button navigation
useEffect(() => { const handleButtonClick = (direction) => {
const handleKeyDown = (e) => { setIsManualScroll(false); // Ensure programmatic scrolling happens
if (e.key === "ArrowRight") { setCurrentSection((prev) => {
setCurrentSection((prev) => Math.min(prev + 1, timelineData.length - 1)); const newSection = Math.max(0, Math.min(prev + direction, timelineData.length - 1));
} else if (e.key === "ArrowLeft") { if (newSection === timelineData.length - 1) {
setCurrentSection((prev) => Math.max(prev - 1, 0)); setTimelineFinished(true);
} }
return newSection;
});
}; };
window.addEventListener("keydown", handleKeyDown); // Scroll to current section (only if not manually scrolling)
return () => { useEffect(() => {
window.removeEventListener("keydown", handleKeyDown); if (!isManualScroll) {
}; sectionRefs[currentSection]?.current?.scrollIntoView({behavior: "smooth", inline: "start"});
}, [timelineData.length]); }
}, [currentSection, isManualScroll]);
useEffect(() => {
const handleScroll = () => {
setIsManualScroll(true);
};
// Scroll the timeline horizontally to the currently selected section const scrollContainer = scrollContainerRef.current;
useEffect(() => { if (scrollContainer) {
sectionRefs[currentSection].current?.scrollIntoView({ scrollContainer.addEventListener("scroll", handleScroll);
behavior: "smooth", }
inline: "start",
});
// If we are on the last section, mark timeline as finished return () => {
if (currentSection === timelineData.length - 1) { if (scrollContainer) {
setTimelineFinished(true); scrollContainer.removeEventListener("scroll", handleScroll);
} }
}, [currentSection, sectionRefs]); };
}, []);
// Navigate left or right with on-screen buttons // Intersection Observer to detect when last section is fully visible
const goLeft = () => { useEffect(() => {
setCurrentSection((prev) => Math.max(prev - 1, 0)); const observer = new IntersectionObserver(
}; (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && entry.target === sectionRefs[timelineData.length - 1].current) {
setTimelineFinished(true);
}
});
},
{threshold: 0.8} // Increased threshold to ensure full visibility before triggering
);
const goRight = () => { sectionRefs.forEach((ref) => {
setCurrentSection((prev) => Math.min(prev + 1, timelineData.length - 1)); if (ref.current) observer.observe(ref.current);
}; });
return ( return () => observer.disconnect();
<div style={{ width: "100%", overflowX: "hidden" }}> }, [sectionRefs]);
{/* ───────────────────────────── return (
1) Intro / Top Section <div style={{width: "100%", overflowX: "hidden"}}>
────────────────────────────── */} {/* About Me Section */}
<section
style={{
minHeight: "100vh",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "2rem",
boxSizing: "border-box",
}}
>
<h1 style={{ fontSize: "2.5rem", marginBottom: "1rem" }}>About Me</h1>
<p style={{ maxWidth: "600px", textAlign: "center" }}>
I’m a passionate developer always excited about new challenges.
Scroll down to check out my coding journey through the years!
</p>
</section>
{/* ─────────────────────────────
2) Timeline Section
────────────────────────────── */}
<section
style={{
position: "relative",
height: "100vh",
overflowY: "hidden", // Prevent vertical scroll here
}}
>
{/* Only show the left button if we're not on the first section */}
{currentSection > 0 && (
<button
onClick={goLeft}
style={{
position: "absolute",
top: "50%",
left: "1rem",
transform: "translateY(-50%)",
zIndex: 10,
backgroundColor: "#333",
color: "#fff",
border: "none",
padding: "0.75rem 1rem",
cursor: "pointer",
borderRadius: "4px",
}}
>
&larr;
</button>
)}
{/* Only show the right button if we're not on the last section */}
{currentSection < timelineData.length - 1 && (
<button
onClick={goRight}
style={{
position: "absolute",
top: "50%",
right: "1rem",
transform: "translateY(-50%)",
zIndex: 10,
backgroundColor: "#333",
color: "#fff",
border: "none",
padding: "0.75rem 1rem",
cursor: "pointer",
borderRadius: "4px",
}}
>
&rarr;
</button>
)}
{/* Horizontal scroll area */}
<div
style={{
display: "flex",
overflowX: "auto",
scrollSnapType: "x mandatory",
width: "100%",
height: "100%",
scrollBehavior: "smooth",
}}
>
{timelineData.map((item, index) => (
<section <section
key={index} ref={aboutMeRef}
ref={sectionRefs[index]} style={{
style={{ minHeight: "100vh",
flex: "0 0 100%", display: "flex",
scrollSnapAlign: "center", flexDirection: "column",
display: "flex", alignItems: "center",
flexDirection: "column", justifyContent: "center",
alignItems: "center", padding: "2rem",
justifyContent: "center", boxSizing: "border-box",
padding: "2rem", }}
boxSizing: "border-box",
}}
> >
<h2 style={{ marginBottom: "1rem" }}>{item.title}</h2> <h1 style={{fontSize: "2.5rem", marginBottom: "1rem"}}>About Me</h1>
<h3 style={{ marginBottom: "1rem" }}>{item.date}</h3> <p style={{maxWidth: "600px", textAlign: "center"}}>
<p style={{ maxWidth: "600px", textAlign: "center" }}> I’m a passionate developer always excited about new challenges.
{item.content} Scroll down to check out my coding journey through the years!
</p> </p>
</section> </section>
))}
</div>
</section>
{/* ───────────────────────────── {/* Timeline Section */}
3) Skills Section <section style={{position: "relative", height: "100vh", overflowY: "hidden"}}>
Only visible if timelineFinished {currentSection > 0 && (
────────────────────────────── */} <button
{timelineFinished && ( onClick={() => handleButtonClick(-1)}
<section style={{
style={{ position: "absolute",
minHeight: "100vh", top: "50%",
display: "flex", left: "1rem",
flexDirection: "column", transform: "translateY(-50%)",
alignItems: "center", zIndex: 10,
justifyContent: "center", backgroundColor: "#333",
padding: "2rem", color: "#fff",
boxSizing: "border-box", border: "none",
}} padding: "0.75rem 1rem",
> cursor: "pointer",
<h2 style={{ fontSize: "2rem", marginBottom: "1rem" }}>My Skills</h2> borderRadius: "4px",
<p style={{ maxWidth: "600px", textAlign: "center" }}> }}
By completing projects in web development, scripting, and game >
design, I’ve cultivated a diverse set of skills — spanning &larr;
JavaScript, Python, C#, and more! </button>
</p> )}
</section> {currentSection < timelineData.length - 1 && (
)} <button
</div> onClick={() => handleButtonClick(1)}
); style={{
position: "absolute",
top: "50%",
right: "1rem",
transform: "translateY(-50%)",
zIndex: 10,
backgroundColor: "#333",
color: "#fff",
border: "none",
padding: "0.75rem 1rem",
cursor: "pointer",
borderRadius: "4px",
}}
>
&rarr;
</button>
)}
<div
ref={scrollContainerRef}
style={{
display: "flex",
overflowX: "auto",
scrollSnapType: "x mandatory",
width: "100%",
height: "100%",
scrollBehavior: "smooth",
}}
>
{timelineData.map((item, index) => (
<section
key={index}
ref={sectionRefs[index]}
style={{
flex: "0 0 100%",
scrollSnapAlign: "center",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "2rem",
boxSizing: "border-box",
}}
>
<h2 style={{marginBottom: "1rem"}}>{item.title}</h2>
<h3 style={{marginBottom: "1rem"}}>{item.date}</h3>
<p style={{maxWidth: "600px", textAlign: "center"}}>{item.content}</p>
</section>
))}
</div>
</section>
{timelineFinished && (
<section
style={{
minHeight: "100vh",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "2rem",
boxSizing: "border-box",
}}
>
<h2 style={{fontSize: "2rem", marginBottom: "1rem"}}>My Skills</h2>
<p style={{maxWidth: "600px", textAlign: "center"}}>
By completing projects in web development, scripting, and game
design, I’ve cultivated a diverse set of skills — spanning
JavaScript, Python, C#, and more!
</p>
</section>
)}
</div>
);
} }