wip: started to add translations
All checks were successful
Build / Explore-Gitea-Actions (push) Successful in 35s
All checks were successful
Build / Explore-Gitea-Actions (push) Successful in 35s
This commit is contained in:
parent
34531fd2cf
commit
81dad2b6ba
@ -2,13 +2,15 @@ import React, { useEffect } from 'react';
|
|||||||
import banquiseServer from '../../assets/banquise_server.svg'
|
import banquiseServer from '../../assets/banquise_server.svg'
|
||||||
import { URLS, SITE_CONFIG } from '../../config/constants';
|
import { URLS, SITE_CONFIG } from '../../config/constants';
|
||||||
import { commonStyles } from '../../styles/components';
|
import { commonStyles } from '../../styles/components';
|
||||||
|
import type { Translation } from '../../types/i18n';
|
||||||
|
|
||||||
interface MobileMenuProps {
|
interface MobileMenuProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
translations: Translation['navigation'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose }) => {
|
export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, translations }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
@ -76,7 +78,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose }) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-semibold text-lg">Nos Services</span>
|
<span className="font-semibold text-lg">{translations.services}</span>
|
||||||
<p className="text-white/60 text-sm">Découvrir notre offre</p>
|
<p className="text-white/60 text-sm">Découvrir notre offre</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -93,7 +95,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose }) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-semibold text-lg">À propos</span>
|
<span className="font-semibold text-lg">{translations.about}</span>
|
||||||
<p className="text-white/60 text-sm">En savoir plus sur nous</p>
|
<p className="text-white/60 text-sm">En savoir plus sur nous</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -106,7 +108,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose }) => {
|
|||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.discord} group-hover:scale-110 transition-transform duration-200`}>
|
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.discord} group-hover:scale-110 transition-transform duration-200`}>
|
||||||
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
|
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||||
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
|
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.30z"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -3,8 +3,14 @@ import { MobileMenu } from './MobileMenu';
|
|||||||
import banquiseServer from '/src/assets/banquise_server.svg'
|
import banquiseServer from '/src/assets/banquise_server.svg'
|
||||||
import { URLS, SITE_CONFIG } from '../../config/constants';
|
import { URLS, SITE_CONFIG } from '../../config/constants';
|
||||||
import { commonStyles } from '../../styles/components';
|
import { commonStyles } from '../../styles/components';
|
||||||
|
import type { Translation } from '../../types/i18n';
|
||||||
|
|
||||||
export const Navigation: React.FC = () => {
|
interface NavigationProps {
|
||||||
|
translations: Translation['navigation'];
|
||||||
|
languageSwitcher: React.ReactElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Navigation: React.FC<NavigationProps> = ({ translations, languageSwitcher }) => {
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||||
const [scrolled, setScrolled] = useState(false);
|
const [scrolled, setScrolled] = useState(false);
|
||||||
|
|
||||||
@ -13,7 +19,6 @@ export const Navigation: React.FC = () => {
|
|||||||
const isScrolled = window.scrollY > 20;
|
const isScrolled = window.scrollY > 20;
|
||||||
setScrolled(isScrolled);
|
setScrolled(isScrolled);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('scroll', handleScroll);
|
window.addEventListener('scroll', handleScroll);
|
||||||
return () => window.removeEventListener('scroll', handleScroll);
|
return () => window.removeEventListener('scroll', handleScroll);
|
||||||
}, []);
|
}, []);
|
||||||
@ -24,7 +29,6 @@ export const Navigation: React.FC = () => {
|
|||||||
setMobileMenuOpen(false);
|
setMobileMenuOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize);
|
window.addEventListener('resize', handleResize);
|
||||||
return () => window.removeEventListener('resize', handleResize);
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
}, []);
|
}, []);
|
||||||
@ -38,7 +42,6 @@ export const Navigation: React.FC = () => {
|
|||||||
}`}>
|
}`}>
|
||||||
<div className={commonStyles.layout.container}>
|
<div className={commonStyles.layout.container}>
|
||||||
<div className="flex justify-between items-center h-16 sm:h-18 lg:h-20 px-4 sm:px-6 lg:px-8">
|
<div className="flex justify-between items-center h-16 sm:h-18 lg:h-20 px-4 sm:px-6 lg:px-8">
|
||||||
|
|
||||||
{/* Logo section */}
|
{/* Logo section */}
|
||||||
<div className="flex items-center space-x-3 sm:space-x-4 group">
|
<div className="flex items-center space-x-3 sm:space-x-4 group">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@ -62,19 +65,29 @@ export const Navigation: React.FC = () => {
|
|||||||
|
|
||||||
{/* Navigation links desktop */}
|
{/* Navigation links desktop */}
|
||||||
<div className="hidden md:flex items-center space-x-1 lg:space-x-2">
|
<div className="hidden md:flex items-center space-x-1 lg:space-x-2">
|
||||||
<a href="#services" className={commonStyles.nav.link}>
|
<a href="#home" className={commonStyles.nav.link}>
|
||||||
<span className="relative z-10">Services</span>
|
<span className="relative z-10">{translations.home}</span>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||||
|
</a>
|
||||||
|
<a href="#services" className={commonStyles.nav.link}>
|
||||||
|
<span className="relative z-10">{translations.services}</span>
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="#about" className={commonStyles.nav.link}>
|
<a href="#about" className={commonStyles.nav.link}>
|
||||||
<span className="relative z-10">À propos</span>
|
<span className="relative z-10">{translations.about}</span>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||||
|
</a>
|
||||||
|
<a href="#contact" className={commonStyles.nav.link}>
|
||||||
|
<span className="relative z-10">{translations.contact}</span>
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Action buttons desktop */}
|
{/* Action buttons desktop */}
|
||||||
<div className="hidden md:flex items-center space-x-3 lg:space-x-4">
|
<div className="hidden md:flex items-center space-x-3 lg:space-x-4">
|
||||||
|
{/* Language switcher */}
|
||||||
|
{languageSwitcher}
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href={URLS.social.discord}
|
href={URLS.social.discord}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -89,7 +102,6 @@ export const Navigation: React.FC = () => {
|
|||||||
<span>Discord</span>
|
<span>Discord</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href={URLS.services.auth}
|
href={URLS.services.auth}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -122,14 +134,13 @@ export const Navigation: React.FC = () => {
|
|||||||
aria-expanded={mobileMenuOpen}
|
aria-expanded={mobileMenuOpen}
|
||||||
>
|
>
|
||||||
<div className="w-6 h-6 relative">
|
<div className="w-6 h-6 relative">
|
||||||
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 ${mobileMenuOpen ? 'rotate-45 top-3' : 'top-1'}`}></span>
|
<span className={`absolute block w-6 h-6 bg-white transition-all duration-300 ${mobileMenuOpen ? 'rotate-45 top-3' : 'top-1'}`}></span>
|
||||||
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 top-3 ${mobileMenuOpen ? 'opacity-0 scale-0' : 'opacity-100'}`}></span>
|
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 top-3 ${mobileMenuOpen ? 'opacity-0 scale-0' : 'opacity-100'}`}></span>
|
||||||
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 ${mobileMenuOpen ? '-rotate-45 top-3' : 'top-5'}`}></span>
|
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 ${mobileMenuOpen ? '-rotate-45 top-3' : 'top-5'}`}></span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Glassmorphism effect bar */}
|
{/* Glassmorphism effect bar */}
|
||||||
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-banquise-blue-lightest/30 to-transparent"></div>
|
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-banquise-blue-lightest/30 to-transparent"></div>
|
||||||
</nav>
|
</nav>
|
||||||
@ -141,6 +152,7 @@ export const Navigation: React.FC = () => {
|
|||||||
<MobileMenu
|
<MobileMenu
|
||||||
isOpen={mobileMenuOpen}
|
isOpen={mobileMenuOpen}
|
||||||
onClose={() => setMobileMenuOpen(false)}
|
onClose={() => setMobileMenuOpen(false)}
|
||||||
|
translations={translations}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import banquiseServer from '/src/assets/banquise_server.svg'
|
import banquiseServer from '/src/assets/banquise_server.svg'
|
||||||
|
import type { Translation } from '../../types/i18n';
|
||||||
|
|
||||||
export const HeroSection: React.FC = () => (
|
interface HeroSectionProps {
|
||||||
|
translations: Translation['hero'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HeroSection: React.FC<HeroSectionProps> = ({ translations }) => (
|
||||||
<section className="min-h-[calc(80vh-72px)] flex flex-col justify-center items-center text-center py-12 sm:py-16 md:py-20 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8 relative z-3">
|
<section className="min-h-[calc(80vh-72px)] flex flex-col justify-center items-center text-center py-12 sm:py-16 md:py-20 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8 relative z-3">
|
||||||
<div className="mb-8 sm:mb-10 md:mb-12 w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 rounded-full bg-gradient-to-br from-banquise-blue-dark/20 to-banquise-blue/10 p-4 sm:p-5 md:p-6 shadow-2xl backdrop-blur-sm border border-banquise-blue-lightest/30 relative group">
|
<div className="mb-8 sm:mb-10 md:mb-12 w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 rounded-full bg-gradient-to-br from-banquise-blue-dark/20 to-banquise-blue/10 p-4 sm:p-5 md:p-6 shadow-2xl backdrop-blur-sm border border-banquise-blue-lightest/30 relative group">
|
||||||
<img
|
<img
|
||||||
@ -15,15 +20,15 @@ export const HeroSection: React.FC = () => (
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-banquise-gray text-3xl sm:text-4xl md:text-5xl lg:text-6xl mb-6 sm:mb-7 md:mb-8 font-extrabold leading-tight max-w-4xl font-heading px-2 relative z-10" style={{ textShadow: '0 2px 10px rgba(0, 0, 0, 0.3)' }}>
|
<h1 className="text-banquise-gray text-3xl sm:text-4xl md:text-5xl lg:text-6xl mb-6 sm:mb-7 md:mb-8 font-extrabold leading-tight max-w-4xl font-heading px-2 relative z-10" style={{ textShadow: '0 2px 10px rgba(0, 0, 0, 0.3)' }}>
|
||||||
Bienvenue sur La Banquise
|
{translations.title}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="text-banquise-gray text-lg sm:text-xl md:text-2xl mb-8 sm:mb-10 md:mb-12 max-w-3xl font-normal opacity-90 leading-relaxed px-2 relative z-10" style={{ textShadow: '0 1px 4px rgba(0, 0, 0, 0.2)' }}>
|
<p className="text-banquise-gray text-lg sm:text-xl md:text-2xl mb-8 sm:mb-10 md:mb-12 max-w-3xl font-normal opacity-90 leading-relaxed px-2 relative z-10" style={{ textShadow: '0 1px 4px rgba(0, 0, 0, 0.2)' }}>
|
||||||
Association d'hébergement et lab réseau pour tous les étudiants et associations de l'EPITA !
|
{translations.subtitle}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="#services" className="inline-flex items-center justify-center bg-gradient-to-r from-banquise-gray to-white text-banquise-blue-dark border-0 py-4 sm:py-5 px-8 sm:px-10 md:px-12 rounded-2xl text-base sm:text-lg font-bold no-underline shadow-xl transition-all duration-300 min-w-48 sm:min-w-56 md:min-w-64 hover:-translate-y-2 hover:shadow-2xl hover:scale-105 backdrop-blur-sm border border-banquise-blue-lightest/20 mx-4 group relative z-10">
|
<a href="#services" className="inline-flex items-center justify-center bg-gradient-to-r from-banquise-gray to-white text-banquise-blue-dark border-0 py-4 sm:py-5 px-8 sm:px-10 md:px-12 rounded-2xl text-base sm:text-lg font-bold no-underline shadow-xl transition-all duration-300 min-w-48 sm:min-w-56 md:min-w-64 hover:-translate-y-2 hover:shadow-2xl hover:scale-105 backdrop-blur-sm border border-banquise-blue-lightest/20 mx-4 group relative z-10">
|
||||||
<span className="text-center text-banquise-blue-dark">Découvrir nos services</span>
|
<span className="text-center text-banquise-blue-dark">{translations.cta}</span>
|
||||||
<span className="ml-2 sm:ml-3 text-lg sm:text-xl transition-transform duration-300 group-hover:translate-x-1 text-banquise-blue-dark">→</span>
|
<span className="ml-2 sm:ml-3 text-lg sm:text-xl transition-transform duration-300 group-hover:translate-x-1 text-banquise-blue-dark">→</span>
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { URLS } from '../../config/constants';
|
import { URLS } from '../../config/constants';
|
||||||
|
import type { Service } from '../../types/service';
|
||||||
interface Service {
|
import type { Translation } from '../../types/i18n';
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
image: string;
|
|
||||||
icon: string;
|
|
||||||
description: string;
|
|
||||||
features: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PopupProps {
|
interface PopupProps {
|
||||||
service: Service;
|
service: Service;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
translations: Translation['common'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Popup: React.FC<PopupProps> = ({ service, onClose }) => {
|
export const Popup: React.FC<PopupProps> = ({ service, onClose, translations }) => {
|
||||||
// Empêcher le scroll du body quand la popup est ouverte
|
// Empêcher le scroll du body quand la popup est ouverte
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
@ -34,7 +28,7 @@ export const Popup: React.FC<PopupProps> = ({ service, onClose }) => {
|
|||||||
<button
|
<button
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="bg-white/90 hover:bg-white border border-banquise-blue/20 text-xl cursor-pointer text-banquise-blue-dark flex items-center justify-center w-10 h-10 sm:w-12 sm:h-12 rounded-full transition-all duration-200 hover:scale-110 active:scale-95 shadow-lg backdrop-blur-sm"
|
className="bg-white/90 hover:bg-white border border-banquise-blue/20 text-xl cursor-pointer text-banquise-blue-dark flex items-center justify-center w-10 h-10 sm:w-12 sm:h-12 rounded-full transition-all duration-200 hover:scale-110 active:scale-95 shadow-lg backdrop-blur-sm"
|
||||||
aria-label="Fermer la popup"
|
aria-label={translations.close}
|
||||||
>
|
>
|
||||||
×
|
×
|
||||||
</button>
|
</button>
|
||||||
@ -100,7 +94,7 @@ export const Popup: React.FC<PopupProps> = ({ service, onClose }) => {
|
|||||||
{/* Fonctionnalités */}
|
{/* Fonctionnalités */}
|
||||||
<h3 className="text-xl sm:text-2xl lg:text-3xl mb-4 lg:mb-6 text-banquise-blue-dark font-heading font-bold flex items-center">
|
<h3 className="text-xl sm:text-2xl lg:text-3xl mb-4 lg:mb-6 text-banquise-blue-dark font-heading font-bold flex items-center">
|
||||||
<span className="text-xl sm:text-2xl lg:text-3xl mr-3">⚡</span>
|
<span className="text-xl sm:text-2xl lg:text-3xl mr-3">⚡</span>
|
||||||
Fonctionnalités principales
|
{translations.discoverFeatures}
|
||||||
</h3>
|
</h3>
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-8">
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-8">
|
||||||
{service.features.map((feature, index) => (
|
{service.features.map((feature, index) => (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user