Refactor App and component files to streamline imports and enhance UI consistency. Removed unused imports and simplified event handlers for better performance. Updated BuildingInfo to utilize Chakra UI modal for improved user experience, and adjusted MultiplierShop functionality comments for clarity.

This commit is contained in:
billy 2025-03-30 15:45:58 -04:00
parent 8245b7b3b2
commit f000fecba2
9 changed files with 29 additions and 75 deletions

View File

@ -1,10 +1,8 @@
import { ResourceDisplay } from './components/ResourceDisplay' import { ResourceDisplay } from './components/ResourceDisplay'
import { BuildingButton } from './components/BuildingButton' import { BuildingButton } from './components/BuildingButton'
import { NextBuildingPreview } from './components/NextBuildingPreview' import { NextBuildingPreview } from './components/NextBuildingPreview'
import { ResetButton } from './components/ResetButton'
import { useGameStore } from './store/gameStore' import { useGameStore } from './store/gameStore'
import { playClickSound, initAudio } from './utils/soundUtils' import { initAudio } from './utils/soundUtils'
import { formatNumber } from './utils/numberUtils'
import { import {
ChakraProvider, ChakraProvider,
Box, Box,
@ -14,9 +12,6 @@ import {
VStack, VStack,
SimpleGrid, SimpleGrid,
Button, Button,
Flex,
Image,
Center,
Modal, Modal,
ModalOverlay, ModalOverlay,
ModalContent, ModalContent,
@ -28,7 +23,6 @@ import {
} from '@chakra-ui/react' } from '@chakra-ui/react'
import theme from './theme' import theme from './theme'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import logoImg from './assets/logo.png'
type BuildingId = 'mouseFarms' | 'keyboardFactories' | 'monitorDisplays' | 'officeSpace' | 'serverRooms' | 'dataCenters' | type BuildingId = 'mouseFarms' | 'keyboardFactories' | 'monitorDisplays' | 'officeSpace' | 'serverRooms' | 'dataCenters' |
'dataCities' | 'dataCountries' | 'dataContinents' | 'dataWorlds' | 'dataMoons' | 'dataCities' | 'dataCountries' | 'dataContinents' | 'dataWorlds' | 'dataMoons' |
@ -39,7 +33,6 @@ type BuildingLevelKey = `${BuildingId}Level`
function App() { function App() {
const { const {
points, points,
playerLevel,
getAvailableBuildings, getAvailableBuildings,
tick, tick,
click, click,
@ -47,7 +40,7 @@ function App() {
const [agreedToTerms, setAgreedToTerms] = useState(false) const [agreedToTerms, setAgreedToTerms] = useState(false)
const [hasStarted, setHasStarted] = useState(false) const [hasStarted, setHasStarted] = useState(false)
const { isOpen, onClose } = useDisclosure({ defaultIsOpen: true }) const { onClose } = useDisclosure({ defaultIsOpen: true })
const availableBuildings = getAvailableBuildings() const availableBuildings = getAvailableBuildings()
// Set up game tick interval // Set up game tick interval
@ -66,7 +59,7 @@ function App() {
// This is now handled globally, but we'll keep a simpler version // This is now handled globally, but we'll keep a simpler version
// for UI feedback only (cursor change, etc) // for UI feedback only (cursor change, etc)
const handleClick = (e: React.MouseEvent) => { const handleClick = () => {
// Don't call click() here as it's now handled globally // Don't call click() here as it's now handled globally
// Just for visual feedback // Just for visual feedback
if (hasStarted) { if (hasStarted) {

View File

@ -3,7 +3,6 @@ import {
Button, Button,
VStack, VStack,
Text, Text,
Badge,
Tooltip, Tooltip,
HStack, HStack,
Image, Image,

View File

@ -1,4 +1,4 @@
import { motion, AnimatePresence } from 'framer-motion' import { Box, Heading, Text, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalCloseButton } from '@chakra-ui/react'
interface BuildingInfoProps { interface BuildingInfoProps {
isOpen: boolean isOpen: boolean
@ -11,44 +11,23 @@ interface BuildingInfoProps {
} }
export const BuildingInfo = ({ isOpen, onClose, title, description, production }: BuildingInfoProps) => { export const BuildingInfo = ({ isOpen, onClose, title, description, production }: BuildingInfoProps) => {
if (!isOpen) return null
return ( return (
<AnimatePresence> <Modal isOpen={isOpen} onClose={onClose} isCentered>
<motion.div <ModalOverlay bg="blackAlpha.700" />
initial={{ opacity: 0 }} <ModalContent bg="background.secondary" maxW="md" mx={4}>
animate={{ opacity: 1 }} <ModalHeader color="text.secondary">{title}</ModalHeader>
exit={{ opacity: 0 }} <ModalCloseButton />
className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50" <ModalBody pb={6}>
onClick={onClose} <Text color="text.primary" mb={4}>{description}</Text>
>
<motion.div
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
className="bg-gray-800 p-6 rounded-lg max-w-md w-full mx-4"
onClick={e => e.stopPropagation()}
>
<div className="flex justify-between items-start mb-4">
<h3 className="text-xl font-bold">{title}</h3>
<button
onClick={onClose}
className="text-gray-400 hover:text-white"
>
</button>
</div>
<p className="text-gray-300 mb-4">{description}</p> <Box p={4} bg="background.card" borderRadius="md">
<Heading as="h4" size="sm" mb={2} color="brand.300">Production:</Heading>
<div className="bg-gray-700 p-4 rounded-lg">
<h4 className="font-semibold mb-2">Production:</h4>
{production.points && ( {production.points && (
<div className="text-green-400">+{production.points} points/s</div> <Text color="text.accent">+{production.points} points/s</Text>
)} )}
</div> </Box>
</motion.div> </ModalBody>
</motion.div> </ModalContent>
</AnimatePresence> </Modal>
) )
} }

View File

@ -1,4 +1,4 @@
import { Box, Button, VStack, HStack, Text, SimpleGrid } from '@chakra-ui/react' import { Box, Button, VStack, Text, SimpleGrid } from '@chakra-ui/react'
import { useGameStore } from '../store/gameStore' import { useGameStore } from '../store/gameStore'
const MULTIPLIER_PURCHASES = [ const MULTIPLIER_PURCHASES = [
@ -11,7 +11,7 @@ const MULTIPLIER_PURCHASES = [
] ]
export function MultiplierShop() { export function MultiplierShop() {
const { points, buyMultiplier } = useGameStore() const { points } = useGameStore()
return ( return (
<Box bg="gray.800" p={6} borderRadius="lg"> <Box bg="gray.800" p={6} borderRadius="lg">
@ -26,7 +26,8 @@ export function MultiplierShop() {
{MULTIPLIER_PURCHASES.map((purchase) => ( {MULTIPLIER_PURCHASES.map((purchase) => (
<Button <Button
key={`${purchase.duration}-${purchase.multiplier}`} key={`${purchase.duration}-${purchase.multiplier}`}
onClick={() => buyMultiplier(purchase.duration, purchase.multiplier)} // Multiplier shop functionality is not yet implemented in the game state
// onClick={() => buyMultiplier(purchase.duration, purchase.multiplier)}
isDisabled={points < purchase.cost} isDisabled={points < purchase.cost}
bg="gray.700" bg="gray.700"
_hover={{ bg: 'gray.600' }} _hover={{ bg: 'gray.600' }}

View File

@ -9,17 +9,6 @@ import { useGameStore } from '../store/gameStore'
import { BUILDING_INFO } from '../store/gameStore' import { BUILDING_INFO } from '../store/gameStore'
import { formatNumber } from '../utils/numberUtils' import { formatNumber } from '../utils/numberUtils'
interface BuildingInfo {
cost: number
levelRequirement: number
title: string
description: string
production: {
points?: number
techParts?: number
}
}
export function NextBuildingPreview() { export function NextBuildingPreview() {
const { playerLevel } = useGameStore() const { playerLevel } = useGameStore()
@ -29,7 +18,7 @@ export function NextBuildingPreview() {
if (!nextBuilding) return null if (!nextBuilding) return null
const [id, info] = nextBuilding const [, info] = nextBuilding
return ( return (
<Tooltip label={`Requires level ${info.levelRequirement}`}> <Tooltip label={`Requires level ${info.levelRequirement}`}>

View File

@ -1,4 +1,4 @@
import { Box, HStack, Text, Progress, Flex, Divider, Tooltip, Image, Button, Icon } from '@chakra-ui/react' import { Box, Text, Progress, Flex, Divider, Tooltip, Image, Button } from '@chakra-ui/react'
import { useGameStore } from '../store/gameStore' import { useGameStore } from '../store/gameStore'
import logoImg from '../assets/logo.png' import logoImg from '../assets/logo.png'
import { ResetButton } from './ResetButton' import { ResetButton } from './ResetButton'

View File

@ -1,6 +1,6 @@
import { IconButton, Tooltip, useBoolean } from '@chakra-ui/react' import { IconButton, Tooltip } from '@chakra-ui/react'
import { toggleSound, isSoundEnabled, initAudio } from '../utils/soundUtils' import { toggleSound, isSoundEnabled, initAudio } from '../utils/soundUtils'
import { useEffect, useState } from 'react' import { useState } from 'react'
export function SoundToggleButton() { export function SoundToggleButton() {
// Initialize the state with the current sound enabled state // Initialize the state with the current sound enabled state

View File

@ -28,7 +28,7 @@ function AppWithGlobalHandlers() {
}, [gameStarted]); }, [gameStarted]);
useEffect(() => { useEffect(() => {
const handleGlobalClick = (e: MouseEvent) => { const handleGlobalClick = () => {
// Only trigger if game has started // Only trigger if game has started
const gameState = useGameStore.getState(); const gameState = useGameStore.getState();
if ((gameStarted || gameState.points > 0) && gameState.playerLevel >= 1) { if ((gameStarted || gameState.points > 0) && gameState.playerLevel >= 1) {
@ -37,7 +37,7 @@ function AppWithGlobalHandlers() {
} }
}; };
const handleGlobalKeyPress = (e: KeyboardEvent) => { const handleGlobalKeyPress = () => {
// Only trigger if game has started // Only trigger if game has started
const gameState = useGameStore.getState(); const gameState = useGameStore.getState();
if ((gameStarted || gameState.points > 0) && gameState.playerLevel >= 1) { if ((gameStarted || gameState.points > 0) && gameState.playerLevel >= 1) {

View File

@ -9,7 +9,6 @@ const SOUND_FILES = {
// AudioManager singleton for handling all game audio // AudioManager singleton for handling all game audio
class AudioManager { class AudioManager {
private soundEnabled: boolean = true; private soundEnabled: boolean = true;
private audioContext: AudioContext | null = null;
private sounds: Map<string, HTMLAudioElement> = new Map(); private sounds: Map<string, HTMLAudioElement> = new Map();
private lastClickIndex: number = -1; private lastClickIndex: number = -1;
private initialized: boolean = false; private initialized: boolean = false;
@ -36,12 +35,6 @@ class AudioManager {
} }
try { try {
// Create AudioContext if possible (will only work after user interaction)
if (window.AudioContext || (window as any).webkitAudioContext) {
const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;
this.audioContext = new AudioContextClass();
}
// Play a silent sound to unlock audio on iOS/Safari // Play a silent sound to unlock audio on iOS/Safari
const silentSound = new Audio(); const silentSound = new Audio();
silentSound.play().catch(e => console.log('Silent sound failed to play:', e)); silentSound.play().catch(e => console.log('Silent sound failed to play:', e));
@ -189,4 +182,4 @@ export const playPurchaseSound = () => audioManager.playPurchaseSound();
export const playLevelUpSound = () => audioManager.playLevelUpSound(); export const playLevelUpSound = () => audioManager.playLevelUpSound();
export const playUpgradeSound = () => audioManager.playUpgradeSound(); export const playUpgradeSound = () => audioManager.playUpgradeSound();
export const toggleSound = (state?: boolean) => audioManager.toggleSound(state); export const toggleSound = (state?: boolean) => audioManager.toggleSound(state);
export const isSoundEnabled = () => audioManager.isSoundEnabled(); export const isSoundEnabled = () => audioManager.isSoundEnabled();