Update inventory to use useReducer

This commit is contained in:
Bill 2021-04-28 13:47:33 -04:00
parent 629205d096
commit fece78897f
23 changed files with 358 additions and 186 deletions

View File

@ -1,50 +1,28 @@
import { FurnitureListAddOrUpdateEvent, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListItemParser, FurnitureListRemovedEvent, FurniturePostItPlacedEvent } from 'nitro-renderer'; import { FurnitureListAddOrUpdateEvent, FurnitureListEvent, FurnitureListInvalidateEvent, FurnitureListItemParser, FurnitureListRemovedEvent, FurniturePostItPlacedEvent } from 'nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { CreateMessageHook } from '../../hooks/messages/message-event'; import { CreateMessageHook } from '../../hooks/messages/message-event';
import { useInventoryContext } from './context/InventoryContext';
import { InventoryMessageHandlerProps } from './InventoryMessageHandler.types'; import { InventoryMessageHandlerProps } from './InventoryMessageHandler.types';
import { FurnitureItem } from './utils/FurnitureItem'; import { InventoryFurnitureActions } from './reducers/InventoryFurnitureReducer';
import { addFurnitureItem, getGroupItemForFurnitureId, mergeFragments, processFragment, removeItemById } from './utils/FurnitureUtilities'; import { mergeFragments } from './utils/FurnitureUtilities';
let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null; let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null;
export const InventoryMessageHandler: FC<InventoryMessageHandlerProps> = props => export const InventoryMessageHandler: FC<InventoryMessageHandlerProps> = props =>
{ {
const { setNeedsFurniUpdate = null, setGroupItems = null } = props; const { dispatchFurnitureState = null } = useInventoryContext();
const onFurnitureListAddOrUpdateEvent = useCallback((event: FurnitureListAddOrUpdateEvent) => const onFurnitureListAddOrUpdateEvent = useCallback((event: FurnitureListAddOrUpdateEvent) =>
{ {
const parser = event.getParser(); const parser = event.getParser();
setGroupItems(prevValue => dispatchFurnitureState({
{ type: InventoryFurnitureActions.ADD_OR_UPDATE_FURNITURE,
const newSet = [ ...prevValue ]; payload: {
parsers: parser.items
for(const item of parser.items) }
{ });
const groupItem = getGroupItemForFurnitureId(newSet, item.itemId); }, [ dispatchFurnitureState ]);
if(groupItem)
{
const furniture = groupItem.getItemById(item.itemId);
if(furniture)
{
furniture.update(item);
groupItem.hasUnseenItems = true;
}
}
else
{
const furniture = new FurnitureItem(item);
addFurnitureItem(newSet, furniture, false);
}
}
return newSet;
});
}, [ setGroupItems ]);
const onFurnitureListEvent = useCallback((event: FurnitureListEvent) => const onFurnitureListEvent = useCallback((event: FurnitureListEvent) =>
{ {
@ -52,41 +30,37 @@ export const InventoryMessageHandler: FC<InventoryMessageHandlerProps> = props =
if(!furniMsgFragments) furniMsgFragments = new Array(parser.totalFragments); if(!furniMsgFragments) furniMsgFragments = new Array(parser.totalFragments);
const merged = mergeFragments(parser.fragment, parser.totalFragments, parser.fragmentNumber, furniMsgFragments); const fragment = mergeFragments(parser.fragment, parser.totalFragments, parser.fragmentNumber, furniMsgFragments);
if(!merged) return; if(!fragment) return;
setGroupItems(prevValue => dispatchFurnitureState({
{ type: InventoryFurnitureActions.PROCESS_FRAGMENT,
return processFragment(prevValue, merged); payload: { fragment }
}); });
}, [ setGroupItems ]); }, [ dispatchFurnitureState ]);
const onFurnitureListInvalidateEvent = useCallback((event: FurnitureListInvalidateEvent) => const onFurnitureListInvalidateEvent = useCallback((event: FurnitureListInvalidateEvent) =>
{ {
setNeedsFurniUpdate(true); dispatchFurnitureState({
}, [ setNeedsFurniUpdate ]); type: InventoryFurnitureActions.SET_NEEDS_UPDATE,
payload: {
flag: true
}
});
}, [ dispatchFurnitureState ]);
const onFurnitureListRemovedEvent = useCallback((event: FurnitureListRemovedEvent) => const onFurnitureListRemovedEvent = useCallback((event: FurnitureListRemovedEvent) =>
{ {
const parser = event.getParser(); const parser = event.getParser();
setGroupItems(prevValue => dispatchFurnitureState({
{ type: InventoryFurnitureActions.REMOVE_FURNITURE,
const newSet = [ ...prevValue ]; payload: {
itemId: parser.itemId
const groupItem = removeItemById(parser.itemId, newSet); }
});
if(groupItem) }, [ dispatchFurnitureState ]);
{
// set all seen
return newSet;
}
return prevValue;
});
}, [ setGroupItems ]);
const onFurniturePostItPlacedEvent = useCallback((event: FurniturePostItPlacedEvent) => const onFurniturePostItPlacedEvent = useCallback((event: FurniturePostItPlacedEvent) =>
{ {

View File

@ -1,8 +1,3 @@
import { Dispatch, SetStateAction } from 'react';
import { GroupItem } from './utils/GroupItem';
export interface InventoryMessageHandlerProps export interface InventoryMessageHandlerProps
{ {
setNeedsFurniUpdate: Dispatch<SetStateAction<boolean>>;
setGroupItems: Dispatch<SetStateAction<GroupItem[]>>;
} }

View File

@ -1,7 +1,7 @@
.nitro-inventory { .nitro-inventory {
width: 475px; width: 475px;
height: 300px; // height: 300px;
max-height: 300px; // max-height: 300px;
} }
@import './views/InventoryViews'; @import './views/InventoryViews';

View File

@ -1,15 +1,18 @@
import classNames from 'classnames'; import classNames from 'classnames';
import { IRoomSession, RoomPreviewer, RoomSessionEvent } from 'nitro-renderer'; import { IRoomSession, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomPreviewer, RoomSessionEvent } from 'nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useReducer, useState } from 'react';
import { GetRoomEngine } from '../../api'; import { GetRoomEngine } from '../../api';
import { InventoryEvent } from '../../events'; import { InventoryEvent } from '../../events';
import { DraggableWindow } from '../../hooks/draggable-window/DraggableWindow'; import { DraggableWindow } from '../../hooks/draggable-window/DraggableWindow';
import { useRoomEngineEvent } from '../../hooks/events/nitro/room/room-engine-event';
import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event'; import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event';
import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { useUiEvent } from '../../hooks/events/ui/ui-event';
import { LocalizeText } from '../../utils/LocalizeText'; import { LocalizeText } from '../../utils/LocalizeText';
import { InventoryContextProvider } from './context/InventoryContext';
import { InventoryMessageHandler } from './InventoryMessageHandler'; import { InventoryMessageHandler } from './InventoryMessageHandler';
import { InventoryTabs, InventoryViewProps } from './InventoryView.types'; import { InventoryTabs, InventoryViewProps } from './InventoryView.types';
import { GroupItem } from './utils/GroupItem'; import { initialInventoryFurniture, inventoryFurnitureReducer } from './reducers/InventoryFurnitureReducer';
import { isObjectMoverRequested, setObjectMoverRequested } from './utils/FurnitureUtilities';
import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView'; import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView';
export const InventoryView: FC<InventoryViewProps> = props => export const InventoryView: FC<InventoryViewProps> = props =>
@ -18,12 +21,9 @@ export const InventoryView: FC<InventoryViewProps> = props =>
const [ isVisible, setIsVisible ] = useState(false); const [ isVisible, setIsVisible ] = useState(false);
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 [ needsFurniUpdate, setNeedsFurniUpdate ] = useState(true);
const [ groupItem, setGroupItem ] = useState<GroupItem>(null);
const [ groupItems, setGroupItems ] = useState<GroupItem[]>([]);
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null); const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
const [ furnitureState, dispatchFurnitureState ] = useReducer(inventoryFurnitureReducer, initialInventoryFurniture);
const onInventoryEvent = useCallback((event: InventoryEvent) => const onInventoryEvent = useCallback((event: InventoryEvent) =>
{ {
@ -45,6 +45,17 @@ export const InventoryView: FC<InventoryViewProps> = props =>
useUiEvent(InventoryEvent.HIDE_INVENTORY, onInventoryEvent); useUiEvent(InventoryEvent.HIDE_INVENTORY, onInventoryEvent);
useUiEvent(InventoryEvent.TOGGLE_INVENTORY, onInventoryEvent); useUiEvent(InventoryEvent.TOGGLE_INVENTORY, onInventoryEvent);
const onRoomEngineObjectPlacedEvent = useCallback((event: RoomEngineObjectPlacedEvent) =>
{
if(!isObjectMoverRequested()) return;
setObjectMoverRequested(false);
if(!event._Str_4057) setIsVisible(true);
}, []);
useRoomEngineEvent(RoomEngineObjectEvent.PLACED, onRoomEngineObjectPlacedEvent);
const onRoomSessionEvent = useCallback((event: RoomSessionEvent) => const onRoomSessionEvent = useCallback((event: RoomSessionEvent) =>
{ {
switch(event.type) switch(event.type)
@ -83,10 +94,8 @@ export const InventoryView: FC<InventoryViewProps> = props =>
} }
return ( return (
<> <InventoryContextProvider value={ { furnitureState, dispatchFurnitureState } }>
<InventoryMessageHandler <InventoryMessageHandler />
setNeedsFurniUpdate={ setNeedsFurniUpdate }
setGroupItems={ setGroupItems } />
{ isVisible && <DraggableWindow handle=".drag-handler"> { isVisible && <DraggableWindow handle=".drag-handler">
<div className="nitro-inventory d-flex flex-column"> <div className="nitro-inventory d-flex flex-column">
<div className="drag-handler d-flex align-items-center bg-primary border border-bottom-0 rounded-top px-3 py-1"> <div className="drag-handler d-flex align-items-center bg-primary border border-bottom-0 rounded-top px-3 py-1">
@ -107,16 +116,11 @@ export const InventoryView: FC<InventoryViewProps> = props =>
</ul> </ul>
<div className="bg-light rounded-bottom border border-top-0 px-3 py-2 h-100 shadow overflow-hidden"> <div className="bg-light rounded-bottom border border-top-0 px-3 py-2 h-100 shadow overflow-hidden">
{ (currentTab === InventoryTabs.FURNITURE ) && <InventoryFurnitureView { (currentTab === InventoryTabs.FURNITURE ) && <InventoryFurnitureView
needsFurniUpdate={ needsFurniUpdate }
setNeedsFurniUpdate={ setNeedsFurniUpdate }
groupItem={ groupItem }
setGroupItem={ setGroupItem }
groupItems={ groupItems }
roomSession={ roomSession } roomSession={ roomSession }
roomPreviewer={ roomPreviewer } /> } roomPreviewer={ roomPreviewer } /> }
</div> </div>
</div> </div>
</DraggableWindow> } </DraggableWindow> }
</> </InventoryContextProvider>
); );
} }

View File

@ -2,8 +2,8 @@ import { createContext, FC, useContext } from 'react';
import { IInventoryContext, InventoryContextProps } from './InventoryContext.types'; import { IInventoryContext, InventoryContextProps } from './InventoryContext.types';
const InventoryContext = createContext<IInventoryContext>({ const InventoryContext = createContext<IInventoryContext>({
currentTab: null, furnitureState: null,
setCurrentTab: null, dispatchFurnitureState: null
}); });
export const InventoryContextProvider: FC<InventoryContextProps> = props => export const InventoryContextProvider: FC<InventoryContextProps> = props =>

View File

@ -1,9 +1,10 @@
import { ProviderProps } from 'react'; import { Dispatch, ProviderProps } from 'react';
import { IInventoryFurnitureAction, IInventoryFurnitureState } from '../reducers/InventoryFurnitureReducer';
export interface IInventoryContext export interface IInventoryContext
{ {
currentTab: string; furnitureState: IInventoryFurnitureState;
setCurrentTab: (tab: string) => void; dispatchFurnitureState: Dispatch<IInventoryFurnitureAction>;
} }
export interface InventoryContextProps extends ProviderProps<IInventoryContext> export interface InventoryContextProps extends ProviderProps<IInventoryContext>

View File

@ -1,14 +0,0 @@
import { createContext, FC, useContext } from 'react';
import { IInventoryFurnitureContext, InventoryFurnitureContextProps } from './InventoryFurnitureContext.types';
const InventoryFurnitureContext = createContext<IInventoryFurnitureContext>({
setNeedsUpdate: null,
setGroupItems: null
});
export const InventoryFurnitureContextProvider: FC<InventoryFurnitureContextProps> = props =>
{
return <InventoryFurnitureContext.Provider value={ props.value }>{ props.children }</InventoryFurnitureContext.Provider>
}
export const useInventoryFurnitureContext = () => useContext(InventoryFurnitureContext);

View File

@ -1,13 +0,0 @@
import { Dispatch, ProviderProps, SetStateAction } from 'react';
import { GroupItem } from '../../utils/GroupItem';
export interface IInventoryFurnitureContext
{
setNeedsUpdate: Dispatch<SetStateAction<boolean>>;
setGroupItems: Dispatch<SetStateAction<GroupItem[]>>;
}
export interface InventoryFurnitureContextProps extends ProviderProps<IInventoryFurnitureContext>
{
}

View File

@ -0,0 +1,137 @@
import { FurnitureListItemParser } from 'nitro-renderer';
import { Reducer } from 'react';
import { FurnitureItem } from '../utils/FurnitureItem';
import { addFurnitureItem, processFragment, removeItemById } from '../utils/FurnitureUtilities';
import { GroupItem } from '../utils/GroupItem';
export interface IInventoryFurnitureState
{
needsFurniUpdate: boolean;
groupItem: GroupItem;
groupItems: GroupItem[];
}
export interface IInventoryFurnitureAction
{
type: string;
payload: {
flag?: boolean;
groupItem?: GroupItem;
parsers?: FurnitureListItemParser[];
itemId?: number;
fragment?: Map<number, FurnitureListItemParser>;
}
}
export class InventoryFurnitureActions
{
public static SET_NEEDS_UPDATE: string = 'IFA_SET_NEEDS_UPDATE';
public static SET_GROUP_ITEM: string = 'IFA_SET_GROUP_ITEM';
public static ADD_OR_UPDATE_FURNITURE: string = 'IFA_ADD_OR_UPDATE_FURNITURE';
public static REMOVE_FURNITURE: string = 'IFA_REMOVE_FURNITURE';
public static PROCESS_FRAGMENT: string = 'IFA_PROCESS_FRAGMENT';
}
export const initialInventoryFurniture: IInventoryFurnitureState = {
needsFurniUpdate: true,
groupItem: null,
groupItems: []
}
export const inventoryFurnitureReducer: Reducer<IInventoryFurnitureState, IInventoryFurnitureAction> = (state, action) =>
{
switch(action.type)
{
case InventoryFurnitureActions.SET_NEEDS_UPDATE:
return { ...state, needsFurniUpdate: (action.payload.flag || false) };
case InventoryFurnitureActions.SET_GROUP_ITEM: {
let groupItem = (action.payload.groupItem || state.groupItem || null);
let index = 0;
if(groupItem)
{
const foundIndex = state.groupItems.indexOf(groupItem);
if(foundIndex > -1) index = foundIndex;
}
groupItem = (state.groupItems[index] || null);
return { ...state, groupItem };
}
case InventoryFurnitureActions.ADD_OR_UPDATE_FURNITURE: {
const groupItems = [ ...state.groupItems ];
for(const item of action.payload.parsers)
{
let i = 0;
let groupItem: GroupItem = null;
while(i < groupItems.length)
{
const group = groupItems[i];
let j = 0;
while(j < group.items.length)
{
const furniture = group.items[j];
if(furniture.id === item.itemId)
{
furniture.update(item);
const newFurniture = [ ...group.items ];
newFurniture[j] = furniture;
group.items = newFurniture;
groupItem = group;
break;
}
j++
}
if(groupItem) break;
i++;
}
if(groupItem)
{
groupItem.hasUnseenItems = true;
groupItems[i] = Object.create(groupItem);
}
else
{
const furniture = new FurnitureItem(item);
addFurnitureItem(groupItems, furniture, false);
}
}
return { ...state, groupItems };
}
case InventoryFurnitureActions.REMOVE_FURNITURE: {
const groupItems = [ ...state.groupItems ];
removeItemById(action.payload.itemId, groupItems);
return { ...state, groupItems };
}
case InventoryFurnitureActions.PROCESS_FRAGMENT: {
const groupItems = [ ...state.groupItems ];
processFragment(groupItems, (action.payload.fragment || null));
return { ...state, groupItems };
}
default:
return state;
}
}

View File

@ -155,9 +155,7 @@ export function processFragment(set: GroupItem[], fragment: Map<number, Furnitur
const emptyExistingSet = (existingIds.length === 0); const emptyExistingSet = (existingIds.length === 0);
const newSet = [ ...set ]; for(const id of removedIds) removeItemById(id, set);
for(const id of removedIds) removeItemById(id, newSet);
for(const id of addedIds) for(const id of addedIds)
{ {
@ -167,10 +165,10 @@ export function processFragment(set: GroupItem[], fragment: Map<number, Furnitur
const item = new FurnitureItem(parser); const item = new FurnitureItem(parser);
addFurnitureItem(newSet, item, true); addFurnitureItem(set, item, true);
} }
return newSet; return set;
} }
export function removeItemById(id: number, set: GroupItem[]): GroupItem export function removeItemById(id: number, set: GroupItem[]): GroupItem

View File

@ -420,4 +420,9 @@ export class GroupItem
{ {
return this._items; return this._items;
} }
public set items(items: FurnitureItem[])
{
this._items = items;
}
} }

View File

@ -1,7 +1,3 @@
.item-container {
height: 216px;
max-height: 216px;
overflow-y: auto;
}
@import './item/InventoryFurnitureItemView'; @import './item/InventoryFurnitureItemView';
@import './results/InventoryFurnitureResultsView';
@import './search/InventoryFurnitureSearchView';

View File

@ -4,45 +4,45 @@ import { GetRoomEngine } from '../../../../api';
import { SendMessageHook } from '../../../../hooks/messages/message-event'; import { SendMessageHook } from '../../../../hooks/messages/message-event';
import { LocalizeText } from '../../../../utils/LocalizeText'; import { LocalizeText } from '../../../../utils/LocalizeText';
import { RoomPreviewerView } from '../../../room-previewer/RoomPreviewerView'; import { RoomPreviewerView } from '../../../room-previewer/RoomPreviewerView';
import { useInventoryContext } from '../../context/InventoryContext';
import { InventoryFurnitureActions } from '../../reducers/InventoryFurnitureReducer';
import { FurniCategory } from '../../utils/FurniCategory'; import { FurniCategory } from '../../utils/FurniCategory';
import { attemptItemPlacement } from '../../utils/FurnitureUtilities'; import { attemptItemPlacement } from '../../utils/FurnitureUtilities';
import { InventoryFurnitureViewProps } from './InventoryFurnitureView.types'; import { InventoryFurnitureViewProps } from './InventoryFurnitureView.types';
import { InventoryFurnitureItemView } from './item/InventoryFurnitureItemView'; import { InventoryFurnitureResultsView } from './results/InventoryFurnitureResultsView';
import { InventoryFurnitureSearchView } from './search/InventoryFurnitureSearchView';
export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props => export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props =>
{ {
const { needsFurniUpdate = false, setNeedsFurniUpdate = null, groupItem = null, setGroupItem = null, groupItems = null, roomSession = null, roomPreviewer = null } = props; const { roomSession = null, roomPreviewer = null } = props;
console.log(props); const { furnitureState = null, dispatchFurnitureState = null } = useInventoryContext();
const { needsFurniUpdate = false, groupItem = null, groupItems = [] } = furnitureState;
useEffect(() => useEffect(() =>
{ {
if(needsFurniUpdate) if(needsFurniUpdate)
{ {
setNeedsFurniUpdate(false); dispatchFurnitureState({
type: InventoryFurnitureActions.SET_NEEDS_UPDATE,
payload: {
flag: false
}
});
SendMessageHook(new FurnitureListComposer()); SendMessageHook(new FurnitureListComposer());
} }
else else
{ {
setGroupItem(prevValue => dispatchFurnitureState({
{ type: InventoryFurnitureActions.SET_GROUP_ITEM,
if(!groupItems || !groupItems.length) return null; payload: {
groupItem: null
let index = 0; }
});
if(prevValue)
{
const foundIndex = groupItems.indexOf(prevValue);
if(foundIndex > -1) index = foundIndex;
}
return groupItems[index];
});
} }
}, [ needsFurniUpdate, setNeedsFurniUpdate, groupItems, setGroupItem ]); }, [ needsFurniUpdate, groupItems, dispatchFurnitureState ]);
useEffect(() => useEffect(() =>
{ {
@ -97,18 +97,13 @@ export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props =>
return ( return (
<div className="row h-100"> <div className="row h-100">
<div className="col col-7"> <div className="col col-7">
<div className="row row-cols-5 g-0 item-container"> <InventoryFurnitureSearchView />
{ groupItems && groupItems.length && groupItems.map((item, index) => <InventoryFurnitureResultsView groupItems={ groupItems } />
{
return <InventoryFurnitureItemView key={ index } groupItem={ item } isActive={ groupItem === item } setGroupItem={ setGroupItem } />
})
}
</div>
</div> </div>
<div className="d-flex flex-column col col-5 justify-space-between"> <div className="d-flex flex-column col col-5 justify-space-between">
<RoomPreviewerView roomPreviewer={ roomPreviewer } height={ 130 } /> <RoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
{ groupItem && <div className="flex-grow-1 py-2"> { groupItem && <div className="d-flex flex-column flex-grow-1">
<p className="fs-6 text-black">{ groupItem.name }</p> <p className="flex-grow-1 fs-6 text-black my-2">{ groupItem.name }</p>
{ !!roomSession && <button type="button" className="btn btn-success" onClick={ event => attemptItemPlacement(groupItem) }>{ LocalizeText('inventory.furni.placetoroom') }</button> } { !!roomSession && <button type="button" className="btn btn-success" onClick={ event => attemptItemPlacement(groupItem) }>{ LocalizeText('inventory.furni.placetoroom') }</button> }
</div> } </div> }
</div> </div>

View File

@ -1,14 +1,7 @@
import { IRoomSession, RoomPreviewer } from 'nitro-renderer'; import { IRoomSession, RoomPreviewer } from 'nitro-renderer';
import { Dispatch, SetStateAction } from 'react';
import { GroupItem } from '../../utils/GroupItem';
export interface InventoryFurnitureViewProps export interface InventoryFurnitureViewProps
{ {
needsFurniUpdate: boolean;
setNeedsFurniUpdate: Dispatch<SetStateAction<boolean>>;
groupItem: GroupItem;
setGroupItem: Dispatch<SetStateAction<GroupItem>>;
groupItems: GroupItem[];
roomSession: IRoomSession; roomSession: IRoomSession;
roomPreviewer: RoomPreviewer; roomPreviewer: RoomPreviewer;
} }

View File

@ -1,19 +1,25 @@
.inventory-furniture-item { .inventory-furniture-item-container {
background-position: center; height: 48px;
background-repeat: no-repeat; max-height: 48px;
height: 50px;
max-height: 50px;
border-color: $muted !important;
background-color: #CDD3D9;
&.active { .inventory-furniture-item {
border-color: $white !important; width: 100%;
background-color: #ECECEC; height: 100%;
} background-position: center;
background-repeat: no-repeat;
.badge { border-color: $muted !important;
top: 3px; background-color: #CDD3D9;
right: 3px; overflow: hidden;
font-size: 10px;
&.active {
border-color: $white !important;
background-color: #ECECEC;
}
.badge {
top: 2px;
right: 2px;
font-size: 8px;
}
} }
} }

View File

@ -1,16 +1,48 @@
import { FC } from 'react'; import { MouseEventType } from 'nitro-renderer';
import { FC, MouseEvent, useCallback, useState } from 'react';
import { useInventoryContext } from '../../../context/InventoryContext';
import { InventoryFurnitureActions } from '../../../reducers/InventoryFurnitureReducer';
import { attemptItemPlacement } from '../../../utils/FurnitureUtilities';
import { InventoryFurnitureItemViewProps } from './InventoryFurnitureItemView.types'; import { InventoryFurnitureItemViewProps } from './InventoryFurnitureItemView.types';
export const InventoryFurnitureItemView: FC<InventoryFurnitureItemViewProps> = props => export const InventoryFurnitureItemView: FC<InventoryFurnitureItemViewProps> = props =>
{ {
const { groupItem = null, isActive = false, setGroupItem = null } = props; const { groupItem } = props;
const { furnitureState, dispatchFurnitureState } = useInventoryContext();
const [ isMouseDown, setMouseDown ] = useState(false);
const isActive = (furnitureState.groupItem === groupItem);
const onMouseEvent = useCallback((event: MouseEvent) =>
{
switch(event.type)
{
case MouseEventType.MOUSE_DOWN:
dispatchFurnitureState({
type: InventoryFurnitureActions.SET_GROUP_ITEM,
payload: {
groupItem
}
});
setMouseDown(true);
return;
case MouseEventType.MOUSE_UP:
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if(!isMouseDown || !isActive) return;
attemptItemPlacement(groupItem);
return;
}
}, [ isActive, isMouseDown, groupItem, dispatchFurnitureState ]);
const imageUrl = `url(${ groupItem.iconUrl })`; const imageUrl = `url(${ groupItem.iconUrl })`;
return ( return (
<div className="col pe-1 pb-1"> <div className="col pe-1 pb-1 inventory-furniture-item-container">
<div className={ 'position-relative border border-2 rounded inventory-furniture-item cursor-pointer ' + (isActive && 'active') } style={ { backgroundImage: imageUrl }} onClick={ event => setGroupItem(groupItem) }> <div className={ 'position-relative border border-2 rounded inventory-furniture-item cursor-pointer ' + (isActive && 'active') } style={ { backgroundImage: imageUrl }} onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
<span className="position-absolute badge border bg-secondary p-1">{ groupItem.getUnlockedCount() }</span> <span className="position-absolute badge border bg-danger px-1 rounded-circle">{ groupItem.getUnlockedCount() }</span>
</div> </div>
</div> </div>
); );

View File

@ -1,9 +1,6 @@
import { Dispatch, SetStateAction } from 'react';
import { GroupItem } from '../../../utils/GroupItem'; import { GroupItem } from '../../../utils/GroupItem';
export interface InventoryFurnitureItemViewProps export interface InventoryFurnitureItemViewProps
{ {
groupItem: GroupItem; groupItem: GroupItem;
isActive: boolean;
setGroupItem: Dispatch<SetStateAction<GroupItem>>;
} }

View File

@ -0,0 +1,5 @@
.item-container {
height: 208px;
max-height: 208px;
overflow-y: auto;
}

View File

@ -0,0 +1,18 @@
import { FC } from 'react';
import { InventoryFurnitureItemView } from '../item/InventoryFurnitureItemView';
import { InventoryFurnitureResultsViewProps } from './InventoryFurnitureResultsView.types';
export const InventoryFurnitureResultsView: FC<InventoryFurnitureResultsViewProps> = props =>
{
const { groupItems = [] } = props;
return (
<div className="row row-cols-5 g-0 item-container">
{ groupItems && groupItems.length && groupItems.map((item, index) =>
{
return <InventoryFurnitureItemView key={ index } groupItem={ item } />
})
}
</div>
);
}

View File

@ -0,0 +1,6 @@
import { GroupItem } from '../../../utils/GroupItem';
export interface InventoryFurnitureResultsViewProps
{
groupItems: GroupItem[];
}

View File

@ -0,0 +1,33 @@
import { ChangeEvent, FC, FormEvent, useEffect, useState } from 'react';
import { InventoryFurnitureSearchViewProps } from './InventoryFurnitureSearchView.types';
export const InventoryFurnitureSearchView: FC<InventoryFurnitureSearchViewProps> = props =>
{
const [ searchValue, setSearchValue ] = useState('');
function onChange(event: ChangeEvent<HTMLInputElement>): void
{
setSearchValue(event.target.value);
}
function handleSubmit(event: FormEvent<HTMLFormElement>): void
{
event.preventDefault();
}
useEffect(() =>
{
}, [ searchValue ]);
return (
<form className="d-flex mb-1" onSubmit={ handleSubmit }>
<div className="d-flex flex-grow-1 me-1">
<input type="text" className="form-control form-control-sm" placeholder="search" />
</div>
<div className="d-flex">
<button type="submit" className="btn btn-primary btn-sm"><i className="fas fa-search"></i></button>
</div>
</form>
);
}

View File

@ -0,0 +1,4 @@
export interface InventoryFurnitureSearchViewProps
{
}