diff --git a/public/images/portfolio-project1.png b/public/images/portfolio-project1.png new file mode 100644 index 0000000..f805b67 Binary files /dev/null and b/public/images/portfolio-project1.png differ diff --git a/public/images/portfolio-project2.png b/public/images/portfolio-project2.png new file mode 100644 index 0000000..0a59a1c Binary files /dev/null and b/public/images/portfolio-project2.png differ diff --git a/public/images/portfolio-project3.png b/public/images/portfolio-project3.png new file mode 100644 index 0000000..50c8d18 Binary files /dev/null and b/public/images/portfolio-project3.png differ diff --git a/src/app/about/page.js b/src/app/about/page.js index 703021c..669d688 100644 --- a/src/app/about/page.js +++ b/src/app/about/page.js @@ -1,5 +1,6 @@ "use client" import {useRef, useState, useEffect} from "react"; +import Link from "next/link"; export default function About() { const timelineData = [ @@ -149,6 +150,8 @@ export default function About() { width: "100%", height: "100%", scrollBehavior: "smooth", + scrollbarWidth: "none", // Firefox + msOverflowStyle: "none", // IE/Edge }} > {timelineData.map((item, index) => ( @@ -220,6 +223,23 @@ export default function About() { ))} +
+ + + +
)} diff --git a/src/app/globals.css b/src/app/globals.css index 5b7db43..f599512 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -129,6 +129,13 @@ html { background-color: #2e002e; } +@keyframes pulsePrompt { + 0% { opacity: 0.6; transform: translateY(0); } + 50% { opacity: 1; transform: translateY(-5px); } + 100% { opacity: 0.6; transform: translateY(0); } +} + + .scrollPrompt { position: fixed; bottom: 20px; @@ -140,6 +147,7 @@ html { font-size: 1rem; z-index: 1000; background: none; + animation: pulsePrompt 2s infinite ease-in-out; } .fade-in-section.is-visible { @@ -151,6 +159,13 @@ html { display: none; } +.learnMoreButton:hover { + background-color: #2e002e; + transform: scale(1.05); + box-shadow: 0 0 10px #600060; +} + + body { -ms-overflow-style: none; scrollbar-width: none; @@ -193,3 +208,71 @@ body { transform: translateY(8px); } } + +body { + overflow-x: hidden; +} + +@media (max-width: 768px) { + .section { + flex-direction: column; + text-align: center; + } +} + +.projectContainer { + min-height: 100vh; + padding: 2rem; + color: white; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; +} + +.projectCard { + max-width: 800px; + padding: 2rem; + border-radius: 10px; + border: 2px solid #3d003d; + background-color: rgba(20, 0, 20, 0.4); + transition: opacity 0.3s ease; +} + +.projectImage { + border-radius: 10px; + margin: 1.5rem 0; + border: 4px solid #3d003d; + animation: pulseBorder 1.5s infinite alternate ease-in-out; +} + +.projectNavigation { + margin-top: 2rem; + display: flex; + gap: 2rem; +} + +.arrowButton { + padding: 0.75rem 1.5rem; + font-size: 1.5rem; + background-color: #3d003d; + border: none; + border-radius: 5px; + color: #fff; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.arrowButton:hover { + background-color: #2e002e; +} + +.fade-in { + opacity: 1; +} + +.fade-out { + opacity: 0; +} + diff --git a/src/app/page.js b/src/app/page.js index 678ff5a..efb040d 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -10,17 +10,21 @@ export default function Home() { const [title, setTitle] = useState("Fretux"); const [phase, setPhase] = useState("normal"); useEffect(() => { + let fadeTimeout; const interval = setInterval(() => { setPhase("fadeOut"); - setTimeout(() => { - setTitle((prev) => (prev === "Fretux" ? "Frederik Spirgi" : "Fretux")); + fadeTimeout = setTimeout(() => { + setTitle(prev => prev === "Fretux" ? "Frederik Spirgi" : "Fretux"); setPhase("fadeIn"); - setTimeout(() => { - setPhase("normal"); - }, 500); + + fadeTimeout = setTimeout(() => setPhase("normal"), 500); }, 500); }, 3000); - return () => clearInterval(interval); + + return () => { + clearInterval(interval); + clearTimeout(fadeTimeout); + }; }, []); useEffect(() => { if (typeof window !== "undefined") { @@ -62,7 +66,8 @@ export default function Home() {

- I'm a passionate developer exploring web, game, and backend technologies with a focus on innovation and creativity. + I'm a passionate developer exploring web, game, and backend technologies with a focus on + innovation and creativity.

diff --git a/src/app/projects/page.js b/src/app/projects/page.js new file mode 100644 index 0000000..1b2bbd8 --- /dev/null +++ b/src/app/projects/page.js @@ -0,0 +1,75 @@ +"use client"; + +import { useState } from "react"; +import Image from "next/image"; + +const projectData = [ + { + title: "Red Lake Stats", + description: "An interactive Javascript and Python application designed to calculate damage statistics for the Roblox game 'The Red Lake'", + image: "/images/portfolio-project1.png", + link: "https://fretux.ch/trlstats", + }, + { + title: "SBB-History", + description: "A website about the creation of the SBB (Swiss Train Corporation) with an interactable map!", + image: "/images/portfolio-project2.png", + link: "https://sbb-history.fretux.ch", + }, + { + title: "Fretux.ch", + description: "My first portfolio website, gameified for more user interaction.", + image: "/images/portfolio-project3.png", + link: "https://fretux.ch", + }, +]; + +export default function ProjectsPage() { + const [currentIndex, setCurrentIndex] = useState(0); + const [fade, setFade] = useState(false); + + const handleNavigation = (direction) => { + setFade(true); + setTimeout(() => { + setCurrentIndex((prev) => { + const newIndex = + direction === "next" + ? (prev + 1) % projectData.length + : (prev - 1 + projectData.length) % projectData.length; + return newIndex; + }); + setFade(false); + }, 300); + }; + + const project = projectData[currentIndex]; + + return ( +
+
+

{project.title}

+ {project.title} +

{project.description}

+ + + +
+
+ + +
+
+ ); +} \ No newline at end of file diff --git a/src/app/projects/project.js b/src/app/projects/project.js deleted file mode 100644 index e69de29..0000000