Catalog updates

This commit is contained in:
Bill 2022-01-19 15:34:23 -05:00
parent 945894db9d
commit c5f8c3c276
38 changed files with 374 additions and 449 deletions

View File

@ -5,7 +5,7 @@ import { CREDITS, PlaySound } from '../../api/utils/PlaySound';
import { Column } from '../../common/Column'; import { Column } from '../../common/Column';
import { Grid } from '../../common/Grid'; import { Grid } from '../../common/Grid';
import { CatalogEvent } from '../../events'; import { CatalogEvent } from '../../events';
import { BatchUpdates, UseMountEffect } from '../../hooks'; import { BatchUpdates } from '../../hooks';
import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { useUiEvent } from '../../hooks/events/ui/ui-event';
import { SendMessageHook } from '../../hooks/messages/message-event'; import { SendMessageHook } from '../../hooks/messages/message-event';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsView, NitroCardView } from '../../layout'; import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsView, NitroCardView } from '../../layout';
@ -17,6 +17,7 @@ import { ICatalogPage } from './common/ICatalogPage';
import { IPageLocalization } from './common/IPageLocalization'; import { IPageLocalization } from './common/IPageLocalization';
import { IPurchasableOffer } from './common/IPurchasableOffer'; import { IPurchasableOffer } from './common/IPurchasableOffer';
import { RequestedPage } from './common/RequestedPage'; import { RequestedPage } from './common/RequestedPage';
import { SearchResult } from './common/SearchResult';
import { CatalogContextProvider } from './context/CatalogContext'; import { CatalogContextProvider } from './context/CatalogContext';
import { CatalogReducer, initialCatalog } from './reducers/CatalogReducer'; import { CatalogReducer, initialCatalog } from './reducers/CatalogReducer';
import { CatalogGiftView } from './views/gift/CatalogGiftView'; import { CatalogGiftView } from './views/gift/CatalogGiftView';
@ -44,6 +45,7 @@ export const CatalogView: FC<{}> = props =>
const [ purchasableOffer, setPurchasableOffer ] = useState<IPurchasableOffer>(null); const [ purchasableOffer, setPurchasableOffer ] = useState<IPurchasableOffer>(null);
const [ currentTab, setCurrentTab ] = useState<ICatalogNode>(null); const [ currentTab, setCurrentTab ] = useState<ICatalogNode>(null);
const [ activeNodes, setActiveNodes ] = useState<ICatalogNode[]>([]); const [ activeNodes, setActiveNodes ] = useState<ICatalogNode[]>([]);
const [ searchResult, setSearchResult ] = useState<SearchResult>(null);
const [ frontPageItems, setFrontPageItems ] = useState<FrontPageItem[]>([]); const [ frontPageItems, setFrontPageItems ] = useState<FrontPageItem[]>([]);
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null); const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
const [ catalogState, dispatchCatalogState ] = useReducer(CatalogReducer, initialCatalog); const [ catalogState, dispatchCatalogState ] = useReducer(CatalogReducer, initialCatalog);
@ -61,50 +63,13 @@ export const CatalogView: FC<{}> = props =>
setPurchasableOffer(null); setPurchasableOffer(null);
setCurrentTab(null); setCurrentTab(null);
setActiveNodes([]); setActiveNodes([]);
setSearchResult(null);
setFrontPageItems([]); setFrontPageItems([]);
setIsInitialized(false); setIsInitialized(false);
setIsVisible(true); setIsVisible(true);
}); });
}, []); }, []);
const getNodeById = useCallback((id: number, node: ICatalogNode = null) =>
{
if(!node) node = rootNode;
if(!node) return null;
if((node.pageId === id) && (node !== rootNode)) return node;
for(const child of node.children)
{
const n = (getNodeById(id, child) as ICatalogNode);
if(n) return n;
}
return null;
}, [ rootNode ]);
const getNodesByOfferId = useCallback((offerId: number, flag: boolean = false) =>
{
if(!currentOffers || !currentOffers.size) return null;
if(flag)
{
const nodes: ICatalogNode[] = [];
const offers = currentOffers.get(offerId);
if(offers && offers.length)
{
for(const offer of offers) (offer.isVisible && nodes.push(offer));
}
if(nodes.length) return nodes;
}
return currentOffers.get(offerId);
}, [ currentOffers ]);
const loadCatalogPage = useCallback((pageId: number, offerId: number) => const loadCatalogPage = useCallback((pageId: number, offerId: number) =>
{ {
if(pageId < 0) return; if(pageId < 0) return;
@ -120,8 +85,17 @@ export const CatalogView: FC<{}> = props =>
const selectOffer = useCallback((offerId: number) => const selectOffer = useCallback((offerId: number) =>
{ {
if(!currentPage || !currentPage.offers || offerId < 0) return;
}, []); for(const offer of currentPage.offers)
{
if(offer.offerId !== offerId) continue;
setCurrentOffer(offer)
return;
}
}, [ currentPage ]);
const showCatalogPage = useCallback((pageId: number, layoutCode: string, localization: IPageLocalization, offers: IPurchasableOffer[], offerId: number, acceptSeasonCurrencyAsCredits: boolean) => const showCatalogPage = useCallback((pageId: number, layoutCode: string, localization: IPageLocalization, offers: IPurchasableOffer[], offerId: number, acceptSeasonCurrencyAsCredits: boolean) =>
{ {
@ -147,7 +121,7 @@ export const CatalogView: FC<{}> = props =>
}); });
}, [ currentPage, forceRefresh, selectOffer ]); }, [ currentPage, forceRefresh, selectOffer ]);
const activateNode = useCallback((targetNode: ICatalogNode) => const activateNode = useCallback((targetNode: ICatalogNode, offerId: number = -1) =>
{ {
setActiveNodes(prevValue => setActiveNodes(prevValue =>
{ {
@ -179,36 +153,19 @@ export const CatalogView: FC<{}> = props =>
return newNodes; return newNodes;
}); });
if(targetNode.pageId > -1) loadCatalogPage(targetNode.pageId, -1); if(targetNode.pageId > -1) loadCatalogPage(targetNode.pageId, offerId);
}, [ setActiveNodes, loadCatalogPage ]); }, [ setActiveNodes, loadCatalogPage ]);
const onCatalogEvent = useCallback((event: CatalogEvent) => const onCatalogEvent = useCallback((event: CatalogEvent) =>
{ {
let save = false;
switch(event.type) switch(event.type)
{ {
case CatalogEvent.SHOW_CATALOG:
setIsVisible(true);
return;
case CatalogEvent.HIDE_CATALOG:
save = true;
setIsVisible(false);
return;
case CatalogEvent.TOGGLE_CATALOG:
save = true;
setIsVisible(value => !value);
return;
case CatalogEvent.PURCHASE_SUCCESS: case CatalogEvent.PURCHASE_SUCCESS:
PlaySound(CREDITS); PlaySound(CREDITS);
return; return;
} }
}, []); }, []);
useUiEvent(CatalogEvent.SHOW_CATALOG, onCatalogEvent);
useUiEvent(CatalogEvent.HIDE_CATALOG, onCatalogEvent);
useUiEvent(CatalogEvent.TOGGLE_CATALOG, onCatalogEvent);
useUiEvent(CatalogEvent.CATALOG_RESET, onCatalogEvent);
useUiEvent(CatalogEvent.PURCHASE_SUCCESS, onCatalogEvent); useUiEvent(CatalogEvent.PURCHASE_SUCCESS, onCatalogEvent);
const linkReceived = useCallback((url: string) => const linkReceived = useCallback((url: string) =>
@ -219,6 +176,15 @@ export const CatalogView: FC<{}> = props =>
switch(parts[1]) switch(parts[1])
{ {
case 'show':
setIsVisible(true);
return;
case 'hide':
setIsVisible(false);
return;
case 'toggle':
setIsVisible(prevValue => !prevValue);
return;
case 'open': case 'open':
if(parts.length > 2) if(parts.length > 2)
{ {
@ -272,7 +238,13 @@ export const CatalogView: FC<{}> = props =>
{ {
if(!isVisible) return; if(!isVisible) return;
if(!isInitialized) SendMessageHook(new GetCatalogIndexComposer(currentType)); if(!isInitialized)
{
SendMessageHook(new GetMarketplaceConfigurationMessageComposer());
SendMessageHook(new GetGiftWrappingConfigurationComposer());
SendMessageHook(new GetClubGiftInfo());
SendMessageHook(new GetCatalogIndexComposer(currentType));
}
}, [ isVisible, isInitialized, currentType ]); }, [ isVisible, isInitialized, currentType ]);
useEffect(() => useEffect(() =>
@ -339,15 +311,8 @@ export const CatalogView: FC<{}> = props =>
setCurrentOffer(null); setCurrentOffer(null);
}, [ currentPage ]); }, [ currentPage ]);
UseMountEffect(() =>
{
SendMessageHook(new GetMarketplaceConfigurationMessageComposer());
SendMessageHook(new GetGiftWrappingConfigurationComposer());
SendMessageHook(new GetClubGiftInfo());
});
return ( return (
<CatalogContextProvider value={ { isVisible, isBusy, setIsBusy, pageId, currentType, setCurrentType, rootNode, setRootNode, currentOffers, setCurrentOffers, currentPage, setCurrentPage, currentOffer, setCurrentOffer, purchasableOffer, setPurchasableOffer, activeNodes, setActiveNodes, frontPageItems, setFrontPageItems, resetState, loadCatalogPage, showCatalogPage, activateNode, catalogState, dispatchCatalogState } }> <CatalogContextProvider value={ { isVisible, isBusy, setIsBusy, pageId, currentType, setCurrentType, rootNode, setRootNode, currentOffers, setCurrentOffers, currentPage, setCurrentPage, currentOffer, setCurrentOffer, purchasableOffer, setPurchasableOffer, activeNodes, setActiveNodes, searchResult, setSearchResult, frontPageItems, setFrontPageItems, roomPreviewer, resetState, loadCatalogPage, showCatalogPage, activateNode, catalogState, dispatchCatalogState } }>
<CatalogMessageHandler /> <CatalogMessageHandler />
{ isVisible && { isVisible &&
<NitroCardView uniqueKey="catalog" className="nitro-catalog"> <NitroCardView uniqueKey="catalog" className="nitro-catalog">

View File

@ -1,4 +0,0 @@
export class CatalogMode
{
public static MODE_NORMAL: string = 'NORMAL';
}

View File

@ -3,7 +3,7 @@ import { SellablePetPaletteData } from '@nitrots/nitro-renderer';
export class CatalogPetPalette export class CatalogPetPalette
{ {
constructor( constructor(
public breed: string, public readonly breed: string,
public palettes: SellablePetPaletteData[] public readonly palettes: SellablePetPaletteData[]
) {} ) {}
} }

View File

@ -1,18 +1,7 @@
import { CatalogPageMessageOfferData, CatalogPageMessageParser, IFurnitureData, INodeData, SellablePetPaletteData } from '@nitrots/nitro-renderer'; import { SellablePetPaletteData } from '@nitrots/nitro-renderer';
import { GetConfiguration, GetProductDataForLocalization, GetRoomEngine } from '../../../api'; import { GetRoomEngine } from '../../../api';
import { ICatalogNode } from './ICatalogNode'; import { ICatalogNode } from './ICatalogNode';
export interface ICatalogOffers
{
[key: string]: INodeData[];
}
export interface ICatalogSearchResult
{
page: INodeData;
furniture: IFurnitureData[];
}
export const GetPixelEffectIcon = (id: number) => export const GetPixelEffectIcon = (id: number) =>
{ {
return ''; return '';
@ -23,13 +12,39 @@ export const GetSubscriptionProductIcon = (id: number) =>
return ''; return '';
} }
export function GetOfferName(offer: CatalogPageMessageOfferData): string export const GetNodeById = (id: number, searchNode: ICatalogNode = null, rootNode: ICatalogNode) =>
{ {
const productData = GetProductDataForLocalization(offer.localizationId); if(!searchNode) searchNode = rootNode;
if(productData) return productData.name; if(!searchNode) return null;
return offer.localizationId; if((searchNode.pageId === id) && (searchNode !== rootNode)) return searchNode;
for(const child of searchNode.children)
{
const node = (GetNodeById(id, child, rootNode) as ICatalogNode);
if(node) return node;
}
return null;
}
export const GetNodesByOfferId = (offerId: number, flag: boolean = false, currentOffers: Map<number, ICatalogNode[]>) =>
{
if(!currentOffers || !currentOffers.size) return null;
if(flag)
{
const nodes: ICatalogNode[] = [];
const offers = currentOffers.get(offerId);
if(offers && offers.length) for(const offer of offers) (offer.isVisible && nodes.push(offer));
if(nodes.length) return nodes;
}
return currentOffers.get(offerId);
} }
export const GetOfferNodes = (offerNodes: Map<number, ICatalogNode[]>, offerId: number) => export const GetOfferNodes = (offerNodes: Map<number, ICatalogNode[]>, offerId: number) =>
@ -50,53 +65,36 @@ export const GetOfferNodes = (offerNodes: Map<number, ICatalogNode[]>, offerId:
return allowedNodes; return allowedNodes;
} }
export const SetOffersToNodes = (offers: ICatalogOffers, pageData: INodeData) => export const FilterCatalogNode = (search: string, furniLines: string[], node: ICatalogNode, nodes: ICatalogNode[]) =>
{ {
if(pageData.offerIds && pageData.offerIds.length) if(node.isVisible && (node.pageId > 0))
{ {
for(const offerId of pageData.offerIds) let nodeAdded = false;
{
let existing = offers[offerId.toString()];
if(!existing) const hayStack = [ node.pageName, node.localization ].join(' ').toLowerCase().replace(/ /gi, '');
{
existing = [];
offers[offerId.toString()] = existing; if(hayStack.indexOf(search) > -1)
{
nodes.push(node);
nodeAdded = true;
} }
if(existing.indexOf(pageData) >= 0) continue; if(!nodeAdded)
{
for(const furniLine of furniLines)
{
if(hayStack.indexOf(furniLine) >= 0)
{
nodes.push(node);
existing.push(pageData); break;
}
}
} }
} }
if(pageData.children && pageData.children.length) for(const child of node.children) FilterCatalogNode(search, furniLines, child, nodes);
{
for(const child of pageData.children) SetOffersToNodes(offers, child);
}
}
export function GetCatalogPageImage(page: CatalogPageMessageParser, index: number = 0): string
{
const imageName = page.localization.images && page.localization.images[index];
if(!imageName || !imageName.length) return null;
let assetUrl = GetConfiguration<string>('catalog.asset.image.url');
assetUrl = assetUrl.replace('%name%', imageName);
return assetUrl;
}
export function GetCatalogPageText(page: CatalogPageMessageParser, index: number = 0): string
{
let message = (page.localization.texts[index] || '');
if(message && message.length) message = message.replace(/\r\n|\r|\n/g, '<br />');
return (message || '');
} }
export function GetPetIndexFromLocalization(localization: string) export function GetPetIndexFromLocalization(localization: string)
@ -160,77 +158,3 @@ export function GetPetAvailableColors(petIndex: number, palettes: SellablePetPal
} }
} }
} }
export function GetCatalogPageTreeByName(page: INodeData, lookup: string, tree: INodeData[])
{
if(page.pageName === lookup) return page;
for(const pageData of page.children)
{
const foundPageData = GetCatalogPageTreeByName(pageData, lookup, tree);
if(foundPageData)
{
tree.push(pageData);
return pageData;
}
}
}
export function GetCatalogPageTreeById(page: INodeData, lookup: number, tree: INodeData[])
{
if(page.pageId === lookup) return page;
for(const pageData of page.children)
{
const foundPageData = GetCatalogPageTreeById(pageData, lookup, tree);
if(foundPageData)
{
tree.push(pageData);
return pageData;
}
}
}
export function GetCatalogPageTreeByOfferId(page: INodeData, lookup: number, tree: INodeData[])
{
if(page.offerIds.indexOf(lookup) >= 0) return page;
for(const pageData of page.children)
{
const foundPageData = GetCatalogPageTreeByOfferId(pageData, lookup, tree);
if(foundPageData)
{
tree.push(pageData);
return pageData;
}
}
}
export function BuildCatalogPageTree(page: INodeData, lookup: string, isOffer: boolean = false)
{
const pageTree: INodeData[] = [];
if(isOffer)
{
GetCatalogPageTreeByOfferId(page, parseInt(lookup), pageTree);
}
else if(isNaN((lookup as unknown) as number))
{
GetCatalogPageTreeByName(page, lookup, pageTree);
}
else
{
GetCatalogPageTreeById(page, parseInt(lookup), pageTree);
}
if(pageTree.length) pageTree.reverse();
return pageTree;
}

View File

@ -1,33 +0,0 @@
import { ICatalogNode } from './ICatalogNode';
export const FilterCatalogNode = (search: string, furniLines: string[], node: ICatalogNode, nodes: ICatalogNode[]) =>
{
if(node.isVisible && (node.pageId > 0))
{
let nodeAdded = false;
const hayStack = [ node.pageName, node.localization ].join(' ').toLowerCase().replace(/ /gi, '');
if(hayStack.indexOf(search) > -1)
{
nodes.push(node);
nodeAdded = true;
}
if(!nodeAdded)
{
for(const furniLine of furniLines)
{
if(hayStack.indexOf(furniLine) >= 0)
{
nodes.push(node);
break;
}
}
}
}
for(const child of node.children) FilterCatalogNode(search, furniLines, child, nodes);
}

View File

@ -1,47 +0,0 @@
import { FurnitureType } from '@nitrots/nitro-renderer';
import { GetConfiguration, GetRoomEngine, GetSessionDataManager } from '../../../api';
export const GetProductIconUrl = (furniClassId: number, productType: string, customParams: string = null) =>
{
switch(productType.toUpperCase())
{
case FurnitureType.BADGE:
return GetSessionDataManager().getBadgeUrl(customParams);
case FurnitureType.ROBOT:
return undefined;
case FurnitureType.FLOOR:
return GetRoomEngine().getFurnitureFloorIconUrl(furniClassId);
case FurnitureType.WALL: {
const furniData = GetSessionDataManager().getWallItemData(furniClassId);
let iconName = '';
if(furniData)
{
switch(furniData.className)
{
case 'floor':
iconName = [ 'th', furniData.className, customParams ].join('_');
break;
case 'wallpaper':
iconName = [ 'th', 'wall', customParams ].join('_');
break;
case 'landscape':
iconName = [ 'th', furniData.className, (customParams || '').replace('.', '_'), '001' ].join('_');
break;
}
if(iconName !== '')
{
const assetUrl = GetConfiguration<string>('catalog.asset.url');
return `${ assetUrl }/${ iconName }.png`;
}
}
return GetRoomEngine().getFurnitureWallIconUrl(furniClassId, customParams);
}
}
return null;
}

View File

@ -21,7 +21,7 @@ export class Product implements IProduct
constructor(productType: string, productClassId: number, extraParam: string, productCount: number, productData: IProductData, furnitureData: IFurnitureData, isUniqueLimitedItem: boolean = false, uniqueLimitedItemSeriesSize: number = 0, uniqueLimitedItemsLeft: number = 0) constructor(productType: string, productClassId: number, extraParam: string, productCount: number, productData: IProductData, furnitureData: IFurnitureData, isUniqueLimitedItem: boolean = false, uniqueLimitedItemSeriesSize: number = 0, uniqueLimitedItemsLeft: number = 0)
{ {
this._productType = productType; this._productType = productType.toLowerCase();
this._productClassId = productClassId; this._productClassId = productClassId;
this._extraParam = extraParam; this._extraParam = extraParam;
this._productCount = productCount; this._productCount = productCount;

View File

@ -0,0 +1,11 @@
import { ICatalogNode } from './ICatalogNode';
import { IPurchasableOffer } from './IPurchasableOffer';
export class SearchResult
{
constructor(
public readonly searchValue: string,
public readonly offers: IPurchasableOffer[],
public readonly filteredNodes: ICatalogNode[]
) {}
}

View File

@ -4,11 +4,11 @@ export class SubscriptionInfo
private _lastUpdated: number; private _lastUpdated: number;
constructor( constructor(
public clubDays: number = 0, public readonly clubDays: number = 0,
public clubPeriods: number = 0, public readonly clubPeriods: number = 0,
public isVip: boolean = false, public readonly isVip: boolean = false,
public pastDays: number = 0, public readonly pastDays: number = 0,
public pastVipDays: number = 0) {} public readonly pastVipDays: number = 0) {}
public get lastUpdated(): number public get lastUpdated(): number
{ {

View File

@ -1,9 +1,10 @@
import { FrontPageItem } from '@nitrots/nitro-renderer'; import { FrontPageItem, RoomPreviewer } from '@nitrots/nitro-renderer';
import { createContext, Dispatch, FC, ProviderProps, SetStateAction, useContext } from 'react'; import { createContext, Dispatch, FC, ProviderProps, SetStateAction, useContext } from 'react';
import { ICatalogNode } from '../common/ICatalogNode'; import { ICatalogNode } from '../common/ICatalogNode';
import { ICatalogPage } from '../common/ICatalogPage'; import { ICatalogPage } from '../common/ICatalogPage';
import { IPageLocalization } from '../common/IPageLocalization'; import { IPageLocalization } from '../common/IPageLocalization';
import { IPurchasableOffer } from '../common/IPurchasableOffer'; import { IPurchasableOffer } from '../common/IPurchasableOffer';
import { SearchResult } from '../common/SearchResult';
import { ICatalogAction, ICatalogState } from '../reducers/CatalogReducer'; import { ICatalogAction, ICatalogState } from '../reducers/CatalogReducer';
export interface ICatalogContext export interface ICatalogContext
@ -26,8 +27,11 @@ export interface ICatalogContext
setPurchasableOffer: Dispatch<SetStateAction<IPurchasableOffer>>; setPurchasableOffer: Dispatch<SetStateAction<IPurchasableOffer>>;
activeNodes: ICatalogNode[]; activeNodes: ICatalogNode[];
setActiveNodes: Dispatch<SetStateAction<ICatalogNode[]>>; setActiveNodes: Dispatch<SetStateAction<ICatalogNode[]>>;
searchResult: SearchResult;
setSearchResult: Dispatch<SetStateAction<SearchResult>>;
frontPageItems: FrontPageItem[]; frontPageItems: FrontPageItem[];
setFrontPageItems: Dispatch<SetStateAction<FrontPageItem[]>>; setFrontPageItems: Dispatch<SetStateAction<FrontPageItem[]>>;
roomPreviewer: RoomPreviewer;
resetState: () => void; resetState: () => void;
loadCatalogPage: (pageId: number, offerId: number) => void; loadCatalogPage: (pageId: number, offerId: number) => void;
showCatalogPage: (pageId: number, layoutCode: string, localization: IPageLocalization, offers: IPurchasableOffer[], offerId: number, acceptSeasonCurrencyAsCredits: boolean) => void; showCatalogPage: (pageId: number, layoutCode: string, localization: IPageLocalization, offers: IPurchasableOffer[], offerId: number, acceptSeasonCurrencyAsCredits: boolean) => void;
@ -56,8 +60,11 @@ const CatalogContext = createContext<ICatalogContext>({
setPurchasableOffer: null, setPurchasableOffer: null,
activeNodes: null, activeNodes: null,
setActiveNodes: null, setActiveNodes: null,
searchResult: null,
setSearchResult: null,
frontPageItems: null, frontPageItems: null,
setFrontPageItems: null, setFrontPageItems: null,
roomPreviewer: null,
resetState: null, resetState: null,
loadCatalogPage: null, loadCatalogPage: null,
showCatalogPage: null, showCatalogPage: null,

View File

@ -2,7 +2,9 @@ import { FC } from 'react';
import { Column } from '../../../../common/Column'; import { Column } from '../../../../common/Column';
import { Grid } from '../../../../common/Grid'; import { Grid } from '../../../../common/Grid';
import { ICatalogNode } from '../../common/ICatalogNode'; import { ICatalogNode } from '../../common/ICatalogNode';
import { useCatalogContext } from '../../context/CatalogContext';
import { CatalogSearchView } from '../search/CatalogSearchView'; import { CatalogSearchView } from '../search/CatalogSearchView';
import { CatalogNavigationItemView } from './CatalogNavigationItemView';
import { CatalogNavigationSetView } from './CatalogNavigationSetView'; import { CatalogNavigationSetView } from './CatalogNavigationSetView';
export interface CatalogNavigationViewProps export interface CatalogNavigationViewProps
@ -13,17 +15,19 @@ export interface CatalogNavigationViewProps
export const CatalogNavigationView: FC<CatalogNavigationViewProps> = props => export const CatalogNavigationView: FC<CatalogNavigationViewProps> = props =>
{ {
const { node = null } = props; const { node = null } = props;
const { searchResult = null } = useCatalogContext();
return ( return (
<> <>
<CatalogSearchView /> <CatalogSearchView />
<Column fullHeight className="nitro-catalog-navigation-grid-container p-1" overflow="hidden"> <Column fullHeight className="nitro-catalog-navigation-grid-container p-1" overflow="hidden">
<Grid grow columnCount={ 1 } gap={ 1 } overflow="auto"> <Grid grow columnCount={ 1 } gap={ 1 } overflow="auto">
{/* { filterNodes && (filteredNodes.length > 0) && filteredNodes.map((node, index) => { searchResult && (searchResult.filteredNodes.length > 0) && searchResult.filteredNodes.map((n, index) =>
{ {
return <CatalogNavigationItemView key={ index } node={ node } isActive={ (activeNodes.indexOf(node) > -1) } selectNode={ selectNode } />; return <CatalogNavigationItemView key={ index } node={ n } />;
})} */} })}
<CatalogNavigationSetView node={ node } /> { !searchResult &&
<CatalogNavigationSetView node={ node } /> }
</Grid> </Grid>
</Column> </Column>
</> </>

View File

@ -60,7 +60,6 @@ export const CatalogPageView: FC<CatalogPageViewProps> = props =>
} }
else else
{ {
console.log('??')
roomPreviewer.addFurnitureIntoRoom(product.productClassId, new Vector3d(90), stuffData); roomPreviewer.addFurnitureIntoRoom(product.productClassId, new Vector3d(90), stuffData);
} }
return; return;

View File

@ -1,18 +1,18 @@
import { StringDataType } from '@nitrots/nitro-renderer'; import { StringDataType } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../../../api'; import { LocalizeText } from '../../../../../api';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { LayoutGridItem } from '../../../../../../common/layout/LayoutGridItem'; import { LayoutGridItem } from '../../../../../common/layout/LayoutGridItem';
import { Text } from '../../../../../../common/Text'; import { Text } from '../../../../../common/Text';
import { InventoryBadgesUpdatedEvent, SetRoomPreviewerStuffDataEvent } from '../../../../../../events'; import { InventoryBadgesUpdatedEvent, SetRoomPreviewerStuffDataEvent } from '../../../../../events';
import { InventoryBadgesRequestEvent } from '../../../../../../events/inventory/InventoryBadgesRequestEvent'; import { InventoryBadgesRequestEvent } from '../../../../../events/inventory/InventoryBadgesRequestEvent';
import { dispatchUiEvent, useUiEvent } from '../../../../../../hooks'; import { dispatchUiEvent, useUiEvent } from '../../../../../hooks';
import { BadgeImageView } from '../../../../../../views/shared/badge-image/BadgeImageView'; import { BadgeImageView } from '../../../../../views/shared/badge-image/BadgeImageView';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogProductPreviewView } from '../../offers/CatalogPageOfferPreviewView'; import { CatalogProductPreviewView } from '../offers/CatalogPageOfferPreviewView';
import { CatalogPageOffersView } from '../../offers/CatalogPageOffersView'; import { CatalogPageOffersView } from '../offers/CatalogPageOffersView';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutBadgeDisplayView: FC<CatalogLayoutProps> = props => export const CatalogLayoutBadgeDisplayView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,5 +1,5 @@
import { FC, useState } from 'react'; import { FC, useState } from 'react';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export interface CatalogLayoutColorGroupViewProps extends CatalogLayoutProps export interface CatalogLayoutColorGroupViewProps extends CatalogLayoutProps
{ {

View File

@ -1,11 +1,11 @@
import { FC } from 'react'; import { FC } from 'react';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogPageDetailsView } from '../../../page-details/CatalogPageDetailsView'; import { CatalogPageDetailsView } from '../../page-details/CatalogPageDetailsView';
import { CatalogProductPreviewView } from '../../offers/CatalogPageOfferPreviewView'; import { CatalogProductPreviewView } from '../offers/CatalogPageOfferPreviewView';
import { CatalogItemGridWidgetView } from '../../widgets/CatalogItemGridWidgetView'; import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutDefaultView: FC<CatalogLayoutProps> = props => export const CatalogLayoutDefaultView: FC<CatalogLayoutProps> = props =>
{ {
@ -16,7 +16,6 @@ export const CatalogLayoutDefaultView: FC<CatalogLayoutProps> = props =>
<Grid> <Grid>
<Column size={ 7 } overflow="hidden"> <Column size={ 7 } overflow="hidden">
<CatalogItemGridWidgetView /> <CatalogItemGridWidgetView />
{/* <CatalogPageOffersView offers={ page.offers } /> */}
</Column> </Column>
<Column size={ 5 } overflow="hidden"> <Column size={ 5 } overflow="hidden">
{ !currentOffer && { !currentOffer &&

View File

@ -1,15 +1,15 @@
import { CatalogGroupsComposer, StringDataType } from '@nitrots/nitro-renderer'; import { CatalogGroupsComposer, StringDataType } from '@nitrots/nitro-renderer';
import { FC, useEffect, useMemo, useState } from 'react'; import { FC, useEffect, useMemo, useState } from 'react';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { SetRoomPreviewerStuffDataEvent } from '../../../../../../events'; import { SetRoomPreviewerStuffDataEvent } from '../../../../../events';
import { dispatchUiEvent } from '../../../../../../hooks'; import { dispatchUiEvent } from '../../../../../hooks';
import { SendMessageHook } from '../../../../../../hooks/messages'; import { SendMessageHook } from '../../../../../hooks/messages';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogSelectGroupView } from '../../../select-group/CatalogSelectGroupView'; import { CatalogSelectGroupView } from '../../select-group/CatalogSelectGroupView';
import { CatalogProductPreviewView } from '../../offers/CatalogPageOfferPreviewView'; import { CatalogProductPreviewView } from '../offers/CatalogPageOfferPreviewView';
import { CatalogPageOffersView } from '../../offers/CatalogPageOffersView'; import { CatalogPageOffersView } from '../offers/CatalogPageOffersView';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutProps> = props => export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,13 +1,13 @@
import { CatalogGroupsComposer } from '@nitrots/nitro-renderer'; import { CatalogGroupsComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { Base } from '../../../../../../common/Base'; import { Base } from '../../../../../common/Base';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { SendMessageHook } from '../../../../../../hooks/messages'; import { SendMessageHook } from '../../../../../hooks/messages';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogSelectGroupView } from '../../../select-group/CatalogSelectGroupView'; import { CatalogSelectGroupView } from '../../select-group/CatalogSelectGroupView';
import { CatalogProductPreviewView } from '../../offers/CatalogPageOfferPreviewView'; import { CatalogProductPreviewView } from '../offers/CatalogPageOfferPreviewView';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayouGuildForumView: FC<CatalogLayoutProps> = props => export const CatalogLayouGuildForumView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,11 +1,11 @@
import { FC } from 'react'; import { FC } from 'react';
import { CreateLinkEvent, LocalizeText } from '../../../../../../api'; import { CreateLinkEvent, LocalizeText } from '../../../../../api';
import { Base } from '../../../../../../common/Base'; import { Base } from '../../../../../common/Base';
import { Button } from '../../../../../../common/Button'; import { Button } from '../../../../../common/Button';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { LayoutImage } from '../../../../../../common/layout/LayoutImage'; import { LayoutImage } from '../../../../../common/layout/LayoutImage';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayouGuildFrontpageView: FC<CatalogLayoutProps> = props => export const CatalogLayouGuildFrontpageView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,5 +1,5 @@
import { FC } from 'react'; import { FC } from 'react';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutInfoLoyaltyView: FC<CatalogLayoutProps> = props => export const CatalogLayoutInfoLoyaltyView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,6 +1,6 @@
import { FC } from 'react'; import { FC } from 'react';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
import { CatalogLayoutPets3View } from '../pets3/CatalogLayoutPets3View'; import { CatalogLayoutPets3View } from './CatalogLayoutPets3View';
export const CatalogLayoutPets2View: FC<CatalogLayoutProps> = props => export const CatalogLayoutPets2View: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,8 +1,8 @@
import { FC } from 'react'; import { FC } from 'react';
import { Base } from '../../../../../../common/Base'; import { Base } from '../../../../../common/Base';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Flex } from '../../../../../../common/Flex'; import { Flex } from '../../../../../common/Flex';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutPets3View: FC<CatalogLayoutProps> = props => export const CatalogLayoutPets3View: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,10 +1,10 @@
import { FC } from 'react'; import { FC } from 'react';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogPageDetailsView } from '../../../page-details/CatalogPageDetailsView'; import { CatalogPageDetailsView } from '../../page-details/CatalogPageDetailsView';
import { CatalogPurchaseView } from '../../purchase/CatalogPurchaseView'; import { CatalogPurchaseView } from '../purchase/CatalogPurchaseView';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutRoomBundleView: FC<CatalogLayoutProps> = props => export const CatalogLayoutRoomBundleView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -0,0 +1,35 @@
import { FC } from 'react';
import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../common/Grid';
import { Text } from '../../../../../common/Text';
import { CatalogAddOnBadgeWidgetView } from '../widgets/CatalogAddOnBadgeWidgetView';
import { CatalogBundleGridWidgetView } from '../widgets/CatalogBundleGridWidgetView';
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
import { CatalogSimplePriceWidgetView } from '../widgets/CatalogSimplePriceWidgetView';
import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutSingleBundleView: FC<CatalogLayoutProps> = props =>
{
const { page = null, roomPreviewer = null } = props;
const imageUrl = page.localization.getImage(1);
return (
<>
<Grid>
<Column justifyContent="center" size={ 7 } overflow="hidden">
<Text dangerouslySetInnerHTML={ { __html: page.localization.getText(2) } } />
<CatalogBundleGridWidgetView />
</Column>
<Column size={ 5 } overflow="hidden">
<Column fullHeight center position="relative">
<CatalogAddOnBadgeWidgetView />
<CatalogSimplePriceWidgetView />
{ imageUrl && <img className="" alt="" src={ imageUrl } /> }
</Column>
<CatalogPurchaseWidgetView />
</Column>
</Grid>
</>
);
}

View File

@ -1,15 +1,15 @@
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../../../api'; import { LocalizeText } from '../../../../../api';
import { Button } from '../../../../../../common/Button'; import { Button } from '../../../../../common/Button';
import { ButtonGroup } from '../../../../../../common/ButtonGroup'; import { ButtonGroup } from '../../../../../common/ButtonGroup';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { BatchUpdates } from '../../../../../../hooks'; import { BatchUpdates } from '../../../../../hooks';
import { IPurchasableOffer } from '../../../../common/IPurchasableOffer'; import { IPurchasableOffer } from '../../../common/IPurchasableOffer';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogProductPreviewView } from '../../offers/CatalogPageOfferPreviewView'; import { CatalogProductPreviewView } from '../offers/CatalogPageOfferPreviewView';
import { CatalogPageOffersView } from '../../offers/CatalogPageOffersView'; import { CatalogPageOffersView } from '../offers/CatalogPageOffersView';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutSpacesView: FC<CatalogLayoutProps> = props => export const CatalogLayoutSpacesView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,10 +1,10 @@
import { FC, useState } from 'react'; import { FC, useState } from 'react';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogProductPreviewView } from '../../offers/CatalogPageOfferPreviewView'; import { CatalogProductPreviewView } from '../offers/CatalogPageOfferPreviewView';
import { CatalogPageOffersView } from '../../offers/CatalogPageOffersView'; import { CatalogPageOffersView } from '../offers/CatalogPageOffersView';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutTrophiesView: FC<CatalogLayoutProps> = props => export const CatalogLayoutTrophiesView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,22 +1,22 @@
import { ClubOfferData, GetClubOffersMessageComposer, PurchaseFromCatalogComposer } from '@nitrots/nitro-renderer'; import { ClubOfferData, GetClubOffersMessageComposer, PurchaseFromCatalogComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { LocalizeText } from '../../../../../../api'; import { LocalizeText } from '../../../../../api';
import { Button } from '../../../../../../common/Button'; import { Button } from '../../../../../common/Button';
import { Column } from '../../../../../../common/Column'; import { Column } from '../../../../../common/Column';
import { Flex } from '../../../../../../common/Flex'; import { Flex } from '../../../../../common/Flex';
import { Grid } from '../../../../../../common/Grid'; import { Grid } from '../../../../../common/Grid';
import { LayoutGridItem } from '../../../../../../common/layout/LayoutGridItem'; import { LayoutGridItem } from '../../../../../common/layout/LayoutGridItem';
import { Text } from '../../../../../../common/Text'; import { Text } from '../../../../../common/Text';
import { CatalogEvent } from '../../../../../../events/catalog/CatalogEvent'; import { CatalogEvent } from '../../../../../events/catalog/CatalogEvent';
import { useUiEvent } from '../../../../../../hooks'; import { useUiEvent } from '../../../../../hooks';
import { SendMessageHook } from '../../../../../../hooks/messages/message-event'; import { SendMessageHook } from '../../../../../hooks/messages/message-event';
import { LoadingSpinnerView } from '../../../../../../layout/loading-spinner/LoadingSpinnerView'; import { LoadingSpinnerView } from '../../../../../layout/loading-spinner/LoadingSpinnerView';
import { GetCurrencyAmount } from '../../../../../../views/purse/common/CurrencyHelper'; import { GetCurrencyAmount } from '../../../../../views/purse/common/CurrencyHelper';
import { GLOBAL_PURSE } from '../../../../../../views/purse/PurseView'; import { GLOBAL_PURSE } from '../../../../../views/purse/PurseView';
import { CurrencyIcon } from '../../../../../../views/shared/currency-icon/CurrencyIcon'; import { CurrencyIcon } from '../../../../../views/shared/currency-icon/CurrencyIcon';
import { CatalogPurchaseState } from '../../../../common/CatalogPurchaseState'; import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState';
import { useCatalogContext } from '../../../../context/CatalogContext'; import { useCatalogContext } from '../../../context/CatalogContext';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
export const CatalogLayoutVipBuyView: FC<CatalogLayoutProps> = props => export const CatalogLayoutVipBuyView: FC<CatalogLayoutProps> = props =>
{ {

View File

@ -1,23 +1,23 @@
import { RoomPreviewer } from '@nitrots/nitro-renderer'; import { RoomPreviewer } from '@nitrots/nitro-renderer';
import { ICatalogPage } from '../../../common/ICatalogPage'; import { ICatalogPage } from '../../../common/ICatalogPage';
import { CatalogLayoutBadgeDisplayView } from './badge-display/CatalogLayoutBadgeDisplayView';
import { CatalogLayoutProps } from './CatalogLayout.types'; import { CatalogLayoutProps } from './CatalogLayout.types';
import { CatalogLayoutDefaultView } from './default/CatalogLayoutDefaultView'; import { CatalogLayoutBadgeDisplayView } from './CatalogLayoutBadgeDisplayView';
import { CatalogLayoutDefaultView } from './CatalogLayoutDefaultView';
import { CatalogLayouGuildCustomFurniView } from './CatalogLayoutGuildCustomFurniView';
import { CatalogLayouGuildForumView } from './CatalogLayoutGuildForumView';
import { CatalogLayouGuildFrontpageView } from './CatalogLayoutGuildFrontpageView';
import { CatalogLayoutInfoLoyaltyView } from './CatalogLayoutInfoLoyaltyView';
import { CatalogLayoutPets2View } from './CatalogLayoutPets2View';
import { CatalogLayoutPets3View } from './CatalogLayoutPets3View';
import { CatalogLayoutRoomBundleView } from './CatalogLayoutRoomBundleView';
import { CatalogLayoutSingleBundleView } from './CatalogLayoutSingleBundleView';
import { CatalogLayoutSpacesView } from './CatalogLayoutSpacesView';
import { CatalogLayoutTrophiesView } from './CatalogLayoutTrophiesView';
import { CatalogLayoutVipBuyView } from './CatalogLayoutVipBuyView';
import { CatalogLayoutFrontpage4View } from './frontpage4/CatalogLayoutFrontpage4View'; import { CatalogLayoutFrontpage4View } from './frontpage4/CatalogLayoutFrontpage4View';
import { CatalogLayouGuildCustomFurniView } from './guild-custom-furni/CatalogLayoutGuildCustomFurniView';
import { CatalogLayouGuildForumView } from './guild-forum/CatalogLayoutGuildForumView';
import { CatalogLayouGuildFrontpageView } from './guild-frontpage/CatalogLayoutGuildFrontpageView';
import { CatalogLayoutInfoLoyaltyView } from './info-loyalty/CatalogLayoutInfoLoyaltyView';
import { CatalogLayoutMarketplaceOwnItemsView } from './marketplace/CatalogLayoutMarketplaceOwnItemsView'; import { CatalogLayoutMarketplaceOwnItemsView } from './marketplace/CatalogLayoutMarketplaceOwnItemsView';
import { CatalogLayoutMarketplacePublicItemsView } from './marketplace/CatalogLayoutMarketplacePublicItemsView'; import { CatalogLayoutMarketplacePublicItemsView } from './marketplace/CatalogLayoutMarketplacePublicItemsView';
import { CatalogLayoutPetView } from './pets/CatalogLayoutPetView'; import { CatalogLayoutPetView } from './pets/CatalogLayoutPetView';
import { CatalogLayoutPets2View } from './pets2/CatalogLayoutPets2View';
import { CatalogLayoutPets3View } from './pets3/CatalogLayoutPets3View';
import { CatalogLayoutRoomBundleView } from './room-bundle/CatalogLayoutRoomBundleView';
import { CatalogLayoutSingleBundleView } from './single-bundle/CatalogLayoutSingleBundleView';
import { CatalogLayoutSpacesView } from './spaces-new/CatalogLayoutSpacesView';
import { CatalogLayoutTrophiesView } from './trophies/CatalogLayoutTrophiesView';
import { CatalogLayoutVipBuyView } from './vip-buy/CatalogLayoutVipBuyView';
import { CatalogLayoutVipGiftsView } from './vip-gifts/CatalogLayoutVipGiftsView'; import { CatalogLayoutVipGiftsView } from './vip-gifts/CatalogLayoutVipGiftsView';
export const GetCatalogLayout = (page: ICatalogPage, roomPreviewer: RoomPreviewer) => export const GetCatalogLayout = (page: ICatalogPage, roomPreviewer: RoomPreviewer) =>

View File

@ -1,26 +0,0 @@
import { FC } from 'react';
import { Column } from '../../../../../../common/Column';
import { Grid } from '../../../../../../common/Grid';
import { CatalogAddOnBadgeWidgetView } from '../../widgets/CatalogAddOnBadgeWidgetView';
import { CatalogBundleGridWidgetView } from '../../widgets/CatalogBundleGridWidgetView';
import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView';
import { CatalogSimplePriceWidgetView } from '../../widgets/CatalogSimplePriceWidgetView';
import { CatalogLayoutProps } from '../CatalogLayout.types';
export const CatalogLayoutSingleBundleView: FC<CatalogLayoutProps> = props =>
{
const { page = null, roomPreviewer = null } = props;
return (
<Grid>
<Column size={ 6 } overflow="hidden">
<CatalogAddOnBadgeWidgetView />
<CatalogSimplePriceWidgetView />
<CatalogPurchaseWidgetView />
</Column>
<Column size={ 6 } overflow="hidden">
<CatalogBundleGridWidgetView />
</Column>
</Grid>
);
}

View File

@ -1,7 +1,6 @@
import { FC } from 'react'; import { FC } from 'react';
import { LayoutGridItem, LayoutGridItemProps } from '../../../../../common/layout/LayoutGridItem'; import { LayoutGridItem, LayoutGridItemProps } from '../../../../../common/layout/LayoutGridItem';
import { AvatarImageView } from '../../../../../views/shared/avatar-image/AvatarImageView'; import { AvatarImageView } from '../../../../../views/shared/avatar-image/AvatarImageView';
import { GetProductIconUrl } from '../../../common/GetProuductIconUrl';
import { IProduct } from '../../../common/IProduct'; import { IProduct } from '../../../common/IProduct';
import { ProductTypeEnum } from '../../../common/ProductTypeEnum'; import { ProductTypeEnum } from '../../../common/ProductTypeEnum';
@ -16,7 +15,7 @@ export const CatalogProductView: FC<CatalogProductViewProps> = props =>
if(!product) return null; if(!product) return null;
const iconUrl = GetProductIconUrl(product.productClassId, product.productType, product.extraParam); const iconUrl = product.getIconUrl(null);
return ( return (
<LayoutGridItem itemImage={ iconUrl } itemCount={ product.productCount } itemUniqueSoldout={ (product.uniqueLimitedItemSeriesSize && !product.uniqueLimitedItemsLeft) } itemUniqueNumber={ product.uniqueLimitedItemSeriesSize } { ...rest }> <LayoutGridItem itemImage={ iconUrl } itemCount={ product.productCount } itemUniqueSoldout={ (product.uniqueLimitedItemSeriesSize && !product.uniqueLimitedItemsLeft) } itemUniqueNumber={ product.uniqueLimitedItemSeriesSize } { ...rest }>

View File

@ -7,17 +7,19 @@ import { Flex } from '../../../../common/Flex';
import { BatchUpdates } from '../../../../hooks'; import { BatchUpdates } from '../../../../hooks';
import { CatalogPage } from '../../common/CatalogPage'; import { CatalogPage } from '../../common/CatalogPage';
import { CatalogType } from '../../common/CatalogType'; import { CatalogType } from '../../common/CatalogType';
import { GetOfferNodes } from '../../common/CatalogUtilities'; import { FilterCatalogNode, GetOfferNodes } from '../../common/CatalogUtilities';
import { FurnitureOffer } from '../../common/FurnitureOffer'; import { FurnitureOffer } from '../../common/FurnitureOffer';
import { ICatalogNode } from '../../common/ICatalogNode';
import { ICatalogPage } from '../../common/ICatalogPage'; import { ICatalogPage } from '../../common/ICatalogPage';
import { IPurchasableOffer } from '../../common/IPurchasableOffer'; import { IPurchasableOffer } from '../../common/IPurchasableOffer';
import { PageLocalization } from '../../common/PageLocalization'; import { PageLocalization } from '../../common/PageLocalization';
import { SearchResult } from '../../common/SearchResult';
import { useCatalogContext } from '../../context/CatalogContext'; import { useCatalogContext } from '../../context/CatalogContext';
export const CatalogSearchView: FC<{}> = props => export const CatalogSearchView: FC<{}> = props =>
{ {
const [ searchValue, setSearchValue ] = useState(''); const [ searchValue, setSearchValue ] = useState('');
const { currentType = null, setActiveNodes = null, currentOffers = null, setCurrentPage = null } = useCatalogContext(); const { currentType = null, rootNode = null, setActiveNodes = null, currentOffers = null, searchResult = null, setSearchResult = null, setCurrentPage = null } = useCatalogContext();
const processSearch = useCallback((search: string) => const processSearch = useCallback((search: string) =>
{ {
@ -69,12 +71,17 @@ export const CatalogSearchView: FC<{}> = props =>
for(const furniture of foundFurniture) offers.push(new FurnitureOffer(furniture)); for(const furniture of foundFurniture) offers.push(new FurnitureOffer(furniture));
let nodes: ICatalogNode[] = [];
FilterCatalogNode(search, foundFurniLines, rootNode, nodes);
BatchUpdates(() => BatchUpdates(() =>
{ {
setCurrentPage((new CatalogPage(-1, 'default_3x3', new PageLocalization([], []), offers, false, 1) as ICatalogPage)); setCurrentPage((new CatalogPage(-1, 'default_3x3', new PageLocalization([], []), offers, false, 1) as ICatalogPage));
setSearchResult(new SearchResult(search, offers, nodes.filter(node => (node.isVisible))));
setActiveNodes([]); setActiveNodes([]);
}); });
}, [ currentOffers, currentType, setCurrentPage, setActiveNodes ]); }, [ currentOffers, currentType, rootNode, setCurrentPage, setSearchResult, setActiveNodes ]);
useEffect(() => useEffect(() =>
{ {

View File

@ -1,4 +1,4 @@
import { FC } from 'react'; import { Dispatch, FC, SetStateAction } from 'react';
import { NitroCardTabsItemView } from '../../../../layout'; import { NitroCardTabsItemView } from '../../../../layout';
import { ICatalogNode } from '../../common/ICatalogNode'; import { ICatalogNode } from '../../common/ICatalogNode';
@ -6,18 +6,13 @@ interface CatalogTabsViewsProps
{ {
node: ICatalogNode; node: ICatalogNode;
currentTab: ICatalogNode; currentTab: ICatalogNode;
setCurrentTab: (node: ICatalogNode) => void; setCurrentTab: Dispatch<SetStateAction<ICatalogNode>>;
} }
export const CatalogTabsViews: FC<CatalogTabsViewsProps> = props => export const CatalogTabsViews: FC<CatalogTabsViewsProps> = props =>
{ {
const { node = null, currentTab = null, setCurrentTab = null } = props; const { node = null, currentTab = null, setCurrentTab = null } = props;
const selectNode = (node: ICatalogNode) =>
{
setCurrentTab(node);
}
return ( return (
<> <>
{ node && (node.children.length > 0) && node.children.map(child => { node && (node.children.length > 0) && node.children.map(child =>
@ -25,7 +20,7 @@ export const CatalogTabsViews: FC<CatalogTabsViewsProps> = props =>
if(!child.isVisible) return null; if(!child.isVisible) return null;
return ( return (
<NitroCardTabsItemView key={ child.pageId } isActive={ (currentTab === child) } onClick={ event => selectNode(child) }> <NitroCardTabsItemView key={ child.pageId } isActive={ (currentTab === child) } onClick={ event => setCurrentTab(child) }>
{ child.localization } { child.localization }
</NitroCardTabsItemView> </NitroCardTabsItemView>
); );

View File

@ -1,7 +1,7 @@
import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, Wait } from '@nitrots/nitro-renderer'; import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, Wait } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { CreateLinkEvent, GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GetUserProfile, GoToDesktop, OpenMessengerChat } from '../../api'; import { CreateLinkEvent, GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GetUserProfile, GoToDesktop, OpenMessengerChat } from '../../api';
import { AvatarEditorEvent, CatalogEvent, FriendsEvent, FriendsMessengerIconEvent, FriendsRequestCountEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events'; import { AvatarEditorEvent, FriendsEvent, FriendsMessengerIconEvent, FriendsRequestCountEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events';
import { AchievementsUIEvent, AchievementsUIUnseenCountEvent } from '../../events/achievements'; import { AchievementsUIEvent, AchievementsUIUnseenCountEvent } from '../../events/achievements';
import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent'; import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent';
import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent';
@ -139,10 +139,10 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
dispatchUiEvent(new InventoryEvent(InventoryEvent.TOGGLE_INVENTORY)); dispatchUiEvent(new InventoryEvent(InventoryEvent.TOGGLE_INVENTORY));
return; return;
case ToolbarViewItems.CATALOG_ITEM: case ToolbarViewItems.CATALOG_ITEM:
dispatchUiEvent(new CatalogEvent(CatalogEvent.TOGGLE_CATALOG)); CreateLinkEvent('catalog/toggle');
return; return;
case ToolbarViewItems.FRIEND_LIST_ITEM: case ToolbarViewItems.FRIEND_LIST_ITEM:
dispatchUiEvent(new CatalogEvent(FriendsEvent.TOGGLE_FRIEND_LIST)); dispatchUiEvent(new FriendsEvent(FriendsEvent.TOGGLE_FRIEND_LIST));
return; return;
case ToolbarViewItems.CAMERA_ITEM: case ToolbarViewItems.CAMERA_ITEM:
dispatchUiEvent(new RoomWidgetCameraEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA)); dispatchUiEvent(new RoomWidgetCameraEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA));

View File

@ -0,0 +1,26 @@
import { NitroEvent } from '@nitrots/nitro-renderer';
import { CatalogWidgetEvent } from './CatalogWidgetEvent';
export class CatalogInitPurchaseEvent extends NitroEvent
{
private _enableBuyAsGift: boolean = true;
private _userName: string;
constructor(enableBuyAsGift: boolean = true, userName: string = null)
{
super(CatalogWidgetEvent.INIT_PURCHASE);
this._enableBuyAsGift = enableBuyAsGift;
this._userName = userName;
}
public get enableBuyAsGift(): boolean
{
return this._enableBuyAsGift;
}
public get userName(): string
{
return this._userName;
}
}

View File

@ -0,0 +1,19 @@
import { NitroEvent } from '@nitrots/nitro-renderer';
import { CatalogWidgetEvent } from './CatalogWidgetEvent';
export class CatalogPurchaseOverrideEvent extends NitroEvent
{
private _callback: Function;
constructor(callback: Function)
{
super(CatalogWidgetEvent.PURCHASE_OVERRIDE);
this._callback = callback;
}
public get callback(): Function
{
return this._callback;
}
}

View File

@ -1,15 +1,14 @@
import { NitroEvent } from '@nitrots/nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { IPurchasableOffer } from '../../components/catalog/common/IPurchasableOffer'; import { IPurchasableOffer } from '../../components/catalog/common/IPurchasableOffer';
import { CatalogWidgetEvent } from './CatalogWidgetEvent';
export class CatalogSelectProductEvent extends NitroEvent export class CatalogSelectProductEvent extends NitroEvent
{ {
public static SELECT_PRODUCT: string = 'CSPE_SELECT_PRODUCT';
private _offer: IPurchasableOffer; private _offer: IPurchasableOffer;
constructor(offer: IPurchasableOffer) constructor(offer: IPurchasableOffer)
{ {
super(CatalogSelectProductEvent.SELECT_PRODUCT); super(CatalogWidgetEvent.SELECT_PRODUCT);
this._offer = offer; this._offer = offer;
} }

View File

@ -1,14 +1,13 @@
import { NitroEvent } from '@nitrots/nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { CatalogWidgetEvent } from './CatalogWidgetEvent';
export class CatalogSetExtraPurchaseParameterEvent extends NitroEvent export class CatalogSetExtraPurchaseParameterEvent extends NitroEvent
{ {
public static SET_EXTRA_PARAM: string = 'CSEPPE_SET_EXTRA_PARAM';
private _parameter: string; private _parameter: string;
constructor(parameter: string) constructor(parameter: string)
{ {
super(CatalogSetExtraPurchaseParameterEvent.SET_EXTRA_PARAM); super(CatalogWidgetEvent.SET_EXTRA_PARM);
this._parameter = parameter; this._parameter = parameter;
} }

View File

@ -0,0 +1,19 @@
import { IObjectData, NitroEvent } from '@nitrots/nitro-renderer';
import { CatalogWidgetEvent } from './CatalogWidgetEvent';
export class CatalogSetRoomPreviewerStuffDataEvent extends NitroEvent
{
private _stuffData: IObjectData;
constructor(stuffData: IObjectData)
{
super(CatalogWidgetEvent.SET_PREVIEWER_STUFFDATA);
this._stuffData = stuffData;
}
public get stuffData(): IObjectData
{
return this._stuffData;
}
}

View File

@ -0,0 +1,28 @@
import { NitroEvent } from '@nitrots/nitro-renderer';
export class CatalogWidgetEvent extends NitroEvent
{
public static WIDGETS_INITIALIZED: string = 'CWE_CWE_WIDGETS_INITIALIZED';
public static SELECT_PRODUCT: string = 'CWE_SELECT_PRODUCT';
public static SET_EXTRA_PARM: string = 'CWE_CWE_SET_EXTRA_PARM';
public static PURCHASE: string = 'CWE_PURCHASE';
public static COLOUR_ARRAY: string = 'CWE_COLOUR_ARRAY';
public static MULTI_COLOUR_ARRAY: string = 'CWE_MULTI_COLOUR_ARRAY';
public static COLOUR_INDEX: string = 'CWE_COLOUR_INDEX';
public static TEXT_INPUT: string = 'CWE_TEXT_INPUT';
public static DROPMENU_SELECT: string = 'CWE_CWE_DROPMENU_SELECT';
public static APPROVE_RESULT: string = 'CWE_CWE_APPROVE_RESULT';
public static PURCHASE_OVERRIDE: string = 'CWE_PURCHASE_OVERRIDE';
public static SELLABLE_PET_PALETTES: string = 'CWE_SELLABLE_PET_PALETTES';
public static INIT_PURCHASE: string = 'CWE_INIT_PURCHASE';
public static UPDATE_ROOM_PREVIEW: string = 'CWE_UPDATE_ROOM_PREVIEW';
public static GUILD_SELECTED: string = 'CWE_GUILD_SELECTED';
public static TOTAL_PRICE_WIDGET_INITIALIZED: string = 'CWE_TOTAL_PRICE_WIDGET_INITIALIZED';
public static PRODUCT_OFFER_UPDATED: string = 'CWE_CWE_PRODUCT_OFFER_UPDATED';
public static SET_PREVIEWER_STUFFDATA: string = 'CWE_CWE_SET_PREVIEWER_STUFFDATA';
public static EXTRA_PARAM_REQUIRED_FOR_BUY: string = 'CWE_CWE_EXTRA_PARAM_REQUIRED_FOR_BUY';
public static TOGGLE: string = 'CWE_CWE_TOGGLE';
public static BUILDER_SUBSCRIPTION_UPDATED: string = 'CWE_CWE_BUILDER_SUBSCRIPTION_UPDATED';
public static ROOM_CHANGED: string = 'CWE_CWE_ROOM_CHANGED';
public static SHOW_WARNING_TEXT: string = 'CWE_CWE_SHOW_WARNING_TEXT';
}