mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
feat: add builders club catalog ui flow
This commit is contained in:
+135
-29
@@ -1,4 +1,4 @@
|
||||
import { BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, CreateLinkEvent, FrontPageItem, FurniturePlaceComposer, FurniturePlacePaintComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GetRoomEngine, GetTickerTime, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LegacyDataType, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, RoomPreviewer, SellablePetPalettesMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
|
||||
import { BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, CreateLinkEvent, FrontPageItem, FurniturePlaceComposer, FurniturePlacePaintComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GetRoomEngine, GetSessionDataManager, GetTickerTime, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LegacyDataType, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, RoomPreviewer, SellablePetPalettesMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { BuilderFurniPlaceableStatus, CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, DispatchUiEvent, FurniCategory, GetFurnitureData, GetProductDataForLocalization, GetRoomSession, GiftWrappingConfiguration, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, Offer, PageLocalization, PlacedObjectPurchaseData, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api';
|
||||
@@ -40,7 +40,10 @@ const useCatalogState = () =>
|
||||
const [ secondsLeft, setSecondsLeft ] = useState(0);
|
||||
const [ updateTime, setUpdateTime ] = useState(0);
|
||||
const [ secondsLeftWithGrace, setSecondsLeftWithGrace ] = useState(0);
|
||||
const { simpleAlert = null } = useNotification();
|
||||
const [ builderPlacementBlockedByVisitors, setBuilderPlacementBlockedByVisitors ] = useState(false);
|
||||
const [ builderPlacementAllowedInCurrentRoom, setBuilderPlacementAllowedInCurrentRoom ] = useState(false);
|
||||
const [ builderTrialRoomHideConfirmed, setBuilderTrialRoomHideConfirmed ] = useState(false);
|
||||
const { simpleAlert = null, showConfirm = null } = useNotification();
|
||||
const requestedPage = useRef(new RequestedPage());
|
||||
|
||||
const resetState = useCallback(() =>
|
||||
@@ -57,37 +60,108 @@ const useCatalogState = () =>
|
||||
setIsVisible(false);
|
||||
}, []);
|
||||
|
||||
const normalizeCatalogType = useCallback((type?: string) =>
|
||||
{
|
||||
if(type === CatalogType.BUILDER) return CatalogType.BUILDER;
|
||||
|
||||
return CatalogType.NORMAL;
|
||||
}, []);
|
||||
|
||||
const resetVisibleCatalogState = useCallback((type?: string) =>
|
||||
{
|
||||
requestedPage.current.resetRequest();
|
||||
|
||||
setPageId(-1);
|
||||
setPreviousPageId(-1);
|
||||
setRootNode(null);
|
||||
setOffersToNodes(null);
|
||||
setCurrentPage(null);
|
||||
setCurrentOffer(null);
|
||||
setActiveNodes([]);
|
||||
setSearchResult(null);
|
||||
setFrontPageItems([]);
|
||||
setNavigationHidden(false);
|
||||
setCurrentType(normalizeCatalogType(type));
|
||||
}, [ normalizeCatalogType ]);
|
||||
|
||||
const openCatalogByType = useCallback((type?: string) =>
|
||||
{
|
||||
const catalogType = normalizeCatalogType(type);
|
||||
|
||||
if(currentType !== catalogType)
|
||||
{
|
||||
resetVisibleCatalogState(catalogType);
|
||||
}
|
||||
|
||||
setIsVisible(true);
|
||||
}, [ currentType, normalizeCatalogType, resetVisibleCatalogState ]);
|
||||
|
||||
const toggleCatalogByType = useCallback((type?: string) =>
|
||||
{
|
||||
const catalogType = normalizeCatalogType(type);
|
||||
|
||||
if(isVisible && (currentType === catalogType))
|
||||
{
|
||||
setIsVisible(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(currentType !== catalogType)
|
||||
{
|
||||
resetVisibleCatalogState(catalogType);
|
||||
}
|
||||
|
||||
setIsVisible(true);
|
||||
}, [ isVisible, currentType, normalizeCatalogType, resetVisibleCatalogState ]);
|
||||
|
||||
const getBuilderFurniPlaceableStatus = useCallback((offer: IPurchasableOffer) =>
|
||||
{
|
||||
if(!offer) return BuilderFurniPlaceableStatus.MISSING_OFFER;
|
||||
|
||||
if((furniCount < 0) || (furniCount >= furniLimit)) return BuilderFurniPlaceableStatus.FURNI_LIMIT_REACHED;
|
||||
|
||||
const roomSession = GetRoomSession();
|
||||
const canUseGuildAdminFallback = (!!roomSession
|
||||
&& roomSession.isGuildRoom
|
||||
&& (roomSession.controllerLevel >= RoomControllerLevel.GUILD_ADMIN)
|
||||
&& (secondsLeft > 0));
|
||||
const usesSharedPlacementPool = (!!roomSession && !roomSession.isRoomOwner && (builderPlacementAllowedInCurrentRoom || canUseGuildAdminFallback));
|
||||
|
||||
if(!roomSession) return BuilderFurniPlaceableStatus.NOT_IN_ROOM;
|
||||
|
||||
if(!roomSession.isRoomOwner) return BuilderFurniPlaceableStatus.NOT_ROOM_OWNER;
|
||||
if(!roomSession.isRoomOwner && !builderPlacementAllowedInCurrentRoom && !canUseGuildAdminFallback) return BuilderFurniPlaceableStatus.NOT_GROUP_ADMIN;
|
||||
|
||||
if(!usesSharedPlacementPool && ((furniCount < 0) || (furniCount >= furniLimit))) return BuilderFurniPlaceableStatus.FURNI_LIMIT_REACHED;
|
||||
|
||||
if((secondsLeft <= 0) && builderPlacementBlockedByVisitors) return BuilderFurniPlaceableStatus.VISITORS_IN_ROOM;
|
||||
|
||||
if(secondsLeft <= 0)
|
||||
{
|
||||
const roomEngine = GetRoomEngine();
|
||||
const userDataManager = roomSession.userDataManager;
|
||||
const sessionDataManager = GetSessionDataManager();
|
||||
|
||||
let objectCount = roomEngine.getRoomObjectCount(roomSession.roomId, RoomObjectCategory.UNIT);
|
||||
if(!roomEngine || !userDataManager || !sessionDataManager) return BuilderFurniPlaceableStatus.OKAY;
|
||||
|
||||
while(objectCount > 0)
|
||||
const roomObjects = roomEngine.getRoomObjects(roomSession.roomId, RoomObjectCategory.UNIT);
|
||||
|
||||
if(!roomObjects || !roomObjects.length) return BuilderFurniPlaceableStatus.OKAY;
|
||||
|
||||
for(const roomObject of roomObjects)
|
||||
{
|
||||
const roomObject = roomEngine.getRoomObjectByIndex(roomSession.roomId, objectCount, RoomObjectCategory.UNIT);
|
||||
const userData = roomSession.userDataManager.getUserDataByIndex(roomObject.id);
|
||||
if(!roomObject) continue;
|
||||
|
||||
if(userData && (userData.type === RoomObjectType.USER) && (userData.roomIndex !== roomSession.ownRoomIndex) && !userData.isModerator) return BuilderFurniPlaceableStatus.VISITORS_IN_ROOM;
|
||||
const userData = userDataManager.getUserDataByIndex(roomObject.id);
|
||||
|
||||
objectCount--;
|
||||
if(!userData || (userData.type !== RoomObjectType.USER)) continue;
|
||||
if(userData.webID === sessionDataManager.userId) continue;
|
||||
if(userData.isModerator) continue;
|
||||
|
||||
return BuilderFurniPlaceableStatus.VISITORS_IN_ROOM;
|
||||
}
|
||||
}
|
||||
|
||||
return BuilderFurniPlaceableStatus.OKAY;
|
||||
}, [ furniCount, furniLimit, secondsLeft ]);
|
||||
}, [ builderPlacementAllowedInCurrentRoom, builderPlacementBlockedByVisitors, furniCount, furniLimit, secondsLeft ]);
|
||||
|
||||
const isDraggable = useCallback((offer: IPurchasableOffer) =>
|
||||
{
|
||||
@@ -419,6 +493,10 @@ const useCatalogState = () =>
|
||||
useMessageEvent<CatalogPagesListEvent>(CatalogPagesListEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const parserCatalogType = normalizeCatalogType(parser.catalogType);
|
||||
|
||||
if(parserCatalogType !== currentType) return;
|
||||
|
||||
const offers: Map<number, ICatalogNode[]> = new Map();
|
||||
|
||||
const getCatalogNode = (node: NodeData, depth: number, parent: ICatalogNode) =>
|
||||
@@ -589,9 +667,14 @@ const useCatalogState = () =>
|
||||
|
||||
setCatalogOptions(prevValue =>
|
||||
{
|
||||
const clubOffers = parser.offers;
|
||||
const windowId = parser.windowId;
|
||||
const clubOffersByWindowId = { ...(prevValue.clubOffersByWindowId || {}) };
|
||||
|
||||
return { ...prevValue, clubOffers };
|
||||
clubOffersByWindowId[windowId] = parser.offers;
|
||||
|
||||
const clubOffers = clubOffersByWindowId[1] || prevValue.clubOffers;
|
||||
|
||||
return { ...prevValue, clubOffers, clubOffersByWindowId };
|
||||
});
|
||||
});
|
||||
|
||||
@@ -679,6 +762,8 @@ const useCatalogState = () =>
|
||||
setSecondsLeft(parser.secondsLeft);
|
||||
setUpdateTime(GetTickerTime());
|
||||
setSecondsLeftWithGrace(parser.secondsLeftWithGrace);
|
||||
setBuilderPlacementBlockedByVisitors(parser.placementBlockedByVisitors);
|
||||
setBuilderPlacementAllowedInCurrentRoom(parser.placementAllowedInCurrentRoom);
|
||||
|
||||
refreshBuilderStatus();
|
||||
});
|
||||
@@ -772,24 +857,40 @@ const useCatalogState = () =>
|
||||
break;
|
||||
}
|
||||
case CatalogType.BUILDER: {
|
||||
let pageId = purchasableOffer.page.pageId;
|
||||
|
||||
if(pageId === DUMMY_PAGE_ID_FOR_OFFER_SEARCH)
|
||||
const placeBuilderItem = () =>
|
||||
{
|
||||
pageId = -1;
|
||||
}
|
||||
let pageId = purchasableOffer.page.pageId;
|
||||
|
||||
switch(event.category)
|
||||
if(pageId === DUMMY_PAGE_ID_FOR_OFFER_SEARCH)
|
||||
{
|
||||
pageId = -1;
|
||||
}
|
||||
|
||||
switch(event.category)
|
||||
{
|
||||
case RoomObjectCategory.FLOOR:
|
||||
SendMessageComposer(new BuildersClubPlaceRoomItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.x, event.y, event.direction));
|
||||
break;
|
||||
case RoomObjectCategory.WALL:
|
||||
SendMessageComposer(new BuildersClubPlaceWallItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.wallLocation));
|
||||
break;
|
||||
}
|
||||
|
||||
if(catalogPlaceMultipleObjects && ((furniCount + 1) < furniLimit)) requestOfferToMover(purchasableOffer);
|
||||
};
|
||||
|
||||
if((secondsLeft <= 0) && (furniCount <= 0) && !builderTrialRoomHideConfirmed && showConfirm)
|
||||
{
|
||||
case RoomObjectCategory.FLOOR:
|
||||
SendMessageComposer(new BuildersClubPlaceRoomItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.x, event.y, event.direction));
|
||||
break;
|
||||
case RoomObjectCategory.WALL:
|
||||
SendMessageComposer(new BuildersClubPlaceWallItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.wallLocation));
|
||||
break;
|
||||
showConfirm(LocalizeText('room.confirm.hide_room'), () =>
|
||||
{
|
||||
setBuilderTrialRoomHideConfirmed(true);
|
||||
placeBuilderItem();
|
||||
}, () => resetPlacedOfferData());
|
||||
}
|
||||
else
|
||||
{
|
||||
placeBuilderItem();
|
||||
}
|
||||
|
||||
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -882,6 +983,11 @@ const useCatalogState = () =>
|
||||
setPurchaseOptions({ quantity: 1, extraData: null, extraParamRequired: false, previewStuffData: null });
|
||||
}, [ currentOffer ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(secondsLeft > 0) setBuilderTrialRoomHideConfirmed(false);
|
||||
}, [ secondsLeft ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!isVisible || rootNode) return;
|
||||
@@ -907,7 +1013,7 @@ const useCatalogState = () =>
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { isVisible, setIsVisible, isBusy, pageId, previousPageId, currentType, rootNode, offersToNodes, currentPage, setCurrentPage, currentOffer, setCurrentOffer, activeNodes, searchResult, setSearchResult, frontPageItems, roomPreviewer, navigationHidden, setNavigationHidden, purchaseOptions, setPurchaseOptions, catalogOptions, setCatalogOptions, getNodeById, getNodeByName, activateNode, openPageById, openPageByName, openPageByOfferId, requestOfferToMover };
|
||||
return { isVisible, setIsVisible, isBusy, pageId, previousPageId, currentType, rootNode, offersToNodes, currentPage, setCurrentPage, currentOffer, setCurrentOffer, activeNodes, searchResult, setSearchResult, frontPageItems, roomPreviewer, navigationHidden, setNavigationHidden, purchaseOptions, setPurchaseOptions, catalogOptions, setCatalogOptions, getNodeById, getNodeByName, activateNode, openPageById, openPageByName, openPageByOfferId, requestOfferToMover, openCatalogByType, toggleCatalogByType, furniCount, furniLimit, maxFurniLimit, secondsLeft, secondsLeftWithGrace, updateTime, catalogPlaceMultipleObjects, setCatalogPlaceMultipleObjects, getBuilderFurniPlaceableStatus };
|
||||
};
|
||||
|
||||
export const useCatalog = () => useBetween(useCatalogState);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { CatalogType } from '../../api';
|
||||
import { useCatalog } from './useCatalog';
|
||||
|
||||
export interface IFavoriteOffer
|
||||
{
|
||||
@@ -8,15 +10,22 @@ export interface IFavoriteOffer
|
||||
iconUrl?: string;
|
||||
}
|
||||
|
||||
const STORAGE_KEY_OFFERS = 'catalog_fav_offers_v2';
|
||||
const STORAGE_KEY_PAGES = 'catalog_fav_pages';
|
||||
const LEGACY_STORAGE_KEY_OFFERS = 'catalog_fav_offers_v2';
|
||||
const LEGACY_STORAGE_KEY_PAGES = 'catalog_fav_pages';
|
||||
const STORAGE_KEY_OFFERS_NORMAL = 'catalog_fav_offers_v3_normal';
|
||||
const STORAGE_KEY_OFFERS_BUILDER = 'catalog_fav_offers_v3_builder';
|
||||
const STORAGE_KEY_PAGES_NORMAL = 'catalog_fav_pages_v2_normal';
|
||||
const STORAGE_KEY_PAGES_BUILDER = 'catalog_fav_pages_v2_builder';
|
||||
|
||||
const readOffers = (): IFavoriteOffer[] =>
|
||||
const normalizeCatalogType = (catalogType?: string) => ((catalogType === CatalogType.BUILDER) ? CatalogType.BUILDER : CatalogType.NORMAL);
|
||||
|
||||
const getOffersStorageKey = (catalogType?: string) => ((normalizeCatalogType(catalogType) === CatalogType.BUILDER) ? STORAGE_KEY_OFFERS_BUILDER : STORAGE_KEY_OFFERS_NORMAL);
|
||||
const getPagesStorageKey = (catalogType?: string) => ((normalizeCatalogType(catalogType) === CatalogType.BUILDER) ? STORAGE_KEY_PAGES_BUILDER : STORAGE_KEY_PAGES_NORMAL);
|
||||
|
||||
const parseOffers = (raw: string): IFavoriteOffer[] =>
|
||||
{
|
||||
try
|
||||
{
|
||||
const raw = localStorage.getItem(STORAGE_KEY_OFFERS);
|
||||
if(!raw) return [];
|
||||
const parsed = JSON.parse(raw);
|
||||
if(!Array.isArray(parsed)) return [];
|
||||
|
||||
@@ -34,12 +43,10 @@ const readOffers = (): IFavoriteOffer[] =>
|
||||
}
|
||||
};
|
||||
|
||||
const readPages = (): number[] =>
|
||||
const parsePages = (raw: string): number[] =>
|
||||
{
|
||||
try
|
||||
{
|
||||
const raw = localStorage.getItem(STORAGE_KEY_PAGES);
|
||||
if(!raw) return [];
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed) ? parsed : [];
|
||||
}
|
||||
@@ -49,28 +56,92 @@ const readPages = (): number[] =>
|
||||
}
|
||||
};
|
||||
|
||||
const writeOffers = (offers: IFavoriteOffer[]) =>
|
||||
const readOffers = (catalogType?: string): IFavoriteOffer[] =>
|
||||
{
|
||||
localStorage.setItem(STORAGE_KEY_OFFERS, JSON.stringify(offers));
|
||||
const storageKey = getOffersStorageKey(catalogType);
|
||||
const raw = localStorage.getItem(storageKey);
|
||||
|
||||
if(raw) return parseOffers(raw);
|
||||
|
||||
if(normalizeCatalogType(catalogType) === CatalogType.NORMAL)
|
||||
{
|
||||
const legacyRaw = localStorage.getItem(LEGACY_STORAGE_KEY_OFFERS);
|
||||
|
||||
if(legacyRaw)
|
||||
{
|
||||
const migrated = parseOffers(legacyRaw);
|
||||
|
||||
localStorage.setItem(storageKey, JSON.stringify(migrated));
|
||||
|
||||
return migrated;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
const writePages = (ids: number[]) =>
|
||||
const readPages = (catalogType?: string): number[] =>
|
||||
{
|
||||
localStorage.setItem(STORAGE_KEY_PAGES, JSON.stringify(ids));
|
||||
const storageKey = getPagesStorageKey(catalogType);
|
||||
const raw = localStorage.getItem(storageKey);
|
||||
|
||||
if(raw) return parsePages(raw);
|
||||
|
||||
if(normalizeCatalogType(catalogType) === CatalogType.NORMAL)
|
||||
{
|
||||
const legacyRaw = localStorage.getItem(LEGACY_STORAGE_KEY_PAGES);
|
||||
|
||||
if(legacyRaw)
|
||||
{
|
||||
const migrated = parsePages(legacyRaw);
|
||||
|
||||
localStorage.setItem(storageKey, JSON.stringify(migrated));
|
||||
|
||||
return migrated;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
const writeOffers = (catalogType: string, offers: IFavoriteOffer[]) =>
|
||||
{
|
||||
localStorage.setItem(getOffersStorageKey(catalogType), JSON.stringify(offers));
|
||||
};
|
||||
|
||||
const writePages = (catalogType: string, ids: number[]) =>
|
||||
{
|
||||
localStorage.setItem(getPagesStorageKey(catalogType), JSON.stringify(ids));
|
||||
};
|
||||
|
||||
const useCatalogFavoritesState = () =>
|
||||
{
|
||||
const [ favoriteOffers, setFavoriteOffers ] = useState<IFavoriteOffer[]>([]);
|
||||
const [ favoritePageIds, setFavoritePageIds ] = useState<number[]>([]);
|
||||
const { currentType = CatalogType.NORMAL } = useCatalog();
|
||||
const catalogType = normalizeCatalogType(currentType);
|
||||
const [ favoriteOffersByType, setFavoriteOffersByType ] = useState<Record<string, IFavoriteOffer[]>>({
|
||||
[CatalogType.NORMAL]: [],
|
||||
[CatalogType.BUILDER]: []
|
||||
});
|
||||
const [ favoritePageIdsByType, setFavoritePageIdsByType ] = useState<Record<string, number[]>>({
|
||||
[CatalogType.NORMAL]: [],
|
||||
[CatalogType.BUILDER]: []
|
||||
});
|
||||
const [ loaded, setLoaded ] = useState(false);
|
||||
const favoriteOffers = favoriteOffersByType[catalogType] || [];
|
||||
const favoritePageIds = favoritePageIdsByType[catalogType] || [];
|
||||
|
||||
const favoriteOfferIds = favoriteOffers.map(f => f.offerId);
|
||||
|
||||
const loadFavorites = useCallback(() =>
|
||||
{
|
||||
setFavoriteOffers(readOffers());
|
||||
setFavoritePageIds(readPages());
|
||||
setFavoriteOffersByType({
|
||||
[CatalogType.NORMAL]: readOffers(CatalogType.NORMAL),
|
||||
[CatalogType.BUILDER]: readOffers(CatalogType.BUILDER)
|
||||
});
|
||||
setFavoritePageIdsByType({
|
||||
[CatalogType.NORMAL]: readPages(CatalogType.NORMAL),
|
||||
[CatalogType.BUILDER]: readPages(CatalogType.BUILDER)
|
||||
});
|
||||
setLoaded(true);
|
||||
}, []);
|
||||
|
||||
@@ -81,32 +152,37 @@ const useCatalogFavoritesState = () =>
|
||||
|
||||
const toggleFavoriteOffer = useCallback((offerId: number, name?: string, iconUrl?: string) =>
|
||||
{
|
||||
setFavoriteOffers(prev =>
|
||||
setFavoriteOffersByType(prev =>
|
||||
{
|
||||
const exists = prev.find(f => f.offerId === offerId);
|
||||
const currentOffers = prev[catalogType] || [];
|
||||
const exists = currentOffers.find(f => f.offerId === offerId);
|
||||
|
||||
if(exists)
|
||||
{
|
||||
const next = prev.filter(f => f.offerId !== offerId);
|
||||
writeOffers(next);
|
||||
return next;
|
||||
const next = currentOffers.filter(f => f.offerId !== offerId);
|
||||
writeOffers(catalogType, next);
|
||||
|
||||
return { ...prev, [catalogType]: next };
|
||||
}
|
||||
|
||||
const next = [ ...prev, { offerId, name, iconUrl } ];
|
||||
writeOffers(next);
|
||||
return next;
|
||||
const next = [ ...currentOffers, { offerId, name, iconUrl } ];
|
||||
writeOffers(catalogType, next);
|
||||
|
||||
return { ...prev, [catalogType]: next };
|
||||
});
|
||||
}, []);
|
||||
}, [ catalogType ]);
|
||||
|
||||
const toggleFavoritePage = useCallback((pageId: number) =>
|
||||
{
|
||||
setFavoritePageIds(prev =>
|
||||
setFavoritePageIdsByType(prev =>
|
||||
{
|
||||
const next = prev.includes(pageId) ? prev.filter(id => id !== pageId) : [ ...prev, pageId ];
|
||||
writePages(next);
|
||||
return next;
|
||||
const currentPages = prev[catalogType] || [];
|
||||
const next = currentPages.includes(pageId) ? currentPages.filter(id => id !== pageId) : [ ...currentPages, pageId ];
|
||||
writePages(catalogType, next);
|
||||
|
||||
return { ...prev, [catalogType]: next };
|
||||
});
|
||||
}, []);
|
||||
}, [ catalogType ]);
|
||||
|
||||
const isFavoriteOffer = useCallback((offerId: number) =>
|
||||
{
|
||||
@@ -123,7 +199,7 @@ const useCatalogFavoritesState = () =>
|
||||
return favoriteOffers.find(f => f.offerId === offerId);
|
||||
}, [ favoriteOffers ]);
|
||||
|
||||
return { favoriteOffers, favoriteOfferIds, favoritePageIds, loaded, loadFavorites, toggleFavoriteOffer, toggleFavoritePage, isFavoriteOffer, isFavoritePage, getFavoriteOffer };
|
||||
return { favoriteOffers, favoriteOfferIds, favoritePageIds, loaded, loadFavorites, toggleFavoriteOffer, toggleFavoritePage, isFavoriteOffer, isFavoritePage, getFavoriteOffer, catalogType };
|
||||
};
|
||||
|
||||
export const useCatalogFavorites = () => useBetween(useCatalogFavoritesState);
|
||||
|
||||
Reference in New Issue
Block a user