diff --git a/index.html b/index.html index e4b78ea..612da80 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Vite + React + TS + Louis Emard
diff --git a/public/CV_Louis_EMARD_EN_.pdf b/public/CV_Louis_EMARD_EN_.pdf new file mode 100644 index 0000000..4f3607b Binary files /dev/null and b/public/CV_Louis_EMARD_EN_.pdf differ diff --git a/public/CV_Louis_Emard_FR_.pdf b/public/CV_Louis_Emard_FR_.pdf new file mode 100644 index 0000000..bc3f06c Binary files /dev/null and b/public/CV_Louis_Emard_FR_.pdf differ diff --git a/src/components/About.tsx b/src/components/About.tsx index ebf562e..7939dd5 100644 --- a/src/components/About.tsx +++ b/src/components/About.tsx @@ -17,8 +17,8 @@ const About = () => {

{t('about.experience_desc')}

-

{t('about.passion_title')}

-

{t('about.passion_desc')}

+

{t('about.approach_title')}

+

{t('about.approach_desc')}

diff --git a/src/components/App.tsx b/src/components/App.tsx index e57ab10..b6bc2f1 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -10,8 +10,22 @@ import { ThemeMenu, ThemeType, ThemeSelected } from './ThemeMenu'; function App() { const { t, i18n } = useTranslation(); - const [theme, setTheme] = useState('dark'); - const [themeSelected, setThemeSelected] = useState('system'); + const [theme, setTheme] = useState(() => { + const savedTheme = localStorage.getItem('theme'); + return (savedTheme as ThemeType) || 'dark'; + }); + const [themeSelected, setThemeSelected] = useState(() => { + const savedThemeSelected = localStorage.getItem('themeSelected'); + return (savedThemeSelected as ThemeSelected) || 'system'; + }); + + // Charger la langue sauvegardée au démarrage + useEffect(() => { + const savedLanguage = localStorage.getItem('language'); + if (savedLanguage && (savedLanguage === 'fr' || savedLanguage === 'en')) { + i18n.changeLanguage(savedLanguage); + } + }, [i18n]); useEffect(() => { if (themeSelected === 'system') { @@ -30,32 +44,51 @@ function App() { setTheme(themeSelected); document.documentElement.className = `theme-${themeSelected}`; } - }, [themeSelected]); + + // Sauvegarder le thème sélectionné + localStorage.setItem('themeSelected', themeSelected); + localStorage.setItem('theme', theme); + }, [themeSelected, theme]); const toggleLanguage = () => { const newLang = i18n.language === 'fr' ? 'en' : 'fr'; i18n.changeLanguage(newLang); + localStorage.setItem('language', newLang); }; const handleThemeChange = (newTheme: ThemeSelected) => { setThemeSelected(newTheme); }; + const scrollToSection = (id: string) => { + const section = document.getElementById(id); + if (section) { + section.scrollIntoView({ behavior: 'smooth' }); + } + } + return ( -
+
+ {/* Background Blobs */} +
+
+
+
+
+ {/* Header */}

- Louis EMARD + Louis EMARD

+
- +
@@ -70,7 +101,7 @@ const ExperiencesList = ({ experiences, t }: ExperiencesListProps) => { const { xpId } = useParams(); return
{experiences.map((exp, index) => )} - + {xpId !== undefined && }
@@ -91,20 +122,55 @@ interface ExperienceSummaryProps { const ExperienceSummary = ({ index, exp, t }: ExperienceSummaryProps) => { return - +
- +

{t(exp.title)}

{t(exp.company)}

- {exp.period} +
+ + {exp.period} + + + + +
-

{t(exp.description)}

-
    + + {t(exp.description)} + + {exp.tasks.map((task, taskIndex) => (
  • {t(task)}
  • ))} -
+
}; @@ -143,14 +209,65 @@ const DetailedExperience = ({ t }: DetailedExperienceProps) => { initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} + transition={{ duration: 0.3, ease: "easeInOut" }} className='fixed top-0 left-0 w-full h-full bg-black bg-opacity-80 flex flex-col items-center justify-center z-0 backdrop-blur-sm' onClick={handleBackgroundClick} > - e.stopPropagation()}> - -

Dev full stack

+ + navigate('/')} + className="absolute top-4 right-4 p-2 rounded-full hover:bg-accent/10 transition-colors group" + whileHover={{ scale: 1.1 }} + whileTap={{ scale: 0.9 }} + initial={{ opacity: 0 }} + animate={{ opacity: 1 }} + exit={{ opacity: 0 }} + transition={{ duration: 0.15 }} + > + + + + + +
+ +

Dev full stack

Meta Video

+
+
+ + 2023 - 2024 + +
+
+ + +

Détails supplémentaires

+

Contenu détaillé de l'expérience...

; diff --git a/src/components/ThemeMenu.tsx b/src/components/ThemeMenu.tsx index 2d704b1..c031dff 100644 --- a/src/components/ThemeMenu.tsx +++ b/src/components/ThemeMenu.tsx @@ -5,9 +5,8 @@ import Moon from '../icons/Moon'; import Sun from '../icons/Sun'; import SystemIcon from '../icons/System'; -export type CustomThemeColor = 'purple' | 'teal' | 'sunset' | 'forest' | 'ocean' | 'rose' | 'amber'; -export type ThemeType = 'light' | 'dark' | `custom-${CustomThemeColor}`; -export type ThemeSelected = 'light' | 'dark' | `custom-${CustomThemeColor}` | 'system'; +export type ThemeType = 'light' | 'dark'; +export type ThemeSelected = 'light' | 'dark' | 'system'; interface ThemeMenuProps { theme: ThemeType; @@ -15,25 +14,9 @@ interface ThemeMenuProps { onThemeChange: (theme: ThemeSelected) => void; } -const customThemes: CustomThemeColor[] = ['purple', 'teal', 'sunset', 'forest', 'ocean', 'rose', 'amber']; - -const getThemeEmoji = (color: CustomThemeColor): string => { - const emojis: Record = { - purple: '💜', - teal: '🩵', - sunset: '🌅', - forest: '🌲', - ocean: '🌊', - rose: '🌹', - amber: '⚡' - }; - return emojis[color]; -}; - export const ThemeMenu = ({ theme, themeSelected, onThemeChange }: ThemeMenuProps) => { const { t } = useTranslation(); const [showThemeMenu, setShowThemeMenu] = useState(false); - const [showCustomSubmenu, setShowCustomSubmenu] = useState(true); const getThemeIcon = () => { if (themeSelected === 'system') { @@ -42,17 +25,12 @@ export const ThemeMenu = ({ theme, themeSelected, onThemeChange }: ThemeMenuProp if (theme === 'light') { return ; } - if (theme.startsWith('custom-')) { - const color = theme.split('-')[1] as CustomThemeColor; - return {getThemeEmoji(color)}; - } return ; }; const handleThemeSelect = (selectedTheme: ThemeSelected) => { onThemeChange(selectedTheme); setShowThemeMenu(false); - setShowCustomSubmenu(false); }; return ( @@ -88,44 +66,6 @@ export const ThemeMenu = ({ theme, themeSelected, onThemeChange }: ThemeMenuProp {t('theme.dark')} - {/* Custom Themes - with submenu */} -
- - - {/* Custom Submenu */} - {/* {showCustomSubmenu && ( */} -
- {customThemes.map((color) => ( - - ))} -
- {/* )} */} -
- {/* System Theme */}