@@ -109,7 +108,7 @@ export default function SkillsSection({
const displayLevel = skillItem.level || calculateSkillLevel(skillItem.value);
// Use provided color or get color based on position in array
const colorClass = skillItem.color || getColorByPosition(skillIndex);
-
+
return (
-
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
new file mode 100644
index 0000000..604a35f
--- /dev/null
+++ b/src/pages/HomePage.tsx
@@ -0,0 +1,21 @@
+import HeroSection from '../components/sections/HeroSection';
+import AboutSection from '../components/sections/AboutSection';
+import ServicesSection from '../components/sections/ServicesSection';
+import SkillsSection from '../components/sections/SkillsSection';
+import CertificationsSection from '../components/sections/CertificationsSection';
+import ProjectsSection from '../components/sections/ProjectsSection';
+import ContactSection from '../components/sections/ContactSection';
+
+export default function HomePage() {
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/pages/ImprintPage.tsx b/src/pages/ImprintPage.tsx
new file mode 100644
index 0000000..4f0f5d5
--- /dev/null
+++ b/src/pages/ImprintPage.tsx
@@ -0,0 +1,113 @@
+import { personalConfig } from '../config/personal';
+
+export default function ImprintPage() {
+ return (
+
+
+
+
Impressum
+
Legal Information
+
+
+
+
+
Angaben gemäß § 5 TMG
+
+
Name: {personalConfig.name}
+
Adresse:
+
Musterstraße 123
+
12345 Musterstadt
+
Deutschland
+
+
+
+
+
Kontakt
+
+
E-Mail: {personalConfig.email.full}
+
Telefon: +49 (0) 123 456789
+
+
+
+
+
Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV
+
+
{personalConfig.name}
+
Musterstraße 123
+
12345 Musterstadt
+
+
+
+
+
Haftungsausschluss
+
+
+
Haftung für Inhalte
+
+ Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den
+ allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht
+ unter der Verpflichtung, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach
+ Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.
+
+
+ Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen
+ Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt
+ der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden
+ Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.
+
+
+
+
+
Haftung für Links
+
+ Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen Einfluss haben.
+ Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der
+ verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich.
+
+
+ Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft.
+ Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche
+ Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht
+ zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
+
+
+
+
+
Urheberrecht
+
+ Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem
+ deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung
+ außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors
+ bzw. Erstellers.
+
+
+ Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.
+ Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte
+ Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem
+ auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis.
+ Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
+
+
+
+
+
+
Datenschutz
+
+
+ Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich.
+ Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder
+ E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis.
+ Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben.
+
+
+ Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per
+ E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch
+ Dritte ist nicht möglich.
+
+
+
+
+
+
+ );
+}
diff --git a/src/scss/App.scss b/src/scss/App.scss
index 1fe7006..66a3c7b 100644
--- a/src/scss/App.scss
+++ b/src/scss/App.scss
@@ -43,3 +43,14 @@ section {
padding: 1rem 1rem;
margin: 0; // Remove any section margins
}
+
+// App-level styles for routing
+.app {
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+
+ &__main {
+ flex: 1;
+ }
+}
diff --git a/src/scss/layout/footer.scss b/src/scss/layout/footer.scss
index 1f9749a..7cc16fb 100644
--- a/src/scss/layout/footer.scss
+++ b/src/scss/layout/footer.scss
@@ -21,13 +21,46 @@
flex-direction: column;
align-items: center;
gap: 1rem;
+ }
+ &__bottom-row {
+ display: flex;
+ align-items: center;
+ gap: 2rem;
+ justify-content: center;
+ flex-wrap: wrap;
+ }
+
+ &__links {
+ display: flex;
+ gap: 1.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ &__link {
+ color: var(--color-text-muted);
+ font-size: 0.875rem;
+ text-decoration: none;
+ padding: 0.5rem;
+ border-radius: 0.25rem;
+ transition: all 0.2s ease-in-out;
+
+ &:hover {
+ color: var(--color-text);
+ background-color: var(--color-background-hover);
+ }
+
+ &:focus {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+ }
}
&__copyright {
color: var(--color-text-muted);
font-size: 0.875rem;
text-align: center;
+ margin: 0;
}
&__social {
@@ -68,4 +101,4 @@
width: 1rem;
height: 1rem;
}
-}
\ No newline at end of file
+}
diff --git a/src/scss/layout/topbar.scss b/src/scss/layout/topbar.scss
index bdef4ba..8e79f0f 100644
--- a/src/scss/layout/topbar.scss
+++ b/src/scss/layout/topbar.scss
@@ -11,8 +11,10 @@
&__name {
font-weight: bold;
font-size: 1.25rem;
+ color: var(--color-text);
+ text-decoration: none;
}
-
+
&__container {
&__button {
@extend %button-reset;
@@ -27,7 +29,7 @@
}
}
}
-
+
&__burger-button {
@include globals.flex-center();
justify-content: space-between;
diff --git a/src/scss/sections/_index.scss b/src/scss/sections/_index.scss
index eaa6481..c0567cd 100644
--- a/src/scss/sections/_index.scss
+++ b/src/scss/sections/_index.scss
@@ -5,4 +5,5 @@
@forward 'skills-section';
@forward 'certifications-section';
@forward 'projects-section';
-@forward 'contact-section';
\ No newline at end of file
+@forward 'contact-section';
+@forward 'imprint-page';
diff --git a/src/scss/sections/imprint-page.scss b/src/scss/sections/imprint-page.scss
new file mode 100644
index 0000000..b8b3b98
--- /dev/null
+++ b/src/scss/sections/imprint-page.scss
@@ -0,0 +1,125 @@
+@use '../globals';
+
+.imprint-page {
+ min-height: 100vh;
+ background: var(--bg-primary);
+ padding: 6rem 0 4rem; // Top padding to account for fixed navigation
+
+ &__container {
+ max-width: 50rem;
+ margin: 0 auto;
+ padding: 0 1rem;
+
+ @include globals.desktop-only {
+ padding: 0 1.5rem;
+ }
+ }
+
+ &__header {
+ text-align: center;
+ margin-bottom: 3rem;
+ }
+
+ &__title {
+ font-size: 2.5rem;
+ font-weight: bold;
+ color: var(--color-text);
+ margin-bottom: 0.5rem;
+
+ @include globals.desktop-only {
+ font-size: 3rem;
+ }
+ }
+
+ &__subtitle {
+ font-size: 1.125rem;
+ color: var(--color-text-muted);
+ }
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ gap: 2.5rem;
+ }
+
+ &__section {
+ background: var(--bg-secondary);
+ padding: 2rem;
+ border-radius: 0.75rem;
+ border: 1px solid var(--border-color);
+ }
+
+ &__section-title {
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: var(--color-text);
+ margin-bottom: 1.5rem;
+ border-bottom: 2px solid var(--color-primary);
+ padding-bottom: 0.5rem;
+ }
+
+ &__subsection {
+ margin-bottom: 2rem;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ &__subsection-title {
+ font-size: 1.25rem;
+ font-weight: 600;
+ color: var(--color-text);
+ margin-bottom: 1rem;
+ }
+
+ &__info {
+ line-height: 1.6;
+
+ p {
+ margin-bottom: 0.5rem;
+ color: var(--color-text);
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ strong {
+ font-weight: 600;
+ color: var(--color-text);
+ }
+ }
+ }
+
+ &__text {
+ line-height: 1.7;
+ color: var(--color-text-muted);
+ margin-bottom: 1rem;
+ text-align: justify;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ // Responsive design
+ @include globals.mobile-only {
+ padding: 5rem 0 3rem;
+
+ &__title {
+ font-size: 2rem;
+ }
+
+ &__section {
+ padding: 1.5rem;
+ }
+
+ &__section-title {
+ font-size: 1.25rem;
+ }
+
+ &__subsection-title {
+ font-size: 1.125rem;
+ }
+ }
+}
diff --git a/src/utils/scrollUtils.ts b/src/utils/scrollUtils.ts
new file mode 100644
index 0000000..d2873b8
--- /dev/null
+++ b/src/utils/scrollUtils.ts
@@ -0,0 +1,28 @@
+import type { NavigateFunction } from 'react-router-dom';
+
+export function scrollToSection(
+ sectionId: string,
+ currentPath: string,
+ navigate?: NavigateFunction
+): void {
+ // If we're on the homepage, scroll directly to the section
+ if (currentPath === '/') {
+ const element = document.getElementById(sectionId);
+ if (element) {
+ element.scrollIntoView({ behavior: 'smooth' });
+ }
+ } else if (navigate) {
+ // If we're on another page, navigate to homepage with hash
+ navigate(`/#${sectionId}`);
+ } else {
+ // Fallback: direct navigation without router
+ window.location.href = `/#${sectionId}`;
+ }
+}
+
+export function scrollToProjects(
+ currentPath: string,
+ navigate?: NavigateFunction
+): void {
+ scrollToSection('projects', currentPath, navigate);
+}
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
index eab843a..8f92ec6 100644
--- a/src/vite-env.d.ts
+++ b/src/vite-env.d.ts
@@ -1,2 +1,4 @@
///
declare module '*.PNG';
+declare module '*.png';
+declare module '*.scss';
diff --git a/vite.config.ts b/vite.config.ts
index 8b0f57b..887d770 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,18 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
-})
+ base: '/',
+ optimizeDeps: {
+ include: ['lucide-react'],
+ entries: ['src/**/*.tsx', 'src/**/*.ts'],
+ force: false,
+ },
+ server: {
+ fs: {
+ allow: ['..'],
+ },
+ },
+});