Merge branch 'fix-monsterplant-info-like-habbo' into '@fix/fixes'

Fix monsterplant info like habbo (Issue #72 - Look in !73) (read desc)

See merge request nitro/nitro-react!76
This commit is contained in:
Bill 2022-08-17 23:32:44 +00:00
commit d658907b45
8 changed files with 205 additions and 40 deletions

View File

@ -0,0 +1,9 @@
export const ConvertSeconds = (seconds: number) =>
{
let numDays = Math.floor(seconds / 86400);
let numHours = Math.floor((seconds % 86400) / 3600);
let numMinutes = Math.floor(((seconds % 86400) % 3600) / 60);
let numSeconds = ((seconds % 86400) % 3600) % 60;
return numDays.toString().padStart(2, '0') + ':' + numHours.toString().padStart(2, '0') + ':' + numMinutes.toString().padStart(2, '0') + ':' + numSeconds.toString().padStart(2, '0');
}

View File

@ -1,5 +1,6 @@
export * from './CloneObject';
export * from './ColorUtils';
export * from './ConvertSeconds';
export * from './LocalizeBadgeDescription';
export * from './LocalizeBageName';
export * from './LocalizeFormattedNumber';

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

View File

@ -301,6 +301,19 @@
}
}
.nitro-counter-time {
width: 36px;
height: 28px;
background: url("../assets/images/infostand/countown-timer.png");
div {
line-height: 28px;
text-align: center;
color: $white;
font-weight: bold;
}
}
.avatar-image {
position: relative;
width: 90px;

View File

@ -0,0 +1,65 @@
import { FC, useMemo } from 'react';
import { Base, BaseProps, Column, Flex, Text } from '..';
import { LocalizeText } from '../../api';
interface LayoutCounterTimeViewProps extends BaseProps<HTMLDivElement>
{
day: string;
hour: string;
minutes: string;
seconds: string;
}
export const LayoutCounterTimeView: FC<LayoutCounterTimeViewProps> = props =>
{
const { day = '00', hour = '00', minutes = '00', seconds = '00', classNames = [], children = null, ...rest } = props;
const getClassNames = useMemo(() =>
{
const newClassNames: string[] = [ 'nitro-counter-time' ];
if(classNames.length) newClassNames.push(...classNames);
return newClassNames;
}, [ classNames ]);
return (
<>
<Column gap={ 1 }>
<Flex gap={ 1 }>
<Column>
<Base classNames={ getClassNames } { ...rest }>
<div>{ day != '00' ? day : hour }</div>
{ children }
</Base>
<Text variant="white" small truncate center={ true }>{ day != '00' ? LocalizeText('countdown_clock_unit_days') : LocalizeText('countdown_clock_unit_hours') }</Text>
</Column>
<Column>
<Base style={ { marginTop: '3px' } }>
:
</Base>
</Column>
<Column>
<Base classNames={ getClassNames } { ...rest }>
<div>{ minutes }</div>
{ children }
</Base>
<Text variant="white" small truncate center={ true }>{ LocalizeText('countdown_clock_unit_minutes') }</Text>
</Column>
<Column>
<Base style={ { marginTop: '3px' } }>
:
</Base>
</Column>
<Column>
<Base classNames={ getClassNames } { ...rest }>
<div>{ seconds }</div>
{ children }
</Base>
<Text variant="white" small truncate center={ true }>{ LocalizeText('countdown_clock_unit_seconds') }</Text>
</Column>
</Flex>
</Column>
</>
);
}

View File

@ -1,6 +1,7 @@
export * from './LayoutAvatarImageView';
export * from './LayoutBackgroundImage';
export * from './LayoutBadgeImageView';
export * from './LayoutCounterTimeView';
export * from './LayoutCurrencyIcon';
export * from './LayoutFurniIconImageView';
export * from './LayoutFurniImageView';

View File

@ -70,6 +70,17 @@
}
}
.body-image-plant {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
max-width: 68px;
height: 85px;
max-height: 90px;
border-radius: $border-radius;
}
.badge-image {
width: 45px;
height: 45px;

View File

@ -1,8 +1,8 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { PetRespectComposer, PetType } from '@nitrots/nitro-renderer';
import { FC } from 'react';
import { AvatarInfoPet, CreateLinkEvent, GetConfiguration, LocalizeText, SendMessageComposer } from '../../../../../api';
import { Base, Button, Column, Flex, LayoutPetImageView, Text, UserProfileIconView } from '../../../../../common';
import { FC, useEffect, useState } from 'react';
import { AvatarInfoPet, CreateLinkEvent, GetConfiguration, LocalizeText, SendMessageComposer, ConvertSeconds } from '../../../../../api';
import { Base, Button, Column, Flex, LayoutPetImageView, LayoutRarityLevelView, Text, UserProfileIconView, LayoutCounterTimeView } from '../../../../../common';
import { useRoom, useSessionInfo } from '../../../../../hooks';
interface InfoStandWidgetPetViewProps
@ -14,9 +14,30 @@ interface InfoStandWidgetPetViewProps
export const InfoStandWidgetPetView: FC<InfoStandWidgetPetViewProps> = props =>
{
const { avatarInfo = null, onClose = null } = props;
const [ remainingGrowTime, setRemainingGrowTime ] = useState(0);
const [ remainingTimeToLive, setRemainingTimeToLive ] = useState(0);
const { roomSession = null } = useRoom();
const { petRespectRemaining = 0, respectPet = null } = useSessionInfo();
useEffect(() =>
{
setRemainingGrowTime(avatarInfo.remainingGrowTime);
setRemainingTimeToLive(avatarInfo.remainingTimeToLive);
}, [ avatarInfo ]);
useEffect(() =>
{
if((avatarInfo.petType !== PetType.MONSTERPLANT) || avatarInfo.dead) return;
const interval = setInterval(() =>
{
setRemainingGrowTime(prevValue => (prevValue - 1));
setRemainingTimeToLive(prevValue => (prevValue - 1));
}, 1000);
return () => clearInterval(interval);
}, [ avatarInfo ]);
if(!avatarInfo) return null;
const processButtonAction = (action: string) =>
@ -64,51 +85,95 @@ export const InfoStandWidgetPetView: FC<InfoStandWidgetPetViewProps> = props =>
<Text variant="white" small wrap>{ LocalizeText(`pet.breed.${ avatarInfo.petType }.${ avatarInfo.petBreed }`) }</Text>
<hr className="m-0" />
</Column>
<Column gap={ 1 }>
<Flex gap={ 1 }>
<Column fullWidth overflow="hidden" className="body-image pet p-1">
<LayoutPetImageView figure={ avatarInfo.petFigure } posture={ avatarInfo.posture } direction={ 4 } />
{ (avatarInfo.petType === PetType.MONSTERPLANT) &&
<>
<Column gap={ 1 }>
<Flex gap={ 1 }>
<Column fullWidth overflow="hidden" className="body-image-plant pet p-1">
<LayoutPetImageView figure={ avatarInfo.petFigure } posture={ avatarInfo.posture } direction={ 4 } />
</Column>
{ !avatarInfo.dead &&
<Column grow gap={ 1 }>
<Text variant="white" center small wrap>{ LocalizeText('pet.level', [ 'level', 'maxlevel' ], [ avatarInfo.level.toString(), avatarInfo.maximumLevel.toString() ]) }</Text>
</Column> }
</Flex>
<hr className="m-0" />
</Column>
<Column grow gap={ 1 }>
<Text variant="white" center small wrap>{ LocalizeText('pet.level', [ 'level', 'maxlevel' ], [ avatarInfo.level.toString(), avatarInfo.maximumLevel.toString() ]) }</Text>
<Column gap={ 1 }>
<Column alignItems="center" gap={ 1 }>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.happiness') }</Text>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.wellbeing') }</Text>
<Base fullWidth overflow="hidden" position="relative" className="bg-light-dark rounded">
<Flex fit center position="absolute">
<Text variant="white" small>{ avatarInfo.happyness + '/' + avatarInfo.maximumHappyness }</Text>
<Text variant="white" small>{ avatarInfo.dead ? '00:00:00' : ConvertSeconds((remainingTimeToLive == 0 ? avatarInfo.remainingTimeToLive : remainingTimeToLive)).split(':')[1] + ':' + ConvertSeconds((remainingTimeToLive == null || remainingTimeToLive == undefined ? 0 : remainingTimeToLive)).split(':')[2] + ':' + ConvertSeconds((remainingTimeToLive == null || remainingTimeToLive == undefined ? 0 : remainingTimeToLive)).split(':')[3] }</Text>
</Flex>
<Base className="bg-info rounded pet-stats" style={ { width: (avatarInfo.happyness / avatarInfo.maximumHappyness) * 100 + '%' } } />
<Base className="bg-success rounded pet-stats" style={ { width: avatarInfo.dead ? '0' : Math.round((avatarInfo.maximumTimeToLive * 100) / (remainingTimeToLive)).toString() } } />
</Base>
</Column>
<br /><br />
<br /><br />
{ remainingGrowTime != 0 && remainingGrowTime > 0 &&
<Column alignItems="center" gap={ 1 }>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.growth') }</Text> <br />
<LayoutCounterTimeView className="top-2 end-2" day={ ConvertSeconds(remainingGrowTime).split(':')[0] } hour={ ConvertSeconds(remainingGrowTime).split(':')[1] } minutes={ ConvertSeconds(remainingGrowTime).split(':')[2] } seconds={ ConvertSeconds(remainingGrowTime).split(':')[3] } />
</Column> }
<br /><br />
<br /><br />
<Column alignItems="center" gap={ 1 }>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.experience') }</Text>
<Base fullWidth overflow="hidden" position="relative" className="bg-light-dark rounded">
<Flex fit center position="absolute">
<Text variant="white" small>{ avatarInfo.experience + '/' + avatarInfo.levelExperienceGoal }</Text>
</Flex>
<Base className="bg-purple rounded pet-stats" style={ { width: (avatarInfo.experience / avatarInfo.levelExperienceGoal) * 100 + '%' } } />
</Base>
</Column>
<Column alignItems="center" gap={ 1 }>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.energy') }</Text>
<Base fullWidth overflow="hidden" position="relative" className="bg-light-dark rounded">
<Flex fit center position="absolute">
<Text variant="white" small>{ avatarInfo.energy + '/' + avatarInfo.maximumEnergy }</Text>
</Flex>
<Base className="bg-success rounded pet-stats" style={ { width: (avatarInfo.energy / avatarInfo.maximumEnergy) * 100 + '%' } } />
</Base>
<Text variant="white" small truncate>{ LocalizeText('Nivel de rareza:') }</Text>
<LayoutRarityLevelView className="top-2 end-2" level={ avatarInfo.rarityLevel } />
</Column>
<br /><br />
<Text variant="white" small wrap>{ LocalizeText('pet.age', [ 'age' ], [ avatarInfo.age.toString() ]) }</Text>
<hr className="m-0" />
</Column>
</Flex>
<hr className="m-0" />
</Column>
<Column gap={ 1 }>
{ avatarInfo.petType !== PetType.MONSTERPLANT &&
<Text variant="white" small wrap>{ LocalizeText('infostand.text.petrespect', [ 'count' ], [ avatarInfo.respect.toString() ]) }</Text>
}
<Text variant="white" small wrap>{ LocalizeText('pet.age', [ 'age' ], [ avatarInfo.age.toString() ]) }</Text>
<hr className="m-0" />
</Column>
</> }
{ (avatarInfo.petType !== PetType.MONSTERPLANT) &&
<>
<Column gap={ 1 }>
<Flex gap={ 1 }>
<Column fullWidth overflow="hidden" className="body-image pet p-1">
<LayoutPetImageView figure={ avatarInfo.petFigure } posture={ avatarInfo.posture } direction={ 4 } />
</Column>
<Column grow gap={ 1 }>
<Text variant="white" center small wrap>{ LocalizeText('pet.level', [ 'level', 'maxlevel' ], [ avatarInfo.level.toString(), avatarInfo.maximumLevel.toString() ]) }</Text>
<Column alignItems="center" gap={ 1 }>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.happiness') }</Text>
<Base fullWidth overflow="hidden" position="relative" className="bg-light-dark rounded">
<Flex fit center position="absolute">
<Text variant="white" small>{ avatarInfo.happyness + '/' + avatarInfo.maximumHappyness }</Text>
</Flex>
<Base className="bg-info rounded pet-stats" style={ { width: (avatarInfo.happyness / avatarInfo.maximumHappyness) * 100 + '%' } } />
</Base>
</Column>
<Column alignItems="center" gap={ 1 }>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.experience') }</Text>
<Base fullWidth overflow="hidden" position="relative" className="bg-light-dark rounded">
<Flex fit center position="absolute">
<Text variant="white" small>{ avatarInfo.experience + '/' + avatarInfo.levelExperienceGoal }</Text>
</Flex>
<Base className="bg-purple rounded pet-stats" style={ { width: (avatarInfo.experience / avatarInfo.levelExperienceGoal) * 100 + '%' } } />
</Base>
</Column>
<Column alignItems="center" gap={ 1 }>
<Text variant="white" small truncate>{ LocalizeText('infostand.pet.text.energy') }</Text>
<Base fullWidth overflow="hidden" position="relative" className="bg-light-dark rounded">
<Flex fit center position="absolute">
<Text variant="white" small>{ avatarInfo.energy + '/' + avatarInfo.maximumEnergy }</Text>
</Flex>
<Base className="bg-success rounded pet-stats" style={ { width: (avatarInfo.energy / avatarInfo.maximumEnergy) * 100 + '%' } } />
</Base>
</Column>
</Column>
</Flex>
<hr className="m-0" />
</Column>
<Column gap={ 1 }>
{ (avatarInfo.petType !== PetType.MONSTERPLANT) &&
<Text variant="white" small wrap>{ LocalizeText('infostand.text.petrespect', [ 'count' ], [ avatarInfo.respect.toString() ]) }</Text> }
<Text variant="white" small wrap>{ LocalizeText('pet.age', [ 'age' ], [ avatarInfo.age.toString() ]) }</Text>
<hr className="m-0" />
</Column>
</> }
<Column gap={ 1 }>
<Flex alignItems="center" gap={ 1 }>
<UserProfileIconView userId={ avatarInfo.ownerId } />
@ -128,11 +193,11 @@ export const InfoStandWidgetPetView: FC<InfoStandWidgetPetViewProps> = props =>
<Button variant="dark" onClick={ event => processButtonAction('train') }>
{ LocalizeText('infostand.button.train') }
</Button> }
{ !avatarInfo.dead && ((avatarInfo.energy / avatarInfo.maximumEnergy) < 0.98) && avatarInfo.petType === PetType.MONSTERPLANT &&
{ !avatarInfo.dead && ((avatarInfo.energy / avatarInfo.maximumEnergy) < 0.98) && (avatarInfo.petType === PetType.MONSTERPLANT) &&
<Button variant="dark" onClick={ event => processButtonAction('treat') }>
{ LocalizeText('infostand.button.pettreat') }
</Button> }
{ roomSession?.isRoomOwner && avatarInfo.petType === PetType.MONSTERPLANT &&
{ roomSession?.isRoomOwner && (avatarInfo.petType === PetType.MONSTERPLANT) &&
<Button variant="dark" onClick={ event => processButtonAction('compost') }>
{ LocalizeText('infostand.button.compost') }
</Button> }