refactor: update pet action handling and restructure pet types for better clarity
This commit is contained in:
parent
8875eb75af
commit
a85a80938b
111
src/App.tsx
111
src/App.tsx
@ -1,18 +1,12 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import ClassSelection from './components/ClassSelection';
|
|
||||||
import PetDisplay from './components/PetDisplay';
|
import PetDisplay from './components/PetDisplay';
|
||||||
import InteractionMenu from './components/InteractionMenu';
|
import InteractionMenu from './components/InteractionMenu';
|
||||||
import NameModal from './components/modal/NameModal';
|
import PetRegister from './components/PetRegister';
|
||||||
import ConfirmationModal from './components/modal/ConfirmationModal';
|
import { Pet } from './types/Pet';
|
||||||
import { Pet, PetClassInfo } from './types/Pet';
|
import { fetchPets } from './services/api/api';
|
||||||
import { fetchPets, createPet } from './services/api/api';
|
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [pet, setPet] = useState<Pet | null>(null);
|
const [pet, setPet] = useState<Pet | null>(null);
|
||||||
const [showConfirmation, setShowConfirmation] = useState(false);
|
|
||||||
const [showNameModal, setShowNameModal] = useState(false);
|
|
||||||
const [petName, setPetName] = useState('');
|
|
||||||
const [selectedClass, setSelectedClass] = useState<{ key: string; info: PetClassInfo } | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadPets = async () => {
|
const loadPets = async () => {
|
||||||
@ -29,78 +23,6 @@ export default function App() {
|
|||||||
loadPets();
|
loadPets();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleClassSelect = (classKey: string, classInfo: PetClassInfo) => {
|
|
||||||
setSelectedClass({ key: classKey, info: classInfo });
|
|
||||||
setShowConfirmation(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleConfirm = () => {
|
|
||||||
if (!selectedClass) return;
|
|
||||||
setShowConfirmation(false);
|
|
||||||
setShowNameModal(true);
|
|
||||||
setPetName('');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleNameSubmit = async () => {
|
|
||||||
if (!selectedClass || !petName.trim()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const newPet = await createPet({
|
|
||||||
name: petName.trim(),
|
|
||||||
class: selectedClass.key,
|
|
||||||
});
|
|
||||||
setPet(newPet);
|
|
||||||
setShowNameModal(false);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error creating pet:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFeed = () => {
|
|
||||||
if (!pet) return;
|
|
||||||
const updatedPet = {
|
|
||||||
...pet,
|
|
||||||
stats: {
|
|
||||||
...pet.stats,
|
|
||||||
strength: Math.min(100, pet.stats.strength + 5)
|
|
||||||
},
|
|
||||||
resources: {
|
|
||||||
...pet.resources,
|
|
||||||
food: Math.max(0, pet.resources.food - 10)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
handlePetUpdate(updatedPet);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePlay = () => {
|
|
||||||
if (!pet) return;
|
|
||||||
const updatedPet = {
|
|
||||||
...pet,
|
|
||||||
stats: {
|
|
||||||
...pet.stats,
|
|
||||||
charisma: Math.min(100, pet.stats.charisma + 5)
|
|
||||||
},
|
|
||||||
resources: {
|
|
||||||
...pet.resources,
|
|
||||||
wisdom: pet.resources.wisdom + 5
|
|
||||||
}
|
|
||||||
};
|
|
||||||
handlePetUpdate(updatedPet);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSleep = () => {
|
|
||||||
if (!pet) return;
|
|
||||||
const updatedPet = {
|
|
||||||
...pet,
|
|
||||||
stats: {
|
|
||||||
intelligence: Math.min(100, pet.stats.intelligence + 5),
|
|
||||||
strength: Math.min(100, pet.stats.strength + 2),
|
|
||||||
charisma: Math.min(100, pet.stats.charisma + 2)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
handlePetUpdate(updatedPet);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCustomize = () => {
|
const handleCustomize = () => {
|
||||||
console.log('Customize pet');
|
console.log('Customize pet');
|
||||||
};
|
};
|
||||||
@ -110,29 +32,7 @@ export default function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!pet) {
|
if (!pet) {
|
||||||
return (
|
return <PetRegister onPetCreated={setPet} />;
|
||||||
<div className="min-h-screen bg-gray-900 text-white">
|
|
||||||
{showNameModal && selectedClass ? (
|
|
||||||
<NameModal
|
|
||||||
selectedClass={selectedClass}
|
|
||||||
petName={petName}
|
|
||||||
setPetName={setPetName}
|
|
||||||
handleNameSubmit={handleNameSubmit}
|
|
||||||
setShowNameModal={setShowNameModal}
|
|
||||||
setSelectedClass={setSelectedClass}
|
|
||||||
/>
|
|
||||||
) : showConfirmation && selectedClass ? (
|
|
||||||
<ConfirmationModal
|
|
||||||
selectedClass={selectedClass}
|
|
||||||
handleConfirm={handleConfirm}
|
|
||||||
setShowConfirmation={setShowConfirmation}
|
|
||||||
setSelectedClass={setSelectedClass}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ClassSelection onSelect={handleClassSelect} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -142,9 +42,6 @@ export default function App() {
|
|||||||
<InteractionMenu
|
<InteractionMenu
|
||||||
pet={pet}
|
pet={pet}
|
||||||
onPetUpdate={handlePetUpdate}
|
onPetUpdate={handlePetUpdate}
|
||||||
onFeed={handleFeed}
|
|
||||||
onPlay={handlePlay}
|
|
||||||
onSleep={handleSleep}
|
|
||||||
onCustomize={handleCustomize}
|
onCustomize={handleCustomize}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,34 +1,35 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { FeatherIcon as GatherIcon } from 'lucide-react';
|
import { FeatherIcon as GatherIcon } from 'lucide-react';
|
||||||
import ResourceSelectionModal from './modal/ResourceSelectionModal';
|
import ResourceSelectionModal from './modal/ResourceSelectionModal';
|
||||||
import CollectResourcesButton from './CollectResourcesButton';
|
|
||||||
import { Pet, Resources } from '../types/Pet';
|
import { Pet, Resources } from '../types/Pet';
|
||||||
import { updatePetAction, getPetGatheredResources, putPetCollectResources } from '../services/api/api';
|
import { updatePetAction, getPetGatheredResources } from '../services/api/api';
|
||||||
import { PetAction } from '../types/PetUpdateActionRequest';
|
import { PetGatherAction } from '../types/PetUpdateActionRequest';
|
||||||
import { isGatheringAction, formatResourceName, getResourceFromAction } from '../utils/petUtils';
|
import { isGatheringAction, formatResourceName, getResourceFromAction } from '../utils/petUtils';
|
||||||
|
|
||||||
interface GatherResourcesButtonProps {
|
interface GatherResourcesButtonProps {
|
||||||
pet: Pet;
|
pet: Pet;
|
||||||
onGatherStart: () => void;
|
onGatherStart: () => void;
|
||||||
onGatherComplete: (updatedPet: Pet) => void;
|
onGatherComplete: (updatedPet: Pet) => void;
|
||||||
|
onResourcesUpdate: (resources: Resources) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceToActionMap: Record<string, PetAction> = {
|
const resourceToActionMap: Record<string, PetGatherAction> = {
|
||||||
wisdom: 'GATHERING_WISDOM',
|
wisdom: 'GATHERING_WISDOM',
|
||||||
gold: 'GATHERING_GOLD',
|
gold: 'GATHERING_GOLD',
|
||||||
food: 'GATHERING_FOOD'
|
food: 'GATHERING_FOOD'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function GatherResourcesButton({ pet, onGatherStart, onGatherComplete }: GatherResourcesButtonProps) {
|
export default function GatherResourcesButton({ pet, onGatherStart, onGatherComplete, onResourcesUpdate }: GatherResourcesButtonProps) {
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [isGathering, setIsGathering] = useState(isGatheringAction(pet.petAction));
|
const [isGathering, setIsGathering] = useState(isGatheringAction(pet.petGatherAction));
|
||||||
const [gatheredResources, setGatheredResources] = useState<Resources>({ wisdom: 0, gold: 0, food: 0, junk: 0 });
|
|
||||||
|
|
||||||
// Initialize gathering check if pet is already gathering
|
// Initialize gathering check if pet is already gathering
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isGatheringAction(pet.petAction)) {
|
if (isGatheringAction(pet.petGatherAction)) {
|
||||||
setIsGathering(true);
|
setIsGathering(true);
|
||||||
const resources = getPetGatheredResources(pet.id).then(setGatheredResources);
|
getPetGatheredResources(pet.id).then(resources => {
|
||||||
|
onResourcesUpdate(resources);
|
||||||
|
});
|
||||||
onGatherStart();
|
onGatherStart();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
@ -40,7 +41,7 @@ export default function GatherResourcesButton({ pet, onGatherStart, onGatherComp
|
|||||||
interval = setInterval(async () => {
|
interval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
const resources = await getPetGatheredResources(pet.id);
|
const resources = await getPetGatheredResources(pet.id);
|
||||||
setGatheredResources(resources);
|
onResourcesUpdate(resources);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to check gathered resources:', error);
|
console.error('Failed to check gathered resources:', error);
|
||||||
}
|
}
|
||||||
@ -55,13 +56,13 @@ export default function GatherResourcesButton({ pet, onGatherStart, onGatherComp
|
|||||||
}, [isGathering, pet.id]);
|
}, [isGathering, pet.id]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsGathering(isGatheringAction(pet.petAction));
|
setIsGathering(isGatheringAction(pet.petGatherAction));
|
||||||
}, [pet.petAction]);
|
}, [pet.petGatherAction]);
|
||||||
|
|
||||||
const handleGatherStart = async (resourceType: string) => {
|
const handleGatherStart = async (resourceType: string) => {
|
||||||
if (resourceType === 'stop') {
|
if (resourceType === 'stop') {
|
||||||
try {
|
try {
|
||||||
await updatePetAction(pet.id, { petActionGather: 'IDLE' });
|
await updatePetAction(pet.id, { gatherAction: 'IDLE' });
|
||||||
setIsGathering(false);
|
setIsGathering(false);
|
||||||
onGatherComplete(pet);
|
onGatherComplete(pet);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -76,7 +77,7 @@ export default function GatherResourcesButton({ pet, onGatherStart, onGatherComp
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const petAction = resourceToActionMap[resourceType];
|
const petAction = resourceToActionMap[resourceType];
|
||||||
const updatedPet = await updatePetAction(pet.id, { petActionGather: petAction });
|
const updatedPet = await updatePetAction(pet.id, { gatherAction: petAction });
|
||||||
onGatherComplete(updatedPet);
|
onGatherComplete(updatedPet);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to gather resources:', error);
|
console.error('Failed to gather resources:', error);
|
||||||
@ -85,17 +86,7 @@ export default function GatherResourcesButton({ pet, onGatherStart, onGatherComp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCollect = async () => {
|
const currentResource = getResourceFromAction(pet.petGatherAction);
|
||||||
try {
|
|
||||||
const updatedPet = await putPetCollectResources(pet.id);
|
|
||||||
setGatheredResources({ wisdom: 0, gold: 0, food: 0, junk: 0 });
|
|
||||||
onGatherComplete(updatedPet);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to collect resources:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const currentResource = getResourceFromAction(pet.petAction);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -114,12 +105,6 @@ export default function GatherResourcesButton({ pet, onGatherStart, onGatherComp
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<CollectResourcesButton
|
|
||||||
petId={pet.id}
|
|
||||||
resources={gatheredResources}
|
|
||||||
onCollect={handleCollect}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ResourceSelectionModal
|
<ResourceSelectionModal
|
||||||
isOpen={isModalOpen}
|
isOpen={isModalOpen}
|
||||||
onClose={() => setIsModalOpen(false)}
|
onClose={() => setIsModalOpen(false)}
|
||||||
|
@ -1,45 +1,119 @@
|
|||||||
import { Pizza, PlayCircle, Moon, Paintbrush } from 'lucide-react';
|
import { Pizza, PlayCircle, Moon } from 'lucide-react';
|
||||||
import GatherResourcesButton from './GatherResourcesButton';
|
import GatherResourcesButton from './GatherResourcesButton';
|
||||||
import { Pet } from '../types/Pet';
|
import CollectResourcesButton from './CollectResourcesButton';
|
||||||
import { useState } from 'react';
|
import { Pet, Resources } from '../types/Pet';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { updatePetAction } from '../services/api/api';
|
||||||
|
import { PetBasicAction } from '../types/PetUpdateActionRequest';
|
||||||
|
import ActionButton from './button/ActionButton';
|
||||||
|
|
||||||
interface InteractionMenuProps {
|
interface InteractionMenuProps {
|
||||||
pet: Pet;
|
pet: Pet;
|
||||||
onPetUpdate: (updatedPet: Pet) => void;
|
onPetUpdate: (updatedPet: Pet) => void;
|
||||||
onFeed: () => void;
|
|
||||||
onPlay: () => void;
|
|
||||||
onSleep: () => void;
|
|
||||||
onCustomize: () => void;
|
onCustomize: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function InteractionMenu({ pet, onPetUpdate, onFeed, onPlay, onSleep, onCustomize }: InteractionMenuProps) {
|
export default function InteractionMenu({ pet, onPetUpdate }: InteractionMenuProps) {
|
||||||
|
const [gatheredResources, setGatheredResources] = useState<Resources>({ wisdom: 0, gold: 0, food: 0, junk: 0 });
|
||||||
|
const [remainingCooldown, setRemainingCooldown] = useState<number | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateCooldown = () => {
|
||||||
|
if (!pet.basicActionCooldown) {
|
||||||
|
setRemainingCooldown(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cooldownTime = new Date(pet.basicActionCooldown).getTime();
|
||||||
|
const now = new Date().getTime();
|
||||||
|
const remaining = Math.max(0, cooldownTime - now);
|
||||||
|
|
||||||
|
if (remaining === 0) {
|
||||||
|
setRemainingCooldown(null);
|
||||||
|
} else {
|
||||||
|
setRemainingCooldown(remaining);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateCooldown();
|
||||||
|
const interval = setInterval(updateCooldown, 1000);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [pet.basicActionCooldown]);
|
||||||
|
|
||||||
|
const formatCooldownTime = (ms: number) => {
|
||||||
|
const minutes = Math.floor(ms / 60000);
|
||||||
|
const seconds = Math.floor((ms % 60000) / 1000);
|
||||||
|
|
||||||
|
if (minutes > 0) {
|
||||||
|
return `${minutes} minute${minutes > 1 ? 's' : ''} remaining`;
|
||||||
|
}
|
||||||
|
return `${seconds} second${seconds > 1 ? 's' : ''} remaining`;
|
||||||
|
};
|
||||||
|
|
||||||
const handleGatherComplete = (updatedPet: Pet) => {
|
const handleGatherComplete = (updatedPet: Pet) => {
|
||||||
onPetUpdate(updatedPet);
|
onPetUpdate(updatedPet);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ActionButton = ({ icon: Icon, label, onClick, color }: { icon: any; label: string; onClick: () => void; color: string }) => (
|
const handleResourcesUpdate = (resources: Resources) => {
|
||||||
<button
|
setGatheredResources(resources);
|
||||||
onClick={onClick}
|
};
|
||||||
className={`flex items-center justify-center space-x-2 bg-${color}-900/30
|
|
||||||
hover:bg-${color}-800/50 border-2 border-${color}-500/50 rounded-lg p-4
|
const handleCollect = () => {
|
||||||
transition-all duration-300 transform hover:scale-105 w-full`}
|
setGatheredResources({ wisdom: 0, gold: 0, food: 0, junk: 0 });
|
||||||
>
|
};
|
||||||
<Icon className="w-6 h-6" />
|
|
||||||
<span>{label}</span>
|
function performBasicAction(basicAction: PetBasicAction): () => void {
|
||||||
</button>
|
return async () => {
|
||||||
);
|
try {
|
||||||
|
const updatedPet = await updatePetAction(pet.id, { basicAction: basicAction });
|
||||||
|
onPetUpdate(updatedPet);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to perform basic action:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||||
<ActionButton icon={Pizza} label="Feed" onClick={onFeed} color="green" />
|
{remainingCooldown !== null && (
|
||||||
<ActionButton icon={PlayCircle} label="Play" onClick={onPlay} color="blue" />
|
<div className="col-span-2 md:col-span-3 text-center p-2 bg-yellow-900/30 border-2 border-yellow-500/50 rounded-lg">
|
||||||
<ActionButton icon={Moon} label="Sleep" onClick={onSleep} color="purple" />
|
<span className="text-yellow-200">Cooldown: {formatCooldownTime(remainingCooldown)}</span>
|
||||||
{/* <ActionButton icon={Paintbrush} label="Customize (coming soon...)" onClick={onCustomize} color="pink" /> */}
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ActionButton
|
||||||
|
icon={Pizza}
|
||||||
|
label="Feed"
|
||||||
|
onClick={performBasicAction('FEED')}
|
||||||
|
color="green"
|
||||||
|
disabled={remainingCooldown !== null}
|
||||||
|
/>
|
||||||
|
<ActionButton
|
||||||
|
icon={PlayCircle}
|
||||||
|
label="Play"
|
||||||
|
onClick={performBasicAction('PLAY')}
|
||||||
|
color="blue"
|
||||||
|
disabled={remainingCooldown !== null}
|
||||||
|
/>
|
||||||
|
<ActionButton
|
||||||
|
icon={Moon}
|
||||||
|
label="Sleep"
|
||||||
|
onClick={performBasicAction('SLEEP')}
|
||||||
|
color="purple"
|
||||||
|
disabled={remainingCooldown !== null}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="col-span-2 md:col-span-3">
|
<div className="col-span-2 md:col-span-3">
|
||||||
<GatherResourcesButton
|
<GatherResourcesButton
|
||||||
pet={pet}
|
pet={pet}
|
||||||
onGatherStart={() => console.log('Gathering started')}
|
onGatherStart={() => console.log('Gathering started')}
|
||||||
onGatherComplete={handleGatherComplete}
|
onGatherComplete={handleGatherComplete}
|
||||||
|
onResourcesUpdate={handleResourcesUpdate}
|
||||||
|
/>
|
||||||
|
<CollectResourcesButton
|
||||||
|
petId={pet.id}
|
||||||
|
resources={gatheredResources}
|
||||||
|
onCollect={handleCollect}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
67
src/components/PetRegister.tsx
Normal file
67
src/components/PetRegister.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import ClassSelection from './ClassSelection';
|
||||||
|
import NameModal from './modal/NameModal';
|
||||||
|
import ConfirmationModal from './modal/ConfirmationModal';
|
||||||
|
import { PetClassInfo } from '../types/Pet';
|
||||||
|
import { createPet } from '../services/api/api';
|
||||||
|
|
||||||
|
interface PetRegisterProps {
|
||||||
|
onPetCreated: (newPet: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PetRegister({ onPetCreated }: PetRegisterProps) {
|
||||||
|
const [showConfirmation, setShowConfirmation] = useState(false);
|
||||||
|
const [showNameModal, setShowNameModal] = useState(false);
|
||||||
|
const [petName, setPetName] = useState('');
|
||||||
|
const [selectedClass, setSelectedClass] = useState<{ key: string; info: PetClassInfo } | null>(null);
|
||||||
|
|
||||||
|
const handleClassSelect = (classKey: string, classInfo: PetClassInfo) => {
|
||||||
|
setSelectedClass({ key: classKey, info: classInfo });
|
||||||
|
setShowConfirmation(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
if (!selectedClass) return;
|
||||||
|
setShowConfirmation(false);
|
||||||
|
setShowNameModal(true);
|
||||||
|
setPetName('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNameSubmit = async () => {
|
||||||
|
if (!selectedClass || !petName.trim()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const newPet = await createPet({
|
||||||
|
name: petName.trim(),
|
||||||
|
class: selectedClass.key,
|
||||||
|
});
|
||||||
|
onPetCreated(newPet);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating pet:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gray-900 text-white">
|
||||||
|
{showNameModal && selectedClass ? (
|
||||||
|
<NameModal
|
||||||
|
selectedClass={selectedClass}
|
||||||
|
petName={petName}
|
||||||
|
setPetName={setPetName}
|
||||||
|
handleNameSubmit={handleNameSubmit}
|
||||||
|
setShowNameModal={setShowNameModal}
|
||||||
|
setSelectedClass={setSelectedClass}
|
||||||
|
/>
|
||||||
|
) : showConfirmation && selectedClass ? (
|
||||||
|
<ConfirmationModal
|
||||||
|
selectedClass={selectedClass}
|
||||||
|
handleConfirm={handleConfirm}
|
||||||
|
setShowConfirmation={setShowConfirmation}
|
||||||
|
setSelectedClass={setSelectedClass}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ClassSelection onSelect={handleClassSelect} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
25
src/components/button/ActionButton.tsx
Normal file
25
src/components/button/ActionButton.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
interface ActionButtonProps {
|
||||||
|
icon: LucideIcon;
|
||||||
|
label: string;
|
||||||
|
onClick: () => void;
|
||||||
|
color: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ActionButton({ icon: Icon, label, onClick, color, disabled }: ActionButtonProps) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={onClick}
|
||||||
|
disabled={disabled}
|
||||||
|
className={`flex items-center justify-center space-x-2 bg-${color}-900/30
|
||||||
|
hover:bg-${color}-800/50 border-2 border-${color}-500/50 rounded-lg p-4
|
||||||
|
transition-all duration-300 transform hover:scale-105 w-full
|
||||||
|
${disabled ? 'opacity-50 cursor-not-allowed' : ''}`}
|
||||||
|
>
|
||||||
|
<Icon className="w-6 h-6" />
|
||||||
|
<span>{label}</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Brain, Coins, Pizza, X, Loader2, StopCircle } from 'lucide-react';
|
import { Brain, Coins, Pizza, X, StopCircle } from 'lucide-react';
|
||||||
import { Pet } from '../../types/Pet';
|
import { Pet } from '../../types/Pet';
|
||||||
import { formatResourceName, getResourceFromAction } from '../../utils/petUtils';
|
import { formatResourceName, getResourceFromAction } from '../../utils/petUtils';
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ export default function ResourceSelectionModal({
|
|||||||
return Math.floor(baseStat * multiplier);
|
return Math.floor(baseStat * multiplier);
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentResource = getResourceFromAction(pet.petAction);
|
const currentResource = getResourceFromAction(pet.petGatherAction);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-50">
|
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-50">
|
||||||
|
@ -28,7 +28,7 @@ export async function createPet(data: PetCreationRequest): Promise<Pet> {
|
|||||||
|
|
||||||
export async function updatePetAction(petId: string, data: PetUpdateActionRequest): Promise<Pet> {
|
export async function updatePetAction(petId: string, data: PetUpdateActionRequest): Promise<Pet> {
|
||||||
try {
|
try {
|
||||||
const response = await api.put<Pet>(`/api/v1/pet/${petId}/action/gather`, data);
|
const response = await api.put<Pet>(`/api/v1/pet/${petId}/action`, data);
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Failed to update pet action:', error.message);
|
console.error('Failed to update pet action:', error.message);
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
// Example usage of the API service
|
|
||||||
import { ApiService } from './index';
|
|
||||||
import { Pet } from '../../types/Pet';
|
|
||||||
|
|
||||||
// Get API service instance
|
|
||||||
const api = ApiService.getInstance();
|
|
||||||
|
|
||||||
// Example functions using the API service
|
|
||||||
export async function getPet(id: string) {
|
|
||||||
try {
|
|
||||||
const response = await api.get<Pet>(`/pets/${id}`);
|
|
||||||
return response.data;
|
|
||||||
} catch (error: any) {
|
|
||||||
if (api.isNetworkError(error)) {
|
|
||||||
console.error('Network error occurred');
|
|
||||||
} else if (api.isTimeoutError(error)) {
|
|
||||||
console.error('Request timed out');
|
|
||||||
} else if (api.isServerError(error)) {
|
|
||||||
console.error('Server error occurred');
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updatePet(id: string, data: Partial<Pet>) {
|
|
||||||
try {
|
|
||||||
const response = await api.put<Pet>(`/pets/${id}`, data);
|
|
||||||
return response.data;
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('Failed to update pet:', error.message);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function gatherResources(id: string, resourceType: string) {
|
|
||||||
try {
|
|
||||||
const response = await api.post<{ success: boolean }>(`/pets/${id}/gather`, {
|
|
||||||
resourceType,
|
|
||||||
});
|
|
||||||
return response.data;
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('Failed to gather resources:', error.message);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { PetAction } from "./PetUpdateActionRequest";
|
import { PetBasicAction, PetGatherAction } from "./PetUpdateActionRequest";
|
||||||
|
|
||||||
export type PetClass = 'FOREST_SPIRIT' | 'OCEAN_GUARDIAN' | 'FIRE_ELEMENTAL' | 'MYTHICAL_BEAST' | 'SHADOW_WALKER' | 'CYBER_PET' | 'BIO_MECHANICAL';
|
export type PetClass = 'FOREST_SPIRIT' | 'OCEAN_GUARDIAN' | 'FIRE_ELEMENTAL' | 'MYTHICAL_BEAST' | 'SHADOW_WALKER' | 'CYBER_PET' | 'BIO_MECHANICAL';
|
||||||
|
|
||||||
@ -6,6 +6,9 @@ export interface PetStats {
|
|||||||
intelligence: number;
|
intelligence: number;
|
||||||
strength: number;
|
strength: number;
|
||||||
charisma: number;
|
charisma: number;
|
||||||
|
maxIntelligence: number;
|
||||||
|
maxStrength: number;
|
||||||
|
maxCharisma: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Resources {
|
export interface Resources {
|
||||||
@ -22,7 +25,9 @@ export interface Pet {
|
|||||||
stats: PetStats;
|
stats: PetStats;
|
||||||
resources: Resources;
|
resources: Resources;
|
||||||
level: number;
|
level: number;
|
||||||
petAction: PetAction;
|
petBasicAction: PetBasicAction;
|
||||||
|
basicActionCooldown: Date;
|
||||||
|
petGatherAction: PetGatherAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PetClassInfo {
|
export interface PetClassInfo {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
export type PetAction = 'IDLE' | 'GATHERING_WISDOM' | 'GATHERING_GOLD' | 'GATHERING_FOOD';
|
export type PetBasicAction = 'UNKNOWN' | 'FEED' | 'PLAY' | 'SLEEP';
|
||||||
|
export type PetGatherAction = 'IDLE' | 'GATHERING_WISDOM' | 'GATHERING_GOLD' | 'GATHERING_FOOD';
|
||||||
|
|
||||||
export interface PetUpdateActionRequest {
|
export interface PetUpdateActionRequest {
|
||||||
petActionGather: PetAction;
|
basicAction?: PetBasicAction;
|
||||||
|
gatherAction?: PetGatherAction;
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
import { PetAction } from '../types/PetUpdateActionRequest';
|
import { PetGatherAction } from '../types/PetUpdateActionRequest';
|
||||||
|
|
||||||
export function isGatheringAction(action: PetAction): boolean {
|
export function isGatheringAction(action: PetGatherAction): boolean {
|
||||||
return action.startsWith('GATHERING_');
|
return action.startsWith('GATHERING_');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getResourceFromAction(action: PetAction): string | null {
|
export function getResourceFromAction(action: PetGatherAction): string | null {
|
||||||
if (!isGatheringAction(action)) return null;
|
if (!isGatheringAction(action)) return null;
|
||||||
return action.replace('GATHERING_', '').toLowerCase();
|
return action.replace('GATHERING_', '').toLowerCase();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user