diff --git a/app/Projects/[slug]/Footer.tsx b/app/Projects/[slug]/Footer.tsx new file mode 100644 index 0000000..cec5312 --- /dev/null +++ b/app/Projects/[slug]/Footer.tsx @@ -0,0 +1,32 @@ +import Link from "next/link"; + +export default function Footer() { + return ( + + ); +} \ No newline at end of file diff --git a/app/Projects/[slug]/page.tsx b/app/Projects/[slug]/page.tsx index fe76005..82168d3 100644 --- a/app/Projects/[slug]/page.tsx +++ b/app/Projects/[slug]/page.tsx @@ -1,76 +1,87 @@ "use client"; -import { useParams, useRouter } from "next/navigation"; -import { useEffect, useState } from "react"; +import {useParams, useRouter} from "next/navigation"; +import {useEffect, useState} from "react"; import Link from "next/link"; import Image from "next/image"; +import Header from "../../components/Header"; +import Footer from "./Footer"; interface Project { - id: string; - title: string; - slug: string; - description: string; - link: string; - image: string; + id: string; + title: string; + slug: string; + description: string; + link: string; + image: string; } export default function ProjectDetail() { - const params = useParams(); - const router = useRouter(); - const { slug } = params as { slug: string }; - const [project, setProject] = useState(null); + const params = useParams(); + const router = useRouter(); + const {slug} = params as { slug: string }; + const [project, setProject] = useState(null); - useEffect(() => { - if (slug) { - fetch("/data/projects.json") - .then((res) => res.json()) - .then((data: Project[]) => { - const found = data.find((proj) => proj.slug === slug); - if (found) { - setProject(found); + useEffect(() => { + if (slug) { + fetch("/data/projects.json") + .then((res) => res.json()) + .then((data: Project[]) => { + const found = data.find((proj) => proj.slug === slug); + if (found) { + setProject(found); - // Log the project view - fetch("/api/stats", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - type: "project_view", - projectId: found.id, - }), - }).catch((err) => console.error("Failed to log project view", err)); - } else { - // Redirect to 404 if project not found - router.replace("/not-found"); - } - }); + // Log the project view + fetch("/api/stats", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + type: "project_view", + projectId: found.id, + }), + }).catch((err) => console.error("Failed to log project view", err)); + } else { + // Redirect to 404 if project not found + router.replace("/not-found"); + } + }); + } + }, [slug, router]); + + if (!project) { + return
Loading...
; } - }, [slug, router]); - if (!project) { - return
Loading...
; - } - - return ( -
-

- {project.title} -

- {project.title} -

- {project.description} -

- - Go back Home - -
- ); -} + return ( +
+
+
+
+

+ {project.title} +

+ {project.title} +

+ {project.description} +

+ + Go back Home + +
+
+
+
+ ); +} \ No newline at end of file diff --git a/app/components/Contact.tsx b/app/components/Contact.tsx index 5041f54..af7242e 100644 --- a/app/components/Contact.tsx +++ b/app/components/Contact.tsx @@ -22,60 +22,61 @@ export default function Contact() { setSuccess(true); setForm({name: "", email: "", message: ""}); } catch (err) { - //use err to avoid unused variable warning if (err instanceof Error) { setError("Failed to send message. Please try again."); } - } }; return ( -
+

Contact Me

-
- {success && ( -

- Your message has been sent successfully! -

- )} - {error &&

{error}

} - - - - -
+
+
+ {success && ( +

+ Your message has been sent successfully! +

+ )} + {error &&

{error}

} + + + + +
+
); -} +} \ No newline at end of file diff --git a/app/components/Footer.tsx b/app/components/Footer.tsx index a1c254b..89bcaa1 100644 --- a/app/components/Footer.tsx +++ b/app/components/Footer.tsx @@ -1,24 +1,42 @@ import Link from "next/link"; export default function Footer() { - return ( -
-

Thank You for Visiting

-

Connect with me on social platforms:

-
- - - {/* Add more social links as needed */} -
-

© Dennis Konkol 2024

- - - -
- ); -} + const scrollToSection = (id: string) => { + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({behavior: "smooth"}); + } + }; + + return ( +
+

Thank You for Visiting

+

Connect with me on social platforms:

+
+ + + + + + + + + + +
+

© Dennis Konkol 2025

+ +
+ ); +} \ No newline at end of file diff --git a/app/components/Header.tsx b/app/components/Header.tsx index 8d8e909..06b6c5d 100644 --- a/app/components/Header.tsx +++ b/app/components/Header.tsx @@ -2,9 +2,6 @@ import {useState} from "react"; import Link from "next/link"; -import {Roboto} from "next/font/google"; - -const inter = Roboto({weight: '400', subsets: ["latin"]}); export default function Header() { const [isSidebarOpen, setIsSidebarOpen] = useState(false); @@ -13,15 +10,28 @@ export default function Header() { setIsSidebarOpen(!isSidebarOpen); }; + const scrollToSection = (id: string) => { + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({behavior: "smooth"}); + } else { + /*go to main page and scroll*/ + window.location.href = `/#${id}`; + } + }; + return ( -
-
-
-
diff --git a/app/globals.css b/app/globals.css index 22ea7f3..af7f949 100644 --- a/app/globals.css +++ b/app/globals.css @@ -4,195 +4,53 @@ @tailwind components; @tailwind utilities; -/* Custom Global Styles */ body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 0; padding: 0; position: relative; min-height: 100vh; } -body::before { - content: ""; - position: fixed; - top: -50%; - left: -50%; - width: 200%; - height: 200%; - z-index: -1; +.bg-radiant-animated { background: radial-gradient(circle at 20% 20%, #ff8185, transparent 25%), radial-gradient(circle at 80% 80%, #ffaa91, transparent 25%), radial-gradient(circle at 50% 50%, #fb7fd9, transparent 25%), radial-gradient(circle at 30% 70%, #9b6fff, transparent 25%), radial-gradient(circle at 70% 30%, #ff8edf, transparent 25%); background-size: 200% 200%; - animation: bubbleAnimation 60s ease infinite; + animation: backgroundAnimation 60s ease infinite alternate; } -@keyframes bubbleAnimation { +.bg-radiant { + background: radial-gradient(circle at 20% 20%, #ff8185, transparent 25%), + radial-gradient(circle at 80% 80%, #ffaa91, transparent 25%), + radial-gradient(circle at 50% 50%, #fb7fd9, transparent 25%), + radial-gradient(circle at 30% 70%, #9b6fff, transparent 25%), + radial-gradient(circle at 70% 30%, #ff8edf, transparent 25%); + background-size: cover; +} + +@keyframes backgroundAnimation { 0% { background-position: 0 0; - transform: rotate(0deg) scale(1.5); - } - 2.5% { - background-position: 5% 5%; - transform: rotate(9deg) scale(1.5); - } - 5% { - background-position: 10% 10%; - transform: rotate(18deg) scale(1.5); - } - 7.5% { - background-position: 15% 15%; - transform: rotate(27deg) scale(1.5); - } - 10% { - background-position: 20% 20%; - transform: rotate(36deg) scale(1.5); - } - 12.5% { - background-position: 25% 25%; - transform: rotate(45deg) scale(1.5); - } - 15% { - background-position: 30% 30%; - transform: rotate(54deg) scale(1.5); - } - 17.5% { - background-position: 35% 35%; - transform: rotate(63deg) scale(1.5); - } - 20% { - background-position: 40% 40%; - transform: rotate(72deg) scale(1.5); - } - 22.5% { - background-position: 45% 45%; - transform: rotate(81deg) scale(1.5); - } - 25% { - background-position: 50% 50%; - transform: rotate(90deg) scale(1.5); - } - 27.5% { - background-position: 55% 55%; - transform: rotate(99deg) scale(1.5); - } - 30% { - background-position: 60% 60%; - transform: rotate(108deg) scale(1.5); - } - 32.5% { - background-position: 65% 65%; - transform: rotate(117deg) scale(1.5); - } - 35% { - background-position: 70% 70%; - transform: rotate(126deg) scale(1.5); - } - 37.5% { - background-position: 75% 75%; - transform: rotate(135deg) scale(1.5); - } - 40% { - background-position: 80% 80%; - transform: rotate(144deg) scale(1.5); - } - 42.5% { - background-position: 85% 85%; - transform: rotate(153deg) scale(1.5); - } - 45% { - background-position: 90% 90%; - transform: rotate(162deg) scale(1.5); - } - 47.5% { - background-position: 95% 95%; - transform: rotate(171deg) scale(1.5); - } - 50% { - background-position: 100% 100%; - transform: rotate(180deg) scale(1.5); - } - 52.5% { - background-position: 95% 95%; - transform: rotate(189deg) scale(1.5); - } - 55% { - background-position: 90% 90%; - transform: rotate(198deg) scale(1.5); - } - 57.5% { - background-position: 85% 85%; - transform: rotate(207deg) scale(1.5); - } - 60% { - background-position: 80% 80%; - transform: rotate(216deg) scale(1.5); - } - 62.5% { - background-position: 75% 75%; - transform: rotate(225deg) scale(1.5); - } - 65% { - background-position: 70% 70%; - transform: rotate(234deg) scale(1.5); - } - 67.5% { - background-position: 65% 65%; - transform: rotate(243deg) scale(1.5); - } - 70% { - background-position: 60% 60%; - transform: rotate(252deg) scale(1.5); - } - 72.5% { - background-position: 55% 55%; - transform: rotate(261deg) scale(1.5); - } - 75% { - background-position: 50% 50%; - transform: rotate(270deg) scale(1.5); - } - 77.5% { - background-position: 45% 45%; - transform: rotate(279deg) scale(1.5); - } - 80% { - background-position: 40% 40%; - transform: rotate(288deg) scale(1.5); - } - 82.5% { - background-position: 35% 35%; - transform: rotate(297deg) scale(1.5); - } - 85% { - background-position: 30% 30%; - transform: rotate(306deg) scale(1.5); - } - 87.5% { - background-position: 25% 25%; - transform: rotate(315deg) scale(1.5); - } - 90% { - background-position: 20% 20%; - transform: rotate(324deg) scale(1.5); - } - 92.5% { - background-position: 15% 15%; - transform: rotate(333deg) scale(1.5); - } - 95% { - background-position: 10% 10%; - transform: rotate(342deg) scale(1.5); - } - 97.5% { - background-position: 5% 5%; - transform: rotate(351deg) scale(1.5); } 100% { - background-position: 0 0; - transform: rotate(360deg) scale(1.5); + background-position: 100% 100%; } +} + +.min-h-screen { + min-height: 100vh; +} + +.flex { + display: flex; +} + +.flex-col { + flex-direction: column; +} + +.flex-grow { + flex-grow: 1; } \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index b957c5b..a87458d 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,36 +1,33 @@ // app/layout.tsx -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import type {Metadata} from "next"; import "./globals.css"; -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); +import {Roboto} from 'next/font/google' +import React from "react"; + +const roboto = Roboto({ + variable: '--font-roboto', + weight: '400', + subsets: ['latin'], +}) -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); export const metadata: Metadata = { - title: "Dennis's Portfolio", - description: "A portfolio website showcasing my work and skills.", + title: "Dennis's Portfolio", + description: "A portfolio website showcasing my work and skills.", }; export default function RootLayout({ - children, -}: { - children: React.ReactNode; + children, + }: { + children: React.ReactNode; }) { - return ( - - + return ( + + {children} - - - ); -} + + + ); +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 90b362e..316eb26 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -8,7 +8,7 @@ import Footer from "./components/Footer"; export default function Home() { return ( - <> +
@@ -17,6 +17,6 @@ export default function Home() {
- +
); } \ No newline at end of file