Files
bozoclicker/src/components/UpgradeShop.tsx
2025-08-04 10:34:04 +00:00

108 lines
4.0 KiB
TypeScript

import React from 'react';
import { UPGRADES } from '../config/upgrades';
import { GameState, MascotTier, UserState } from '../types'; // Import MascotTier
interface UpgradeShopProps {
gameState: GameState;
userState: UserState | null;
onPurchase: (upgradeId: string) => void;
}
// Helper function to get mascot name from image source
const getMascotName = (imageSrc: string): string => {
const fileName = imageSrc.split('/').pop() || '';
const nameWithoutExtension = fileName.split('.')[0];
// remove the word neurosama if it exists in the name
if (nameWithoutExtension.includes('neurosama')) {
return nameWithoutExtension.replace('neurosama', '').trim();
}
return nameWithoutExtension
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
};
export function UpgradeShop({ userState, onPurchase }: UpgradeShopProps) { // Changed from userClicks
if (!userState) {
return null; // Or a loading/signed-out state
}
const { clicks: userClicks, upgrades: userUpgrades } = userState;
return (
<div className="bg-gradient-to-b from-purple-800 to-pink-600 p-6 rounded-xl border-4 border-cyan-400 shadow-2xl">
<h2 className="text-3xl font-bold text-yellow-300 mb-6 text-center" style={{ fontFamily: 'Comic Sans MS, cursive' }}>
BOZO SHOP
</h2>
<div className="space-y-4">
{UPGRADES.map((upgrade) => {
const owned = userUpgrades[upgrade.id]?.owned || 0;
const cost = userUpgrades[upgrade.id]?.cost || upgrade.baseCost;
const canAfford = userClicks >= cost;
// If it's a one-time upgrade and already owned, don't display it
if (upgrade.oneTime && owned > 0) {
return null;
}
let description = upgrade.description;
// Custom description for Friend Boost upgrade
if (upgrade.id === 'friendBoost' && upgrade.mascotTiers) {
const nextMascotTier = upgrade.mascotTiers.find(
(tier: MascotTier) => owned < tier.level
);
if (nextMascotTier) {
description = `Spawns various clickable friends. Next: ${getMascotName(nextMascotTier.imageSrc)} at level ${nextMascotTier.level}`;
} else {
description = 'All mascots unlocked! Spawns various clickable friends.';
}
}
return (
<div
key={upgrade.id}
className={`bg-gradient-to-r from-pink-500 to-purple-600 p-4 rounded-lg border-2 transition-all duration-300 ${
canAfford
? 'border-green-400 hover:scale-105 cursor-pointer hover:shadow-lg'
: 'border-gray-500 opacity-60'
}`}
onClick={() => canAfford && onPurchase(upgrade.id)}
>
<div className="flex justify-between items-center">
<div className="flex-1">
<div className="flex items-center space-x-2">
<span className="text-2xl">{upgrade.icon}</span>
<h3 className="text-lg font-bold text-white">{upgrade.name}</h3>
{owned > 0 && (
<span className="bg-yellow-400 text-black px-2 py-1 rounded-full text-sm font-bold">
{owned}
</span>
)}
</div>
<p className="text-cyan-200 text-sm mt-1">{description}</p>
</div>
<div className="text-right">
<div className={`text-xl font-bold ${canAfford ? 'text-green-300' : 'text-red-300'}`}>
{cost.toLocaleString()}
</div>
<div className="text-xs text-gray-300">clicks</div>
</div>
</div>
</div>
);
})}
</div>
<div className="mt-6 text-center">
<div className="text-2xl font-bold text-yellow-300">
Your Clicks: {userClicks.toLocaleString()}
</div>
</div>
</div>
);
}