From 8ecec92aec4d776a669360e147c10ee9711ee063 Mon Sep 17 00:00:00 2001 From: fretuks Date: Thu, 30 Jul 2026 23:45:01 +0200 Subject: [PATCH] update website --- src/app/about/page.js | 321 +------ src/app/components/CustomCursor.jsx | 67 ++ src/app/components/Footer.js | 15 +- src/app/components/Nav.js | 13 +- src/app/contact/page.js | 82 +- src/app/globals.css | 1217 ++++++++++++--------------- src/app/layout.js | 41 +- src/app/page.js | 108 +-- src/app/projects/page.js | 107 +-- 9 files changed, 719 insertions(+), 1252 deletions(-) create mode 100644 src/app/components/CustomCursor.jsx diff --git a/src/app/about/page.js b/src/app/about/page.js index 1dc172b..9aff1c3 100644 --- a/src/app/about/page.js +++ b/src/app/about/page.js @@ -1,298 +1,29 @@ -"use client" -import {useRef, useState, useEffect} from "react"; import Link from "next/link"; -import FadeInSection from "@/app/components/FadeInSection"; - +export const metadata = {title: "About"}; +const timeline = [ + {year: "2018", title: "The first spark", text: "I discovered programming through Scratch, turning small ideas into simple, playable games.", skills: ["Scratch", "Game logic"]}, + {year: "2022", title: "Into the web", text: "I began building websites and learned the foundations of HTML, CSS, and accessible interface design.", skills: ["HTML", "CSS", "JavaScript"]}, + {year: "2022", title: "From screen to hardware", text: "A Raspberry Pi opened the door to Python scripting, Linux, and the fun of connecting software with real hardware.", skills: ["Python", "Linux", "Raspberry Pi"]}, + {year: "2024", title: "Full stack & beyond", text: "I expanded into databases, backend systems, Java, and larger projects—while continuing to sharpen my eye for frontend craft.", skills: ["SQL", "Python", "Java", "JavaScript"]}, +]; export default function About() { - const timelineData = [ - { - date: "2018", - title: "First Contact with Coding", - content: - "I discovered my passion for technology by experimenting with Scratch and creating some simple Games.", - }, - { - date: "2022", - title: "Exploring Web & Scripting", - content: - "Started creating small websites and got into HTML, CSS", - }, - { - date: "2022", - title: "Raspberry Pi & Python", - content: - "Created some simple Python scripts for my Raspberry Pi, experimenting with the Raspberry Pi OS", - }, - { - date: "2024", - title: "Full Stack & Beyond", - content: - "Ventured into backend (SQL, Python, Javascript, Java) and continued refining my frontend abilities.", - }, - ]; - - function getSkillEmoji(name) { - switch (name) { - case "JavaScript": return "🟨"; - case "Python": return "🐍"; - case "Java": return "☕"; - case "SQL": return "💾"; - case "HTML & CSS": return "🎨"; - default: return "💡"; - } - } - - const skills = [ - { - name: "JavaScript", - level: 80, - waveSpeed: "2s", - progression: [0, 30, 60, 80], - }, - { - name: "Python", - level: 75, - waveSpeed: "2.5s", - progression: [10, 25, 50, 75], - }, - { - name: "Java", - level: 50, - waveSpeed: "3s", - progression: [0, 0, 0, 60], - }, - { - name: "SQL", - level: 85, - waveSpeed: "2.2s", - progression: [0, 0, 0, 85], - }, - { - name: "HTML & CSS", - level: 70, - waveSpeed: "2.7s", - progression: [0, 30, 50, 80], - }, - ]; - - const getSkillLabel = (level) => { - if (level < 25) return "Beginner"; - if (level < 50) return "Intermediate"; - if (level < 75) return "Advanced"; - return "Expert"; - }; - - const sectionRefs = useRef([]); - const aboutMeRef = useRef(null); - const buttonSectionRef = useRef(null); - const scrollContainerRef = useRef(null); - const [currentSection, setCurrentSection] = useState(0); - const [timelineFinished, setTimelineFinished] = useState(false); - const [showScrollPrompt, setShowScrollPrompt] = useState(false); - useEffect(() => { - setCurrentSection(0); - setTimelineFinished(false); - setTimeout(() => { - sectionRefs.current[0]?.scrollIntoView({behavior: "auto", inline: "start"}); - window.scrollTo({top: 0, behavior: "smooth"}); - }, 100); - }, []); - - useEffect(() => { - let scrollListener; - - if (timelineFinished) { - setShowScrollPrompt(true); - - scrollListener = () => { - setShowScrollPrompt(false); - window.removeEventListener("scroll", scrollListener); - }; - - window.addEventListener("scroll", scrollListener); - } - - return () => { - if (scrollListener) { - window.removeEventListener("scroll", scrollListener); - } - }; - }, [timelineFinished]); - const [isNavigating, setIsNavigating] = useState(false); - const handleButtonClick = (direction) => { - if (isNavigating) return; - setIsNavigating(true); - setCurrentSection((prev) => { - const newSection = Math.max(0, Math.min(prev + direction, timelineData.length - 1)); - sectionRefs.current[newSection]?.scrollIntoView({behavior: "smooth", inline: "start"}); - return newSection; - }); - setTimeout(() => { - setIsNavigating(false); - }, 600); - }; - useEffect(() => { - const observer = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - const index = sectionRefs.current.findIndex((el) => el === entry.target); - if (entry.isIntersecting && index !== -1) { - setCurrentSection(index); - } - if (entry.isIntersecting && index === timelineData.length - 1) { - setTimelineFinished(true); - } - - }); - }, - {threshold: 0.6} - ); - sectionRefs.current.forEach((el) => { - if (el) observer.observe(el); - }); - return () => observer.disconnect(); - }, [timelineData.length]); - useEffect(() => { - setTimelineFinished(currentSection === timelineData.length - 1); - }, [currentSection, timelineData.length]); - return ( -
- -
-

About Me

-

- I’m a passionate developer always excited about new challenges. - Scroll down to learn more about me! -

-
-
- {/* Timeline Section */} -
- {/* Navigation buttons and timeline content here */} -
- {timelineData.map((item, index) => { - const adjustedSkills = skills.map((s) => { - const stepLevel = s.progression?.[index] ?? 0; - return { - ...s, - level: Math.floor((s.level * stepLevel) / 100), - }; - }); - return ( -
(sectionRefs.current[index] = el)} - className="timeline-page" - > -
-
- {item.date} -

{item.title}

-
-

{item.content}

-
- {adjustedSkills.filter((s) => s.level > 0).map((skill, sIndex) => ( - - {getSkillEmoji(skill.name)} {skill.name} - {getSkillLabel(skill.level)} - - ))} -
-
-
- ); - })} -
- {currentSection > 0 && ( - - )} - {currentSection < timelineData.length - 1 && ( - - )} -
- {timelineFinished && showScrollPrompt && ( -
- ⬇ Scroll down to continue ⬇ -
- )} - {/* FINAL BUTTON SECTION - MOVED OUTSIDE */} - {timelineFinished && ( - // Fügen Sie dem Button-Section einen z-Index hinzu -
- - - -
- )} + return (<> +
+

About me

Always
learning.

+

I’m a developer driven by curiosity, thoughtful details, and the satisfying moment when a complex problem finally clicks.

+
+
+ +
{timeline.map(item => ( +
+
{item.year}
+

{item.title}

{item.text}

{item.skills.map(skill => {skill})}
+
+ ))}
- ) -} \ No newline at end of file + ); +} diff --git a/src/app/components/CustomCursor.jsx b/src/app/components/CustomCursor.jsx new file mode 100644 index 0000000..b4ebbf9 --- /dev/null +++ b/src/app/components/CustomCursor.jsx @@ -0,0 +1,67 @@ +"use client"; + +import React, {useEffect, useRef, useState} from "react"; + +export default function CustomCursor() { + const cursorRef = useRef(null); + const rafRef = useRef(0); + const targetPos = useRef({ x: 0, y: 0 }); + const currentPos = useRef({ x: 0, y: 0 }); + const [hidden, setHidden] = useState(true); + const [active, setActive] = useState(false); + const [clicking, setClicking] = useState(false); + const animate = () => { + const lerp = 0.18; + currentPos.current.x += (targetPos.current.x - currentPos.current.x) * lerp; + currentPos.current.y += (targetPos.current.y - currentPos.current.y) * lerp; + + if (cursorRef.current) { + cursorRef.current.style.transform = `translate3d(${currentPos.current.x}px, ${currentPos.current.y}px, 0)`; + } + rafRef.current = requestAnimationFrame(animate); + }; + useEffect(() => { + const move = (e) => { + targetPos.current.x = e.clientX; + targetPos.current.y = e.clientY; + setHidden(false); + }; + const mouseEnter = () => setHidden(false); + const mouseLeave = () => setHidden(true); + const mouseDown = () => setClicking(true); + const mouseUp = () => setClicking(false); + const updateActive = (e) => { + const el = e.target; + const clickable = el.closest?.( + 'a, button, [role="button"], input[type="submit"], input[type="button"], .clickable' + ); + setActive(Boolean(clickable)); + }; + window.addEventListener("mousemove", move, { passive: true }); + window.addEventListener("mouseenter", mouseEnter, { passive: true }); + window.addEventListener("mouseleave", mouseLeave, { passive: true }); + window.addEventListener("mousedown", mouseDown, { passive: true }); + window.addEventListener("mouseup", mouseUp, { passive: true }); + window.addEventListener("mouseover", updateActive, { passive: true }); + rafRef.current = requestAnimationFrame(animate); + return () => { + window.removeEventListener("mousemove", move); + window.removeEventListener("mouseenter", mouseEnter); + window.removeEventListener("mouseleave", mouseLeave); + window.removeEventListener("mousedown", mouseDown); + window.removeEventListener("mouseup", mouseUp); + window.removeEventListener("mouseover", updateActive); + cancelAnimationFrame(rafRef.current); + }; + }, []); + let className = "custom-cursor"; + if (hidden) className += " custom-cursor--hidden"; + if (active) className += " custom-cursor--active"; + if (clicking) className += " custom-cursor--click"; + return ( + + ); +} \ No newline at end of file diff --git a/src/app/components/Footer.js b/src/app/components/Footer.js index 1cb8139..cca2b74 100644 --- a/src/app/components/Footer.js +++ b/src/app/components/Footer.js @@ -1,15 +1,10 @@ export default function Footer() { return ( -