mirror of
https://github.com/duckietm/Nitro-Cool-UI.git
synced 2025-06-21 22:36:58 +00:00
Revert "Fix: Inventory Fixes"
This reverts commit ef023e67eef7ef1c711491612733e498cef3bcf0.
This commit is contained in:
parent
ef023e67ee
commit
3e94b7d5c4
@ -1,7 +1,10 @@
|
|||||||
.nitro-inventory {
|
.nitro-inventory {
|
||||||
width: $inventory-width;
|
|
||||||
height: $inventory-height;
|
height: $inventory-height;
|
||||||
min-width: 326px;
|
min-height: $inventory-height;
|
||||||
|
max-height: $inventory-height + 150px;
|
||||||
|
width: $inventory-width;
|
||||||
|
min-width: $inventory-width;
|
||||||
|
max-width: $inventory-width;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@ -11,29 +14,169 @@
|
|||||||
|
|
||||||
&.trading {
|
&.trading {
|
||||||
width: 535px;
|
width: 535px;
|
||||||
min-height: 505px;
|
min-height: $inventory-height + 315px !important;
|
||||||
|
max-width: $inventory-width + 15px !important;
|
||||||
|
min-width: $inventory-width + 15px !important;
|
||||||
|
|
||||||
.trading-inventory {
|
.trading-inventory {
|
||||||
height: 200px;
|
max-height: 240px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.empty-image {
|
.nitro-item-count {
|
||||||
background: url('@/assets/images/inventory/empty.png') no-repeat;
|
top: 0px;
|
||||||
width: 129px;
|
right: -2px;
|
||||||
height: 181px;
|
background-color: white;
|
||||||
}
|
padding: 0px;
|
||||||
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
color: #306A83;
|
||||||
|
border: 1px solid #2F6982;
|
||||||
|
font-weight: normal !important;
|
||||||
|
font-family: Goldfish;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.trade-button {
|
.empty-image {
|
||||||
min-height: 0;
|
background: url("@/assets/images/inventory/empty.png");
|
||||||
font-size: 8px;
|
background-repeat: no-repeat;
|
||||||
padding: 1px 2px;
|
width: 129px;
|
||||||
z-index: 5;
|
height: 181px;
|
||||||
}
|
}
|
||||||
|
.empty-petsimage {
|
||||||
|
background: url("@/assets/images/inventory/petsempty.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 220px;
|
||||||
|
height: 220px;
|
||||||
|
}
|
||||||
|
.empty-furniimage {
|
||||||
|
background: url("@/assets/images/inventory/furniempty.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 220px;
|
||||||
|
height: 220px;
|
||||||
|
}
|
||||||
|
.empty-botsimage {
|
||||||
|
background: url("@/assets/images/inventory/botsempty.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 220px;
|
||||||
|
height: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
.trade-bg {
|
.bubble-inventory {
|
||||||
border-image-source: url(@/assets/images/inventory/trading_bg.png);
|
position: relative;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 5px;
|
||||||
|
width: auto;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 5px;
|
||||||
|
text-align: left;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.bubble-inventory-bottom-left:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 15%;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border: 20px solid transparent;
|
||||||
|
border-top-color: #fff;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-right: 0;
|
||||||
|
margin-left: -10px;
|
||||||
|
margin-bottom: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trade-button {
|
||||||
|
min-height: 0;
|
||||||
|
font-size: 8px;
|
||||||
|
padding: 1px 2px;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trade-bg {
|
||||||
|
border-image-source: url('@/assets/images/inventory/trading_bg.png');
|
||||||
border-image-slice: 15 15 15 15 fill;
|
border-image-slice: 15 15 15 15 fill;
|
||||||
border-image-width: 15px 15px 15px 15px;
|
border-image-width: 15px 15px 15px 15px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-align {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 230px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quantity-input {
|
||||||
|
width: 49px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lock-design-left {
|
||||||
|
margin-left: 21px;
|
||||||
|
margin-right: 33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lock-design-right {
|
||||||
|
margin-left: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divisor {
|
||||||
|
height: 180px;
|
||||||
|
border-left: 2px solid #B4B4B4;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inventory-items {
|
||||||
|
|
||||||
|
border-image-source: url(@/assets/images/inventory/item.png) !important;
|
||||||
|
border-image-slice: 6 6 6 6 fill !important;
|
||||||
|
border-image-width: 6px 6px 6px 6px !important;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-image-source: url(@/assets/images/inventory/selected_item.png) !important;
|
||||||
|
border-image-slice: 6 6 6 6 fill !important;
|
||||||
|
border-image-width: 6px 6px 6px 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.unseen {
|
||||||
|
background-color: #9BCA64;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-item-count {
|
||||||
|
top: 0px;
|
||||||
|
right: -2px;
|
||||||
|
background-color: white;
|
||||||
|
padding: 0px;
|
||||||
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
color: #306A83;
|
||||||
|
border: 1px solid #2F6982;
|
||||||
|
font-weight: normal !important;
|
||||||
|
font-family: Goldfish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calc-wrapper {
|
||||||
|
width: 96%;
|
||||||
|
height: calc(100% - 100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-list-badges {
|
||||||
|
width: 335px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-badges {
|
||||||
|
width: 145px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-inventory-category-filter {
|
||||||
|
background-color: #C9C9C9;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-shadow-around-text {
|
||||||
|
text-shadow: -1px 0 white, 0 1px white, 1px 0 #ececec, 0 -1px white;
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
import { BadgePointLimitsEvent, ILinkEventTracker, IRoomSession, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomPreviewer, RoomSessionEvent } from '@nitrots/nitro-renderer';
|
import { BadgePointLimitsEvent, ILinkEventTracker, IRoomSession, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomPreviewer, RoomSessionEvent } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { AddEventLinkTracker, GetLocalization, GetRoomEngine, isObjectMoverRequested, LocalizeText, RemoveLinkEventTracker, setObjectMoverRequested, UnseenItemCategory } from '../../api';
|
import { AddEventLinkTracker, GetLocalization, GetRoomEngine, GroupItem, LocalizeText, RemoveLinkEventTracker, isObjectMoverRequested, setObjectMoverRequested } from '../../api';
|
||||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
|
||||||
import { useInventoryTrade, useInventoryUnseenTracker, useMessageEvent, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../hooks';
|
import { useInventoryBadges, useInventoryFurni, useInventoryTrade, useInventoryUnseenTracker, useMessageEvent, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../hooks';
|
||||||
|
import { TABS, TAB_BADGES, TAB_BOTS, TAB_FURNITURE, TAB_PETS, UNSEEN_CATEGORIES } from './constants';
|
||||||
|
import { InventoryCategoryFilterView } from './views/InventoryCategoryFilterView';
|
||||||
import { InventoryBadgeView } from './views/badge/InventoryBadgeView';
|
import { InventoryBadgeView } from './views/badge/InventoryBadgeView';
|
||||||
import { InventoryBotView } from './views/bot/InventoryBotView';
|
import { InventoryBotView } from './views/bot/InventoryBotView';
|
||||||
import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView';
|
import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView';
|
||||||
@ -10,12 +12,6 @@ import { InventoryTradeView } from './views/furniture/InventoryTradeView';
|
|||||||
import { InventoryPetView } from './views/pet/InventoryPetView';
|
import { InventoryPetView } from './views/pet/InventoryPetView';
|
||||||
import { InventoryFurnitureDeleteView } from './views/furniture/InventoryFurnitureDeleteView';
|
import { InventoryFurnitureDeleteView } from './views/furniture/InventoryFurnitureDeleteView';
|
||||||
|
|
||||||
const TAB_FURNITURE: string = 'inventory.furni';
|
|
||||||
const TAB_BOTS: string = 'inventory.bots';
|
|
||||||
const TAB_PETS: string = 'inventory.furni.tab.pets';
|
|
||||||
const TAB_BADGES: string = 'inventory.badges';
|
|
||||||
const TABS = [ TAB_FURNITURE, TAB_BOTS, TAB_PETS, TAB_BADGES ];
|
|
||||||
const UNSEEN_CATEGORIES = [ UnseenItemCategory.FURNI, UnseenItemCategory.BOT, UnseenItemCategory.PET, UnseenItemCategory.BADGE ];
|
|
||||||
|
|
||||||
export const InventoryView: FC<{}> = props =>
|
export const InventoryView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
@ -23,8 +19,12 @@ export const InventoryView: FC<{}> = props =>
|
|||||||
const [ currentTab, setCurrentTab ] = useState<string>(TABS[0]);
|
const [ currentTab, setCurrentTab ] = useState<string>(TABS[0]);
|
||||||
const [ roomSession, setRoomSession ] = useState<IRoomSession>(null);
|
const [ roomSession, setRoomSession ] = useState<IRoomSession>(null);
|
||||||
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
|
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
|
||||||
|
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>([]);
|
||||||
|
const [ filteredBadgeCodes, setFilteredBadgeCodes ] = useState<string[]>([]);
|
||||||
const { isTrading = false, stopTrading = null } = useInventoryTrade();
|
const { isTrading = false, stopTrading = null } = useInventoryTrade();
|
||||||
const { getCount = null, resetCategory = null } = useInventoryUnseenTracker();
|
const { getCount = null } = useInventoryUnseenTracker();
|
||||||
|
const { groupItems = [] } = useInventoryFurni();
|
||||||
|
const { badgeCodes = [] } = useInventoryBadges();
|
||||||
|
|
||||||
const onClose = () =>
|
const onClose = () =>
|
||||||
{
|
{
|
||||||
@ -119,36 +119,34 @@ export const InventoryView: FC<{}> = props =>
|
|||||||
if(!isVisible) return null;
|
if(!isVisible) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NitroCardView uniqueKey={ 'inventory' } className={ isTrading ? 'nitro-inventory trading' : 'nitro-inventory' } theme={ isTrading ? 'primary' : '' } >
|
<NitroCardView uniqueKey={ 'inventory' } className={ `${ isTrading ? 'nitro-inventory trading no-resize' : 'nitro-inventory' }` } theme={ isTrading ? 'primary' : '' } >
|
||||||
<NitroCardHeaderView headerText={ LocalizeText('inventory.title') } onCloseClick={ onClose } />
|
<NitroCardHeaderView headerText={ LocalizeText('inventory.title') } onCloseClick={ onClose } />
|
||||||
{ !isTrading &&
|
<>
|
||||||
<>
|
<NitroCardTabsView>
|
||||||
<NitroCardTabsView>
|
{ TABS.map((name, index) =>
|
||||||
{ TABS.map((name, index) =>
|
{
|
||||||
{
|
return (
|
||||||
return (
|
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => setCurrentTab(name) } count={ getCount(UNSEEN_CATEGORIES[index]) }>
|
||||||
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => setCurrentTab(name) } count={ getCount(UNSEEN_CATEGORIES[index]) }>
|
{ LocalizeText(name) }
|
||||||
{ LocalizeText(name) }
|
</NitroCardTabsItemView>
|
||||||
</NitroCardTabsItemView>
|
);
|
||||||
);
|
}) }
|
||||||
}) }
|
</NitroCardTabsView>
|
||||||
</NitroCardTabsView>
|
<NitroCardContentView overflow="hidden">
|
||||||
<NitroCardContentView>
|
{ (currentTab !== TAB_PETS && currentTab !== TAB_BOTS) && <InventoryCategoryFilterView currentTab={ currentTab } groupItems={ groupItems } setGroupItems={ setFilteredGroupItems } badgeCodes={ badgeCodes } setBadgeCodes={ setFilteredBadgeCodes } /> }
|
||||||
{ (currentTab === TAB_FURNITURE ) &&
|
{ (currentTab === TAB_FURNITURE ) &&
|
||||||
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } isTrading={ isTrading } filteredGroupItems={ filteredGroupItems } /> }
|
||||||
{ (currentTab === TAB_BOTS ) &&
|
{ (currentTab === TAB_PETS ) &&
|
||||||
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } isTrading={ isTrading } /> }
|
||||||
{ (currentTab === TAB_PETS ) &&
|
{ (currentTab === TAB_BADGES ) &&
|
||||||
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
|
<InventoryBadgeView filteredBadgeCodes={ filteredBadgeCodes } /> }
|
||||||
{ (currentTab === TAB_BADGES ) &&
|
{ (currentTab === TAB_BOTS ) &&
|
||||||
<InventoryBadgeView /> }
|
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } isTrading={ isTrading } /> }
|
||||||
</NitroCardContentView>
|
|
||||||
</> }
|
{ isTrading && <InventoryTradeView currentTab={ currentTab } setCurrentTab={ (e) => setCurrentTab(e) } cancelTrade={ onClose } /> }
|
||||||
{ isTrading &&
|
</NitroCardContentView>
|
||||||
<NitroCardContentView>
|
|
||||||
<InventoryTradeView cancelTrade={ onClose } />
|
|
||||||
</NitroCardContentView> }
|
|
||||||
<InventoryFurnitureDeleteView />
|
<InventoryFurnitureDeleteView />
|
||||||
</NitroCardView>
|
</>
|
||||||
);
|
</NitroCardView>
|
||||||
|
);
|
||||||
}
|
}
|
@ -1,26 +1,41 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Column, Grid, GridProps, Text } from '../../../common';
|
import { CreateLinkEvent, LocalizeText } from '../../../api';
|
||||||
|
import { Button, Column, Flex, Grid, GridProps, Text } from '../../../common';
|
||||||
|
|
||||||
export interface InventoryCategoryEmptyViewProps extends GridProps
|
export interface InventoryCategoryEmptyViewProps extends GridProps
|
||||||
{
|
{
|
||||||
title: string;
|
title: string;
|
||||||
desc: string;
|
desc: string;
|
||||||
|
isTrading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InventoryCategoryEmptyView: FC<InventoryCategoryEmptyViewProps> = props =>
|
export const InventoryCategoryEmptyView: FC<InventoryCategoryEmptyViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { title = '', desc = '', children = null, ...rest } = props;
|
const { title = '', desc = '', isTrading = false, children = null, ...rest } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid { ...rest }>
|
<Grid {...rest}>
|
||||||
<Column center size={ 5 } overflow="hidden">
|
<Column justifyContent="start" center size={6} overflow="hidden">
|
||||||
<div className="empty-image" />
|
<div className="empty-furniimage" />
|
||||||
</Column>
|
</Column>
|
||||||
<Column justifyContent="center" size={ 7 } overflow="hidden">
|
<Column justifyContent="center" size={6} overflow="hidden">
|
||||||
<Text bold fontSize={ 5 } overflow="unset" truncate>{ title }</Text>
|
<div className="bubble-inventory bubble-inventory-bottom-left">
|
||||||
<Text overflow="auto">{ desc }</Text>
|
<Text fontSize={6} overflow="unset" truncate>
|
||||||
</Column>
|
{title}
|
||||||
{ children }
|
</Text>
|
||||||
</Grid>
|
<Text overflow="auto" fontSize={6}>
|
||||||
);
|
{" "}
|
||||||
}
|
{desc}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className="empty-image" />
|
||||||
|
{ !isTrading &&
|
||||||
|
<Flex gap={ 2 } position="absolute" className="bottom-2">
|
||||||
|
<Button className="py-1" onClick={ () => CreateLinkEvent('catalog/open') }>{ LocalizeText('inventory.open.catalog') }</Button>
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
</Column>
|
||||||
|
{children}
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,40 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { CreateLinkEvent, LocalizeText } from '../../../api';
|
||||||
|
import { Button, Column, Flex, Grid, GridProps, Text } from '../../../common';
|
||||||
|
|
||||||
|
export interface InventoryCategoryEmptyViewBots extends GridProps
|
||||||
|
{
|
||||||
|
title: string;
|
||||||
|
desc: string;
|
||||||
|
isTrading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InventoryCategoryEmptyViewBots: FC< InventoryCategoryEmptyViewBotsProps> = (props) => {
|
||||||
|
const { title = '', desc = '', isTrading = false, children = null, ...rest } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid {...rest}>
|
||||||
|
<Column justifyContent="start" center size={6} overflow="hidden">
|
||||||
|
<div className="empty-botsimage" />
|
||||||
|
</Column>
|
||||||
|
<Column justifyContent="center" size={6} overflow="hidden">
|
||||||
|
<div className="bubble-inventory bubble-inventory-bottom-left">
|
||||||
|
<Text fontSize={6} overflow="unset" truncate>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
<Text overflow="auto" fontSize={6}>
|
||||||
|
{" "}
|
||||||
|
{desc}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className="empty-image" />
|
||||||
|
{ !isTrading &&
|
||||||
|
<Flex gap={ 2 } position="absolute" className="bottom-2">
|
||||||
|
<Button className="py-1" onClick={ () => CreateLinkEvent('catalog/open') }>{ LocalizeText('inventory.open.catalog') }</Button>
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
</Column>
|
||||||
|
{children}
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,40 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { CreateLinkEvent, LocalizeText } from '../../../api';
|
||||||
|
import { Button, Column, Flex, Grid, GridProps, Text } from '../../../common';
|
||||||
|
|
||||||
|
export interface InventoryCategoryEmptyViewPets extends GridProps
|
||||||
|
{
|
||||||
|
title: string;
|
||||||
|
desc: string;
|
||||||
|
isTrading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InventoryCategoryEmptyViewPets: FC< InventoryCategoryEmptyViewBotsProps> = (props) => {
|
||||||
|
const { title = '', desc = '', isTrading = false, children = null, ...rest } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid {...rest}>
|
||||||
|
<Column justifyContent="start" center size={6} overflow="hidden">
|
||||||
|
<div className="empty-petsimage" />
|
||||||
|
</Column>
|
||||||
|
<Column justifyContent="center" size={6} overflow="hidden">
|
||||||
|
<div className="bubble-inventory bubble-inventory-bottom-left">
|
||||||
|
<Text fontSize={6} overflow="unset" truncate>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
<Text overflow="auto" fontSize={6}>
|
||||||
|
{" "}
|
||||||
|
{desc}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className="empty-image" />
|
||||||
|
{ !isTrading &&
|
||||||
|
<Flex gap={ 2 } position="absolute" className="bottom-2">
|
||||||
|
<Button className="py-1" onClick={ () => CreateLinkEvent('catalog/open') }>{ LocalizeText('inventory.open.catalog') }</Button>
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
</Column>
|
||||||
|
{children}
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
107
src/components/inventory/views/InventoryCategoryFilterView.tsx
Normal file
107
src/components/inventory/views/InventoryCategoryFilterView.tsx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react';
|
||||||
|
import { GroupItem, LocalizeBadgeName, LocalizeText } from '../../../api';
|
||||||
|
import { Flex } from '../../../common';
|
||||||
|
import { InventoryFilterType, TAB_BADGES, TAB_FURNITURE } from '../constants';
|
||||||
|
|
||||||
|
export interface InventoryCategoryFilterViewProps
|
||||||
|
{
|
||||||
|
currentTab: string;
|
||||||
|
groupItems: GroupItem[];
|
||||||
|
badgeCodes: string[];
|
||||||
|
setGroupItems: Dispatch<SetStateAction<GroupItem[]>>;
|
||||||
|
setBadgeCodes: Dispatch<SetStateAction<string[]>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InventoryCategoryFilterView: FC<InventoryCategoryFilterViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { currentTab = null, groupItems = [], badgeCodes = [], setGroupItems = null, setBadgeCodes = null } = props;
|
||||||
|
const [ filterType, setFilterType ] = useState<string>(InventoryFilterType.EVERYTHING);
|
||||||
|
const [ filterPlace, setFilterPlace ] = useState<string>(InventoryFilterType.IN_INVENTORY);
|
||||||
|
const [ searchValue, setSearchValue ] = useState('');
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if (currentTab !== TAB_BADGES) return;
|
||||||
|
|
||||||
|
let filteredBadgeCodes = [ ...badgeCodes ];
|
||||||
|
|
||||||
|
const filteredBadges = badgeCodes.filter( badge => badge.startsWith('ACH_') );
|
||||||
|
|
||||||
|
const numberMap = {};
|
||||||
|
|
||||||
|
filteredBadges.forEach(badge =>
|
||||||
|
{
|
||||||
|
const name = badge.split(/[\d]+/)[0];
|
||||||
|
const number = Number(badge.replace(name, ''));
|
||||||
|
|
||||||
|
if (numberMap[name] === undefined || number > numberMap[name])
|
||||||
|
{
|
||||||
|
numberMap[name] = number;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const allBadges = Object.keys(numberMap).map( name => `${ name }${ numberMap[name] }` ).concat( badgeCodes.filter( badge => !badge.startsWith('ACH_') ) );
|
||||||
|
|
||||||
|
filteredBadgeCodes = allBadges.filter(badgeCode =>
|
||||||
|
{
|
||||||
|
return LocalizeBadgeName(badgeCode).toLocaleLowerCase().includes(searchValue?.toLocaleLowerCase().replace(' ', ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
setBadgeCodes(filteredBadgeCodes);
|
||||||
|
|
||||||
|
}, [ badgeCodes, currentTab, searchValue, setBadgeCodes ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if (currentTab !== TAB_FURNITURE) return;
|
||||||
|
|
||||||
|
let filteredGroupItems = [ ...groupItems ];
|
||||||
|
|
||||||
|
const comparison = searchValue.toLocaleLowerCase();
|
||||||
|
|
||||||
|
if (filterType === InventoryFilterType.EVERYTHING) return setGroupItems(groupItems.filter( item => item.name.toLocaleLowerCase().includes(comparison) ));
|
||||||
|
|
||||||
|
filteredGroupItems = groupItems.filter(item =>
|
||||||
|
{
|
||||||
|
const isWallFilter = (filterType === InventoryFilterType.WALL) ? item.isWallItem : false;
|
||||||
|
const isFloorFilter = (filterType === InventoryFilterType.FLOOR) ? !item.isWallItem : false;
|
||||||
|
const isSearchFilter = (item.name.toLocaleLowerCase().includes(comparison)) ? true : false;
|
||||||
|
|
||||||
|
return comparison && comparison.length ? (isSearchFilter && (isWallFilter || isFloorFilter)) : isWallFilter || isFloorFilter;
|
||||||
|
});
|
||||||
|
|
||||||
|
setGroupItems(filteredGroupItems);
|
||||||
|
}, [ groupItems, setGroupItems, searchValue, filterType, currentTab ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setFilterType(InventoryFilterType.EVERYTHING);
|
||||||
|
setFilterPlace(InventoryFilterType.IN_INVENTORY);
|
||||||
|
setSearchValue('');
|
||||||
|
}, [ currentTab ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex className="nitro-inventory-category-filter rounded p-1 mt-n1" style={ { width: currentTab === TAB_BADGES ? '320px' : '100%' } }>
|
||||||
|
<Flex className="position-relative">
|
||||||
|
<Flex fullWidth alignItems="center" position="relative">
|
||||||
|
<input type="text" className="form-control form-control-sm" value={ searchValue } onChange={ event => setSearchValue(event.target.value) } />
|
||||||
|
</Flex>
|
||||||
|
{ (searchValue && !!searchValue.length) && <i className="icon icon-clear position-absolute cursor-pointer end-1 top-1" onClick={ event => setSearchValue('') } /> }
|
||||||
|
</Flex>
|
||||||
|
{ (currentTab !== TAB_BADGES) &&
|
||||||
|
<>
|
||||||
|
<Flex alignItems="center" position="relative" className="ms-2">
|
||||||
|
<select className="form-select form-select-sm" value={ filterType } onChange={ event => setFilterType(event.target.value) }>
|
||||||
|
{ [ InventoryFilterType.EVERYTHING, InventoryFilterType.FLOOR, InventoryFilterType.WALL ].map((type, index) => <option key={ index } value={ type }>{ LocalizeText(type) }</option>) }
|
||||||
|
</select>
|
||||||
|
</Flex>
|
||||||
|
<Flex alignItems="center" position="relative" className="ms-2">
|
||||||
|
<select className="form-select form-select-sm" value={ filterPlace } onChange={ event => setFilterPlace(event.target.value) } disabled={ currentTab === TAB_FURNITURE }>
|
||||||
|
{ [ InventoryFilterType.ANYWHERE, InventoryFilterType.IN_ROOM, InventoryFilterType.IN_INVENTORY ].map((type, index) => <option key={ index } value={ type }>{ LocalizeText(type) }</option>) }
|
||||||
|
</select>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
@ -11,7 +11,7 @@ export const InventoryBadgeItemView: FC<PropsWithChildren<{ badgeCode: string }>
|
|||||||
const unseen = isUnseen(UnseenItemCategory.BADGE, getBadgeId(badgeCode));
|
const unseen = isUnseen(UnseenItemCategory.BADGE, getBadgeId(badgeCode));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutGridItem itemActive={ (selectedBadgeCode === badgeCode) } itemUnseen={ unseen } onMouseDown={ event => setSelectedBadgeCode(badgeCode) } onDoubleClick={ event => toggleBadge(selectedBadgeCode) } { ...rest }>
|
<LayoutGridItem className="badge-container" itemActive={ (selectedBadgeCode === badgeCode) } itemUnseen={ unseen } onMouseDown={ event => setSelectedBadgeCode(badgeCode) } onDoubleClick={ event => toggleBadge(selectedBadgeCode) } { ...rest }>
|
||||||
<LayoutBadgeImageView badgeCode={ badgeCode } />
|
<LayoutBadgeImageView badgeCode={ badgeCode } />
|
||||||
{ children }
|
{ children }
|
||||||
</LayoutGridItem>
|
</LayoutGridItem>
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { LocalizeBadgeName, LocalizeText, UnseenItemCategory } from '../../../../api';
|
import { LocalizeBadgeName, LocalizeText, UnseenItemCategory } from '../../../../api';
|
||||||
import { AutoGrid, Button, Column, Flex, Grid, LayoutBadgeImageView, Text } from '../../../../common';
|
import { AutoGrid, Button, Column, Flex, Grid, LayoutBadgeImageView, Text } from '../../../../common';
|
||||||
import { useInventoryBadges, useInventoryUnseenTracker } from '../../../../hooks';
|
import { useAchievements, useInventoryBadges, useInventoryUnseenTracker } from '../../../../hooks';
|
||||||
import { InventoryBadgeItemView } from './InventoryBadgeItemView';
|
import { InventoryBadgeItemView } from './InventoryBadgeItemView';
|
||||||
|
|
||||||
export const InventoryBadgeView: FC<{}> = props =>
|
interface InventoryBadgeViewProps
|
||||||
{
|
{
|
||||||
|
filteredBadgeCodes: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InventoryBadgeView: FC<InventoryBadgeViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { filteredBadgeCodes = [] } = props;
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const { badgeCodes = [], activeBadgeCodes = [], selectedBadgeCode = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, getBadgeId = null, activate = null, deactivate = null } = useInventoryBadges();
|
const { activeBadgeCodes = [], selectedBadgeCode = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, getBadgeId = null, activate = null, deactivate = null } = useInventoryBadges();
|
||||||
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
||||||
|
const { achievementScore = 0 } = useAchievements();
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@ -34,33 +41,41 @@ export const InventoryBadgeView: FC<{}> = props =>
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid>
|
<div className="badge-wrapper calc-wrapper mt-n2">
|
||||||
<Column size={ 7 } overflow="hidden">
|
<Grid gap={ 1 }>
|
||||||
<AutoGrid columnCount={ 4 }>
|
<Column overflow="hidden" className="size-list-badges mt-1">
|
||||||
{ badgeCodes && (badgeCodes.length > 0) && badgeCodes.map((badgeCode, index) =>
|
<AutoGrid gap={ 1 } columnCount={ 5 }>
|
||||||
{
|
{ filteredBadgeCodes && filteredBadgeCodes.length > 0 && filteredBadgeCodes.map((badgeCode, index) =>
|
||||||
if(isWearingBadge(badgeCode)) return null;
|
{
|
||||||
|
if (isWearingBadge(badgeCode)) return null;
|
||||||
|
|
||||||
return <InventoryBadgeItemView key={ index } badgeCode={ badgeCode } />
|
return <InventoryBadgeItemView key={ index } badgeCode={ badgeCode } />;
|
||||||
}) }
|
}) }
|
||||||
</AutoGrid>
|
|
||||||
</Column>
|
|
||||||
<Column className="justify-content-between" size={ 5 } overflow="auto">
|
|
||||||
<Column overflow="hidden" gap={ 2 }>
|
|
||||||
<Text>{ LocalizeText('inventory.badges.activebadges') }</Text>
|
|
||||||
<AutoGrid columnCount={ 3 }>
|
|
||||||
{ activeBadgeCodes && (activeBadgeCodes.length > 0) && activeBadgeCodes.map((badgeCode, index) => <InventoryBadgeItemView key={ index } badgeCode={ badgeCode } />) }
|
|
||||||
</AutoGrid>
|
</AutoGrid>
|
||||||
</Column>
|
</Column>
|
||||||
|
<Column className="justify-content-between size-badges position-absolute end-2 mt-n4" overflow="auto">
|
||||||
|
<Column overflow="hidden">
|
||||||
|
<Text center bold>{ LocalizeText('inventory.badges.activebadges') }</Text>
|
||||||
|
<AutoGrid gap={ 1 } columnCount={ 5 }>
|
||||||
|
{ activeBadgeCodes && (activeBadgeCodes.length > 0) && activeBadgeCodes.map((badgeCode, index) => <InventoryBadgeItemView key={ index } badgeCode={ badgeCode } />) }
|
||||||
|
</AutoGrid>
|
||||||
|
</Column>
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
<Column gap={ 0 } position="absolute" className="bottom-2" style={ { width: '96%' } }>
|
||||||
{ !!selectedBadgeCode &&
|
{ !!selectedBadgeCode &&
|
||||||
<Column grow justifyContent="end" gap={ 2 }>
|
<Flex className="bg-white pb-1 px-2 rounded mt-2" style={ { height: '50px' } } justifyContent={ 'between' } alignItems={ 'end' } gap={ 2 }>
|
||||||
<Flex alignItems="center" gap={ 2 }>
|
<Flex alignItems="start" gap={ 2 }>
|
||||||
<LayoutBadgeImageView shrink badgeCode={ selectedBadgeCode } />
|
<LayoutBadgeImageView shrink badgeCode={ selectedBadgeCode } />
|
||||||
<Text>{ LocalizeBadgeName(selectedBadgeCode) }</Text>
|
<Text className="font-bold mt-2">{ LocalizeBadgeName(selectedBadgeCode) }</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Button disabled={ !isWearingBadge(selectedBadgeCode) && !canWearBadges() } onClick={ event => toggleBadge(selectedBadgeCode) }>{ LocalizeText(isWearingBadge(selectedBadgeCode) ? 'inventory.badges.clearbadge' : 'inventory.badges.wearbadge') }</Button>
|
<Button className="btn btn-primary mb-1" style={ { fontSize: '12px' } } disabled={ !isWearingBadge(selectedBadgeCode) && !canWearBadges() } onClick={ event => toggleBadge(selectedBadgeCode) }>{ LocalizeText(isWearingBadge(selectedBadgeCode) ? 'inventory.badges.clearbadge' : 'inventory.badges.wearbadge') }</Button>
|
||||||
</Column> }
|
</Flex>
|
||||||
|
}
|
||||||
|
<div className="nitro-progress-bar text-white mt-1">
|
||||||
|
<Text small center style={ { marginTop: '-1px' } }>{ LocalizeText('achievements.categories.score', [ 'score' ], [ achievementScore.toString() ]) }</Text>
|
||||||
|
</div>
|
||||||
</Column>
|
</Column>
|
||||||
</Grid>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,43 +1,58 @@
|
|||||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
import { MouseEventType } from "@nitrots/nitro-renderer";
|
||||||
import { FC, MouseEvent, PropsWithChildren, useState } from 'react';
|
import { FC, MouseEvent, PropsWithChildren, useState } from "react";
|
||||||
import { attemptBotPlacement, IBotItem, UnseenItemCategory } from '../../../../api';
|
import {
|
||||||
import { LayoutAvatarImageView, LayoutGridItem } from '../../../../common';
|
attemptBotPlacement,
|
||||||
import { useInventoryBots, useInventoryUnseenTracker } from '../../../../hooks';
|
IBotItem,
|
||||||
|
UnseenItemCategory,
|
||||||
|
} from "../../../../api";
|
||||||
|
import { LayoutAvatarImageView, LayoutGridItem } from "../../../../common";
|
||||||
|
import { useInventoryBots, useInventoryUnseenTracker } from "../../../../hooks";
|
||||||
|
|
||||||
export const InventoryBotItemView: FC<PropsWithChildren<{ botItem: IBotItem }>> = props =>
|
export const InventoryBotItemView: FC<
|
||||||
{
|
PropsWithChildren<{ botItem: IBotItem }>
|
||||||
const { botItem = null, children = null, ...rest } = props;
|
> = (props) => {
|
||||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
const { botItem = null, children = null, ...rest } = props;
|
||||||
const { selectedBot = null, setSelectedBot = null } = useInventoryBots();
|
const [isMouseDown, setMouseDown] = useState(false);
|
||||||
const { isUnseen = null } = useInventoryUnseenTracker();
|
const { selectedBot = null, setSelectedBot = null } = useInventoryBots();
|
||||||
const unseen = isUnseen(UnseenItemCategory.BOT, botItem.botData.id);
|
const { isUnseen = null } = useInventoryUnseenTracker();
|
||||||
|
const unseen = isUnseen(UnseenItemCategory.BOT, botItem.botData.id);
|
||||||
|
|
||||||
const onMouseEvent = (event: MouseEvent) =>
|
const onMouseEvent = (event: MouseEvent) => {
|
||||||
{
|
switch (event.type) {
|
||||||
switch(event.type)
|
case MouseEventType.MOUSE_DOWN:
|
||||||
{
|
setSelectedBot(botItem);
|
||||||
case MouseEventType.MOUSE_DOWN:
|
setMouseDown(true);
|
||||||
setSelectedBot(botItem);
|
return;
|
||||||
setMouseDown(true);
|
case MouseEventType.MOUSE_UP:
|
||||||
return;
|
setMouseDown(false);
|
||||||
case MouseEventType.MOUSE_UP:
|
return;
|
||||||
setMouseDown(false);
|
case MouseEventType.ROLL_OUT:
|
||||||
return;
|
if (!isMouseDown || selectedBot !== botItem) return;
|
||||||
case MouseEventType.ROLL_OUT:
|
|
||||||
if(!isMouseDown || (selectedBot !== botItem)) return;
|
|
||||||
|
|
||||||
attemptBotPlacement(botItem);
|
attemptBotPlacement(botItem);
|
||||||
return;
|
return;
|
||||||
case 'dblclick':
|
case "dblclick":
|
||||||
attemptBotPlacement(botItem);
|
attemptBotPlacement(botItem);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutGridItem itemActive={ (selectedBot === botItem) } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest }>
|
<LayoutGridItem
|
||||||
<LayoutAvatarImageView figure={ botItem.botData.figure } direction={ 3 } headOnly={ true } />
|
itemActive={selectedBot === botItem}
|
||||||
{ children }
|
itemUnseen={unseen}
|
||||||
</LayoutGridItem>
|
onMouseDown={onMouseEvent}
|
||||||
);
|
onMouseUp={onMouseEvent}
|
||||||
}
|
onMouseOut={onMouseEvent}
|
||||||
|
onDoubleClick={onMouseEvent}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
<LayoutAvatarImageView
|
||||||
|
figure={botItem.botData.figure}
|
||||||
|
direction={3}
|
||||||
|
headOnly={true}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</LayoutGridItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { attemptBotPlacement, GetRoomEngine, LocalizeText, UnseenItemCategory } from '../../../../api';
|
import { GetRoomEngine, LocalizeText, UnseenItemCategory, attemptBotPlacement } from '../../../../api';
|
||||||
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
|
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
|
||||||
import { useInventoryBots, useInventoryUnseenTracker } from '../../../../hooks';
|
import { useInventoryBots, useInventoryUnseenTracker } from '../../../../hooks';
|
||||||
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
|
import { InventoryCategoryEmptyViewBots } from '../InventoryCategoryEmptyViewBots';
|
||||||
import { InventoryBotItemView } from './InventoryBotItemView';
|
import { InventoryBotItemView } from './InventoryBotItemView';
|
||||||
|
|
||||||
interface InventoryBotViewProps
|
interface InventoryBotViewProps
|
||||||
{
|
{
|
||||||
roomSession: IRoomSession;
|
roomSession: IRoomSession;
|
||||||
roomPreviewer: RoomPreviewer;
|
roomPreviewer: RoomPreviewer;
|
||||||
|
isTrading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InventoryBotView: FC<InventoryBotViewProps> = props =>
|
export const InventoryBotView: FC<InventoryBotViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { roomSession = null, roomPreviewer = null } = props;
|
const { roomSession = null, roomPreviewer = null, isTrading = false } = props;
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const { botItems = [], selectedBot = null, activate = null, deactivate = null } = useInventoryBots();
|
const { botItems = [], selectedBot = null, activate = null, deactivate = null } = useInventoryBots();
|
||||||
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
||||||
@ -64,7 +65,7 @@ export const InventoryBotView: FC<InventoryBotViewProps> = props =>
|
|||||||
return () => setIsVisible(false);
|
return () => setIsVisible(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if(!botItems || !botItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } />;
|
if(!botItems || !botItems.length) return <InventoryCategoryEmptyViewBots title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } isTrading={ isTrading } />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid>
|
<Grid>
|
||||||
@ -81,7 +82,7 @@ export const InventoryBotView: FC<InventoryBotViewProps> = props =>
|
|||||||
<Column grow justifyContent="between" gap={ 2 }>
|
<Column grow justifyContent="between" gap={ 2 }>
|
||||||
<Text grow truncate>{ selectedBot.botData.name }</Text>
|
<Text grow truncate>{ selectedBot.botData.name }</Text>
|
||||||
{ !!roomSession &&
|
{ !!roomSession &&
|
||||||
<Button onClick={ event => attemptBotPlacement(selectedBot) }>
|
<Button variant="success" onClick={ event => attemptBotPlacement(selectedBot) }>
|
||||||
{ LocalizeText('inventory.furni.placetoroom') }
|
{ LocalizeText('inventory.furni.placetoroom') }
|
||||||
</Button> }
|
</Button> }
|
||||||
</Column> }
|
</Column> }
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
import { MouseEventType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, MouseEvent, useState } from 'react';
|
import { FC, MouseEvent, useState } from 'react';
|
||||||
import { attemptItemPlacement, GroupItem } from '../../../../api';
|
import { GroupItem, attemptItemPlacement } from '../../../../api';
|
||||||
import { LayoutGridItem } from '../../../../common';
|
import { LayoutGridItem } from '../../../../common';
|
||||||
import { useInventoryFurni } from '../../../../hooks';
|
import { useInventoryFurni } from '../../../../hooks';
|
||||||
|
|
||||||
export const InventoryFurnitureItemView: FC<{ groupItem: GroupItem }> = props =>
|
export const InventoryFurnitureItemView: FC<{ groupItem: GroupItem, isTrading: boolean, attemptItemOffer: (count: number) => void, setGroupItem: (item: GroupItem) => void }> = props =>
|
||||||
{
|
{
|
||||||
const { groupItem = null, ...rest } = props;
|
const { groupItem = null, isTrading = null, attemptItemOffer = null, setGroupItem = null, ...rest } = props;
|
||||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
const [ isMouseDown, setMouseDown ] = useState(false);
|
||||||
const { selectedItem = null, setSelectedItem = null } = useInventoryFurni();
|
const { selectedItem = null, setSelectedItem = null } = useInventoryFurni();
|
||||||
|
|
||||||
@ -24,15 +24,16 @@ export const InventoryFurnitureItemView: FC<{ groupItem: GroupItem }> = props =>
|
|||||||
case MouseEventType.ROLL_OUT:
|
case MouseEventType.ROLL_OUT:
|
||||||
if(!isMouseDown || !(groupItem === selectedItem)) return;
|
if(!isMouseDown || !(groupItem === selectedItem)) return;
|
||||||
|
|
||||||
attemptItemPlacement(groupItem);
|
if (!isTrading) attemptItemPlacement(groupItem);
|
||||||
return;
|
return;
|
||||||
case 'dblclick':
|
case 'dblclick':
|
||||||
attemptItemPlacement(groupItem);
|
if (!isTrading) attemptItemPlacement(groupItem);
|
||||||
|
if (isTrading) (setGroupItem(groupItem), attemptItemOffer(1))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const count = groupItem.getUnlockedCount();
|
const count = groupItem.getUnlockedCount();
|
||||||
|
|
||||||
return <LayoutGridItem className={ !count ? 'opacity-0-5 ' : '' } itemImage={ groupItem.iconUrl } itemCount={ groupItem.getUnlockedCount() } itemActive={ (groupItem === selectedItem) } itemUniqueNumber={ groupItem.stuffData.uniqueNumber } itemUnseen={ groupItem.hasUnseenItems } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest } />;
|
return <LayoutGridItem className={ !count ? 'inventory-items opacity-0-5 ' : 'inventory-items' } itemImage={ groupItem.iconUrl } itemCount={ groupItem.getUnlockedCount() } itemActive={ (groupItem === selectedItem) } itemUniqueNumber={ groupItem.stuffData.uniqueNumber } itemUnseen={ groupItem.hasUnseenItems } onClick={ event => (count && setGroupItem(groupItem)) } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest } />;
|
||||||
}
|
}
|
||||||
|
@ -1,158 +1,49 @@
|
|||||||
import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer';
|
import { AdvancedMap } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { FaChevronLeft, FaChevronRight, FaLock, FaUnlock } from 'react-icons/fa';
|
import { GroupItem, LocalizeText, TradeState } from '../../../../api';
|
||||||
import { FurniCategory, getGuildFurniType, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, SendMessageComposer, TradeState } from '../../../../api';
|
|
||||||
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
|
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
|
||||||
import { useInventoryTrade, useNotification } from '../../../../hooks';
|
import { useInventoryTrade } from '../../../../hooks';
|
||||||
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
|
import { MAX_ITEMS_TO_TRADE, TABS, TAB_FURNITURE } from '../../constants';
|
||||||
|
|
||||||
interface InventoryTradeViewProps
|
interface InventoryTradeViewProps
|
||||||
{
|
{
|
||||||
|
currentTab: string;
|
||||||
|
setCurrentTab: (value: string) => void;
|
||||||
cancelTrade: () => void;
|
cancelTrade: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_ITEMS_TO_TRADE: number = 9;
|
|
||||||
|
|
||||||
export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { cancelTrade = null } = props;
|
const { currentTab = null, setCurrentTab = null, cancelTrade = null } = props;
|
||||||
const [ groupItem, setGroupItem ] = useState<GroupItem>(null);
|
|
||||||
const [ ownGroupItem, setOwnGroupItem ] = useState<GroupItem>(null);
|
const [ ownGroupItem, setOwnGroupItem ] = useState<GroupItem>(null);
|
||||||
const [ otherGroupItem, setOtherGroupItem ] = useState<GroupItem>(null);
|
const [ otherGroupItem, setOtherGroupItem ] = useState<GroupItem>(null);
|
||||||
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null);
|
|
||||||
const [ countdownTick, setCountdownTick ] = useState(3);
|
const [ countdownTick, setCountdownTick ] = useState(3);
|
||||||
const [ quantity, setQuantity ] = useState<number>(1);
|
const { ownUser = null, otherUser = null, tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useInventoryTrade();
|
||||||
const { ownUser = null, otherUser = null, groupItems = [], tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useInventoryTrade();
|
|
||||||
const { simpleAlert = null } = useNotification();
|
|
||||||
|
|
||||||
const canTradeItem = (isWallItem: boolean, spriteId: number, category: number, groupable: boolean, stuffData: IObjectData) =>
|
|
||||||
{
|
|
||||||
if(!ownUser || ownUser.accepts || !ownUser.userItems) return false;
|
|
||||||
|
|
||||||
if(ownUser.userItems.length < MAX_ITEMS_TO_TRADE) return true;
|
|
||||||
|
|
||||||
if(!groupable) return false;
|
|
||||||
|
|
||||||
let type = spriteId.toString();
|
|
||||||
|
|
||||||
if(category === FurniCategory.POSTER)
|
|
||||||
{
|
|
||||||
type = ((type + 'poster') + stuffData.getLegacyString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(category === FurniCategory.GUILD_FURNI)
|
|
||||||
{
|
|
||||||
type = getGuildFurniType(spriteId, stuffData);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
type = (((isWallItem) ? 'I' : 'S') + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !!ownUser.userItems.getValue(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
const attemptItemOffer = (count: number) =>
|
|
||||||
{
|
|
||||||
if(!groupItem) return;
|
|
||||||
|
|
||||||
const tradeItems = groupItem.getTradeItems(count);
|
|
||||||
|
|
||||||
if(!tradeItems || !tradeItems.length) return;
|
|
||||||
|
|
||||||
let coreItem: IFurnitureItem = null;
|
|
||||||
const itemIds: number[] = [];
|
|
||||||
|
|
||||||
for(const item of tradeItems)
|
|
||||||
{
|
|
||||||
itemIds.push(item.id);
|
|
||||||
|
|
||||||
if(!coreItem) coreItem = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ownItemCount = ownUser.userItems.length;
|
|
||||||
|
|
||||||
if((ownItemCount + itemIds.length) <= 1500)
|
|
||||||
{
|
|
||||||
if(!coreItem.isGroupable && (itemIds.length))
|
|
||||||
{
|
|
||||||
SendMessageComposer(new TradingListAddItemComposer(itemIds.pop()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const tradeIds: number[] = [];
|
|
||||||
|
|
||||||
for(const itemId of itemIds)
|
|
||||||
{
|
|
||||||
if(canTradeItem(coreItem.isWallItem, coreItem.type, coreItem.category, coreItem.isGroupable, coreItem.stuffData))
|
|
||||||
{
|
|
||||||
tradeIds.push(itemId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tradeIds.length)
|
|
||||||
{
|
|
||||||
if(tradeIds.length === 1)
|
|
||||||
{
|
|
||||||
SendMessageComposer(new TradingListAddItemComposer(tradeIds.pop()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SendMessageComposer(new TradingListAddItemsComposer(...tradeIds));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
simpleAlert(LocalizeText('trading.items.too_many_items.desc'), NotificationAlertType.DEFAULT, null, null, LocalizeText('trading.items.too_many_items.title'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getLockIcon = (accepts: boolean) =>
|
const getLockIcon = (accepts: boolean) =>
|
||||||
{
|
{
|
||||||
if(accepts)
|
if(accepts)
|
||||||
{
|
{
|
||||||
return <FaLock className="mt-auto pb-5 text-success fa-icon" />
|
return <Base className="mt-auto mb-5 pb-5 icon icon-lock-locked" />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return <FaUnlock className="mt-auto pb-5 text-danger fa-icon" />
|
return <Base className="mt-auto mb-5 pb-5 icon icon-lock-open" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateQuantity = (value: number, totalItemCount: number) =>
|
const getTotalCredits = (items: AdvancedMap<string, GroupItem>): number =>
|
||||||
{
|
{
|
||||||
if(isNaN(Number(value)) || Number(value) < 0 || !value) value = 1;
|
return items.getValues().map( item => Number(item.iconUrl.split('/')[item.iconUrl.split('/').length - 1]?.split('_')[1]) * item.items.length ).reduce((acc, cur) => acc + (isNaN(cur) ? 0 : cur), 0);
|
||||||
|
|
||||||
value = Math.max(Number(value), 1);
|
|
||||||
value = Math.min(Number(value), totalItemCount);
|
|
||||||
|
|
||||||
if(value === quantity) return;
|
|
||||||
|
|
||||||
setQuantity(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeCount = (totalItemCount: number) =>
|
|
||||||
{
|
|
||||||
updateQuantity(quantity, totalItemCount);
|
|
||||||
attemptItemOffer(quantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
setQuantity(1);
|
|
||||||
}, [ groupItem ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
if(tradeState !== TradeState.TRADING_STATE_COUNTDOWN) return;
|
if(tradeState !== TradeState.TRADING_STATE_COUNTDOWN) return;
|
||||||
|
|
||||||
setCountdownTick(3);
|
setCountdownTick(3);
|
||||||
|
|
||||||
const interval = setInterval(() =>
|
const interval = window.setInterval(() =>
|
||||||
{
|
{
|
||||||
setCountdownTick(prevValue =>
|
setCountdownTick(prevValue =>
|
||||||
{
|
{
|
||||||
@ -178,102 +69,93 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Column>
|
<Column>
|
||||||
<Flex>
|
<Column fullWidth size={ 12 } overflow="hidden" className="trade-bg p-2 text-black">
|
||||||
<Column size={ 4 } fullWidth overflow="hidden" className="trading-inventory">
|
{ currentTab === TAB_FURNITURE &&
|
||||||
<InventoryFurnitureSearchView groupItems={ groupItems } setGroupItems={ setFilteredGroupItems } />
|
<>
|
||||||
<Flex column fullHeight fullWidth justifyContent="between" overflow="hidden" gap={ 2 }>
|
<Text small>{ LocalizeText('inventory.trading.info.add') }</Text>
|
||||||
<AutoGrid columnCount={ 3 }>
|
<Grid gap={ 0 } overflow="hidden" className="px-2">
|
||||||
{ filteredGroupItems && (filteredGroupItems.length > 0) && filteredGroupItems.map((item, index) =>
|
<Column size={ 4 } overflow="hidden">
|
||||||
{
|
<Flex>
|
||||||
const count = item.getUnlockedCount();
|
{ (ownUser.accepts) && <Base className="icon icon-confirmed" /> }
|
||||||
|
<small className={ ownUser.accepts ? 'px-2' : '' }><b>{ LocalizeText('inventory.trading.you') }</b> { LocalizeText('inventory.trading.areoffering') }</small>
|
||||||
|
</Flex>
|
||||||
|
<AutoGrid columnCount={ 3 } columnMinWidth={ 35 } columnMinHeight={ 35 }>
|
||||||
|
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
||||||
|
{
|
||||||
|
const item = (ownUser.userItems.getWithIndex(i) || null);
|
||||||
|
|
||||||
return (
|
if(!item) return <LayoutGridItem key={ i } />;
|
||||||
<LayoutGridItem key={ index } className={ !count ? 'opacity-0-5 ' : '' } itemImage={ item.iconUrl } itemCount={ count } itemActive={ (groupItem === item) } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => (count && setGroupItem(item)) } onDoubleClick={ event => attemptItemOffer(1) }>
|
|
||||||
{ ((count > 0) && (groupItem === item)) &&
|
return (
|
||||||
<Button position="absolute" variant="success" className="trade-button bottom-1 end-1" onClick={ event => attemptItemOffer(1) }>
|
<LayoutGridItem key={ i } itemActive={ (ownGroupItem === item) } itemImage={ item.iconUrl } itemCount={ item.getTotalCount() } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => setOwnGroupItem(item) } onDoubleClick={ event => removeItem(item) }>
|
||||||
<FaChevronRight className="fa-icon" />
|
{ (ownGroupItem === item) &&
|
||||||
</Button>
|
<Base position="absolute" onClick={ event => removeItem(item) } /> }
|
||||||
}
|
</LayoutGridItem>
|
||||||
</LayoutGridItem>
|
);
|
||||||
);
|
}) }
|
||||||
}) }
|
</AutoGrid>
|
||||||
</AutoGrid>
|
<Column gap={ 0 } fullWidth>
|
||||||
<Column gap={ 1 } alignItems="end">
|
<small>{ LocalizeText('inventory.trading.info.itemcount', [ 'value' ], [ ownUser.itemCount.toString() ]) }</small>
|
||||||
<Grid overflow="hidden">
|
<small className="credits-align">{ LocalizeText('inventory.trading.info.creditvalue.own', [ 'value' ], [ getTotalCredits(ownUser.userItems).toString() ]) }</small>
|
||||||
<Column size={ 6 } overflow="hidden">
|
</Column>
|
||||||
<input type="number" className="form-control form-control-sm quantity-input" placeholder={ LocalizeText('catalog.bundlewidget.spinner.select.amount') } disabled={ !groupItem } value={ quantity } onChange={ event => setQuantity(event.target.valueAsNumber) } />
|
|
||||||
</Column>
|
</Column>
|
||||||
<Column size={ 6 } overflow="hidden">
|
<Flex className="lock-design-left">
|
||||||
<Button variant="secondary" disabled={ !groupItem } onClick={ event => changeCount(groupItem.getUnlockedCount()) }>{ LocalizeText('inventory.trading.areoffering') }</Button>
|
{ getLockIcon(ownUser.accepts) }
|
||||||
|
</Flex>
|
||||||
|
<Flex className="divisor"></Flex>
|
||||||
|
<Column size={ 4 } overflow="hidden">
|
||||||
|
<Flex>
|
||||||
|
{ (otherUser.accepts) && <Base className="icon icon-confirmed" /> }
|
||||||
|
<small className={ otherUser.accepts ? 'px-2' : '' }><b>{ otherUser.userName }</b> { LocalizeText('inventory.trading.isoffering') }</small>
|
||||||
|
</Flex>
|
||||||
|
<AutoGrid columnCount={ 3 } columnMinWidth={ 35 } columnMinHeight={ 35 }>
|
||||||
|
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
||||||
|
{
|
||||||
|
const item = (otherUser.userItems.getWithIndex(i) || null);
|
||||||
|
|
||||||
|
if(!item) return <LayoutGridItem key={ i } />;
|
||||||
|
|
||||||
|
return <LayoutGridItem key={ i } itemActive={ (otherGroupItem === item) } itemImage={ item.iconUrl } itemCount={ item.getTotalCount() } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => setOtherGroupItem(item) } />;
|
||||||
|
}) }
|
||||||
|
</AutoGrid>
|
||||||
|
<Column gap={ 0 } fullWidth>
|
||||||
|
<small>{ LocalizeText('inventory.trading.info.itemcount', [ 'value' ], [ otherUser.itemCount.toString() ]) }</small>
|
||||||
|
<small>{ LocalizeText('inventory.trading.info.creditvalue', [ 'value' ], [ getTotalCredits(otherUser.userItems).toString() ]) }</small>
|
||||||
|
</Column>
|
||||||
</Column>
|
</Column>
|
||||||
|
<Flex className="lock-design-right">
|
||||||
|
{ getLockIcon(otherUser.accepts) }
|
||||||
|
</Flex>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Base fullWidth className="badge bg-muted">
|
</>
|
||||||
{ groupItem ? groupItem.name : LocalizeText('catalog_selectproduct') }
|
}
|
||||||
</Base>
|
{ currentTab !== TAB_FURNITURE &&
|
||||||
</Column>
|
<>
|
||||||
</Flex>
|
<Flex className="px-2">
|
||||||
</Column>
|
<Base className="flex-shrink-0 icon icon-report-room" />
|
||||||
</Flex>
|
<Text bold>{ LocalizeText('inventory.trading.minimized.trade_in_progress') }</Text>
|
||||||
<Column fullWidth size={ 8 } overflow="hidden" className="trade-bg p-2">
|
|
||||||
<Grid overflow="hidden">
|
|
||||||
<Column size={ 4 } overflow="hidden">
|
|
||||||
<Flex justifyContent="between" alignItems="center">
|
|
||||||
<Text>{ LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }:</Text>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<AutoGrid columnCount={ 3 }>
|
</>
|
||||||
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
}
|
||||||
{
|
|
||||||
const item = (ownUser.userItems.getWithIndex(i) || null);
|
|
||||||
|
|
||||||
if(!item) return <LayoutGridItem key={ i } />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LayoutGridItem key={ i } itemActive={ (ownGroupItem === item) } itemImage={ item.iconUrl } itemCount={ item.getTotalCount() } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => setOwnGroupItem(item) } onDoubleClick={ event => removeItem(item) }>
|
|
||||||
{ (ownGroupItem === item) &&
|
|
||||||
<Button position="absolute" variant="danger" className="trade-button bottom-1 start-1" onClick={ event => removeItem(item) }>
|
|
||||||
<FaChevronLeft className="fa-icon" />
|
|
||||||
</Button> }
|
|
||||||
</LayoutGridItem>
|
|
||||||
);
|
|
||||||
}) }
|
|
||||||
</AutoGrid>
|
|
||||||
<Base fullWidth className="badge bg-muted">
|
|
||||||
{ ownGroupItem ? ownGroupItem.name : LocalizeText('catalog_selectproduct') }
|
|
||||||
</Base>
|
|
||||||
</Column>
|
|
||||||
{ getLockIcon(ownUser.accepts) }
|
|
||||||
<Column size={ 4 } overflow="hidden">
|
|
||||||
<Flex justifyContent="between" alignItems="center">
|
|
||||||
<Text>{ otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:</Text>
|
|
||||||
</Flex>
|
|
||||||
<AutoGrid columnCount={ 3 }>
|
|
||||||
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
|
|
||||||
{
|
|
||||||
const item = (otherUser.userItems.getWithIndex(i) || null);
|
|
||||||
|
|
||||||
if(!item) return <LayoutGridItem key={ i } />;
|
|
||||||
|
|
||||||
return <LayoutGridItem key={ i } itemActive={ (otherGroupItem === item) } itemImage={ item.iconUrl } itemCount={ item.getTotalCount() } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => setOtherGroupItem(item) } />;
|
|
||||||
}) }
|
|
||||||
</AutoGrid>
|
|
||||||
<Base fullWidth className="badge bg-muted w-100">
|
|
||||||
{ otherGroupItem ? otherGroupItem.name : LocalizeText('catalog_selectproduct') }
|
|
||||||
</Base>
|
|
||||||
</Column>
|
|
||||||
{ getLockIcon(otherUser.accepts) }
|
|
||||||
</Grid>
|
|
||||||
<Flex grow justifyContent="between">
|
<Flex grow justifyContent="between">
|
||||||
|
{ (currentTab === TAB_FURNITURE) &&
|
||||||
|
<>
|
||||||
|
{ (tradeState === TradeState.TRADING_STATE_READY) &&
|
||||||
|
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText('inventory.trading.accept') }</Button> }
|
||||||
|
{ (tradeState === TradeState.TRADING_STATE_RUNNING) &&
|
||||||
|
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText(ownUser.accepts ? 'inventory.trading.modify' : 'inventory.trading.accept') }</Button> }
|
||||||
|
{ (tradeState === TradeState.TRADING_STATE_COUNTDOWN) &&
|
||||||
|
<Button variant="secondary" disabled>{ LocalizeText('inventory.trading.countdown', [ 'counter' ], [ countdownTick.toString() ]) }</Button> }
|
||||||
|
{ (tradeState === TradeState.TRADING_STATE_CONFIRMING) &&
|
||||||
|
<Button variant="secondary" onClick={ progressTrade }>{ LocalizeText('inventory.trading.button.restore') }</Button> }
|
||||||
|
{ (tradeState === TradeState.TRADING_STATE_CONFIRMED) &&
|
||||||
|
<Button variant="secondary">{ LocalizeText('inventory.trading.info.waiting') }</Button> }
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
{ (currentTab !== TAB_FURNITURE) &&
|
||||||
|
<Button variant="secondary" onClick={ () => setCurrentTab(TABS[0]) }>{ LocalizeText('inventory.trading.minimized.continue_trade') }</Button>
|
||||||
|
}
|
||||||
<Button variant="danger" onClick={ cancelTrade }>{ LocalizeText('generic.cancel') }</Button>
|
<Button variant="danger" onClick={ cancelTrade }>{ LocalizeText('generic.cancel') }</Button>
|
||||||
{ (tradeState === TradeState.TRADING_STATE_READY) &&
|
|
||||||
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText('inventory.trading.accept') }</Button> }
|
|
||||||
{ (tradeState === TradeState.TRADING_STATE_RUNNING) &&
|
|
||||||
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText(ownUser.accepts ? 'inventory.trading.modify' : 'inventory.trading.accept') }</Button> }
|
|
||||||
{ (tradeState === TradeState.TRADING_STATE_COUNTDOWN) &&
|
|
||||||
<Button variant="secondary" disabled>{ LocalizeText('inventory.trading.countdown', [ 'counter' ], [ countdownTick.toString() ]) }</Button> }
|
|
||||||
{ (tradeState === TradeState.TRADING_STATE_CONFIRMING) &&
|
|
||||||
<Button variant="secondary" onClick={ progressTrade }>{ LocalizeText('inventory.trading.button.restore') }</Button> }
|
|
||||||
{ (tradeState === TradeState.TRADING_STATE_CONFIRMED) &&
|
|
||||||
<Button variant="secondary">{ LocalizeText('inventory.trading.info.waiting') }</Button> }
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Column>
|
</Column>
|
||||||
</Column>
|
</Column>
|
||||||
|
@ -1,43 +1,58 @@
|
|||||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
import { MouseEventType } from "@nitrots/nitro-renderer";
|
||||||
import { FC, MouseEvent, PropsWithChildren, useState } from 'react';
|
import { FC, MouseEvent, PropsWithChildren, useState } from "react";
|
||||||
import { attemptPetPlacement, IPetItem, UnseenItemCategory } from '../../../../api';
|
import {
|
||||||
import { LayoutGridItem, LayoutPetImageView } from '../../../../common';
|
attemptPetPlacement,
|
||||||
import { useInventoryPets, useInventoryUnseenTracker } from '../../../../hooks';
|
IPetItem,
|
||||||
|
UnseenItemCategory,
|
||||||
|
} from "../../../../api";
|
||||||
|
import { LayoutGridItem, LayoutPetImageView } from "../../../../common";
|
||||||
|
import { useInventoryPets, useInventoryUnseenTracker } from "../../../../hooks";
|
||||||
|
|
||||||
export const InventoryPetItemView: FC<PropsWithChildren<{ petItem: IPetItem }>> = props =>
|
export const InventoryPetItemView: FC<
|
||||||
{
|
PropsWithChildren<{ petItem: IPetItem }>
|
||||||
const { petItem = null, children = null, ...rest } = props;
|
> = (props) => {
|
||||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
const { petItem = null, children = null, ...rest } = props;
|
||||||
const { selectedPet = null, setSelectedPet = null } = useInventoryPets();
|
const [isMouseDown, setMouseDown] = useState(false);
|
||||||
const { isUnseen } = useInventoryUnseenTracker();
|
const { selectedPet = null, setSelectedPet = null } = useInventoryPets();
|
||||||
const unseen = isUnseen(UnseenItemCategory.PET, petItem.petData.id);
|
const { isUnseen } = useInventoryUnseenTracker();
|
||||||
|
const unseen = isUnseen(UnseenItemCategory.PET, petItem.petData.id);
|
||||||
|
|
||||||
const onMouseEvent = (event: MouseEvent) =>
|
const onMouseEvent = (event: MouseEvent) => {
|
||||||
{
|
switch (event.type) {
|
||||||
switch(event.type)
|
case MouseEventType.MOUSE_DOWN:
|
||||||
{
|
setSelectedPet(petItem);
|
||||||
case MouseEventType.MOUSE_DOWN:
|
setMouseDown(true);
|
||||||
setSelectedPet(petItem);
|
return;
|
||||||
setMouseDown(true);
|
case MouseEventType.MOUSE_UP:
|
||||||
return;
|
setMouseDown(false);
|
||||||
case MouseEventType.MOUSE_UP:
|
return;
|
||||||
setMouseDown(false);
|
case MouseEventType.ROLL_OUT:
|
||||||
return;
|
if (!isMouseDown || !(petItem === selectedPet)) return;
|
||||||
case MouseEventType.ROLL_OUT:
|
|
||||||
if(!isMouseDown || !(petItem === selectedPet)) return;
|
|
||||||
|
|
||||||
attemptPetPlacement(petItem);
|
attemptPetPlacement(petItem);
|
||||||
return;
|
return;
|
||||||
case 'dblclick':
|
case "dblclick":
|
||||||
attemptPetPlacement(petItem);
|
attemptPetPlacement(petItem);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutGridItem itemActive={ (petItem === selectedPet) } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest }>
|
<LayoutGridItem
|
||||||
<LayoutPetImageView figure={ petItem.petData.figureData.figuredata } direction={ 3 } headOnly={ true } />
|
itemActive={petItem === selectedPet}
|
||||||
{ children }
|
itemUnseen={unseen}
|
||||||
</LayoutGridItem>
|
onMouseDown={onMouseEvent}
|
||||||
);
|
onMouseUp={onMouseEvent}
|
||||||
}
|
onMouseOut={onMouseEvent}
|
||||||
|
onDoubleClick={onMouseEvent}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
<LayoutPetImageView
|
||||||
|
figure={petItem.petData.figureData.figuredata}
|
||||||
|
direction={3}
|
||||||
|
headOnly={true}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</LayoutGridItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { attemptPetPlacement, GetRoomEngine, LocalizeText, UnseenItemCategory } from '../../../../api';
|
import { GetRoomEngine, LocalizeText, UnseenItemCategory, attemptPetPlacement } from '../../../../api';
|
||||||
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
|
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
|
||||||
import { useInventoryPets, useInventoryUnseenTracker } from '../../../../hooks';
|
import { useInventoryPets, useInventoryUnseenTracker } from '../../../../hooks';
|
||||||
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
|
import { InventoryCategoryEmptyViewPets } from '../InventoryCategoryEmptyViewPets';
|
||||||
import { InventoryPetItemView } from './InventoryPetItemView';
|
import { InventoryPetItemView } from './InventoryPetItemView';
|
||||||
|
|
||||||
interface InventoryPetViewProps
|
interface InventoryPetViewProps
|
||||||
{
|
{
|
||||||
roomSession: IRoomSession;
|
roomSession: IRoomSession;
|
||||||
roomPreviewer: RoomPreviewer;
|
roomPreviewer: RoomPreviewer;
|
||||||
|
isTrading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InventoryPetView: FC<InventoryPetViewProps> = props =>
|
export const InventoryPetView: FC<InventoryPetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { roomSession = null, roomPreviewer = null } = props;
|
const { roomSession = null, roomPreviewer = null, isTrading = false } = props;
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const { petItems = null, selectedPet = null, activate = null, deactivate = null } = useInventoryPets();
|
const { petItems = null, selectedPet = null, activate = null, deactivate = null } = useInventoryPets();
|
||||||
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
||||||
@ -63,7 +64,7 @@ export const InventoryPetView: FC<InventoryPetViewProps> = props =>
|
|||||||
return () => setIsVisible(false);
|
return () => setIsVisible(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if(!petItems || !petItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } />;
|
if(!petItems || !petItems.length) return <InventoryCategoryEmptyViewPets title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } isTrading={ isTrading } />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid>
|
<Grid>
|
||||||
@ -80,7 +81,7 @@ export const InventoryPetView: FC<InventoryPetViewProps> = props =>
|
|||||||
<Column grow justifyContent="between" gap={ 2 }>
|
<Column grow justifyContent="between" gap={ 2 }>
|
||||||
<Text grow truncate>{ selectedPet.petData.name }</Text>
|
<Text grow truncate>{ selectedPet.petData.name }</Text>
|
||||||
{ !!roomSession &&
|
{ !!roomSession &&
|
||||||
<Button onClick={ event => attemptPetPlacement(selectedPet) }>
|
<Button variant="success" onClick={ event => attemptPetPlacement(selectedPet) }>
|
||||||
{ LocalizeText('inventory.furni.placetoroom') }
|
{ LocalizeText('inventory.furni.placetoroom') }
|
||||||
</Button> }
|
</Button> }
|
||||||
</Column> }
|
</Column> }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user