diff --git a/README.md b/README.md index 0af157b..a6ea5db 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,8 @@ Les traductions sont centralisées dans `src/utils/translations.ts`. Pour ajoute 3. **Cloud-1** - Infrastructure automatisée avec Docker/Ansible 4. **Minishell** - Réimplémentation d'un shell bash en C 5. **Cube3D** - Moteur 3D RayCaster +6. **etsidemain.com** - Site vitrine pour conseil en transformation régénérative +7. **avopieces.fr** - Plateforme juridique IA pour procédures de divorce ## 📱 Responsive Design diff --git a/index.html b/index.html index 38091af..781c4c0 100644 --- a/index.html +++ b/index.html @@ -15,9 +15,22 @@ + + + + + + + +
diff --git a/public/images/projects/avopieces.svg b/public/images/projects/avopieces.svg new file mode 100644 index 0000000..ed87c90 --- /dev/null +++ b/public/images/projects/avopieces.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/public/images/projects/cloud.svg b/public/images/projects/cloud.svg new file mode 100644 index 0000000..efd48c4 --- /dev/null +++ b/public/images/projects/cloud.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/projects/cube3d.svg b/public/images/projects/cube3d.svg new file mode 100644 index 0000000..e73a84b --- /dev/null +++ b/public/images/projects/cube3d.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/public/images/projects/etsidemain.svg b/public/images/projects/etsidemain.svg new file mode 100644 index 0000000..86d6503 --- /dev/null +++ b/public/images/projects/etsidemain.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/public/images/projects/minishell.svg b/public/images/projects/minishell.svg new file mode 100644 index 0000000..e442ea2 --- /dev/null +++ b/public/images/projects/minishell.svg @@ -0,0 +1,11 @@ + + + + $ + + $ + + $ + + + \ No newline at end of file diff --git a/public/images/projects/nas.svg b/public/images/projects/nas.svg new file mode 100644 index 0000000..db60e5e --- /dev/null +++ b/public/images/projects/nas.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/projects/transcendence.svg b/public/images/projects/transcendence.svg new file mode 100644 index 0000000..5960458 --- /dev/null +++ b/public/images/projects/transcendence.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/components/CookieBanner.tsx b/src/components/CookieBanner.tsx new file mode 100644 index 0000000..a39daf0 --- /dev/null +++ b/src/components/CookieBanner.tsx @@ -0,0 +1,173 @@ +import { useState } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { Cookie, X, Settings } from "lucide-react"; +import { useLanguage } from "@/contexts/LanguageContext"; +import { useCookieBanner } from "@/contexts/CookieBannerContext"; + +export const CookieBanner = () => { + const { t } = useLanguage(); + const { isVisible, hideBanner } = useCookieBanner(); + const [showDetails, setShowDetails] = useState(false); + + const acceptAllCookies = () => { + localStorage.setItem("cookieConsent", "accepted"); + localStorage.setItem("analyticsEnabled", "true"); + hideBanner(); + + // Activer Google Tag Manager + if (typeof window !== 'undefined' && (window as any).gtag) { + (window as any).gtag('consent', 'update', { + 'analytics_storage': 'granted' + }); + } + }; + + const acceptNecessaryOnly = () => { + localStorage.setItem("cookieConsent", "necessary"); + localStorage.setItem("analyticsEnabled", "false"); + hideBanner(); + + // Désactiver les cookies analytiques + if (typeof window !== 'undefined' && (window as any).gtag) { + (window as any).gtag('consent', 'update', { + 'analytics_storage': 'denied' + }); + } + }; + + const rejectAll = () => { + localStorage.setItem("cookieConsent", "rejected"); + localStorage.setItem("analyticsEnabled", "false"); + hideBanner(); + + // Désactiver tous les cookies non nécessaires + if (typeof window !== 'undefined' && (window as any).gtag) { + (window as any).gtag('consent', 'update', { + 'analytics_storage': 'denied' + }); + } + }; + + return ( + + {isVisible && ( + <> + {/* Overlay pour mobile */} + + + {/* Bannière de cookies */} + + +
+ {/* Header */} +
+
+
+ +
+
+

Gestion des cookies

+

+ Nous utilisons des cookies pour améliorer votre expérience +

+
+
+ +
+ + {/* Contenu */} +
+

+ Ce site utilise des cookies pour analyser le trafic et personnaliser le contenu. + Les cookies analytiques nous aident à comprendre comment vous utilisez notre site. +

+ + {showDetails && ( + +
+

🍪 Cookies nécessaires

+

+ Requis pour le fonctionnement de base du site (préférences, sécurité) +

+
+
+

📊 Cookies analytiques

+

+ Google Analytics pour mesurer l'audience et améliorer le site +

+
+
+ )} +
+ + {/* Actions */} +
+ + +
+ + + +
+
+
+
+
+ + )} +
+ ); +}; \ No newline at end of file diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 0000000..f3216f3 --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,179 @@ +import { motion } from "framer-motion"; +import { useState } from "react"; +import { useLanguage } from "@/contexts/LanguageContext"; +import { useCookieBanner } from "@/contexts/CookieBannerContext"; +import { Button } from "@/components/ui/button"; +import { Separator } from "@/components/ui/separator"; +import { LegalNoticeModal } from "@/components/LegalNoticeModal"; +import { Github, Mail, ExternalLink, Cookie, FileText } from "lucide-react"; + +export const Footer = () => { + const { t } = useLanguage(); + const { showBanner } = useCookieBanner(); + const [showLegalNotice, setShowLegalNotice] = useState(false); + + const reopenCookiePreferences = () => { + // Simplement rouvrir la bannière sans recharger + showBanner(); + }; + + const currentYear = new Date().getFullYear(); + + const footerLinks = [ + { + icon: , + label: "Mentions légales", + onClick: () => setShowLegalNotice(true) + }, + { + icon: , + label: "Gestion des cookies", + onClick: reopenCookiePreferences + } + ]; + + const socialLinks = [ + { + icon: , + label: "GitHub", + href: "https://github.com/kinou-p" + }, + { + icon: , + label: "Email", + href: "mailto:contact@apommier.com" + } + ]; + + return ( +
+
+
+ {/* Colonne 1: Logo et description */} + +
+ Alexandre Pommier +
+

+ Étudiant développeur à 42, passionné par les technologies web et systèmes. + Créateur de solutions innovantes pour un avenir numérique. +

+
+ {socialLinks.map((link, index) => ( + + {link.icon} + + ))} +
+
+ + {/* Colonne 2: Navigation rapide */} + +

Navigation

+ +
+ + {/* Colonne 3: Informations légales */} + +

Informations

+ +
+
+ + + + {/* Bas du footer */} + +
+ © {currentYear} Alexandre Pommier. Tous droits réservés. +
+
+
+ Construit avec + + React + +
+
+
+
+ + {/* Modal mentions légales */} + setShowLegalNotice(false)} + /> +
+ ); +}; \ No newline at end of file diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 67101a1..5b8df44 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -15,6 +15,10 @@ export const Header = () => { } }; + const scrollToTop = () => { + window.scrollTo({ top: 0, behavior: "smooth" }); + }; + return ( { className="fixed top-0 left-0 right-0 z-50 border-b border-border/40 bg-background/80 backdrop-blur-lg" >
- AP - +