import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; import { FaChevronLeft, FaChevronRight, FaLock, FaUnlock } from 'react-icons/fa'; import { FurniCategory, getGuildFurniType, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, SendMessageComposer, TradeState } from '../../../../api'; import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common'; import { useInventoryTrade, useNotification } from '../../../../hooks'; import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView'; interface InventoryTradeViewProps { cancelTrade: () => void; } const MAX_ITEMS_TO_TRADE: number = 9; export const InventoryTradeView: FC = props => { const { cancelTrade = null } = props; const [ groupItem, setGroupItem ] = useState(null); const [ ownGroupItem, setOwnGroupItem ] = useState(null); const [ otherGroupItem, setOtherGroupItem ] = useState(null); const [ filteredGroupItems, setFilteredGroupItems ] = useState(null); const [ countdownTick, setCountdownTick ] = useState(3); const [ quantity, setQuantity ] = useState(1); 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) => { if(accepts) { return } else { return } } const updateQuantity = (value: number, totalItemCount: number) => { if(isNaN(Number(value)) || Number(value) < 0 || !value) value = 1; 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(() => { if(tradeState !== TradeState.TRADING_STATE_COUNTDOWN) return; setCountdownTick(3); const interval = setInterval(() => { setCountdownTick(prevValue => { const newValue = (prevValue - 1); if(newValue === 0) clearInterval(interval); return newValue; }); }, 1000); return () => clearInterval(interval); }, [ tradeState, setTradeState ]); useEffect(() => { if(countdownTick !== 0) return; setTradeState(TradeState.TRADING_STATE_CONFIRMING); }, [ countdownTick, setTradeState ]); if((tradeState === TradeState.TRADING_STATE_READY) || !ownUser || !otherUser) return null; return ( { filteredGroupItems && (filteredGroupItems.length > 0) && filteredGroupItems.map((item, index) => { const count = item.getUnlockedCount(); return ( (count && setGroupItem(item)) } onDoubleClick={ event => attemptItemOffer(1) }> { ((count > 0) && (groupItem === item)) && } ); }) } setQuantity(event.target.valueAsNumber) } /> { groupItem ? groupItem.name : LocalizeText('catalog_selectproduct') } { LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }: { getLockIcon(ownUser.accepts) } { Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) => { const item = (ownUser.userItems.getWithIndex(i) || null); if(!item) return ; return ( setOwnGroupItem(item) } onDoubleClick={ event => removeItem(item) }> { (ownGroupItem === item) && } ); }) } { ownGroupItem ? ownGroupItem.name : LocalizeText('catalog_selectproduct') } { otherUser.userName } { LocalizeText('inventory.trading.isoffering') }: { getLockIcon(otherUser.accepts) } { Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) => { const item = (otherUser.userItems.getWithIndex(i) || null); if(!item) return ; return setOtherGroupItem(item) } />; }) } { otherGroupItem ? otherGroupItem.name : LocalizeText('catalog_selectproduct') } { (tradeState === TradeState.TRADING_STATE_READY) && } { (tradeState === TradeState.TRADING_STATE_RUNNING) && } { (tradeState === TradeState.TRADING_STATE_COUNTDOWN) && } { (tradeState === TradeState.TRADING_STATE_CONFIRMING) && } { (tradeState === TradeState.TRADING_STATE_CONFIRMED) && } ); }