Init
This commit is contained in:
36
.gitignore
vendored
Normal file
36
.gitignore
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
3
.npmrc
Normal file
3
.npmrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
auto-install-peers=true
|
||||||
|
strict-peer-dependencies=false
|
||||||
|
|
||||||
40
README.md
Normal file
40
README.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Farmine Land - Site Gaming
|
||||||
|
|
||||||
|
Site web Next.js pour le jeu Farmine Land, un MMORPG 2D Open-World.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Développement
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Ouvrez [http://localhost:3000](http://localhost:3000) dans votre navigateur.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build
|
||||||
|
pnpm start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
- `/app` - Pages et layout Next.js
|
||||||
|
- `/components` - Composants React réutilisables
|
||||||
|
- `Navigation.tsx` - Barre de navigation
|
||||||
|
- `HeroSection.tsx` - Section principale avec logo et description
|
||||||
|
- `Leaderboard.tsx` - Tableau des classements
|
||||||
|
|
||||||
|
## Technologies
|
||||||
|
|
||||||
|
- Next.js 14
|
||||||
|
- React 18
|
||||||
|
- TypeScript
|
||||||
|
- Tailwind CSS
|
||||||
|
|
||||||
12
app/events/page.tsx
Normal file
12
app/events/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Navigation from "@/components/Navigation";
|
||||||
|
import EventsPageSection from "@/components/EventsPageSection";
|
||||||
|
|
||||||
|
export default function EventsPage() {
|
||||||
|
return (
|
||||||
|
<main className="min-h-screen bg-black relative">
|
||||||
|
<Navigation />
|
||||||
|
<EventsPageSection />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
26
app/globals.css
Normal file
26
app/globals.css
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
body {
|
||||||
|
@apply bg-black text-white;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
.pixel-border {
|
||||||
|
border: 2px solid;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
image-rendering: -moz-crisp-edges;
|
||||||
|
image-rendering: crisp-edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-pixel {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.8);
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
33
app/layout.tsx
Normal file
33
app/layout.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Orbitron, Rajdhani } from "next/font/google";
|
||||||
|
import "./globals.css";
|
||||||
|
|
||||||
|
const orbitron = Orbitron({
|
||||||
|
subsets: ["latin"],
|
||||||
|
weight: ["400", "500", "600", "700", "800", "900"],
|
||||||
|
variable: "--font-orbitron",
|
||||||
|
});
|
||||||
|
|
||||||
|
const rajdhani = Rajdhani({
|
||||||
|
subsets: ["latin"],
|
||||||
|
weight: ["300", "400", "500", "600", "700"],
|
||||||
|
variable: "--font-rajdhani",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Game of Tech - Peaksys",
|
||||||
|
description: "In a digital world of cutting-edge technology",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: Readonly<{
|
||||||
|
children: React.ReactNode;
|
||||||
|
}>) {
|
||||||
|
return (
|
||||||
|
<html lang="fr" className={`${orbitron.variable} ${rajdhani.variable}`}>
|
||||||
|
<body className="antialiased">{children}</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
12
app/leaderboard/page.tsx
Normal file
12
app/leaderboard/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Navigation from "@/components/Navigation";
|
||||||
|
import LeaderboardSection from "@/components/LeaderboardSection";
|
||||||
|
|
||||||
|
export default function LeaderboardPage() {
|
||||||
|
return (
|
||||||
|
<main className="min-h-screen bg-black relative">
|
||||||
|
<Navigation />
|
||||||
|
<LeaderboardSection />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
13
app/page.tsx
Normal file
13
app/page.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import Navigation from "@/components/Navigation";
|
||||||
|
import HeroSection from "@/components/HeroSection";
|
||||||
|
import EventsSection from "@/components/EventsSection";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<main className="min-h-screen bg-black relative">
|
||||||
|
<Navigation />
|
||||||
|
<HeroSection />
|
||||||
|
<EventsSection />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
215
components/EventsPageSection.tsx
Normal file
215
components/EventsPageSection.tsx
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
interface Event {
|
||||||
|
id: number;
|
||||||
|
date: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
type: "summit" | "launch" | "festival" | "competition";
|
||||||
|
status: "upcoming" | "live" | "past";
|
||||||
|
}
|
||||||
|
|
||||||
|
const events: Event[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
date: "NOVEMBER 18th, 2023",
|
||||||
|
name: "Tech Innovation Summit",
|
||||||
|
description:
|
||||||
|
"Join industry leaders and innovators for a day of cutting-edge technology discussions, AI breakthroughs, and networking opportunities.",
|
||||||
|
type: "summit",
|
||||||
|
status: "past",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
date: "DECEMBER 3rd, 2023",
|
||||||
|
name: "AI Revolution Launch",
|
||||||
|
description:
|
||||||
|
"Witness the launch of revolutionary AI systems that will reshape the gaming landscape. Exclusive previews and early access opportunities.",
|
||||||
|
type: "launch",
|
||||||
|
status: "past",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
date: "DECEMBER 22nd, 2023",
|
||||||
|
name: "Winter Code Festival",
|
||||||
|
description:
|
||||||
|
"A celebration of coding excellence with hackathons, coding challenges, and prizes. Showcase your skills and compete with the best developers.",
|
||||||
|
type: "festival",
|
||||||
|
status: "past",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
date: "JANUARY 15th, 2024",
|
||||||
|
name: "Quantum Computing Expo",
|
||||||
|
description:
|
||||||
|
"Explore the future of quantum computing in gaming. Interactive demos, expert talks, and hands-on workshops for all skill levels.",
|
||||||
|
type: "summit",
|
||||||
|
status: "upcoming",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
date: "FEBRUARY 8th, 2024",
|
||||||
|
name: "Cyber Arena Championship",
|
||||||
|
description:
|
||||||
|
"The ultimate competitive gaming event. Compete for glory, exclusive rewards, and the title of Cyber Arena Champion. Registration now open.",
|
||||||
|
type: "competition",
|
||||||
|
status: "upcoming",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
date: "MARCH 12th, 2024",
|
||||||
|
name: "Spring Tech Gala",
|
||||||
|
description:
|
||||||
|
"An elegant evening celebrating technological achievements. Awards ceremony, networking, and exclusive announcements from top tech companies.",
|
||||||
|
type: "festival",
|
||||||
|
status: "upcoming",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const getEventTypeColor = (type: Event["type"]) => {
|
||||||
|
switch (type) {
|
||||||
|
case "summit":
|
||||||
|
return "from-blue-600 to-cyan-500";
|
||||||
|
case "launch":
|
||||||
|
return "from-purple-600 to-pink-500";
|
||||||
|
case "festival":
|
||||||
|
return "from-pixel-gold to-orange-500";
|
||||||
|
case "competition":
|
||||||
|
return "from-red-600 to-orange-500";
|
||||||
|
default:
|
||||||
|
return "from-gray-600 to-gray-500";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusBadge = (status: Event["status"]) => {
|
||||||
|
switch (status) {
|
||||||
|
case "upcoming":
|
||||||
|
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">
|
||||||
|
Upcoming
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
case "live":
|
||||||
|
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">
|
||||||
|
Live Now
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
case "past":
|
||||||
|
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">
|
||||||
|
Past
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function EventsPageSection() {
|
||||||
|
return (
|
||||||
|
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||||
|
{/* Background Image */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url('/got-2.jpg')`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Dark overlay for readability */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative z-10 w-full max-w-6xl mx-auto px-8 py-16">
|
||||||
|
{/* Title Section */}
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<h1 className="text-5xl md:text-7xl font-gaming font-black mb-4 tracking-tight">
|
||||||
|
<span
|
||||||
|
className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent"
|
||||||
|
style={{
|
||||||
|
textShadow: "0 0 30px rgba(218, 165, 32, 0.5)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
EVENTS
|
||||||
|
</span>
|
||||||
|
</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">
|
||||||
|
<span>✦</span>
|
||||||
|
<span>Upcoming & Past Events</span>
|
||||||
|
<span>✦</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-400 text-sm max-w-2xl mx-auto">
|
||||||
|
Join us for exciting tech events, competitions, and celebrations
|
||||||
|
throughout the year
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Events Grid */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{events.map((event) => (
|
||||||
|
<div
|
||||||
|
key={event.id}
|
||||||
|
className="bg-black/60 border border-pixel-gold/30 rounded-lg overflow-hidden backdrop-blur-sm hover:border-pixel-gold/50 transition group"
|
||||||
|
>
|
||||||
|
{/* Event Header */}
|
||||||
|
<div
|
||||||
|
className={`h-2 bg-gradient-to-r ${getEventTypeColor(
|
||||||
|
event.type
|
||||||
|
)}`}
|
||||||
|
></div>
|
||||||
|
|
||||||
|
{/* Event Content */}
|
||||||
|
<div className="p-6">
|
||||||
|
{/* Status Badge */}
|
||||||
|
<div className="flex justify-between items-start mb-4">
|
||||||
|
{getStatusBadge(event.status)}
|
||||||
|
<span className="text-pixel-gold text-xs uppercase tracking-widest">
|
||||||
|
{event.type}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Date */}
|
||||||
|
<div className="text-white text-sm font-bold uppercase tracking-widest mb-3">
|
||||||
|
{event.date}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Event Name */}
|
||||||
|
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-pixel-gold transition">
|
||||||
|
{event.name}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
{/* Description */}
|
||||||
|
<p className="text-gray-400 text-sm leading-relaxed mb-4">
|
||||||
|
{event.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Action Button */}
|
||||||
|
{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">
|
||||||
|
Register Now
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{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">
|
||||||
|
Join Live
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{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">
|
||||||
|
Event Ended
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Footer Info */}
|
||||||
|
<div className="mt-12 text-center">
|
||||||
|
<p className="text-gray-500 text-sm">
|
||||||
|
Stay updated with our latest events and announcements
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
49
components/EventsSection.tsx
Normal file
49
components/EventsSection.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
interface Event {
|
||||||
|
date: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const events: Event[] = [
|
||||||
|
{
|
||||||
|
date: "NOVEMBER 18th, 2023",
|
||||||
|
name: "Tech Innovation Summit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "DECEMBER 3rd, 2023",
|
||||||
|
name: "AI Revolution Launch",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "DECEMBER 22nd, 2023",
|
||||||
|
name: "Winter Code Festival",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function EventsSection() {
|
||||||
|
return (
|
||||||
|
<section className="w-full bg-gray-950 border-t border-pixel-gold/30 py-16">
|
||||||
|
<div className="max-w-7xl mx-auto px-8">
|
||||||
|
<div className="flex flex-col md:flex-row items-center justify-around gap-8">
|
||||||
|
{events.map((event, index) => (
|
||||||
|
<div key={index} className="flex flex-col items-center">
|
||||||
|
<div className="flex flex-col items-center mb-4">
|
||||||
|
<span className="text-pixel-gold text-xs uppercase tracking-widest mb-2">
|
||||||
|
Event
|
||||||
|
</span>
|
||||||
|
<div className="w-16 h-px bg-pixel-gold"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-white text-lg font-bold mb-2 uppercase tracking-wide">
|
||||||
|
{event.date}
|
||||||
|
</div>
|
||||||
|
<div className="text-white text-base text-center">
|
||||||
|
{event.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
71
components/HeroSection.tsx
Normal file
71
components/HeroSection.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
export default function HeroSection() {
|
||||||
|
return (
|
||||||
|
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24">
|
||||||
|
{/* Background Image */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url('/got-2.jpg')`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Dark overlay for readability */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Hero Content */}
|
||||||
|
<div className="relative z-10 w-full max-w-5xl mx-auto px-8 py-16 text-center">
|
||||||
|
{/* Game Title */}
|
||||||
|
<h1 className="text-6xl md:text-8xl lg:text-9xl font-gaming font-black mb-4 tracking-tight">
|
||||||
|
<span
|
||||||
|
className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent"
|
||||||
|
style={{
|
||||||
|
textShadow: "0 0 30px rgba(218, 165, 32, 0.5)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
GAME.OF.TECH
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{/* Subtitle */}
|
||||||
|
<div className="text-pixel-gold text-xl md:text-2xl font-gaming-subtitle font-semibold flex items-center justify-center gap-2 mb-8 tracking-wider">
|
||||||
|
<span>✦</span>
|
||||||
|
<span>Peaksys</span>
|
||||||
|
<span>✦</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Description */}
|
||||||
|
<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
|
||||||
|
evolving and ancient code awaits discovery. Go on an epic journey to
|
||||||
|
forge alliances, conquer challenges and tell your story of innovation
|
||||||
|
as part of a flourishing tech gaming community.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Call-to-Action Buttons */}
|
||||||
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4 mb-16">
|
||||||
|
<button className="px-8 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition">
|
||||||
|
PLAY NOW
|
||||||
|
</button>
|
||||||
|
<button className="px-8 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition flex items-center gap-2">
|
||||||
|
<span>⏵</span>
|
||||||
|
<span>Watch Trailer</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style jsx>{`
|
||||||
|
@keyframes float {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
96
components/Leaderboard.tsx
Normal file
96
components/Leaderboard.tsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
interface LeaderboardEntry {
|
||||||
|
rank: number;
|
||||||
|
username: string;
|
||||||
|
score: number;
|
||||||
|
level: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format number with consistent locale to avoid hydration mismatch
|
||||||
|
const formatScore = (score: number): string => {
|
||||||
|
return score.toLocaleString("en-US");
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockLeaderboard: LeaderboardEntry[] = [
|
||||||
|
{ rank: 1, username: "DragonSlayer99", score: 125000, level: 85 },
|
||||||
|
{ rank: 2, username: "MineMaster", score: 118500, level: 82 },
|
||||||
|
{ rank: 3, username: "CraftKing", score: 112000, level: 80 },
|
||||||
|
{ rank: 4, username: "PixelWarrior", score: 105500, level: 78 },
|
||||||
|
{ rank: 5, username: "FarminePro", score: 99000, level: 75 },
|
||||||
|
{ rank: 6, username: "GoldDigger", score: 92500, level: 73 },
|
||||||
|
{ rank: 7, username: "EpicGamer", score: 87000, level: 71 },
|
||||||
|
{ rank: 8, username: "Legendary", score: 81500, level: 69 },
|
||||||
|
{ rank: 9, username: "MysticMiner", score: 76000, level: 67 },
|
||||||
|
{ rank: 10, username: "TopPlayer", score: 70500, level: 65 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Leaderboard() {
|
||||||
|
return (
|
||||||
|
<section className="w-full bg-black py-16 px-6 border-t-2 border-pixel-dark-purple">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<h2 className="text-4xl md:text-5xl font-bold text-center mb-12 text-pixel-gold text-pixel">
|
||||||
|
LEADERBOARD
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="bg-black/80 border-2 border-pixel-gold/30 rounded-lg overflow-hidden backdrop-blur-sm">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="bg-gray-900/80 border-b-2 border-pixel-gold/30 grid grid-cols-12 gap-4 p-4 font-bold text-sm text-gray-300">
|
||||||
|
<div className="col-span-1 text-center">Rank</div>
|
||||||
|
<div className="col-span-5">Player</div>
|
||||||
|
<div className="col-span-3 text-right">Score</div>
|
||||||
|
<div className="col-span-3 text-right">Level</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Entries */}
|
||||||
|
<div className="divide-y divide-pixel-gold/10">
|
||||||
|
{mockLeaderboard.map((entry) => (
|
||||||
|
<div
|
||||||
|
key={entry.rank}
|
||||||
|
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
||||||
|
entry.rank <= 3 ? "bg-gray-950/50" : "bg-black/40"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="col-span-1 text-center">
|
||||||
|
<span
|
||||||
|
className={`inline-block w-8 h-8 rounded-full flex items-center justify-center font-bold ${
|
||||||
|
entry.rank === 1
|
||||||
|
? "bg-pixel-gold text-black"
|
||||||
|
: entry.rank === 2
|
||||||
|
? "bg-gray-600 text-white"
|
||||||
|
: entry.rank === 3
|
||||||
|
? "bg-orange-800 text-white"
|
||||||
|
: "bg-gray-900 text-gray-400 border border-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{entry.rank}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-5 flex items-center">
|
||||||
|
<span className="font-bold text-pixel-gold">
|
||||||
|
{entry.username}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3 text-right flex items-center justify-end">
|
||||||
|
<span className="font-mono text-gray-300">
|
||||||
|
{formatScore(entry.score)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3 text-right flex items-center justify-end">
|
||||||
|
<span className="font-bold text-gray-400">
|
||||||
|
Lv.{entry.level}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Additional info */}
|
||||||
|
<div className="mt-8 text-center text-sm text-gray-500">
|
||||||
|
<p>Compete with players worldwide and climb the ranks!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
156
components/LeaderboardSection.tsx
Normal file
156
components/LeaderboardSection.tsx
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
interface LeaderboardEntry {
|
||||||
|
rank: number;
|
||||||
|
username: string;
|
||||||
|
score: number;
|
||||||
|
level: number;
|
||||||
|
avatar?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format number with consistent locale to avoid hydration mismatch
|
||||||
|
const formatScore = (score: number): string => {
|
||||||
|
return score.toLocaleString("en-US");
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockLeaderboard: LeaderboardEntry[] = [
|
||||||
|
{ rank: 1, username: "TechMaster2024", score: 125000, level: 85 },
|
||||||
|
{ rank: 2, username: "CodeWarrior", score: 118500, level: 82 },
|
||||||
|
{ rank: 3, username: "AIGenius", score: 112000, level: 80 },
|
||||||
|
{ rank: 4, username: "DevLegend", score: 105500, level: 78 },
|
||||||
|
{ rank: 5, username: "InnovationPro", score: 99000, level: 75 },
|
||||||
|
{ rank: 6, username: "TechNinja", score: 92500, level: 73 },
|
||||||
|
{ rank: 7, username: "DigitalHero", score: 87000, level: 71 },
|
||||||
|
{ rank: 8, username: "CodeCrusher", score: 81500, level: 69 },
|
||||||
|
{ rank: 9, username: "TechWizard", score: 76000, level: 67 },
|
||||||
|
{ rank: 10, username: "InnovationKing", score: 70500, level: 65 },
|
||||||
|
{ rank: 11, username: "DevMaster", score: 68000, level: 64 },
|
||||||
|
{ rank: 12, username: "TechElite", score: 65500, level: 63 },
|
||||||
|
{ rank: 13, username: "CodeChampion", score: 63000, level: 62 },
|
||||||
|
{ rank: 14, username: "AIVisionary", score: 60500, level: 61 },
|
||||||
|
{ rank: 15, username: "TechPioneer", score: 58000, level: 60 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function LeaderboardSection() {
|
||||||
|
return (
|
||||||
|
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||||
|
{/* Background Image */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url('/leaderboard-bg.jpg')`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Dark overlay for readability */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative z-10 w-full max-w-6xl mx-auto px-8 py-16">
|
||||||
|
{/* Title Section */}
|
||||||
|
<div className="text-center mb-12">
|
||||||
|
<h1 className="text-5xl md:text-7xl font-gaming font-black mb-4 tracking-tight">
|
||||||
|
<span
|
||||||
|
className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent"
|
||||||
|
style={{
|
||||||
|
textShadow: "0 0 30px rgba(218, 165, 32, 0.5)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
LEADERBOARD
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<div className="text-pixel-gold text-lg md:text-xl font-gaming-subtitle font-semibold flex items-center justify-center gap-2 tracking-wide">
|
||||||
|
<span>✦</span>
|
||||||
|
<span>Top Players</span>
|
||||||
|
<span>✦</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Leaderboard Table */}
|
||||||
|
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg overflow-hidden backdrop-blur-sm">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="bg-gray-900/80 border-b border-pixel-gold/30 grid grid-cols-12 gap-4 p-4 font-bold text-xs uppercase tracking-widest text-gray-300">
|
||||||
|
<div className="col-span-1 text-center">Rank</div>
|
||||||
|
<div className="col-span-6">Player</div>
|
||||||
|
<div className="col-span-3 text-right">Score</div>
|
||||||
|
<div className="col-span-2 text-right">Level</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Entries */}
|
||||||
|
<div className="divide-y divide-pixel-gold/10">
|
||||||
|
{mockLeaderboard.map((entry) => (
|
||||||
|
<div
|
||||||
|
key={entry.rank}
|
||||||
|
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
||||||
|
entry.rank <= 3
|
||||||
|
? "bg-gradient-to-r from-pixel-gold/10 via-pixel-gold/5 to-transparent"
|
||||||
|
: "bg-black/40"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{/* Rank */}
|
||||||
|
<div className="col-span-1 flex items-center justify-center">
|
||||||
|
<span
|
||||||
|
className={`inline-flex items-center justify-center w-10 h-10 rounded-full font-bold text-sm ${
|
||||||
|
entry.rank === 1
|
||||||
|
? "bg-gradient-to-br from-pixel-gold to-orange-500 text-black shadow-lg shadow-pixel-gold/50"
|
||||||
|
: entry.rank === 2
|
||||||
|
? "bg-gradient-to-br from-gray-400 to-gray-500 text-black"
|
||||||
|
: entry.rank === 3
|
||||||
|
? "bg-gradient-to-br from-orange-700 to-orange-800 text-white"
|
||||||
|
: "bg-gray-900 text-gray-400 border border-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{entry.rank}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Player */}
|
||||||
|
<div className="col-span-6 flex items-center gap-3">
|
||||||
|
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-gray-800 to-gray-900 border border-pixel-gold/30 flex items-center justify-center">
|
||||||
|
<span className="text-pixel-gold text-xs font-bold">
|
||||||
|
{entry.username.charAt(0).toUpperCase()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className={`font-bold ${
|
||||||
|
entry.rank <= 3 ? "text-pixel-gold" : "text-white"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{entry.username}
|
||||||
|
</span>
|
||||||
|
{entry.rank <= 3 && (
|
||||||
|
<span className="text-pixel-gold text-xs">✦</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Score */}
|
||||||
|
<div className="col-span-3 flex items-center justify-end">
|
||||||
|
<span className="font-mono text-gray-300">
|
||||||
|
{formatScore(entry.score)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Level */}
|
||||||
|
<div className="col-span-2 flex items-center justify-end">
|
||||||
|
<span className="font-bold text-gray-400">
|
||||||
|
Lv.{entry.level}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Footer Info */}
|
||||||
|
<div className="mt-8 text-center">
|
||||||
|
<p className="text-gray-500 text-sm">
|
||||||
|
Compete with players worldwide and climb the ranks!
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-600 text-xs mt-2">
|
||||||
|
Rankings update every hour
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
50
components/Navigation.tsx
Normal file
50
components/Navigation.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
export default function Navigation() {
|
||||||
|
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">
|
||||||
|
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||||
|
{/* Logo - Left */}
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="text-white text-2xl font-gaming font-bold tracking-tight">
|
||||||
|
GAME.OF.TECH
|
||||||
|
</div>
|
||||||
|
<div className="text-pixel-gold text-sm font-gaming-subtitle font-semibold flex items-center gap-1 tracking-wide">
|
||||||
|
<span>✦</span>
|
||||||
|
<span>Game of Tech</span>
|
||||||
|
<span>✦</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Navigation Links - Center */}
|
||||||
|
<div className="flex items-center gap-6">
|
||||||
|
<a
|
||||||
|
href="/"
|
||||||
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||||
|
>
|
||||||
|
HOME
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="/events"
|
||||||
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||||
|
>
|
||||||
|
EVENTS
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="/leaderboard"
|
||||||
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||||
|
>
|
||||||
|
LEADERBOARD
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Play Now Button - Right */}
|
||||||
|
<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">
|
||||||
|
PLAY NOW
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
7
next.config.js
Normal file
7
next.config.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
||||||
|
|
||||||
25
package.json
Normal file
25
package.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "got-mc",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "15.5.7",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^22.0.0",
|
||||||
|
"@types/react": "^19.0.0",
|
||||||
|
"@types/react-dom": "^19.0.0",
|
||||||
|
"autoprefixer": "^10.4.19",
|
||||||
|
"postcss": "^8.4.40",
|
||||||
|
"tailwindcss": "^3.4.7",
|
||||||
|
"typescript": "^5.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
1223
pnpm-lock.yaml
generated
Normal file
1223
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
7
postcss.config.js
Normal file
7
postcss.config.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
BIN
public/got-2.jpg
Normal file
BIN
public/got-2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
BIN
public/got-background.jpg
Normal file
BIN
public/got-background.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
BIN
public/leaderboard-bg.jpg
Normal file
BIN
public/leaderboard-bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
29
tailwind.config.ts
Normal file
29
tailwind.config.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
content: [
|
||||||
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
'pixel-purple': '#0a0515',
|
||||||
|
'pixel-dark': '#000000',
|
||||||
|
'pixel-red': '#8b0000',
|
||||||
|
'pixel-gold': '#daa520',
|
||||||
|
'pixel-brown': '#3d2817',
|
||||||
|
'pixel-dark-purple': '#1a0d2e',
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
'pixel': ['Courier New', 'monospace'],
|
||||||
|
'gaming': ['var(--font-orbitron)', 'sans-serif'],
|
||||||
|
'gaming-subtitle': ['var(--font-rajdhani)', 'sans-serif'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
|
export default config;
|
||||||
|
|
||||||
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user