import { CreateLinkEvent, PetRespectComposer, PetType } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState, useCallback } from 'react';
import { FaTimes } from 'react-icons/fa';
import { AvatarInfoPet, ConvertSeconds, GetConfigurationValue, LocalizeText, SendMessageComposer } from '../../../../../api';
import { Button, Column, Flex, LayoutCounterTimeView, LayoutPetImageView, LayoutRarityLevelView, Text, UserProfileIconView } from '../../../../../common';
import { useRoom, useSessionInfo } from '../../../../../hooks';
// TypeScript interface for AvatarInfoPet
interface AvatarInfoPet {
id: number;
name: string;
petType: number;
petBreed: number;
petFigure: string;
posture: string;
level: number;
maximumLevel: number;
age: number;
ownerId: number;
ownerName: string;
respect: number;
dead?: boolean;
energy?: number;
maximumEnergy?: number;
happyness?: number;
maximumHappyness?: number;
experience?: number;
levelExperienceGoal?: number;
remainingGrowTime?: number;
remainingTimeToLive?: number;
maximumTimeToLive?: number;
rarityLevel?: number;
isOwner?: boolean;
}
interface InfoStandWidgetPetViewProps {
avatarInfo: AvatarInfoPet;
onClose: () => void;
}
const PetHeader: FC<{ name: string; petType: number; petBreed: number; onClose: () => void }> = ({ name, petType, petBreed, onClose }) => (
{name}
{LocalizeText(`pet.breed.${petType}.${petBreed}`)}
);
const MonsterplantStats: FC<{
avatarInfo: AvatarInfoPet;
remainingGrowTime: number;
remainingTimeToLive: number;
}> = ({ avatarInfo, remainingGrowTime, remainingTimeToLive }) => (
<>
{!avatarInfo.dead && (
{LocalizeText('pet.level', ['level', 'maxlevel'], [avatarInfo.level.toString(), avatarInfo.maximumLevel.toString()])}
)}
{LocalizeText('infostand.pet.text.wellbeing')}
{avatarInfo.dead || remainingTimeToLive <= 0
? '00:00:00'
: `${ConvertSeconds(remainingTimeToLive).split(':')[1]}:${ConvertSeconds(remainingTimeToLive).split(':')[2]}:${ConvertSeconds(remainingTimeToLive).split(':')[3]}`}
{remainingGrowTime > 0 && (
{LocalizeText('infostand.pet.text.growth')}
)}
{LocalizeText('infostand.pet.text.raritylevel', ['level'], [LocalizeText(`infostand.pet.raritylevel.${avatarInfo.rarityLevel}`)])}
{LocalizeText('pet.age', ['age'], [avatarInfo.age.toString()])}
>
);
// Sub-component: Regular Pet Stats
const RegularPetStats: FC<{ avatarInfo: AvatarInfoPet }> = ({ avatarInfo }) => (
<>
{LocalizeText('pet.level', ['level', 'maxlevel'], [avatarInfo.level.toString(), avatarInfo.maximumLevel.toString()])}
{LocalizeText('infostand.pet.text.happiness')}
{avatarInfo.happyness + '/' + avatarInfo.maximumHappyness}
{LocalizeText('infostand.pet.text.experience')}
{avatarInfo.experience + '/' + avatarInfo.levelExperienceGoal}
{LocalizeText('infostand.pet.text.energy')}
{avatarInfo.energy + '/' + avatarInfo.maximumEnergy}
{LocalizeText('infostand.text.petrespect', ['count'], [avatarInfo.respect.toString()])}
{LocalizeText('pet.age', ['age'], [avatarInfo.age.toString()])}
>
);
export const InfoStandWidgetPetView: FC = ({ avatarInfo, onClose }) => {
const [remainingGrowTime, setRemainingGrowTime] = useState(0);
const [remainingTimeToLive, setRemainingTimeToLive] = useState(0);
const { roomSession = null } = useRoom();
const { petRespectRemaining = 0, respectPet = null } = useSessionInfo();
useEffect(() => {
setRemainingGrowTime(avatarInfo.remainingGrowTime || 0);
setRemainingTimeToLive(avatarInfo.remainingTimeToLive || 0);
}, [avatarInfo]);
useEffect(() => {
if (avatarInfo.petType !== PetType.MONSTERPLANT || avatarInfo.dead) return;
const interval = setInterval(() => {
setRemainingGrowTime((prev) => (prev <= 0 ? 0 : prev - 1));
setRemainingTimeToLive((prev) => (prev <= 0 ? 0 : prev - 1));
}, 1000);
return () => clearInterval(interval);
}, [avatarInfo]);
const processButtonAction = useCallback(
async (action: string) => {
try {
let hideMenu = true;
if (!action) return;
switch (action) {
case 'respect':
await respectPet(avatarInfo.id);
if (petRespectRemaining - 1 >= 1) hideMenu = false;
break;
case 'buyfood':
CreateLinkEvent('catalog/open/' + GetConfigurationValue('catalog.links')['pets.buy_food']);
break;
case 'train':
roomSession?.requestPetCommands(avatarInfo.id);
break;
case 'treat':
SendMessageComposer(new PetRespectComposer(avatarInfo.id));
break;
case 'compost':
roomSession?.compostPlant(avatarInfo.id);
break;
case 'pick_up':
roomSession?.pickupPet(avatarInfo.id);
break;
}
if (hideMenu) onClose();
} catch (error) {
console.error(`Failed to process action ${action}:`, error);
}
},
[avatarInfo, petRespectRemaining, respectPet, roomSession, onClose]
);
const buttons = [
{
action: 'buyfood',
label: LocalizeText('infostand.button.buyfood'),
condition: avatarInfo.petType !== PetType.MONSTERPLANT,
},
{
action: 'train',
label: LocalizeText('infostand.button.train'),
condition: avatarInfo.isOwner && avatarInfo.petType !== PetType.MONSTERPLANT,
},
{
action: 'treat',
label: LocalizeText('infostand.button.pettreat'),
condition:
!avatarInfo.dead &&
avatarInfo.petType === PetType.MONSTERPLANT &&
avatarInfo.energy / avatarInfo.maximumEnergy < 0.98,
},
{
action: 'compost',
label: LocalizeText('infostand.button.compost'),
condition: roomSession?.isRoomOwner && avatarInfo.petType === PetType.MONSTERPLANT,
},
{
action: 'pick_up',
label: LocalizeText('inventory.pets.pickup'),
condition: avatarInfo.isOwner,
},
{
action: 'respect',
label: LocalizeText('infostand.button.petrespect', ['count'], [petRespectRemaining.toString()]),
condition: petRespectRemaining > 0 && avatarInfo.petType !== PetType.MONSTERPLANT,
},
];
if (!avatarInfo) return {LocalizeText('generic.loading')};
return (
{avatarInfo.petType === PetType.MONSTERPLANT ? (
) : (
)}
{LocalizeText('infostand.text.petowner', ['name'], [avatarInfo.ownerName])}
{buttons.map(
(button) =>
button.condition && (
)
)}
);
};