feat: setup, landing page

This commit is contained in:
Louis
2025-10-24 14:24:49 +02:00
parent b62fbe505b
commit 5eb0beafb3
25 changed files with 1834 additions and 466 deletions

110
src/components/App.tsx Normal file
View File

@@ -0,0 +1,110 @@
import { useState, useEffect } from 'react'
import { useTranslation } from 'react-i18next';
import Hero from './Hero';
import About from './About';
import Experience from './Experience/Experience';
import Skills from './Skills';
import Education from './Education';
import Contact from './Contact';
import { ThemeMenu, ThemeType, ThemeSelected } from './ThemeMenu';
function App() {
const { t, i18n } = useTranslation();
const [theme, setTheme] = useState<ThemeType>('dark');
const [themeSelected, setThemeSelected] = useState<ThemeSelected>('system');
useEffect(() => {
if (themeSelected === 'system') {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleChange = () => {
const systemTheme = mediaQuery.matches ? 'dark' : 'light';
setTheme(systemTheme);
document.documentElement.className = `theme-${systemTheme}`;
};
handleChange();
mediaQuery.addEventListener('change', handleChange);
return () => mediaQuery.removeEventListener('change', handleChange);
} else {
setTheme(themeSelected);
document.documentElement.className = `theme-${themeSelected}`;
}
}, [themeSelected]);
const toggleLanguage = () => {
const newLang = i18n.language === 'fr' ? 'en' : 'fr';
i18n.changeLanguage(newLang);
};
const handleThemeChange = (newTheme: ThemeSelected) => {
setThemeSelected(newTheme);
};
return (
<div className="min-h-screen text-secondary bg-primary transition-colors duration-300">
{/* Header */}
<header className='fixed top-0 left-0 right-0 z-50 flex justify-between items-center gap-4 text-sm w-full px-8 py-6 bg-primary/80 backdrop-blur-md border-b border-secondary/10'>
<h1 className='text-2xl font-bold'>
<span className='text-accent'>L</span>ouis <span className='text-accent'>E</span>MARD
</h1>
<nav className='flex gap-6 h-full justify-center items-center'>
<a href='#about' className='hover:text-accent transition-colors'>{t('nav.about')}</a>
<a href='#experience' className='hover:text-accent transition-colors'>{t('nav.experience')}</a>
<a href='#skills' className='hover:text-accent transition-colors'>{t('nav.skills')}</a>
<a href='#education' className='hover:text-accent transition-colors'>{t('nav.education')}</a>
<a href='#contact' className='hover:text-accent transition-colors'>{t('nav.contact')}</a>
{/* Language Toggle */}
<button
onClick={toggleLanguage}
className='px-3 py-1 border border-secondary/20 rounded hover:border-accent hover:text-accent transition-all'
>
{i18n.language.toUpperCase()}
</button>
{/* Theme Menu */}
<ThemeMenu
theme={theme}
themeSelected={themeSelected}
onThemeChange={handleThemeChange}
/>
</nav>
</header>
{/* Main Content */}
<main>
<Hero />
<About />
<Experience />
<Skills />
<Education />
<Contact />
</main>
{/* Footer */}
<footer className='py-8 border-t border-secondary/10 bg-secondary/5'>
<div className='flex flex-col md:flex-row gap-6 justify-center items-center text-sm'>
<a href='https://git.louisemard.dev' target='_blank' rel='noopener noreferrer' className='hover:text-accent transition-colors'>
Gitea
</a>
<a href='https://github.com/LouisDrame' target='_blank' rel='noopener noreferrer' className='hover:text-accent transition-colors'>
GitHub
</a>
<a href='https://www.linkedin.com/in/louis-emard-9b6a931a2/' target='_blank' rel='noopener noreferrer' className='hover:text-accent transition-colors'>
LinkedIn
</a>
<a href='https://www.collective.work/profile/louis-emard' target='_blank' rel='noopener noreferrer' className='hover:text-accent transition-colors'>
Collective
</a>
</div>
<p className='text-center mt-4 text-secondary/50 text-xs'>
© {new Date().getFullYear()} Louis EMARD. All rights reserved.
</p>
</footer>
</div>
)
}
export default App