refactor: clean up imports, fix typos, and enhance pet action handling

This commit is contained in:
José Henrique 2025-02-01 13:50:27 -03:00
parent f133e18302
commit 8875eb75af
14 changed files with 341 additions and 113 deletions

View File

@ -1,7 +1,9 @@
import React, { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import ClassSelection from './components/ClassSelection'; 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 ConfirmationModal from './components/modal/ConfirmationModal';
import { Pet, PetClassInfo } from './types/Pet'; import { Pet, PetClassInfo } from './types/Pet';
import { fetchPets, createPet } from './services/api/api'; import { fetchPets, createPet } from './services/api/api';
@ -56,7 +58,7 @@ export default function App() {
const handleFeed = () => { const handleFeed = () => {
if (!pet) return; if (!pet) return;
setPet({ const updatedPet = {
...pet, ...pet,
stats: { stats: {
...pet.stats, ...pet.stats,
@ -66,12 +68,13 @@ export default function App() {
...pet.resources, ...pet.resources,
food: Math.max(0, pet.resources.food - 10) food: Math.max(0, pet.resources.food - 10)
} }
}); };
handlePetUpdate(updatedPet);
}; };
const handlePlay = () => { const handlePlay = () => {
if (!pet) return; if (!pet) return;
setPet({ const updatedPet = {
...pet, ...pet,
stats: { stats: {
...pet.stats, ...pet.stats,
@ -81,104 +84,50 @@ export default function App() {
...pet.resources, ...pet.resources,
wisdom: pet.resources.wisdom + 5 wisdom: pet.resources.wisdom + 5
} }
}); };
handlePetUpdate(updatedPet);
}; };
const handleSleep = () => { const handleSleep = () => {
if (!pet) return; if (!pet) return;
setPet({ const updatedPet = {
...pet, ...pet,
stats: { stats: {
intelligence: Math.min(100, pet.stats.intelligence + 5), intelligence: Math.min(100, pet.stats.intelligence + 5),
strength: Math.min(100, pet.stats.strength + 2), strength: Math.min(100, pet.stats.strength + 2),
charisma: Math.min(100, pet.stats.charisma + 2) charisma: Math.min(100, pet.stats.charisma + 2)
} }
}); };
handlePetUpdate(updatedPet);
}; };
const handleCustomize = () => { const handleCustomize = () => {
console.log('Customize pet'); console.log('Customize pet');
}; };
const handlePetUpdate = (updatedPet: Pet) => {
setPet(updatedPet);
};
if (!pet) { if (!pet) {
return ( return (
<div className="min-h-screen bg-gray-900 text-white"> <div className="min-h-screen bg-gray-900 text-white">
{showNameModal && selectedClass ? ( {showNameModal && selectedClass ? (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"> <NameModal
<div className="bg-gray-800 p-6 rounded-xl max-w-md w-full"> selectedClass={selectedClass}
<h2 className="text-2xl font-bold mb-2">Name Your Pet</h2> petName={petName}
<p className="text-gray-400 mb-6"> setPetName={setPetName}
Creating a new {selectedClass.info.name.toLowerCase()} pet handleNameSubmit={handleNameSubmit}
</p> setShowNameModal={setShowNameModal}
<div className="space-y-4"> setSelectedClass={setSelectedClass}
<div>
<label htmlFor="petName" className="block text-sm font-medium text-gray-300 mb-2">
Pet Name
</label>
<input
type="text"
id="petName"
value={petName}
onChange={(e) => setPetName(e.target.value)}
className="w-full px-4 py-2 bg-gray-700 border border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="Enter a name for your pet"
autoFocus
/> />
</div>
<div className="flex space-x-4">
<button
onClick={handleNameSubmit}
disabled={!petName.trim()}
className={`flex-1 px-4 py-2 rounded-lg ${
petName.trim()
? 'bg-blue-600 hover:bg-blue-700'
: 'bg-blue-600/50 cursor-not-allowed'
}`}
>
Create Pet
</button>
<button
onClick={() => {
setShowNameModal(false);
setSelectedClass(null);
}}
className="flex-1 px-4 py-2 bg-gray-600 hover:bg-gray-700 rounded-lg"
>
Cancel
</button>
</div>
</div>
</div>
</div>
) : showConfirmation && selectedClass ? ( ) : showConfirmation && selectedClass ? (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center p-4"> <ConfirmationModal
<div className="bg-gray-800 p-6 rounded-xl max-w-md w-full"> selectedClass={selectedClass}
<h2 className="text-2xl font-bold mb-4">Confirm Selection</h2> handleConfirm={handleConfirm}
<p className="mb-4">Are you sure you want to choose {selectedClass.info.name}?</p> setShowConfirmation={setShowConfirmation}
<div className="space-y-2 mb-6"> setSelectedClass={setSelectedClass}
{selectedClass.info.modifiers.map((modifier, index) => ( />
<div key={index} className="text-sm text-gray-300"> {modifier}</div>
))}
</div>
<div className="flex space-x-4">
<button
onClick={handleConfirm}
className="flex-1 bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded"
>
Confirm
</button>
<button
onClick={() => {
setShowConfirmation(false);
setSelectedClass(null);
}}
className="flex-1 bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded"
>
Cancel
</button>
</div>
</div>
</div>
) : ( ) : (
<ClassSelection onSelect={handleClassSelect} /> <ClassSelection onSelect={handleClassSelect} />
)} )}
@ -192,6 +141,7 @@ export default function App() {
<PetDisplay pet={pet} /> <PetDisplay pet={pet} />
<InteractionMenu <InteractionMenu
pet={pet} pet={pet}
onPetUpdate={handlePetUpdate}
onFeed={handleFeed} onFeed={handleFeed}
onPlay={handlePlay} onPlay={handlePlay}
onSleep={handleSleep} onSleep={handleSleep}

View File

@ -1,4 +1,3 @@
import React from 'react';
import { PET_CLASSES } from '../data/petClasses'; import { PET_CLASSES } from '../data/petClasses';
import { PetClassInfo } from '../types/Pet'; import { PetClassInfo } from '../types/Pet';

View File

@ -0,0 +1,40 @@
import { Resources } from '../types/Pet';
import { putPetCollectResources } from '../services/api/api';
interface CollectResourcesButtonProps {
petId: string;
resources: Resources;
onCollect: () => void;
}
export default function CollectResourcesButton({ petId, resources, onCollect }: CollectResourcesButtonProps) {
const hasResources = Object.values(resources).some(value => value > 0);
if (!hasResources) return null;
const handleCollect = async () => {
try {
await putPetCollectResources(petId);
onCollect();
} catch (error) {
console.error('Failed to collect resources:', error);
}
};
return (
<button
onClick={handleCollect}
className="flex items-center justify-center space-x-2
bg-green-900/30 hover:bg-green-800/50
border-2 border-green-500/50 rounded-lg p-4
transition-all duration-300 transform hover:scale-105 w-full mt-2"
>
<span>
Collect: {Object.entries(resources)
.filter(([_, value]) => value > 0)
.map(([key, value]) => `${value} ${key}`)
.join(', ')}
</span>
</button>
);
}

View File

@ -1,14 +1,16 @@
import React, { useState } from 'react'; import { useState, useEffect } from 'react';
import { FeatherIcon as GatherIcon } from 'lucide-react'; import { FeatherIcon as GatherIcon } from 'lucide-react';
import ResourceSelectionModal from './ResourceSelectionModal'; import ResourceSelectionModal from './modal/ResourceSelectionModal';
import { Pet } from '../types/Pet'; import CollectResourcesButton from './CollectResourcesButton';
import { updatePetAction } from '../services/api/api'; import { Pet, Resources } from '../types/Pet';
import { updatePetAction, getPetGatheredResources, putPetCollectResources } from '../services/api/api';
import { PetAction } from '../types/PetUpdateActionRequest'; import { PetAction } from '../types/PetUpdateActionRequest';
import { isGatheringAction, formatResourceName, getResourceFromAction } from '../utils/petUtils';
interface GatherResourcesButtonProps { interface GatherResourcesButtonProps {
pet: Pet; pet: Pet;
onGatherStart: () => void; onGatherStart: () => void;
onGatherComplete: () => void; onGatherComplete: (updatedPet: Pet) => void;
} }
const resourceToActionMap: Record<string, PetAction> = { const resourceToActionMap: Record<string, PetAction> = {
@ -19,39 +21,105 @@ const resourceToActionMap: Record<string, PetAction> = {
export default function GatherResourcesButton({ pet, onGatherStart, onGatherComplete }: GatherResourcesButtonProps) { export default function GatherResourcesButton({ pet, onGatherStart, onGatherComplete }: GatherResourcesButtonProps) {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [isGathering, setIsGathering] = useState(false); const [isGathering, setIsGathering] = useState(isGatheringAction(pet.petAction));
const [gatheredResources, setGatheredResources] = useState<Resources>({ wisdom: 0, gold: 0, food: 0, junk: 0 });
// Initialize gathering check if pet is already gathering
useEffect(() => {
if (isGatheringAction(pet.petAction)) {
setIsGathering(true);
const resources = getPetGatheredResources(pet.id).then(setGatheredResources);
onGatherStart();
}
}, []);
useEffect(() => {
let interval: number;
if (isGathering) {
interval = setInterval(async () => {
try {
const resources = await getPetGatheredResources(pet.id);
setGatheredResources(resources);
} catch (error) {
console.error('Failed to check gathered resources:', error);
}
}, 10000);
}
return () => {
if (interval) {
clearInterval(interval);
}
};
}, [isGathering, pet.id]);
useEffect(() => {
setIsGathering(isGatheringAction(pet.petAction));
}, [pet.petAction]);
const handleGatherStart = async (resourceType: string) => { const handleGatherStart = async (resourceType: string) => {
if (resourceType === 'stop') {
try {
await updatePetAction(pet.id, { petActionGather: 'IDLE' });
setIsGathering(false);
onGatherComplete(pet);
} catch (error) {
console.error('Failed to stop gathering:', error);
}
setIsModalOpen(false);
return;
}
setIsGathering(true); setIsGathering(true);
onGatherStart(); onGatherStart();
try { try {
const petAction = resourceToActionMap[resourceType]; const petAction = resourceToActionMap[resourceType];
await updatePetAction(pet.id, { petAction }); const updatedPet = await updatePetAction(pet.id, { petActionGather: petAction });
onGatherComplete(); onGatherComplete(updatedPet);
} catch (error) { } catch (error) {
console.error('Failed to gather resources:', error); console.error('Failed to gather resources:', error);
} finally { } finally {
setIsGathering(false);
setIsModalOpen(false); setIsModalOpen(false);
} }
}; };
const handleCollect = async () => {
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>
<button <button
onClick={() => setIsModalOpen(true)} onClick={() => setIsModalOpen(true)}
disabled={isGathering}
className={`flex items-center justify-center space-x-2 className={`flex items-center justify-center space-x-2
bg-amber-900/30 hover:bg-amber-800/50 bg-amber-900/30 hover:bg-amber-800/50
border-2 border-amber-500/50 rounded-lg p-4 border-2 border-amber-500/50 rounded-lg p-4
transition-all duration-300 transform hover:scale-105 w-full transition-all duration-300 transform hover:scale-105 w-full`}
${isGathering ? 'opacity-50 cursor-not-allowed' : ''}`}
> >
<GatherIcon className="w-6 h-6" /> <GatherIcon className="w-6 h-6" />
<span>{isGathering ? 'Gathering...' : 'Gather Resources'}</span> <span>
{isGathering && currentResource
? `Gathering ${formatResourceName(currentResource)}...`
: 'Gather Resources'}
</span>
</button> </button>
<CollectResourcesButton
petId={pet.id}
resources={gatheredResources}
onCollect={handleCollect}
/>
<ResourceSelectionModal <ResourceSelectionModal
isOpen={isModalOpen} isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)} onClose={() => setIsModalOpen(false)}
@ -59,6 +127,6 @@ export default function GatherResourcesButton({ pet, onGatherStart, onGatherComp
pet={pet} pet={pet}
isGathering={isGathering} isGathering={isGathering}
/> />
</> </div>
); );
} }

View File

@ -1,17 +1,22 @@
import React from 'react';
import { Pizza, PlayCircle, Moon, Paintbrush } from 'lucide-react'; import { Pizza, PlayCircle, Moon, Paintbrush } from 'lucide-react';
import GatherResourcesButton from './GatherResourcesButton'; import GatherResourcesButton from './GatherResourcesButton';
import { Pet } from '../types/Pet'; import { Pet } from '../types/Pet';
import { useState } from 'react';
interface InteractionMenuProps { interface InteractionMenuProps {
pet: Pet; pet: Pet;
onPetUpdate: (updatedPet: Pet) => void;
onFeed: () => void; onFeed: () => void;
onPlay: () => void; onPlay: () => void;
onSleep: () => void; onSleep: () => void;
onCustomize: () => void; onCustomize: () => void;
} }
export default function InteractionMenu({ pet, onFeed, onPlay, onSleep, onCustomize }: InteractionMenuProps) { export default function InteractionMenu({ pet, onPetUpdate, onFeed, onPlay, onSleep, onCustomize }: InteractionMenuProps) {
const handleGatherComplete = (updatedPet: Pet) => {
onPetUpdate(updatedPet);
};
const ActionButton = ({ icon: Icon, label, onClick, color }: { icon: any; label: string; onClick: () => void; color: string }) => ( const ActionButton = ({ icon: Icon, label, onClick, color }: { icon: any; label: string; onClick: () => void; color: string }) => (
<button <button
onClick={onClick} onClick={onClick}
@ -29,12 +34,12 @@ export default function InteractionMenu({ pet, onFeed, onPlay, onSleep, onCustom
<ActionButton icon={Pizza} label="Feed" onClick={onFeed} color="green" /> <ActionButton icon={Pizza} label="Feed" onClick={onFeed} color="green" />
<ActionButton icon={PlayCircle} label="Play" onClick={onPlay} color="blue" /> <ActionButton icon={PlayCircle} label="Play" onClick={onPlay} color="blue" />
<ActionButton icon={Moon} label="Sleep" onClick={onSleep} color="purple" /> <ActionButton icon={Moon} label="Sleep" onClick={onSleep} color="purple" />
<ActionButton icon={Paintbrush} label="Customize" onClick={onCustomize} color="pink" /> {/* <ActionButton icon={Paintbrush} label="Customize (coming soon...)" onClick={onCustomize} color="pink" /> */}
<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={() => console.log('Gathering completed')} onGatherComplete={handleGatherComplete}
/> />
</div> </div>
</div> </div>

View File

@ -1,4 +1,3 @@
import React from 'react';
import { Pet } from '../types/Pet'; import { Pet } from '../types/Pet';
import { Brain, Dumbbell, Heart, Sparkles, Coins, Pizza, Trash2 } from 'lucide-react'; import { Brain, Dumbbell, Heart, Sparkles, Coins, Pizza, Trash2 } from 'lucide-react';
import { PET_CLASSES } from '../data/petClasses'; import { PET_CLASSES } from '../data/petClasses';

View File

@ -0,0 +1,46 @@
import { PetClassInfo } from '../../types/Pet';
interface ConfirmationModalProps {
selectedClass: { key: string; info: PetClassInfo };
handleConfirm: () => void;
setShowConfirmation: (show: boolean) => void;
setSelectedClass: (selected: { key: string; info: PetClassInfo } | null) => void;
}
export default function ConfirmationModal({
selectedClass,
handleConfirm,
setShowConfirmation,
setSelectedClass,
}: ConfirmationModalProps) {
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center p-4">
<div className="bg-gray-800 p-6 rounded-xl max-w-md w-full">
<h2 className="text-2xl font-bold mb-4">Confirm Selection</h2>
<p className="mb-4">Are you sure you want to choose {selectedClass.info.name}?</p>
<div className="space-y-2 mb-6">
{selectedClass.info.modifiers.map((modifier, index) => (
<div key={index} className="text-sm text-gray-300"> {modifier}</div>
))}
</div>
<div className="flex space-x-4">
<button
onClick={handleConfirm}
className="flex-1 bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded"
>
Confirm
</button>
<button
onClick={() => {
setShowConfirmation(false);
setSelectedClass(null);
}}
className="flex-1 bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded"
>
Cancel
</button>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,68 @@
import { PetClassInfo } from '../../types/Pet';
interface NameModalProps {
selectedClass: { key: string; info: PetClassInfo };
petName: string;
setPetName: (name: string) => void;
handleNameSubmit: () => void;
setShowNameModal: (show: boolean) => void;
setSelectedClass: (selected: { key: string; info: PetClassInfo } | null) => void;
}
export default function NameModal({
selectedClass,
petName,
setPetName,
handleNameSubmit,
setShowNameModal,
setSelectedClass,
}: NameModalProps) {
return (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4">
<div className="bg-gray-800 p-6 rounded-xl max-w-md w-full">
<h2 className="text-2xl font-bold mb-2">Name Your Pet</h2>
<p className="text-gray-400 mb-6">
Creating a new {selectedClass.info.name.toLowerCase()} pet
</p>
<div className="space-y-4">
<div>
<label htmlFor="petName" className="block text-sm font-medium text-gray-300 mb-2">
Pet Name
</label>
<input
type="text"
id="petName"
value={petName}
onChange={(e) => setPetName(e.target.value)}
className="w-full px-4 py-2 bg-gray-700 border border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="Enter a name for your pet"
autoFocus
/>
</div>
<div className="flex space-x-4">
<button
onClick={handleNameSubmit}
disabled={!petName.trim()}
className={`flex-1 px-4 py-2 rounded-lg ${
petName.trim()
? 'bg-blue-600 hover:bg-blue-700'
: 'bg-blue-600/50 cursor-not-allowed'
}`}
>
Create Pet
</button>
<button
onClick={() => {
setShowNameModal(false);
setSelectedClass(null);
}}
className="flex-1 px-4 py-2 bg-gray-600 hover:bg-gray-700 rounded-lg"
>
Cancel
</button>
</div>
</div>
</div>
</div>
);
}

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { Brain, Coins, Pizza, X, Loader2 } from 'lucide-react'; import { Brain, Coins, Pizza, X, Loader2, StopCircle } from 'lucide-react';
import { Pet } from '../types/Pet'; import { Pet } from '../../types/Pet';
import { formatResourceName, getResourceFromAction } from '../../utils/petUtils';
interface ResourceSelectionModalProps { interface ResourceSelectionModalProps {
isOpen: boolean; isOpen: boolean;
@ -67,19 +68,28 @@ export default function ResourceSelectionModal({
return Math.floor(baseStat * multiplier); return Math.floor(baseStat * multiplier);
}; };
const currentResource = getResourceFromAction(pet.petAction);
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">
<div className="bg-gray-800 rounded-xl max-w-2xl w-full p-6 relative"> <div className="bg-gray-800 rounded-xl max-w-2xl w-full p-6 relative">
<button <button
onClick={onClose} onClick={onClose}
className="absolute top-4 right-4 text-gray-400 hover:text-white" className="absolute top-4 right-4 text-gray-400 hover:text-white"
disabled={isGathering}
> >
<X className="w-6 h-6" /> <X className="w-6 h-6" />
</button> </button>
<h2 className="text-2xl font-bold mb-6 text-white">Gather Resources</h2> <h2 className="text-2xl font-bold mb-6 text-white">Gather Resources</h2>
{isGathering && currentResource && (
<div className="mb-4 p-4 bg-blue-900/30 border-2 border-blue-500/30 rounded-lg">
<p className="text-blue-300">
Currently gathering {formatResourceName(currentResource)}
</p>
</div>
)}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{resourceOptions.map((option) => ( {resourceOptions.map((option) => (
<button <button
@ -110,10 +120,16 @@ export default function ResourceSelectionModal({
</div> </div>
{isGathering && ( {isGathering && (
<div className="mt-4 flex items-center justify-center text-blue-400"> <button
<Loader2 className="w-6 h-6 animate-spin mr-2" /> onClick={() => onGather('stop')}
<span>Gathering resources...</span> className="mt-4 w-full flex items-center justify-center space-x-2
</div> bg-red-900/30 hover:bg-red-800/50
border-2 border-red-500/30 rounded-lg p-4
transition-all duration-300"
>
<StopCircle className="w-6 h-6 text-red-400" />
<span>Stop Gathering</span>
</button>
)} )}
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
import { ApiService } from './index'; import { ApiService } from './index';
import { Pet } from '../../types/Pet'; import { Pet, Resources } from '../../types/Pet';
import { PetCreationRequest } from '../../types/PetCreationRequest'; import { PetCreationRequest } from '../../types/PetCreationRequest';
import { PetUpdateActionRequest } from '../../types/PetUpdateActionRequest'; import { PetUpdateActionRequest } from '../../types/PetUpdateActionRequest';
@ -28,10 +28,30 @@ 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`, data); const response = await api.put<Pet>(`/api/v1/pet/${petId}/action/gather`, 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);
throw error; throw error;
} }
} }
export async function getPetGatheredResources(petId: string): Promise<Resources> {
try {
const response = await api.get<Resources>(`/api/v1/pet/${petId}/resources/gathered`);
return response.data;
} catch (error: any) {
console.error('Failed to fetch pet gathered resources:', error.message);
throw error;
}
}
export async function putPetCollectResources(petId: string): Promise<Pet> {
try {
const response = await api.put<Pet>(`/api/v1/pet/${petId}/resources/collect`);
return response.data;
} catch (error: any) {
console.error('Failed to collect pet gathered resources:', error.message);
throw error;
}
}

View File

@ -1,3 +1,5 @@
import { PetAction } 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';
export interface PetStats { export interface PetStats {
@ -20,6 +22,7 @@ export interface Pet {
stats: PetStats; stats: PetStats;
resources: Resources; resources: Resources;
level: number; level: number;
petAction: PetAction;
} }
export interface PetClassInfo { export interface PetClassInfo {

View File

@ -1,6 +1,6 @@
import { PetClass } from "./Pet"; import { PetClass } from "./Pet";
export interface PetCrationRequest { export interface PetCreationRequest {
name: string; name: string;
class: PetClass; class: PetClass;
} }

View File

@ -1,5 +1,5 @@
export type PetAction = 'IDLE' | 'GATHERING_WISDOM' | 'GATHERING_GOLD' | 'GATHERING_FOOD'; export type PetAction = 'IDLE' | 'GATHERING_WISDOM' | 'GATHERING_GOLD' | 'GATHERING_FOOD';
export interface PetUpdateActionRequest { export interface PetUpdateActionRequest {
petAction: PetAction; petActionGather: PetAction;
} }

14
src/utils/petUtils.ts Normal file
View File

@ -0,0 +1,14 @@
import { PetAction } from '../types/PetUpdateActionRequest';
export function isGatheringAction(action: PetAction): boolean {
return action.startsWith('GATHERING_');
}
export function getResourceFromAction(action: PetAction): string | null {
if (!isGatheringAction(action)) return null;
return action.replace('GATHERING_', '').toLowerCase();
}
export function formatResourceName(resource: string): string {
return resource.charAt(0).toUpperCase() + resource.slice(1);
}