Fix pet purchasing

This commit is contained in:
Bill 2022-02-03 23:51:31 -05:00
parent 6538b58250
commit 6f4a41ff33
4 changed files with 87 additions and 41 deletions

View File

@ -5,6 +5,5 @@ export interface IPurchaseOptions
quantity?: number; quantity?: number;
extraData?: string; extraData?: string;
extraParamRequired?: boolean; extraParamRequired?: boolean;
purchaseCallback?: Function;
previewStuffData?: IObjectData; previewStuffData?: IObjectData;
} }

View File

@ -8,7 +8,7 @@ export interface CatalogLayoutColorGroupViewProps extends CatalogLayoutProps
export const CatalogLayoutColorGroupingView : FC<CatalogLayoutColorGroupViewProps> = props => export const CatalogLayoutColorGroupingView : FC<CatalogLayoutColorGroupViewProps> = props =>
{ {
const { page = null, roomPreviewer = null } = props; const { page = null } = props;
const [ colorableItems, setColorableItems ] = useState<Map<string, number[]>>(new Map<string, number[]>()); const [ colorableItems, setColorableItems ] = useState<Map<string, number[]>>(new Map<string, number[]>());
// const offers = useMemo(() => // const offers = useMemo(() =>

View File

@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ColorConverter, GetSellablePetPalettesComposer, SellablePetPaletteData } from '@nitrots/nitro-renderer'; import { ApproveNameMessageComposer, ColorConverter, GetSellablePetPalettesComposer, PurchaseFromCatalogComposer, SellablePetPaletteData } 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 { Base } from '../../../../../../common/Base'; import { Base } from '../../../../../../common/Base';
@ -9,9 +9,9 @@ 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 { CatalogNameResultEvent } from '../../../../../../events'; import { CatalogNameResultEvent, CatalogPurchaseFailureEvent } from '../../../../../../events';
import { CatalogWidgetEvent } from '../../../../../../events/catalog/CatalogWidgetEvent'; import { CatalogWidgetEvent } from '../../../../../../events/catalog/CatalogWidgetEvent';
import { BatchUpdates, useUiEvent } from '../../../../../../hooks'; import { BatchUpdates, dispatchUiEvent, useUiEvent } from '../../../../../../hooks';
import { SendMessageHook } from '../../../../../../hooks/messages/message-event'; import { SendMessageHook } from '../../../../../../hooks/messages/message-event';
import { PetImageView } from '../../../../../../views/shared/pet-image/PetImageView'; import { PetImageView } from '../../../../../../views/shared/pet-image/PetImageView';
import { useCatalogContext } from '../../../../CatalogContext'; import { useCatalogContext } from '../../../../CatalogContext';
@ -34,39 +34,9 @@ export const CatalogLayoutPetView: FC<CatalogLayoutProps> = props =>
const [ petName, setPetName ] = useState(''); const [ petName, setPetName ] = useState('');
const [ approvalPending, setApprovalPending ] = useState(true); const [ approvalPending, setApprovalPending ] = useState(true);
const [ approvalResult, setApprovalResult ] = useState(-1); const [ approvalResult, setApprovalResult ] = useState(-1);
const { currentOffer = null, setCurrentOffer = null, catalogOptions = null, roomPreviewer = null } = useCatalogContext(); const { currentOffer = null, setCurrentOffer = null, setPurchaseOptions = null, catalogOptions = null, roomPreviewer = null } = useCatalogContext();
const { petPalettes = [] } = catalogOptions; const { petPalettes = [] } = catalogOptions;
const validationErrorMessage = () =>
{
let key: string = '';
switch(approvalResult)
{
case 1:
key = 'catalog.alert.petname.long';
break;
case 2:
key = 'catalog.alert.petname.short';
break;
case 3:
key = 'catalog.alert.petname.chars';
break;
case 4:
key = 'catalog.alert.petname.bobba';
break;
}
return LocalizeText(key);
}
const onCatalogNameResultEvent = useCallback((event: CatalogNameResultEvent) =>
{
setApprovalPending(false);
}, []);
useUiEvent(CatalogWidgetEvent.APPROVE_RESULT, onCatalogNameResultEvent)
const getColor = useMemo(() => const getColor = useMemo(() =>
{ {
if(!sellableColors.length || (selectedColorIndex === -1)) return 0xFFFFFF; if(!sellableColors.length || (selectedColorIndex === -1)) return 0xFFFFFF;
@ -103,6 +73,60 @@ export const CatalogLayoutPetView: FC<CatalogLayoutProps> = props =>
return `${ paletteId }\n${ colorString }`; return `${ paletteId }\n${ colorString }`;
}, [ sellablePalettes, selectedPaletteIndex, petIndex, sellableColors, selectedColorIndex ]); }, [ sellablePalettes, selectedPaletteIndex, petIndex, sellableColors, selectedColorIndex ]);
const validationErrorMessage = useMemo(() =>
{
let key: string = '';
console.log(approvalResult);
switch(approvalResult)
{
case 1:
key = 'catalog.alert.petname.long';
break;
case 2:
key = 'catalog.alert.petname.short';
break;
case 3:
key = 'catalog.alert.petname.chars';
break;
case 4:
key = 'catalog.alert.petname.bobba';
break;
}
if(!key || !key.length) return '';
return LocalizeText(key);
}, [ approvalResult ]);
const purchasePet = useCallback(() =>
{
if(approvalResult === -1)
{
SendMessageHook(new ApproveNameMessageComposer(petName, 1));
return;
}
if(approvalResult === 0)
{
SendMessageHook(new PurchaseFromCatalogComposer(page.pageId, currentOffer.offerId, `${ petName }\n${ petPurchaseString }`, 1));
return;
}
}, [ page, currentOffer, petName, petPurchaseString, approvalResult ]);
const onCatalogNameResultEvent = useCallback((event: CatalogNameResultEvent) =>
{
setApprovalResult(event.result);
if(event.result === 0) purchasePet();
else dispatchUiEvent(new CatalogPurchaseFailureEvent(-1));
}, [ purchasePet ]);
useUiEvent(CatalogWidgetEvent.APPROVE_RESULT, onCatalogNameResultEvent);
useEffect(() => useEffect(() =>
{ {
if(!page || !page.offers.length) return; if(!page || !page.offers.length) return;
@ -184,6 +208,11 @@ export const CatalogLayoutPetView: FC<CatalogLayoutProps> = props =>
roomPreviewer.addPetIntoRoom(petFigureString); roomPreviewer.addPetIntoRoom(petFigureString);
}, [ roomPreviewer, petIndex, sellablePalettes, selectedPaletteIndex, getColor ]); }, [ roomPreviewer, petIndex, sellablePalettes, selectedPaletteIndex, getColor ]);
useEffect(() =>
{
setApprovalResult(-1);
}, [ petName ]);
if(!currentOffer) return null; if(!currentOffer) return null;
return ( return (
@ -222,12 +251,12 @@ export const CatalogLayoutPetView: FC<CatalogLayoutProps> = props =>
<Column grow gap={ 1 }> <Column grow gap={ 1 }>
<input type="text" className="form-control form-control-sm w-100" placeholder={ LocalizeText('widgets.petpackage.name.title') } value={ petName } onChange={ event => setPetName(event.target.value) } /> <input type="text" className="form-control form-control-sm w-100" placeholder={ LocalizeText('widgets.petpackage.name.title') } value={ petName } onChange={ event => setPetName(event.target.value) } />
{ (approvalResult > 0) && { (approvalResult > 0) &&
<Base className="invalid-feedback">{ validationErrorMessage }</Base> } <Base className="invalid-feedback d-block m-0">{ validationErrorMessage }</Base> }
</Column> </Column>
<Flex justifyContent="end"> <Flex justifyContent="end">
<CatalogTotalPriceWidget justifyContent="end" alignItems="end" /> <CatalogTotalPriceWidget justifyContent="end" alignItems="end" />
</Flex> </Flex>
<CatalogPurchaseWidgetView /> <CatalogPurchaseWidgetView purchaseCallback={ purchasePet } />
</Column> </Column>
</> } </> }
</Column> </Column>

View File

@ -15,15 +15,16 @@ import { Offer } from '../../../common/Offer';
interface CatalogPurchaseWidgetViewProps interface CatalogPurchaseWidgetViewProps
{ {
noGiftOption?: boolean; noGiftOption?: boolean;
purchaseCallback?: () => void;
} }
export const CatalogPurchaseWidgetView: FC<CatalogPurchaseWidgetViewProps> = props => export const CatalogPurchaseWidgetView: FC<CatalogPurchaseWidgetViewProps> = props =>
{ {
const { noGiftOption = false } = props; const { noGiftOption = false, purchaseCallback = null } = props;
const [ purchaseWillBeGift, setPurchaseWillBeGift ] = useState(false); const [ purchaseWillBeGift, setPurchaseWillBeGift ] = useState(false);
const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE); const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE);
const { currentOffer = null, currentPage = null, purchaseOptions = null, setPurchaseOptions = null, getNodesByOfferId = null } = useCatalogContext(); const { currentOffer = null, currentPage = null, purchaseOptions = null, setPurchaseOptions = null, getNodesByOfferId = null } = useCatalogContext();
const { quantity = 1, extraData = '', extraParamRequired = false, purchaseCallback = null, previewStuffData = null } = purchaseOptions; const { quantity = 1, extraData = '', extraParamRequired = false, previewStuffData = null } = purchaseOptions;
const onCatalogInitPurchaseEvent = useCallback((event: CatalogInitPurchaseEvent) => const onCatalogInitPurchaseEvent = useCallback((event: CatalogInitPurchaseEvent) =>
{ {
@ -86,6 +87,8 @@ export const CatalogPurchaseWidgetView: FC<CatalogPurchaseWidgetViewProps> = pro
return; return;
} }
setPurchaseState(CatalogPurchaseState.PURCHASE);
if(purchaseCallback) if(purchaseCallback)
{ {
purchaseCallback(); purchaseCallback();
@ -114,10 +117,25 @@ export const CatalogPurchaseWidgetView: FC<CatalogPurchaseWidgetViewProps> = pro
return () => return () =>
{ {
setPurchaseState(CatalogPurchaseState.NONE); setPurchaseState(CatalogPurchaseState.NONE);
setPurchaseOptions({ quantity: 1, extraData: '', extraParamRequired: false, purchaseCallback: null, previewStuffData: null }); setPurchaseOptions({ quantity: 1, extraData: '', extraParamRequired: false, previewStuffData: null });
} }
}, [ currentOffer, setPurchaseOptions ]); }, [ currentOffer, setPurchaseOptions ]);
useEffect(() =>
{
let timeout: ReturnType<typeof setTimeout> = null;
if((purchaseState === CatalogPurchaseState.CONFIRM) || (purchaseState === CatalogPurchaseState.FAILED))
{
timeout = setTimeout(() => setPurchaseState(CatalogPurchaseState.NONE), 3000);
}
return () =>
{
if(timeout) clearTimeout(timeout);
}
}, [ purchaseState ]);
if(!currentOffer) return null; if(!currentOffer) return null;
const PurchaseButton = () => const PurchaseButton = () =>