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

933 lines
32 KiB
TypeScript

"use client";
import type React from "react";
import { useState, useEffect } from "react";
import Link from "next/link";
import {
ChevronLeft,
Sword,
Shield,
Zap,
Heart,
Brain,
Eye,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { useToast } from "@/hooks/use-toast";
import { useUser } from "@/context/user-context";
import { enemies, type Enemy } from "@/data/enemies";
import { CombatActions } from "@/components/combat-actions";
import { EnemySelection } from "@/components/enemy-selection";
import { CombatVisualization } from "@/components/combat-visualization";
export default function CombatPage() {
const {
userStats,
setUserStats,
addExp,
addItem,
addGold,
removeItem,
inCombat: contextInCombat,
setInCombat: setContextInCombat,
} = useUser();
const { toast } = useToast();
// Combat states
const [selectedEnemy, setSelectedEnemy] = useState<Enemy | null>(null);
const [inCombat, setInCombat] = useState(false);
const [playerTurn, setPlayerTurn] = useState(true);
const [playerHp, setPlayerHp] = useState(userStats.hp);
const [playerMp, setPlayerMp] = useState(userStats.mp);
const [enemyHp, setEnemyHp] = useState(0);
const [enemyMaxHp, setEnemyMaxHp] = useState(0);
const [showRewards, setShowRewards] = useState(false);
const [rewards, setRewards] = useState<{
exp: number;
gold: number;
items: any[];
}>({ exp: 0, gold: 0, items: [] });
const [isDefending, setIsDefending] = useState(false);
const [skillCooldowns, setSkillCooldowns] = useState<Record<string, number>>(
{}
);
const [combatLog, setCombatLog] = useState<string[]>([]);
// Animation states
const [isAttacking, setIsAttacking] = useState(false);
const [isAnimating, setIsAnimating] = useState(false);
const [currentDamage, setCurrentDamage] = useState(0);
const [isCriticalHit, setIsCriticalHit] = useState(false);
const [currentSkill, setCurrentSkill] = useState<string | undefined>(
undefined
);
// Reset combat state when component unmounts
useEffect(() => {
return () => {
if (inCombat) {
// Save player HP/MP state when leaving combat
setUserStats((prev) => ({
...prev,
hp: playerHp,
mp: playerMp,
}));
}
};
}, [inCombat, playerHp, playerMp, setUserStats]);
// Sync local combat state with context combat state
useEffect(() => {
setContextInCombat(inCombat);
}, [inCombat, setContextInCombat]);
// Start combat with selected enemy
const startCombat = (enemy: Enemy) => {
setSelectedEnemy(enemy);
setEnemyHp(calculateEnemyHp(enemy));
setEnemyMaxHp(calculateEnemyHp(enemy));
setPlayerHp(userStats.hp);
setPlayerMp(userStats.mp);
setPlayerTurn(true);
setInCombat(true);
setIsDefending(false);
setSkillCooldowns({});
setCombatLog([]);
};
// Calculate enemy HP based on level and vitality
const calculateEnemyHp = (enemy: Enemy) => {
return Math.floor(100 + enemy.level * 10 + enemy.stats.vit * 5);
};
// Calculate damage based on attacker's strength and defender's vitality
const calculateDamage = (
attackerStr: number,
defenderVit: number,
isCritical = false
) => {
const baseDamage = Math.max(
1,
Math.floor(attackerStr * 1.5 - defenderVit * 0.5)
);
const randomFactor = 0.8 + Math.random() * 0.4; // 80% to 120% damage variation
const criticalMultiplier = isCritical ? 1.5 : 1;
return Math.floor(baseDamage * randomFactor * criticalMultiplier);
};
// Check for critical hit based on agility
const checkCritical = (agility: number) => {
const critChance = agility * 0.5; // 0.5% per agility point
return Math.random() * 100 < critChance;
};
// Player attacks enemy
const playerAttack = () => {
if (!selectedEnemy || !inCombat || !playerTurn || isAnimating) return;
const isCritical = checkCritical(userStats.stats.agi);
const damage = calculateDamage(
userStats.stats.str,
selectedEnemy.stats.vit,
isCritical
);
// Set current damage for visualization
setCurrentDamage(damage);
setIsCriticalHit(isCritical);
setCurrentSkill(undefined);
setIsAnimating(true);
setIsAttacking(true);
addToCombatLog(`You attacked ${selectedEnemy.name} for ${damage} damage!`);
};
// Handle animation completion
const handleAnimationComplete = () => {
setIsAnimating(false);
setIsAttacking(false);
if (!selectedEnemy || !inCombat) return;
if (playerTurn) {
// Player attack logic after animation
const newEnemyHp = Math.max(0, enemyHp - currentDamage);
setEnemyHp(newEnemyHp);
if (newEnemyHp <= 0) {
endCombat(true);
return; // Important: Stop execution here to prevent enemy turn
} else {
setPlayerTurn(false);
// Enemy's turn after a shorter delay
setTimeout(() => enemyTurn(), 300); // Reduced from 1000ms to 300ms
}
} else {
// Enemy attack logic after animation
if (isDefending) {
setIsDefending(false);
}
// Check if player is defeated
if (playerHp <= 0) {
endCombat(false);
return; // Important: Stop execution here
}
setPlayerTurn(true);
}
};
// Player defends to reduce incoming damage
const playerDefend = () => {
if (!inCombat || !playerTurn || isAnimating) return;
setIsAnimating(true);
setIsDefending(true);
addToCombatLog("You defended!");
setTimeout(() => {
setIsAnimating(false);
setPlayerTurn(false);
// Enemy's turn after a shorter delay
setTimeout(() => enemyTurn(), 300); // Reduced from 500ms to 300ms
}, 600); // Reduced from 1000ms to 600ms
};
// Player uses a skill
const playerUseSkill = (
skillName: string,
mpCost: number,
cooldown: number
) => {
if (!selectedEnemy || !inCombat || !playerTurn || isAnimating) return;
if (playerMp < mpCost) {
toast({
title: "Not enough MP",
description: `You need ${mpCost} MP to use this skill.`,
variant: "destructive",
});
return;
}
if (skillCooldowns[skillName] && skillCooldowns[skillName] > 0) {
toast({
title: "Skill on cooldown",
description: `This skill will be available in ${skillCooldowns[skillName]} turns.`,
variant: "destructive",
});
return;
}
// Reduce MP
setPlayerMp((prev) => prev - mpCost);
// Set cooldown
setSkillCooldowns((prev) => ({
...prev,
[skillName]: cooldown,
}));
let damage = 0;
// Different skills have different effects
switch (skillName) {
case "Power Strike":
damage = calculateDamage(
userStats.stats.str * 2,
selectedEnemy.stats.vit
);
break;
case "Double Slash":
const hit1 = calculateDamage(
userStats.stats.str * 0.7,
selectedEnemy.stats.vit
);
const hit2 = calculateDamage(
userStats.stats.str * 0.7,
selectedEnemy.stats.vit
);
damage = hit1 + hit2;
break;
case "Fireball":
damage = calculateDamage(
userStats.stats.int * 2,
selectedEnemy.stats.vit
);
break;
case "Heal":
const healAmount = Math.floor(userStats.stats.int * 1.5);
setPlayerHp((prev) => Math.min(userStats.maxHp, prev + healAmount));
damage = 0;
break;
default:
damage = 0;
}
// Set current damage and skill for visualization
setCurrentDamage(damage);
setIsCriticalHit(false);
setCurrentSkill(skillName);
setIsAnimating(true);
setIsAttacking(true);
addToCombatLog(`You used ${skillName} for ${damage} damage!`);
};
// Player uses an item
const playerUseItem = (itemId: string) => {
if (!inCombat || !playerTurn || isAnimating) return;
const item = userStats.inventory.find((i) => i.id === itemId);
if (!item) {
toast({
title: "Item not found",
description: "The selected item could not be found in your inventory.",
variant: "destructive",
});
return;
}
let effectApplied = false;
// Apply item effects based on item type and id
if (item.type === "Consumable") {
// First check for specific item IDs for built-in items
if (item.id === "item-health-potion") {
const healAmount = 100;
setPlayerHp((prev) => Math.min(userStats.maxHp, prev + healAmount));
toast({
title: "Health Restored",
description: `You used a Health Potion and restored ${healAmount} HP.`,
});
effectApplied = true;
} else if (item.id === "item-mana-potion") {
const manaAmount = 50;
setPlayerMp((prev) => Math.min(userStats.maxMp, prev + manaAmount));
toast({
title: "Mana Restored",
description: `You used a Mana Potion and restored ${manaAmount} MP.`,
});
effectApplied = true;
} else if (item.id === "item-greater-health-potion") {
const healAmount = 200;
setPlayerHp((prev) => Math.min(userStats.maxHp, prev + healAmount));
toast({
title: "Health Restored",
description: `You used a Greater Health Potion and restored ${healAmount} HP.`,
});
effectApplied = true;
} else if (item.id === "item-greater-mana-potion") {
const manaAmount = 100;
setPlayerMp((prev) => Math.min(userStats.maxMp, prev + manaAmount));
toast({
title: "Mana Restored",
description: `You used a Greater Mana Potion and restored ${manaAmount} MP.`,
});
effectApplied = true;
} else if (item.id === "item-healing-elixir") {
const healAmount = 350;
setPlayerHp((prev) => Math.min(userStats.maxHp, prev + healAmount));
toast({
title: "Health Restored",
description: `You used a Healing Elixir and restored ${healAmount} HP.`,
});
effectApplied = true;
} else if (item.id === "item-mana-elixir") {
const manaAmount = 175;
setPlayerMp((prev) => Math.min(userStats.maxMp, prev + manaAmount));
toast({
title: "Mana Restored",
description: `You used a Mana Elixir and restored ${manaAmount} MP.`,
});
effectApplied = true;
}
// For other consumables, check name patterns
else if (
item.name.toLowerCase().includes("health") ||
item.name.toLowerCase().includes("healing") ||
item.name.toLowerCase().includes("hp")
) {
// Default healing amount (can be customized based on rarity)
let healAmount = 50;
if (item.rarity === "Uncommon") healAmount = 100;
if (item.rarity === "Rare") healAmount = 200;
if (item.rarity === "Epic") healAmount = 350;
if (item.rarity === "Legendary") healAmount = 500;
setPlayerHp((prev) => Math.min(userStats.maxHp, prev + healAmount));
toast({
title: "Health Restored",
description: `You used ${item.name} and restored ${healAmount} HP.`,
});
effectApplied = true;
} else if (
item.name.toLowerCase().includes("mana") ||
item.name.toLowerCase().includes("mp")
) {
// Default mana restoration amount
let manaAmount = 25;
if (item.rarity === "Uncommon") manaAmount = 50;
if (item.rarity === "Rare") manaAmount = 100;
if (item.rarity === "Epic") manaAmount = 175;
if (item.rarity === "Legendary") manaAmount = 250;
setPlayerMp((prev) => Math.min(userStats.maxMp, prev + manaAmount));
toast({
title: "Mana Restored",
description: `You used ${item.name} and restored ${manaAmount} MP.`,
});
effectApplied = true;
} else {
toast({
title: "Item Effect Unknown",
description: "This item's effect is not implemented yet.",
variant: "destructive",
});
}
} else {
toast({
title: "Cannot Use Item",
description: "Only consumable items can be used in combat.",
variant: "destructive",
});
return;
}
if (effectApplied) {
// Remove the item from inventory
removeItem(itemId, 1);
// End player's turn
setPlayerTurn(false);
setTimeout(() => enemyTurn(), 300); // Reduced from 1000ms to 300ms
}
};
// Enemy takes their turn
const enemyTurn = () => {
if (!selectedEnemy || !inCombat) return;
// Reduce cooldowns
setSkillCooldowns((prev) => {
const newCooldowns = { ...prev };
Object.keys(newCooldowns).forEach((skill) => {
if (newCooldowns[skill] > 0) {
newCooldowns[skill] -= 1;
}
});
return newCooldowns;
});
// Enemy decides what to do (for now, just basic attack)
const damage = calculateDamage(
selectedEnemy.stats.str,
userStats.stats.vit
);
// Apply defense reduction if player is defending
const actualDamage = isDefending ? Math.floor(damage * 0.5) : damage;
// Set current damage for visualization
setCurrentDamage(actualDamage);
setIsCriticalHit(false);
setCurrentSkill(undefined);
setIsAnimating(true);
setIsAttacking(true);
// Update player HP
const newPlayerHp = Math.max(0, playerHp - actualDamage);
setPlayerHp(newPlayerHp);
addToCombatLog(
`${selectedEnemy.name} attacked you for ${actualDamage} damage!`
);
// Check if player is defeated - this will be handled in handleAnimationComplete
};
// Add message to combat log
const addToCombatLog = (message: string) => {
setCombatLog((prev) => [...prev, message]);
};
// End combat and determine rewards or penalties
const endCombat = (victory: boolean) => {
if (!selectedEnemy) return;
if (victory) {
addToCombatLog(`You have defeated ${selectedEnemy.name}!`);
// Set rewards
const combatRewards = {
exp: selectedEnemy.rewards.exp,
gold: selectedEnemy.rewards.gold,
items: selectedEnemy.rewards.items,
};
setRewards(combatRewards);
setShowRewards(true);
toast({
title: "Victory!",
description: `You have defeated ${selectedEnemy.name}!`,
});
} else {
addToCombatLog(`You have been defeated by ${selectedEnemy.name}.`);
// Apply defeat penalties (lose some gold, etc.)
const goldLoss = Math.floor(userStats.gold * 0.1); // Lose 10% of gold
setUserStats((prev) => ({
...prev,
hp: Math.max(1, Math.floor(prev.maxHp * 0.1)), // Restore to 10% HP
gold: Math.max(0, prev.gold - goldLoss),
}));
addToCombatLog(
`You lost ${goldLoss} gold and barely escaped with your life.`
);
}
setInCombat(false);
setIsAnimating(false);
setIsAttacking(false);
};
// Claim rewards after victory
const claimRewards = () => {
if (!selectedEnemy) return;
// Add experience
addExp(rewards.exp);
// Add gold
addGold(rewards.gold);
// Add items to inventory
rewards.items.forEach((item) => {
addItem(item);
});
// Show toast notification
toast({
title: "Rewards Claimed",
description: `You gained ${rewards.exp} EXP, ${rewards.gold} Gold, and ${rewards.items.length} items.`,
});
// Reset combat
setShowRewards(false);
setSelectedEnemy(null);
};
// Skip turn (for testing)
const skipTurn = () => {
if (!inCombat) return;
if (playerTurn) {
setPlayerTurn(false);
setTimeout(() => enemyTurn(), 500);
} else {
setPlayerTurn(true);
}
};
// Flee from combat
const fleeCombat = () => {
if (!inCombat || !selectedEnemy || isAnimating) return;
// 50% chance to successfully flee based on agility difference
const fleeChance = 50 + (userStats.stats.agi - selectedEnemy.stats.agi) * 2;
if (Math.random() * 100 < fleeChance) {
toast({
title: "Escaped",
description: "You successfully fled from combat!",
});
setInCombat(false);
setSelectedEnemy(null);
} else {
toast({
title: "Failed to Escape",
description: "You failed to flee!",
});
setPlayerTurn(false);
setTimeout(() => enemyTurn(), 300); // Reduced from 1000ms to 300ms
}
};
return (
<div className="min-h-screen bg-[#0a0e14] text-[#e0f2ff] pb-16 md:pb-0">
<div className="container mx-auto px-4 py-6">
{/* Header */}
<header className="flex items-center justify-between mb-8">
<div className="flex items-center">
<Link href="/" className="mr-4">
<Button
variant="ghost"
size="icon"
className="hover:bg-[#1e2a3a]"
>
<ChevronLeft className="h-5 w-5" />
<span className="sr-only">Back</span>
</Button>
</Link>
<h1 className="text-2xl font-bold tracking-tight text-[#4cc9ff]">
Combat Arena
</h1>
</div>
<div className="flex items-center">
<div className="bg-[#1e2a3a] px-3 py-1 rounded-lg flex items-center">
<span className="text-[#8bacc1] mr-2">Gold:</span>
<span className="text-yellow-400 font-bold">
{userStats.gold}
</span>
</div>
</div>
</header>
{/* Recovery notification card */}
<div className="mb-6">
<Card className="bg-[#0a0e14]/80 border-[#1e2a3a] relative">
<div className="absolute inset-0 border border-[#4cc9ff]/10"></div>
<CardContent className="p-4 relative z-10">
<div className="flex items-start gap-3">
<Heart className="h-5 w-5 text-red-400 mt-0.5 flex-shrink-0" />
<div>
<h3 className="text-sm font-medium text-[#4cc9ff] mb-1">
Automatic Recovery System
</h3>
<p className="text-xs text-[#8bacc1]">
Your character naturally recovers 10% of maximum HP and MP
every 5 minutes when not in combat. This recovery continues
even when you're offline, allowing you to return stronger
after a break.
</p>
</div>
</div>
</CardContent>
</Card>
</div>
{/* Main Combat Area */}
<div className="grid grid-cols-1 gap-6">
{/* Left Column - Combat Area */}
<div className="lg:col-span-1">
{!selectedEnemy && !inCombat ? (
<EnemySelection enemies={enemies} onSelectEnemy={startCombat} />
) : (
<>
{/* Combat Visualization */}
{inCombat && selectedEnemy && (
<CombatVisualization
playerName={userStats.name || "Hunter"}
enemyName={selectedEnemy.name}
isPlayerTurn={playerTurn}
isAttacking={isAttacking}
isDefending={isDefending}
attackDamage={currentDamage}
isCritical={isCriticalHit}
skillName={currentSkill}
playerHp={playerHp}
playerMaxHp={userStats.maxHp}
playerMp={playerMp}
playerMaxMp={userStats.maxMp}
playerLevel={userStats.level}
enemyHp={enemyHp}
enemyMaxHp={enemyMaxHp}
playerStats={userStats.stats}
onAnimationComplete={handleAnimationComplete}
/>
)}
{!inCombat && selectedEnemy && (
<Card className="bg-[#0a0e14]/80 border-[#1e2a3a] relative mb-4">
<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-[#4cc9ff]">
{selectedEnemy.name}
</CardTitle>
<Badge className="bg-[#1e2a3a]">
Level {selectedEnemy.level}
</Badge>
</div>
<CardDescription>
{selectedEnemy.description}
</CardDescription>
</CardHeader>
<CardContent className="relative z-10">
{/* Enemy Stats */}
<div className="grid grid-cols-3 gap-2 text-xs mb-4">
<div className="flex flex-col items-center p-2 bg-[#1e2a3a] rounded-md">
<Sword className="h-3 w-3 text-[#4cc9ff] mb-1" />
<span className="text-[#8bacc1]">STR</span>
<span>{selectedEnemy.stats.str}</span>
</div>
<div className="flex flex-col items-center p-2 bg-[#1e2a3a] rounded-md">
<Shield className="h-3 w-3 text-[#4cc9ff] mb-1" />
<span className="text-[#8bacc1]">VIT</span>
<span>{selectedEnemy.stats.vit}</span>
</div>
<div className="flex flex-col items-center p-2 bg-[#1e2a3a] rounded-md">
<Zap className="h-3 w-3 text-[#4cc9ff] mb-1" />
<span className="text-[#8bacc1]">AGI</span>
<span>{selectedEnemy.stats.agi}</span>
</div>
<div className="flex flex-col items-center p-2 bg-[#1e2a3a] rounded-md">
<Brain className="h-3 w-3 text-[#4cc9ff] mb-1" />
<span className="text-[#8bacc1]">INT</span>
<span>{selectedEnemy.stats.int}</span>
</div>
<div className="flex flex-col items-center p-2 bg-[#1e2a3a] rounded-md">
<Eye className="h-3 w-3 text-[#4cc9ff] mb-1" />
<span className="text-[#8bacc1]">PER</span>
<span>{selectedEnemy.stats.per}</span>
</div>
</div>
</CardContent>
{!inCombat && !showRewards && (
<CardFooter className="relative z-10">
<Button
className="w-full bg-transparent border border-[#4cc9ff] hover:bg-[#4cc9ff]/10 text-[#4cc9ff]"
onClick={() => startCombat(selectedEnemy)}
>
Start Combat
</Button>
</CardFooter>
)}
{showRewards && (
<CardFooter className="relative z-10">
<Button
className="w-full bg-transparent border border-[#4cc9ff] hover:bg-[#4cc9ff]/10 text-[#4cc9ff]"
onClick={claimRewards}
>
Claim Rewards
</Button>
</CardFooter>
)}
</Card>
)}
</>
)}
</div>
{/* Right Column - Player Stats (hidden during combat) */}
{!inCombat && (
<div className="lg:col-span-1">
<Card className="bg-[#0a0e14]/80 border-[#1e2a3a] relative h-full">
<div className="absolute inset-0 border border-[#4cc9ff]/10"></div>
<CardHeader className="pb-2 relative z-10">
<CardTitle className="text-[#4cc9ff]">Your Stats</CardTitle>
<CardDescription>
Level {userStats.level} Hunter
</CardDescription>
</CardHeader>
<CardContent className="relative z-10">
{/* HP/MP Bars */}
<div className="space-y-4">
<div>
<div className="flex justify-between text-xs mb-1">
<span className="flex items-center">
<Heart className="h-3 w-3 text-red-400 mr-1" />
<span>HP</span>
</span>
<span>
{playerHp}/{userStats.maxHp}
</span>
</div>
<Progress
value={(playerHp / userStats.maxHp) * 100}
className="h-2 bg-[#1e2a3a]"
>
<div className="h-full bg-gradient-to-r from-red-500 to-red-600 rounded-full" />
</Progress>
</div>
<div>
<div className="flex justify-between text-xs mb-1">
<span className="flex items-center">
<Zap className="h-3 w-3 text-blue-400 mr-1" />
<span>MP</span>
</span>
<span>
{playerMp}/{userStats.maxMp}
</span>
</div>
<Progress
value={(playerMp / userStats.maxMp) * 100}
className="h-2 bg-[#1e2a3a]"
>
<div className="h-full bg-gradient-to-r from-blue-500 to-blue-600 rounded-full" />
</Progress>
</div>
</div>
<Separator className="my-4 bg-[#1e2a3a]" />
{/* Stats */}
<div className="grid grid-cols-2 gap-y-2 text-sm">
<div className="flex items-center">
<Sword className="h-4 w-4 text-[#4cc9ff] mr-2" />
<span className="text-[#8bacc1] mr-1">STR:</span>
<span>{userStats.stats.str}</span>
</div>
<div className="flex items-center">
<Shield className="h-4 w-4 text-[#4cc9ff] mr-2" />
<span className="text-[#8bacc1] mr-1">VIT:</span>
<span>{userStats.stats.vit}</span>
</div>
<div className="flex items-center">
<Zap className="h-4 w-4 text-[#4cc9ff] mr-2" />
<span className="text-[#8bacc1] mr-1">AGI:</span>
<span>{userStats.stats.agi}</span>
</div>
<div className="flex items-center">
<Brain className="h-4 w-4 text-[#4cc9ff] mr-2" />
<span className="text-[#8bacc1] mr-1">INT:</span>
<span>{userStats.stats.int}</span>
</div>
<div className="flex items-center">
<Eye className="h-4 w-4 text-[#4cc9ff] mr-2" />
<span className="text-[#8bacc1] mr-1">PER:</span>
<span>{userStats.stats.per}</span>
</div>
</div>
</CardContent>
</Card>
</div>
)}
</div>
{/* Combat Actions */}
{inCombat && playerTurn && (
<div className="mt-6">
<CombatActions
onAttack={playerAttack}
onDefend={playerDefend}
onUseSkill={playerUseSkill}
onUseItem={playerUseItem}
onFlee={fleeCombat}
playerStats={userStats}
playerMp={playerMp}
skillCooldowns={skillCooldowns}
/>
</div>
)}
{/* Rewards Dialog */}
<Dialog open={showRewards} onOpenChange={setShowRewards}>
<DialogContent
className="bg-[#0a0e14] border-[#1e2a3a] text-[#e0f2ff] w-[90%] sm:max-w-md animate-solo-modal"
style={
{
"--solo-expand-duration": "0.5s",
"--solo-expand-easing": "cubic-bezier(0.16, 1, 0.3, 1)",
} as React.CSSProperties
}
>
<DialogHeader>
<DialogTitle className="text-[#4cc9ff]">
Victory Rewards
</DialogTitle>
<DialogDescription className="text-[#8bacc1]">
You have defeated {selectedEnemy?.name}!
</DialogDescription>
</DialogHeader>
<div className="py-4">
<div className="space-y-4">
<div className="flex justify-between items-center">
<span>Experience:</span>
<span className="text-[#4cc9ff] font-bold">
{rewards.exp} EXP
</span>
</div>
<div className="flex justify-between items-center">
<span>Gold:</span>
<span className="text-yellow-400 font-bold">
{rewards.gold} Gold
</span>
</div>
<Separator className="bg-[#1e2a3a]" />
<div>
<h4 className="mb-2 font-medium">Items:</h4>
<div className="space-y-2">
{rewards.items.map((item, index) => (
<div
key={index}
className="flex justify-between items-center p-2 bg-[#1e2a3a] rounded-md"
>
<div className="flex items-center">
<div
className={`w-2 h-2 rounded-full mr-2 ${
item.rarity === "Common"
? "bg-gray-400"
: item.rarity === "Uncommon"
? "bg-green-400"
: item.rarity === "Rare"
? "bg-[#4cc9ff]"
: item.rarity === "Epic"
? "bg-purple-400"
: "bg-yellow-400"
}`}
></div>
<span>{item.name}</span>
</div>
<Badge
className={
item.type === "Material"
? "bg-amber-900 text-amber-200"
: item.type === "Weapon"
? "bg-red-900 text-red-200"
: item.type === "Armor"
? "bg-blue-900 text-blue-200"
: item.type === "Accessory"
? "bg-purple-900 text-purple-200"
: "bg-green-900 text-green-200"
}
>
{item.type}
</Badge>
</div>
))}
</div>
</div>
</div>
</div>
<DialogFooter>
<Button
className="w-full bg-transparent border border-[#4cc9ff] hover:bg-[#4cc9ff]/10 text-[#4cc9ff]"
onClick={claimRewards}
>
Claim Rewards
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</div>
);
}