Translate event details and UI text to French, including event names, descriptions, and status labels. Update navigation styles for consistency.

This commit is contained in:
Julien Froidefond
2025-12-08 17:22:14 +01:00
parent 4e6ce54e0f
commit c5bd94ec69
5 changed files with 196 additions and 48 deletions

View File

@@ -12,55 +12,55 @@ interface Event {
const events: Event[] = [ const events: Event[] = [
{ {
id: 1, id: 1,
date: "NOVEMBER 18th, 2023", date: "18 NOVEMBRE 2023",
name: "Tech Innovation Summit", name: "Sommet de l'Innovation Tech",
description: description:
"Join industry leaders and innovators for a day of cutting-edge technology discussions, AI breakthroughs, and networking opportunities.", "Rejoignez les leaders de l'industrie et les innovateurs pour une journée de discussions sur les technologies de pointe, les percées de l'IA et des opportunités de networking.",
type: "summit", type: "summit",
status: "past", status: "past",
}, },
{ {
id: 2, id: 2,
date: "DECEMBER 3rd, 2023", date: "3 DÉCEMBRE 2023",
name: "AI Revolution Launch", name: "Lancement de la Révolution IA",
description: description:
"Witness the launch of revolutionary AI systems that will reshape the gaming landscape. Exclusive previews and early access opportunities.", "Assistez au lancement de systèmes d'IA révolutionnaires qui vont remodeler le paysage du gaming. Aperçus exclusifs et opportunités d'accès anticipé.",
type: "launch", type: "launch",
status: "past", status: "past",
}, },
{ {
id: 3, id: 3,
date: "DECEMBER 22nd, 2023", date: "22 DÉCEMBRE 2023",
name: "Winter Code Festival", name: "Festival du Code d'Hiver",
description: description:
"A celebration of coding excellence with hackathons, coding challenges, and prizes. Showcase your skills and compete with the best developers.", "Une célébration de l'excellence en programmation avec des hackathons, des défis de codage et des prix. Montrez vos compétences et rivalisez avec les meilleurs développeurs.",
type: "festival", type: "festival",
status: "past", status: "past",
}, },
{ {
id: 4, id: 4,
date: "JANUARY 15th, 2024", date: "15 JANVIER 2024",
name: "Quantum Computing Expo", name: "Expo Informatique Quantique",
description: description:
"Explore the future of quantum computing in gaming. Interactive demos, expert talks, and hands-on workshops for all skill levels.", "Explorez l'avenir de l'informatique quantique dans le gaming. Démonstrations interactives, conférences d'experts et ateliers pratiques pour tous les niveaux.",
type: "summit", type: "summit",
status: "upcoming", status: "upcoming",
}, },
{ {
id: 5, id: 5,
date: "FEBRUARY 8th, 2024", date: "8 FÉVRIER 2024",
name: "Cyber Arena Championship", name: "Championnat Cyber Arena",
description: description:
"The ultimate competitive gaming event. Compete for glory, exclusive rewards, and the title of Cyber Arena Champion. Registration now open.", "L'événement de gaming compétitif ultime. Compétissez pour la gloire, des récompenses exclusives et le titre de Champion Cyber Arena. Inscriptions ouvertes.",
type: "competition", type: "competition",
status: "upcoming", status: "upcoming",
}, },
{ {
id: 6, id: 6,
date: "MARCH 12th, 2024", date: "12 MARS 2024",
name: "Spring Tech Gala", name: "Gala Tech du Printemps",
description: description:
"An elegant evening celebrating technological achievements. Awards ceremony, networking, and exclusive announcements from top tech companies.", "Une soirée élégante célébrant les réalisations technologiques. Cérémonie de remise de prix, networking et annonces exclusives des plus grandes entreprises tech.",
type: "festival", type: "festival",
status: "upcoming", status: "upcoming",
}, },
@@ -81,24 +81,39 @@ const getEventTypeColor = (type: Event["type"]) => {
} }
}; };
const getEventTypeLabel = (type: Event["type"]) => {
switch (type) {
case "summit":
return "Sommet";
case "launch":
return "Lancement";
case "festival":
return "Festival";
case "competition":
return "Compétition";
default:
return type;
}
};
const getStatusBadge = (status: Event["status"]) => { const getStatusBadge = (status: Event["status"]) => {
switch (status) { switch (status) {
case "upcoming": case "upcoming":
return ( return (
<span className="px-3 py-1 bg-green-900/50 border border-green-500/50 text-green-400 text-xs uppercase tracking-widest rounded"> <span className="px-3 py-1 bg-green-900/50 border border-green-500/50 text-green-400 text-xs uppercase tracking-widest rounded">
Upcoming À venir
</span> </span>
); );
case "live": case "live":
return ( return (
<span className="px-3 py-1 bg-red-900/50 border border-red-500/50 text-red-400 text-xs uppercase tracking-widest rounded animate-pulse"> <span className="px-3 py-1 bg-red-900/50 border border-red-500/50 text-red-400 text-xs uppercase tracking-widest rounded animate-pulse">
Live Now En direct
</span> </span>
); );
case "past": case "past":
return ( return (
<span className="px-3 py-1 bg-gray-800/50 border border-gray-600/50 text-gray-400 text-xs uppercase tracking-widest rounded"> <span className="px-3 py-1 bg-gray-800/50 border border-gray-600/50 text-gray-400 text-xs uppercase tracking-widest rounded">
Past Pas
</span> </span>
); );
} }
@@ -134,12 +149,12 @@ export default function EventsPageSection() {
</h1> </h1>
<div className="text-pixel-gold text-lg md:text-xl font-gaming-subtitle font-semibold flex items-center justify-center gap-2 mb-6 tracking-wide"> <div className="text-pixel-gold text-lg md:text-xl font-gaming-subtitle font-semibold flex items-center justify-center gap-2 mb-6 tracking-wide">
<span></span> <span></span>
<span>Upcoming & Past Events</span> <span>Événements à venir et passés</span>
<span></span> <span></span>
</div> </div>
<p className="text-gray-400 text-sm max-w-2xl mx-auto"> <p className="text-gray-400 text-sm max-w-2xl mx-auto">
Join us for exciting tech events, competitions, and celebrations Rejoignez-nous pour des événements tech passionnants, des
throughout the year compétitions et des célébrations tout au long de l'année
</p> </p>
</div> </div>
@@ -163,7 +178,7 @@ export default function EventsPageSection() {
<div className="flex justify-between items-start mb-4"> <div className="flex justify-between items-start mb-4">
{getStatusBadge(event.status)} {getStatusBadge(event.status)}
<span className="text-pixel-gold text-xs uppercase tracking-widest"> <span className="text-pixel-gold text-xs uppercase tracking-widest">
{event.type} {getEventTypeLabel(event.type)}
</span> </span>
</div> </div>
@@ -185,17 +200,17 @@ export default function EventsPageSection() {
{/* Action Button */} {/* Action Button */}
{event.status === "upcoming" && ( {event.status === "upcoming" && (
<button className="w-full px-4 py-2 border border-pixel-gold/50 bg-black/40 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition"> <button className="w-full px-4 py-2 border border-pixel-gold/50 bg-black/40 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition">
Register Now S'inscrire maintenant
</button> </button>
)} )}
{event.status === "live" && ( {event.status === "live" && (
<button className="w-full px-4 py-2 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-xs tracking-widest rounded hover:bg-red-900/30 transition animate-pulse"> <button className="w-full px-4 py-2 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-xs tracking-widest rounded hover:bg-red-900/30 transition animate-pulse">
Join Live Rejoindre en direct
</button> </button>
)} )}
{event.status === "past" && ( {event.status === "past" && (
<button className="w-full px-4 py-2 border border-gray-600/50 bg-gray-900/20 text-gray-500 uppercase text-xs tracking-widest rounded cursor-not-allowed"> <button className="w-full px-4 py-2 border border-gray-600/50 bg-gray-900/20 text-gray-500 uppercase text-xs tracking-widest rounded cursor-not-allowed">
Event Ended Événement terminé
</button> </button>
)} )}
</div> </div>
@@ -206,7 +221,7 @@ export default function EventsPageSection() {
{/* Footer Info */} {/* Footer Info */}
<div className="mt-12 text-center"> <div className="mt-12 text-center">
<p className="text-gray-500 text-sm"> <p className="text-gray-500 text-sm">
Stay updated with our latest events and announcements Restez informé de nos derniers événements et annonces
</p> </p>
</div> </div>
</div> </div>

View File

@@ -7,16 +7,16 @@ interface Event {
const events: Event[] = [ const events: Event[] = [
{ {
date: "NOVEMBER 18th, 2023", date: "18 NOVEMBRE 2023",
name: "Tech Innovation Summit", name: "Sommet de l'Innovation Tech",
}, },
{ {
date: "DECEMBER 3rd, 2023", date: "3 DÉCEMBRE 2023",
name: "AI Revolution Launch", name: "Lancement de la Révolution IA",
}, },
{ {
date: "DECEMBER 22nd, 2023", date: "22 DÉCEMBRE 2023",
name: "Winter Code Festival", name: "Festival du Code d'Hiver",
}, },
]; ];
@@ -29,7 +29,7 @@ export default function EventsSection() {
<div key={index} className="flex flex-col items-center"> <div key={index} className="flex flex-col items-center">
<div className="flex flex-col items-center mb-4"> <div className="flex flex-col items-center mb-4">
<span className="text-pixel-gold text-xs uppercase tracking-widest mb-2"> <span className="text-pixel-gold text-xs uppercase tracking-widest mb-2">
Event Événement
</span> </span>
<div className="w-16 h-px bg-pixel-gold"></div> <div className="w-16 h-px bg-pixel-gold"></div>
</div> </div>
@@ -46,4 +46,3 @@ export default function EventsSection() {
</section> </section>
); );
} }

View File

@@ -37,10 +37,11 @@ export default function HeroSection() {
{/* Description */} {/* Description */}
<p className="text-white text-base md:text-lg max-w-3xl mx-auto mb-12 leading-relaxed px-4"> <p className="text-white text-base md:text-lg max-w-3xl mx-auto mb-12 leading-relaxed px-4">
In a digital world of cutting-edge technology, where AI systems are Dans un monde numérique de technologie de pointe, les systèmes d'IA
evolving and ancient code awaits discovery. Go on an epic journey to évoluent et où d'anciens codes attendent d'être découverts. Partez
forge alliances, conquer challenges and tell your story of innovation pour un voyage épique pour forger des alliances, conquérir des défis
as part of a flourishing tech gaming community. et raconter votre histoire d'innovation au sein d'une communauté de
gaming tech florissante.
</p> </p>
{/* Call-to-Action Buttons */} {/* Call-to-Action Buttons */}

View File

@@ -1,15 +1,17 @@
"use client"; "use client";
import PlayerStats from "./PlayerStats";
export default function Navigation() { export default function Navigation() {
return ( return (
<nav className="w-full fixed top-0 left-0 z-50 px-8 py-6 bg-black/80 backdrop-blur-sm border-b border-gray-800/30"> <nav className="w-full fixed top-0 left-0 z-50 px-8 py-3 bg-black/80 backdrop-blur-sm border-b border-gray-800/30">
<div className="max-w-7xl mx-auto flex items-center justify-between"> <div className="max-w-7xl mx-auto flex items-center justify-between">
{/* Logo - Left */} {/* Logo - Left */}
<div className="flex flex-col"> <div className="flex flex-col">
<div className="text-white text-2xl font-gaming font-bold tracking-tight"> <div className="text-white text-xl font-gaming font-bold tracking-tight">
GAME.OF.TECH GAME.OF.TECH
</div> </div>
<div className="text-pixel-gold text-sm font-gaming-subtitle font-semibold flex items-center gap-1 tracking-wide"> <div className="text-pixel-gold text-xs font-gaming-subtitle font-semibold flex items-center gap-1 tracking-wide">
<span></span> <span></span>
<span>Game of Tech</span> <span>Game of Tech</span>
<span></span> <span></span>
@@ -38,11 +40,9 @@ export default function Navigation() {
</a> </a>
</div> </div>
{/* Play Now Button - Right */} {/* Player Stats - Right */}
<div> <div>
<button className="px-6 py-2 border border-pixel-gold/50 bg-black/40 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition"> <PlayerStats />
PLAY NOW
</button>
</div> </div>
</div> </div>
</nav> </nav>

133
components/PlayerStats.tsx Normal file
View File

@@ -0,0 +1,133 @@
"use client";
import { useEffect, useState } from "react";
interface PlayerStatsProps {
username?: string;
avatar?: string;
hp?: number;
maxHp?: number;
xp?: number;
maxXp?: number;
level?: number;
}
// Format number with consistent locale to avoid hydration mismatch
const formatNumber = (num: number): string => {
return num.toLocaleString("en-US");
};
export default function PlayerStats({
username = "DragonSlayer99",
avatar = "/got-2.jpg",
hp = 750,
maxHp = 1000,
xp = 3250,
maxXp = 5000,
level = 42,
}: PlayerStatsProps) {
const [hpPercentage, setHpPercentage] = useState(0);
const [xpPercentage, setXpPercentage] = useState(0);
useEffect(() => {
// Animate HP bar
const hpTimer = setTimeout(() => {
setHpPercentage((hp / maxHp) * 100);
}, 100);
// Animate XP bar
const xpTimer = setTimeout(() => {
setXpPercentage((xp / maxXp) * 100);
}, 200);
return () => {
clearTimeout(hpTimer);
clearTimeout(xpTimer);
};
}, [hp, maxHp, xp, maxXp]);
const hpColor =
hpPercentage > 60
? "from-green-600 to-green-700"
: hpPercentage > 30
? "from-yellow-600 to-orange-700"
: "from-red-700 to-red-900";
return (
<div className="flex items-center gap-3">
{/* Avatar */}
<div className="w-10 h-10 rounded-full border border-pixel-gold/20 overflow-hidden bg-gray-900">
<img
src={avatar}
alt={username}
className="w-full h-full object-cover"
/>
</div>
{/* Stats */}
<div className="flex flex-col gap-1.5 min-w-[200px]">
{/* Username & Level */}
<div className="flex items-center gap-2">
<div className="text-pixel-gold font-gaming font-bold text-sm tracking-wider">
{username}
</div>
<div className="text-gray-400 font-pixel text-xs uppercase border border-pixel-gold/30 px-1.5 py-0.5 bg-black/40">
Lv.{level}
</div>
</div>
{/* Bars side by side */}
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2">
{/* HP Bar */}
<div className="relative h-2 flex-1 bg-gray-900 border border-gray-700 rounded overflow-hidden">
<div
className={`absolute inset-0 bg-gradient-to-r ${hpColor} transition-all duration-1000 ease-out`}
style={{ width: `${hpPercentage}%` }}
>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/10 to-transparent animate-shimmer"></div>
</div>
{hpPercentage < 30 && (
<div className="absolute inset-0 border border-red-500 rounded animate-pulse"></div>
)}
</div>
{/* XP Bar */}
<div className="relative h-2 flex-1 bg-gray-900 border border-pixel-gold/30 rounded overflow-hidden">
<div
className="absolute inset-0 bg-gradient-to-r from-pixel-gold/80 via-pixel-gold/70 to-pixel-gold/80 transition-all duration-1000 ease-out"
style={{ width: `${xpPercentage}%` }}
>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/10 to-transparent animate-shimmer"></div>
</div>
</div>
</div>
{/* Labels */}
<div className="flex items-center gap-2 text-[8px] font-pixel text-gray-400">
<div className="flex-1 text-left">
HP {hp} / {maxHp}
</div>
<div className="flex-1 text-right">
XP {formatNumber(xp)} / {formatNumber(maxXp)}
</div>
</div>
</div>
</div>
<style jsx>{`
@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.animate-shimmer {
animation: shimmer 2s infinite;
}
`}</style>
</div>
);
}