feat: setup, landing page
This commit is contained in:
110
src/components/App.tsx
Normal file
110
src/components/App.tsx
Normal 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
|
||||
Reference in New Issue
Block a user