diff --git a/src/components/catalog/views/page/widgets/CatalogAddOnBadgeWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogAddOnBadgeWidgetView.tsx index 0e38349d..c9610b02 100644 --- a/src/components/catalog/views/page/widgets/CatalogAddOnBadgeWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogAddOnBadgeWidgetView.tsx @@ -1,6 +1,7 @@ import { FC, useCallback, useState } from 'react'; import { BaseProps } from '../../../../../common/Base'; import { CatalogSelectProductEvent } from '../../../../../events'; +import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent'; import { useUiEvent } from '../../../../../hooks'; import { BadgeImageView } from '../../../../../views/shared/badge-image/BadgeImageView'; @@ -19,7 +20,7 @@ export const CatalogAddOnBadgeWidgetView: FC = if(event.offer.badgeCode) setBadgeCode(event.offer.badgeCode); }, []); - useUiEvent(CatalogSelectProductEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); + useUiEvent(CatalogWidgetEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); if(!badgeCode || !badgeCode.length) return null; diff --git a/src/components/catalog/views/page/widgets/CatalogBundleGridWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogBundleGridWidgetView.tsx index a9935c89..341da9e2 100644 --- a/src/components/catalog/views/page/widgets/CatalogBundleGridWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogBundleGridWidgetView.tsx @@ -1,7 +1,8 @@ -import { FC, useCallback, useState } from 'react'; +import { FC, useCallback, useEffect, useState } from 'react'; import { Grid, GridProps } from '../../../../../common/Grid'; import { LayoutGridItem } from '../../../../../common/layout/LayoutGridItem'; import { CatalogPageReadyEvent, CatalogSelectProductEvent } from '../../../../../events'; +import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent'; import { dispatchUiEvent, useUiEvent } from '../../../../../hooks'; import { IPurchasableOffer } from '../../../common/IPurchasableOffer'; import { useCatalogContext } from '../../../context/CatalogContext'; @@ -22,7 +23,7 @@ export const CatalogBundleGridWidgetView: FC = setOffer(event.offer); }, []); - useUiEvent(CatalogSelectProductEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); + useUiEvent(CatalogWidgetEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); const onCatalogPageReadyEvent = useCallback((event: CatalogPageReadyEvent) => { @@ -35,11 +36,16 @@ export const CatalogBundleGridWidgetView: FC = useUiEvent(CatalogPageReadyEvent.PAGE_READY, onCatalogPageReadyEvent); + useEffect(() => + { + return () => setOffer(null); + }, [ currentPage ]); + if(!offer) return null; return ( - { offer.products && (offer.products.length > 0) && offer.products.map((product, index) => ) } + { offer.products && (offer.products.length > 0) && offer.products.map((product, index) => ) } { children } ); diff --git a/src/components/catalog/views/page/widgets/CatalogFirstProductSelectorWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogFirstProductSelectorWidgetView.tsx new file mode 100644 index 00000000..f751ecc4 --- /dev/null +++ b/src/components/catalog/views/page/widgets/CatalogFirstProductSelectorWidgetView.tsx @@ -0,0 +1,20 @@ +import { FC, useCallback } from 'react'; +import { CatalogPageReadyEvent, CatalogSelectProductEvent } from '../../../../../events'; +import { dispatchUiEvent, useUiEvent } from '../../../../../hooks'; +import { useCatalogContext } from '../../../context/CatalogContext'; + +export const CatalogFirstProductSelectorWidgetView: FC<{}> = props => +{ + const { currentPage = null } = useCatalogContext(); + + const onCatalogPageReadyEvent = useCallback((event: CatalogPageReadyEvent) => + { + if(!currentPage || !currentPage.offers.length) return; + + dispatchUiEvent(new CatalogSelectProductEvent(currentPage.offers[0])); + }, [ currentPage ]); + + useUiEvent(CatalogPageReadyEvent.PAGE_READY, onCatalogPageReadyEvent); + + return null; +} diff --git a/src/components/catalog/views/page/widgets/CatalogItemGridWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogItemGridWidgetView.tsx index e5f02782..f2e3d255 100644 --- a/src/components/catalog/views/page/widgets/CatalogItemGridWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogItemGridWidgetView.tsx @@ -1,5 +1,9 @@ import { FC } from 'react'; import { Grid, GridProps } from '../../../../../common/Grid'; +import { CatalogSelectProductEvent, CatalogSetExtraPurchaseParameterEvent } from '../../../../../events'; +import { dispatchUiEvent } from '../../../../../hooks'; +import { IPurchasableOffer } from '../../../common/IPurchasableOffer'; +import { ProductTypeEnum } from '../../../common/ProductTypeEnum'; import { useCatalogContext } from '../../../context/CatalogContext'; import { CatalogGridOfferView } from '../offers/CatalogGridOfferView'; @@ -11,13 +15,28 @@ interface CatalogItemGridWidgetViewProps extends GridProps export const CatalogItemGridWidgetView: FC = props => { const { children = null, ...rest } = props; - const { currentOffer = null, currentPage = null } = useCatalogContext(); + const { currentOffer = null, setCurrentOffer = null, currentPage = null } = useCatalogContext(); if(!currentPage) return null; + const selectOffer = (offer: IPurchasableOffer) => + { + setCurrentOffer(offer); + + dispatchUiEvent(new CatalogSelectProductEvent(offer)); + + if(offer.product && (offer.product.productType === ProductTypeEnum.WALL)) + { + dispatchUiEvent(new CatalogSetExtraPurchaseParameterEvent(offer.product.extraParam)); + } + } + return ( - { currentPage.offers && (currentPage.offers.length > 0) && currentPage.offers.map((offer, index) => ) } + { currentPage.offers && (currentPage.offers.length > 0) && currentPage.offers.map((offer, index) => + { + return selectOffer(offer) } />; + }) } { children } ); diff --git a/src/components/catalog/views/page/widgets/CatalogPriceDisplayWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogPriceDisplayWidgetView.tsx index 775c83c2..e758eaa2 100644 --- a/src/components/catalog/views/page/widgets/CatalogPriceDisplayWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogPriceDisplayWidgetView.tsx @@ -17,7 +17,7 @@ export const CatalogPriceDisplayWidgetView: FC + { (offer.priceInCredits > 0) && { offer.priceInCredits } diff --git a/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx index 53456a6d..e9ae0ba3 100644 --- a/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx @@ -1,22 +1,123 @@ -import { FC, useCallback } from 'react'; -import { CatalogSelectProductEvent } from '../../../../../events'; +import { IObjectData } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import { LocalizeText } from '../../../../../api'; +import { Button } from '../../../../../common/Button'; +import { CatalogSelectProductEvent, CatalogSetExtraPurchaseParameterEvent } from '../../../../../events'; +import { CatalogInitPurchaseEvent } from '../../../../../events/catalog/CatalogInitPurchaseEvent'; +import { CatalogPurchaseOverrideEvent } from '../../../../../events/catalog/CatalogPurchaseOverrideEvent'; +import { CatalogSetRoomPreviewerStuffDataEvent } from '../../../../../events/catalog/CatalogSetRoomPreviewerStuffDataEvent'; +import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent'; import { useUiEvent } from '../../../../../hooks'; +import { IPurchasableOffer } from '../../../common/IPurchasableOffer'; +import { Offer } from '../../../common/Offer'; interface CatalogPurchaseWidgetViewProps { - + noGiftOption?: boolean; } export const CatalogPurchaseWidgetView: FC = props => { - const {} = props; + const { noGiftOption = false } = props; + const [ offer, setOffer ] = useState(null); + const [ quantity, setQuantity ] = useState(1); + const [ extraData, setExtraData ] = useState(''); + const [ extraParamRequired, setExtraParamRequired ] = useState(false); + const [ giftEnabled, setGiftEnabled ] = useState(false); + const [ purchaseCallback, setPurchaseCallback ] = useState(null); + const [ previewStuffData, setPreviewStuffData ] = useState(null); + const [ purchaseWillBeGift, setPurchaseWillBeGift ] = useState(false); const onCatalogSelectProductEvent = useCallback((event: CatalogSelectProductEvent) => + { + setOffer(event.offer); + }, []); + + useUiEvent(CatalogWidgetEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); + + const onCatalogSetExtraPurchaseParameterEvent = useCallback((event: CatalogSetExtraPurchaseParameterEvent) => + { + setExtraData(event.parameter); + setGiftEnabled(offer && offer.giftable); + }, [ offer ]); + + useUiEvent(CatalogWidgetEvent.SET_EXTRA_PARM, onCatalogSetExtraPurchaseParameterEvent); + + const onCatalogPurchaseOverrideEvent = useCallback((event: CatalogPurchaseOverrideEvent) => + { + setPurchaseCallback(event.callback); + }, []); + + useUiEvent(CatalogWidgetEvent.PURCHASE_OVERRIDE, onCatalogPurchaseOverrideEvent); + + const onCatalogInitPurchaseEvent = useCallback((event: CatalogInitPurchaseEvent) => + { + if(!offer) return; + + // show purchase confirmation + // offer, page.pageId, extraData, quantity, previewStuffData, null, true, null + }, [ offer ]); + + useUiEvent(CatalogWidgetEvent.INIT_PURCHASE, onCatalogInitPurchaseEvent); + + const onCatalogSetRoomPreviewerStuffDataEvent = useCallback((event: CatalogSetRoomPreviewerStuffDataEvent) => + { + setPreviewStuffData(event.stuffData); + }, []); + + useUiEvent(CatalogWidgetEvent.SET_PREVIEWER_STUFFDATA, onCatalogSetRoomPreviewerStuffDataEvent); + + const onCatalogWidgetEvent = useCallback((event: CatalogWidgetEvent) => + { + setExtraParamRequired(true); + }, []); + + useUiEvent(CatalogWidgetEvent.EXTRA_PARAM_REQUIRED_FOR_BUY, onCatalogWidgetEvent); + + const isLimitedSoldOut = useMemo(() => + { + if(!offer) return false; + + if(extraParamRequired && (!extraData || !extraData.length)) return false; + + if(offer.pricingModel === Offer.PRICING_MODEL_SINGLE) + { + const product = offer.product; + + if(product && product.isUniqueLimitedItem) return !product.uniqueLimitedItemsLeft; + } + + return false; + }, [ offer, extraParamRequired, extraData ]); + + const purchase = useCallback((isGift: boolean = false) => { }, []); - useUiEvent(CatalogSelectProductEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); + useEffect(() => + { + setQuantity(1); + setPurchaseWillBeGift(false); + }, [ offer ]); - return null; + if(!offer) return null; + + const getPurchaseButton = () => + { + const priceCredits = (offer.priceInCredits * quantity); + const pricePoints = (offer.priceInActivityPoints * quantity); + } + + return ( + <> + + { (!noGiftOption && !offer.isRentOffer) && + } + + ); } diff --git a/src/components/catalog/views/page/widgets/CatalogSimplePriceWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogSimplePriceWidgetView.tsx index e6f5a493..aba2257f 100644 --- a/src/components/catalog/views/page/widgets/CatalogSimplePriceWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogSimplePriceWidgetView.tsx @@ -1,6 +1,7 @@ import { FC, useCallback, useState } from 'react'; import { BaseProps } from '../../../../../common/Base'; import { CatalogSelectProductEvent } from '../../../../../events'; +import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent'; import { useUiEvent } from '../../../../../hooks'; import { IPurchasableOffer } from '../../../common/IPurchasableOffer'; import { CatalogPriceDisplayWidgetView } from './CatalogPriceDisplayWidgetView'; @@ -20,7 +21,7 @@ export const CatalogSimplePriceWidgetView: FC setOffer(event.offer); }, []); - useUiEvent(CatalogSelectProductEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); + useUiEvent(CatalogWidgetEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); return ; } diff --git a/src/components/catalog/views/page/widgets/CatalogSingleViewWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogSingleViewWidgetView.tsx new file mode 100644 index 00000000..c62535d9 --- /dev/null +++ b/src/components/catalog/views/page/widgets/CatalogSingleViewWidgetView.tsx @@ -0,0 +1,7 @@ +import { FC } from 'react'; +import { CatalogFirstProductSelectorWidgetView } from './CatalogFirstProductSelectorWidgetView'; + +export const CatalogSingleViewWidgetView: FC<{}> = props => +{ + return ; +} diff --git a/src/components/catalog/views/page/widgets/CatalogViewProductWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogViewProductWidgetView.tsx new file mode 100644 index 00000000..497349be --- /dev/null +++ b/src/components/catalog/views/page/widgets/CatalogViewProductWidgetView.tsx @@ -0,0 +1,38 @@ +import { IObjectData } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useState } from 'react'; +import { CatalogSelectProductEvent } from '../../../../../events'; +import { CatalogSetRoomPreviewerStuffDataEvent } from '../../../../../events/catalog/CatalogSetRoomPreviewerStuffDataEvent'; +import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent'; +import { BatchUpdates, useUiEvent } from '../../../../../hooks'; +import { IPurchasableOffer } from '../../../common/IPurchasableOffer'; +import { useCatalogContext } from '../../../context/CatalogContext'; + +export const CatalogViewProductWidgetView: FC<{}> = props => +{ + const [ selectedProductEvent, setSelectedProductEvent ] = useState(null); + const [ offer, setOffer ] = useState(null); + const [ stuffData, setStuffData ] = useState(null); + const { roomPreviewer = null } = useCatalogContext(); + + const onCatalogSelectProductEvent = useCallback((event: CatalogSelectProductEvent) => + { + BatchUpdates(() => + { + setSelectedProductEvent(event); + setOffer(event.offer); + }) + }, []); + + useUiEvent(CatalogWidgetEvent.SELECT_PRODUCT, onCatalogSelectProductEvent); + + const onCatalogSetRoomPreviewerStuffDataEvent = useCallback((event: CatalogSetRoomPreviewerStuffDataEvent) => + { + setStuffData(event.stuffData); + + if(roomPreviewer) roomPreviewer.reset(false); + }, [ roomPreviewer ]); + + useUiEvent(CatalogWidgetEvent.SET_PREVIEWER_STUFFDATA, onCatalogSetRoomPreviewerStuffDataEvent); + + return null; +}