Solo-Leveling-Self-Improvem.../app/page.tsx

541 lines
20 KiB
TypeScript

"use client";
import type React from "react";
import Link from "next/link";
import { Shield, Zap, Eye, Brain, Heart, Menu, X, Award } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { useUser } from "@/context/user-context";
// Import the NameInputModal component
import { MobileNav } from "@/components/mobile-nav";
import { NameInputModal } from "@/components/name-input-modal";
export default function Dashboard() {
const { userStats, addExp, completeQuest } = useUser();
// Calculate progress percentage for XP bar
const expPercentage = (userStats.exp / userStats.expToNextLevel) * 100;
return (
<div className="min-h-screen bg-[#0a0e14] text-[#e0f2ff] pb-16 md:pb-0">
{/* Add the NameInputModal component */}
<NameInputModal />
<div className="container mx-auto px-4 py-6">
{/* Header */}
<header className="flex items-center justify-between mb-8">
<div className="flex items-center gap-2">
<Award className="h-8 w-8 text-[#4cc9ff]" />
<h1 className="text-2xl font-bold tracking-tight text-[#4cc9ff]">
SOLO LEVEL UP
</h1>
</div>
<div className="flex items-center gap-4">
<div className="hidden md:flex items-center gap-6">
<Link
href="/quests"
className="text-sm font-medium hover:text-[#4cc9ff] transition-colors"
>
Quests
</Link>
<Link
href="/inventory"
className="text-sm font-medium hover:text-[#4cc9ff] transition-colors"
>
Inventory
</Link>
<Link
href="/equipment"
className="text-sm font-medium hover:text-[#4cc9ff] transition-colors"
>
Equipment
</Link>
<Link
href="/combat"
className="text-sm font-medium hover:text-[#4cc9ff] transition-colors"
>
Combat
</Link>
<Link
href="/skills"
className="text-sm font-medium hover:text-[#4cc9ff] transition-colors"
>
Skills
</Link>
<Link
href="/profile"
className="text-sm font-medium hover:text-[#4cc9ff] transition-colors"
>
Profile
</Link>
</div>
<div className="hidden">
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="md:hidden">
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle menu</span>
</Button>
</SheetTrigger>
<SheetContent
side="right"
className="bg-[#0a0e14] border-[#1e2a3a]"
>
<div className="flex items-center justify-between mb-8">
<h2 className="text-xl font-bold text-[#4cc9ff]">Menu</h2>
<SheetTrigger asChild>
<Button variant="ghost" size="icon">
<X className="h-5 w-5" />
<span className="sr-only">Close menu</span>
</Button>
</SheetTrigger>
</div>
<nav className="flex flex-col gap-4">
<Link
href="/quests"
className="text-base font-medium hover:text-[#4cc9ff] transition-colors"
>
Quests
</Link>
<Link
href="/inventory"
className="text-base font-medium hover:text-[#4cc9ff] transition-colors"
>
Inventory
</Link>
<Link
href="/equipment"
className="text-base font-medium hover:text-[#4cc9ff] transition-colors"
>
Equipment
</Link>
<Link
href="/combat"
className="text-base font-medium hover:text-[#4cc9ff] transition-colors"
>
Combat
</Link>
<Link
href="/skills"
className="text-base font-medium hover:text-[#4cc9ff] transition-colors"
>
Skills
</Link>
</nav>
</SheetContent>
</Sheet>
</div>
</div>
</header>
{/* Main Status Panel */}
<div className="mb-8 relative">
<div className="absolute inset-0 border border-[#4cc9ff]/30 rounded-lg shadow-[0_0_15px_rgba(76,201,255,0.15)]"></div>
<div className="absolute inset-0 border-t-2 border-l-2 border-r-2 border-b-2 border-[#4cc9ff]/20 rounded-lg"></div>
<div className="absolute top-0 left-0 w-[20px] h-[20px] border-t-2 border-l-2 border-[#4cc9ff]"></div>
<div className="absolute top-0 right-0 w-[20px] h-[20px] border-t-2 border-r-2 border-[#4cc9ff]"></div>
<div className="absolute bottom-0 left-0 w-[20px] h-[20px] border-b-2 border-l-2 border-[#4cc9ff]"></div>
<div className="absolute bottom-0 right-0 w-[20px] h-[20px] border-b-2 border-r-2 border-[#4cc9ff]"></div>
<div className="p-6 relative z-10">
<div className="text-center mb-6">
<h2 className="text-xl uppercase tracking-wider text-[#4cc9ff] border-b border-[#4cc9ff]/30 pb-2 inline-block">
STATUS
</h2>
</div>
<div className="flex flex-col md:flex-row gap-8 items-center justify-center">
{/* Level and Title */}
<div className="text-center">
<div className="text-7xl font-bold text-[#4cc9ff] mb-1">
{userStats.level}
</div>
<div className="text-sm uppercase tracking-wider text-[#8bacc1]">
LEVEL
</div>
{/* Add name display above job */}
<div className="mt-4">
<div className="text-xs text-[#8bacc1]">NAME:</div>
<div className="text-sm font-medium">
{userStats.name || "Unnamed"}
</div>
</div>
<div className="mt-2">
<div className="text-xs text-[#8bacc1]">JOB:</div>
<div className="text-sm">{userStats.job || "None"}</div>
</div>
<div className="mt-2">
<div className="text-xs text-[#8bacc1]">TITLE:</div>
<div className="text-sm">{userStats.title || "None"}</div>
</div>
</div>
{/* HP/MP Bars */}
<div className="w-full max-w-md">
<div className="mb-4">
<div className="flex justify-between text-xs mb-1">
<span className="flex items-center">
<span className="text-[#4cc9ff] mr-1">HP</span>
</span>
<span>
{userStats.hp}/{userStats.maxHp}
</span>
</div>
<Progress
value={(userStats.hp / userStats.maxHp) * 100}
className="h-2 bg-[#1e2a3a]"
>
<div className="h-full bg-gradient-to-r from-[#4cc9ff] to-[#4cc9ff]/70 rounded-full" />
</Progress>
</div>
<div className="mb-4">
<div className="flex justify-between text-xs mb-1">
<span className="flex items-center">
<span className="text-[#4cc9ff] mr-1">MP</span>
</span>
<span>
{userStats.mp}/{userStats.maxMp}
</span>
</div>
<Progress
value={(userStats.mp / userStats.maxMp) * 100}
className="h-2 bg-[#1e2a3a]"
>
<div className="h-full bg-gradient-to-r from-[#4cc9ff] to-[#4cc9ff]/70 rounded-full" />
</Progress>
</div>
<div className="mb-4">
<div className="flex justify-between text-xs mb-1">
<span className="flex items-center">
<span className="text-[#4cc9ff] mr-1">EXP</span>
</span>
<span>
{userStats.exp}/{userStats.expToNextLevel}
</span>
</div>
<Progress value={expPercentage} className="h-2 bg-[#1e2a3a]">
<div className="h-full bg-gradient-to-r from-[#4cc9ff] to-[#4cc9ff]/70 rounded-full" />
</Progress>
</div>
<div>
<div className="flex justify-between text-xs mb-1">
<span className="flex items-center">
<span className="text-[#4cc9ff] mr-1">FATIGUE</span>
</span>
<span>{userStats.fatigue}</span>
</div>
<Progress
value={userStats.fatigue}
className="h-2 bg-[#1e2a3a]"
>
<div className="h-full bg-gradient-to-r from-[#ff4c4c] to-[#ff4c4c]/70 rounded-full" />
</Progress>
</div>
</div>
</div>
{/* Stats Grid */}
<div className="mt-8 relative">
<div className="absolute inset-0 border border-[#4cc9ff]/20 rounded-lg"></div>
<div className="p-6 relative z-10">
<div className="grid grid-cols-2 md:grid-cols-3 gap-y-6 gap-x-12">
<StatDisplay
icon={<Shield className="h-5 w-5 text-[#4cc9ff]" />}
name="STR"
value={userStats.stats.str}
/>
<StatDisplay
icon={<Heart className="h-5 w-5 text-[#4cc9ff]" />}
name="VIT"
value={userStats.stats.vit}
/>
<StatDisplay
icon={<Zap className="h-5 w-5 text-[#4cc9ff]" />}
name="AGI"
value={userStats.stats.agi}
/>
<StatDisplay
icon={<Brain className="h-5 w-5 text-[#4cc9ff]" />}
name="INT"
value={userStats.stats.int}
/>
<StatDisplay
icon={<Eye className="h-5 w-5 text-[#4cc9ff]" />}
name="PER"
value={userStats.stats.per}
/>
<div className="flex flex-col sm:flex-row sm:items-center">
<div>
<div className="text-xs text-[#8bacc1] mb-1">
Available Points
</div>
<div className="text-3xl font-bold text-[#4cc9ff]">
{userStats.statPoints}
</div>
</div>
<Link href="/stats" className="mt-2 sm:mt-0 sm:ml-4">
<Button className="w-full sm:w-auto bg-transparent border border-[#4cc9ff] hover:bg-[#4cc9ff]/10 text-[#4cc9ff]">
Allocate
</Button>
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Equipment Section */}
<div className="mb-8 relative">
<div className="absolute inset-0 border border-[#4cc9ff]/30 rounded-lg shadow-[0_0_15px_rgba(76,201,255,0.15)]"></div>
<div className="absolute inset-0 border-t-2 border-l-2 border-r-2 border-b-2 border-[#4cc9ff]/20 rounded-lg"></div>
<div className="absolute top-0 left-0 w-[20px] h-[20px] border-t-2 border-l-2 border-[#4cc9ff]"></div>
<div className="absolute top-0 right-0 w-[20px] h-[20px] border-t-2 border-r-2 border-[#4cc9ff]"></div>
<div className="absolute bottom-0 left-0 w-[20px] h-[20px] border-b-2 border-l-2 border-[#4cc9ff]"></div>
<div className="absolute bottom-0 right-0 w-[20px] h-[20px] border-b-2 border-r-2 border-[#4cc9ff]"></div>
<div className="p-6 relative z-10">
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl uppercase tracking-wider text-[#4cc9ff]">
EQUIPMENT
</h2>
<Link href="/equipment">
<Button className="bg-transparent border border-[#4cc9ff] hover:bg-[#4cc9ff]/10 text-[#4cc9ff]">
View All
</Button>
</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<EquipmentCard
name="Shadow Monarch's Helmet"
rarity="Legendary"
stats={["+15% Intelligence", "+10% Perception"]}
setBonus="Shadow Monarch Set (2/5)"
slot="Head"
/>
<EquipmentCard
name="Gauntlets of Strength"
rarity="Epic"
stats={["+12 Strength", "+8% Critical Rate"]}
setBonus="Warrior's Set (1/5)"
slot="Hands"
/>
<EquipmentCard
name="Boots of Agility"
rarity="Rare"
stats={["+10 Agility", "+5% Movement Speed"]}
setBonus="None"
slot="Feet"
/>
</div>
</div>
</div>
{/* Active Quests Section */}
<div className="relative">
<div className="absolute inset-0 border border-[#4cc9ff]/30 rounded-lg shadow-[0_0_15px_rgba(76,201,255,0.15)]"></div>
<div className="absolute inset-0 border-t-2 border-l-2 border-r-2 border-b-2 border-[#4cc9ff]/20 rounded-lg"></div>
<div className="absolute top-0 left-0 w-[20px] h-[20px] border-t-2 border-l-2 border-[#4cc9ff]"></div>
<div className="absolute top-0 right-0 w-[20px] h-[20px] border-t-2 border-r-2 border-[#4cc9ff]"></div>
<div className="absolute bottom-0 left-0 w-[20px] h-[20px] border-b-2 border-l-2 border-[#4cc9ff]"></div>
<div className="absolute bottom-0 right-0 w-[20px] h-[20px] border-b-2 border-r-2 border-[#4cc9ff]"></div>
<div className="p-6 relative z-10">
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl uppercase tracking-wider text-[#4cc9ff]">
ACTIVE QUESTS
</h2>
<Link href="/quests">
<Button className="bg-transparent border border-[#4cc9ff] hover:bg-[#4cc9ff]/10 text-[#4cc9ff]">
View All
</Button>
</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{userStats.quests
.filter((q) => !q.completed)
.slice(0, 4)
.map((quest) => (
<QuestCard
key={quest.id}
title={quest.title}
description={quest.description}
reward={quest.reward}
progress={quest.progress}
difficulty={quest.difficulty}
onComplete={() => completeQuest(quest.id)}
/>
))}
{userStats.quests.filter((q) => !q.completed).length === 0 && (
<div className="col-span-2 text-center py-8 text-[#8bacc1]">
No active quests. Create some quests to start leveling up!
</div>
)}
</div>
</div>
</div>
</div>
{/* Add the mobile navigation bar */}
<MobileNav />
</div>
);
}
function StatDisplay({
icon,
name,
value,
}: {
icon: React.ReactNode;
name: string;
value: number;
}) {
return (
<div className="flex items-center">
<div className="mr-3">{icon}</div>
<div>
<div className="text-xs text-[#8bacc1] mb-1">{name}</div>
<div className="text-3xl font-bold text-[#4cc9ff]">{value}</div>
</div>
</div>
);
}
function EquipmentCard({
name,
rarity,
stats,
setBonus,
slot,
}: {
name: string;
rarity: "Common" | "Uncommon" | "Rare" | "Epic" | "Legendary";
stats: string[];
setBonus: string;
slot: string;
}) {
const rarityColors = {
Common: "text-gray-400",
Uncommon: "text-green-400",
Rare: "text-[#4cc9ff]",
Epic: "text-purple-400",
Legendary: "text-yellow-400",
};
return (
<Card className="bg-[#0a0e14]/80 border-[#1e2a3a] overflow-hidden relative">
<div className="absolute inset-0 border border-[#4cc9ff]/10"></div>
<div
className={`h-1 w-full bg-gradient-to-r ${
rarity === "Common"
? "from-gray-500 to-gray-600"
: rarity === "Uncommon"
? "from-green-500 to-green-600"
: rarity === "Rare"
? "from-[#4cc9ff] to-[#4cc9ff]/60"
: rarity === "Epic"
? "from-purple-500 to-purple-600"
: "from-yellow-500 to-yellow-600"
}`}
></div>
<CardHeader className="pb-2 relative z-10">
<div className="flex justify-between items-start">
<CardTitle className={`text-base ${rarityColors[rarity]}`}>
{name}
</CardTitle>
<span className="text-xs text-[#8bacc1]">{slot}</span>
</div>
<CardDescription className={rarityColors[rarity]}>
{rarity}
</CardDescription>
</CardHeader>
<CardContent className="relative z-10">
<div className="space-y-1">
{stats.map((stat, index) => (
<div key={index} className="text-xs">
{stat}
</div>
))}
<Separator className="my-2 bg-[#1e2a3a]" />
<div className="text-xs text-[#8bacc1]">{setBonus}</div>
</div>
</CardContent>
</Card>
);
}
function QuestCard({
title,
description,
reward,
progress,
difficulty,
onComplete,
}: {
title: string;
description: string;
reward: string;
progress: number;
difficulty: "S" | "A" | "B" | "C" | "D" | "E";
onComplete: () => void;
}) {
const difficultyColors = {
S: "bg-red-500",
A: "bg-orange-500",
B: "bg-yellow-500",
C: "bg-green-500",
D: "bg-blue-500",
E: "bg-purple-500",
};
return (
<Card className="bg-[#0a0e14]/80 border-[#1e2a3a] relative">
<div className="absolute inset-0 border border-[#4cc9ff]/10"></div>
<CardHeader className="pb-2 relative z-10">
<div className="flex justify-between items-start">
<CardTitle className="text-base">{title}</CardTitle>
<div
className={`${difficultyColors[difficulty]} w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold`}
>
{difficulty}
</div>
</div>
<CardDescription>{description}</CardDescription>
</CardHeader>
<CardContent className="relative z-10">
<div className="space-y-2">
<div className="flex justify-between text-xs">
<span>Progress</span>
<span>{progress}%</span>
</div>
<Progress value={progress} className="h-2 bg-[#1e2a3a]">
<div className="h-full bg-gradient-to-r from-[#4cc9ff] to-[#4cc9ff]/60 rounded-full" />
</Progress>
<div className="text-xs mt-2">
<span className="text-[#8bacc1]">Reward: </span>
<span className="text-[#4cc9ff]">{reward}</span>
</div>
</div>
</CardContent>
</Card>
);
}