mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-23 14:40:50 +01:00
Add pet name approval
This commit is contained in:
parent
058f8e6dcc
commit
f56164e3c2
@ -9,4 +9,5 @@ export class CatalogEvent extends NitroEvent
|
||||
public static PURCHASE_FAILED: string = 'CE_PURCHASE_FAILED';
|
||||
public static SOLD_OUT: string = 'CE_SOLD_OUT';
|
||||
public static APPROVE_NAME_RESULT: string = 'CE_APPROVE_NAME_RESULT';
|
||||
public static PURCHASE_APPROVED: string = 'CE_PURCHASE_APPROVED';
|
||||
}
|
||||
|
@ -112,6 +112,31 @@ export const CatalogLayoutPetView: FC<CatalogLayoutPetViewProps> = props =>
|
||||
return LocalizeText(`pet.breed.${ petIndex }.${ sellablePalettes[selectedPaletteIndex].breedId }`);
|
||||
}, [ petIndex, sellablePalettes, selectedPaletteIndex ]);
|
||||
|
||||
const petPurchaseString = useMemo(() =>
|
||||
{
|
||||
if(!sellablePalettes.length || (selectedPaletteIndex === -1)) return '';
|
||||
|
||||
const paletteId = sellablePalettes[selectedPaletteIndex].paletteId;
|
||||
|
||||
let color = 0xFFFFFF;
|
||||
|
||||
if(petIndex <= 7)
|
||||
{
|
||||
if(selectedColorIndex === -1) return '';
|
||||
|
||||
color = sellableColors[selectedColorIndex][0];
|
||||
}
|
||||
|
||||
let colorString = color.toString(16).toUpperCase();
|
||||
|
||||
while(colorString.length < 6)
|
||||
{
|
||||
colorString = ('0' + colorString);
|
||||
}
|
||||
|
||||
return `${ paletteId }\n${ colorString }`;
|
||||
}, [ sellablePalettes, selectedPaletteIndex, petIndex, sellableColors, selectedColorIndex ]);
|
||||
|
||||
if(!activeOffer) return null;
|
||||
|
||||
return (
|
||||
@ -143,7 +168,7 @@ export const CatalogLayoutPetView: FC<CatalogLayoutPetViewProps> = props =>
|
||||
</button> }
|
||||
</RoomPreviewerView>
|
||||
<div className="fs-6 text-black mt-1 overflow-hidden">{ petBreedName }</div>
|
||||
<CatalogLayoutPetPurchaseView offer={ activeOffer } pageId={ pageParser.pageId } />
|
||||
<CatalogLayoutPetPurchaseView offer={ activeOffer } pageId={ pageParser.pageId } extra={ petPurchaseString } />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,12 +1,61 @@
|
||||
import { FC } from 'react';
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { CatalogEvent, CatalogNameResultEvent } from '../../../../../../../events';
|
||||
import { useUiEvent } from '../../../../../../../hooks/events/ui/ui-event';
|
||||
import { LocalizeText } from '../../../../../../../utils/LocalizeText';
|
||||
import { CatalogPetNameApprovalViewProps } from './CatalogPetNameApprovalView.types';
|
||||
|
||||
export const CatalogPetNameApprovalView: FC<CatalogPetNameApprovalViewProps> = props =>
|
||||
{
|
||||
const { petNameValue = null, setPetNameValue = null } = props;
|
||||
const { petNameValue = null, setPetNameValue = null, nameApproved = false, setNameApproved = null } = props;
|
||||
const [ validationResult, setValidationResult ] = useState(-1);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setValidationResult(-1);
|
||||
}, [ petNameValue ]);
|
||||
|
||||
const onCatalogNameResultEvent = useCallback((event: CatalogNameResultEvent) =>
|
||||
{
|
||||
if(event.result === 0)
|
||||
{
|
||||
setNameApproved(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setValidationResult(event.result);
|
||||
}, [ setNameApproved ]);
|
||||
|
||||
useUiEvent(CatalogEvent.APPROVE_NAME_RESULT, onCatalogNameResultEvent);
|
||||
|
||||
const validationErrorMessage = useMemo(() =>
|
||||
{
|
||||
let key: string = '';
|
||||
|
||||
switch(validationResult)
|
||||
{
|
||||
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);
|
||||
}, [ validationResult ]);
|
||||
|
||||
return (
|
||||
<input type="text" className="form-control form-control-sm" placeholder={ LocalizeText('widgets.petpackage.name.title') } value={ petNameValue } onChange={ event => setPetNameValue(event.target.value) } />
|
||||
<div className="input-group has-validation">
|
||||
<input type="text" className={ 'form-control form-control-sm '+ ((validationResult > 0) ? 'is-invalid ' : '') } placeholder={ LocalizeText('widgets.petpackage.name.title') } value={ petNameValue } onChange={ event => setPetNameValue(event.target.value) } />
|
||||
{ (validationResult > 0) &&
|
||||
<div className="invalid-feedback">{ validationErrorMessage }</div> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -4,4 +4,6 @@ export interface CatalogPetNameApprovalViewProps
|
||||
{
|
||||
petNameValue: string;
|
||||
setPetNameValue: Dispatch<SetStateAction<string>>;
|
||||
nameApproved: boolean;
|
||||
setNameApproved: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
import { FC, useState } from 'react';
|
||||
import { ApproveNameMessageComposer } from 'nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { CatalogEvent } from '../../../../../../../events';
|
||||
import { useUiEvent } from '../../../../../../../hooks/events/ui/ui-event';
|
||||
import { SendMessageHook } from '../../../../../../../hooks/messages/message-event';
|
||||
import { CurrencyIcon } from '../../../../../../../utils/currency-icon/CurrencyIcon';
|
||||
import { LocalizeText } from '../../../../../../../utils/LocalizeText';
|
||||
import { CatalogPurchaseButtonView } from '../../../purchase/purchase-button/CatalogPurchaseButtonView';
|
||||
@ -9,13 +13,31 @@ export const CatalogLayoutPetPurchaseView: FC<CatalogLayoutPetPurchaseViewProps>
|
||||
{
|
||||
const { offer = null, pageId = -1, extra = '' } = props;
|
||||
const [ petNameValue, setPetNameValue ] = useState('');
|
||||
const [ nameApproved, setNameApproved ] = useState(false);
|
||||
|
||||
const extraData = ((extra && extra.length) ? extra : (offer?.products[0]?.extraParam || null));
|
||||
const onCatalogEvent = useCallback((event: CatalogEvent) =>
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case CatalogEvent.PURCHASE_SUCCESS:
|
||||
setNameApproved(false);
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
|
||||
useUiEvent(CatalogEvent.PURCHASE_SUCCESS, onCatalogEvent);
|
||||
|
||||
const beforePurchase = useCallback(() =>
|
||||
{
|
||||
SendMessageHook(new ApproveNameMessageComposer(petNameValue, 1));
|
||||
}, [ petNameValue ]);
|
||||
|
||||
const extraData = `${ petNameValue }\n${ extra }`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="d-flex flex-grow-1 justify-content-center align-items-center">
|
||||
<CatalogPetNameApprovalView petNameValue={ petNameValue } setPetNameValue={ setPetNameValue } />
|
||||
<CatalogPetNameApprovalView petNameValue={ petNameValue } setPetNameValue={ setPetNameValue } nameApproved={ nameApproved } setNameApproved={ setNameApproved } />
|
||||
</div>
|
||||
<div className="d-flex flex-column flex-grow-1 justify-content-end w-100">
|
||||
<div className="d-flex align-items-end">
|
||||
@ -36,7 +58,7 @@ export const CatalogLayoutPetPurchaseView: FC<CatalogLayoutPetPurchaseViewProps>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex flex-column mt-1">
|
||||
<CatalogPurchaseButtonView className="btn-sm w-100" offer={ offer } pageId={ pageId } extra={ extraData } quantity={ 1 } />
|
||||
<CatalogPurchaseButtonView className="btn-sm w-100" offer={ offer } pageId={ pageId } extra={ extraData } quantity={ 1 } isPurchaseAllowed={ nameApproved } beforePurchase={ beforePurchase } />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
@ -10,8 +10,9 @@ import { CatalogPurchaseButtonViewProps, CatalogPurchaseState } from './CatalogP
|
||||
|
||||
export const CatalogPurchaseButtonView: FC<CatalogPurchaseButtonViewProps> = props =>
|
||||
{
|
||||
const { className = '', offer = null, pageId = -1, extra = null, quantity = 1 } = props;
|
||||
const { className = '', offer = null, pageId = -1, extra = null, quantity = 1, isPurchaseAllowed = true, beforePurchase = null } = props;
|
||||
const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE);
|
||||
const [ pendingApproval, setPendingApproval ] = useState(false);
|
||||
|
||||
const onCatalogEvent = useCallback((event: CatalogEvent) =>
|
||||
{
|
||||
@ -31,16 +32,43 @@ export const CatalogPurchaseButtonView: FC<CatalogPurchaseButtonViewProps> = pro
|
||||
|
||||
const purchase = useCallback(() =>
|
||||
{
|
||||
setPurchaseState(CatalogPurchaseState.PURCHASE);
|
||||
|
||||
SendMessageHook(new CatalogPurchaseComposer(pageId, offer.offerId, extra, quantity));
|
||||
}, [ pageId, offer, extra, quantity ]);
|
||||
|
||||
const attemptPurchase = useCallback(() =>
|
||||
{
|
||||
setPurchaseState(CatalogPurchaseState.PURCHASE);
|
||||
|
||||
if(beforePurchase) beforePurchase();
|
||||
|
||||
if(!isPurchaseAllowed)
|
||||
{
|
||||
setPendingApproval(true);
|
||||
setPurchaseState(CatalogPurchaseState.NONE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
purchase();
|
||||
}, [ isPurchaseAllowed, beforePurchase, purchase ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setPurchaseState(CatalogPurchaseState.NONE);
|
||||
}, [ offer, quantity ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(pendingApproval && isPurchaseAllowed)
|
||||
{
|
||||
setPendingApproval(false);
|
||||
|
||||
purchase();
|
||||
|
||||
return;
|
||||
}
|
||||
}, [ purchaseState, pendingApproval, isPurchaseAllowed, purchase ]);
|
||||
|
||||
const product = offer.products[0];
|
||||
|
||||
if(product && product.uniqueLimitedItem && !product.uniqueLimitedItemsLeft)
|
||||
@ -61,7 +89,7 @@ export const CatalogPurchaseButtonView: FC<CatalogPurchaseButtonViewProps> = pro
|
||||
switch(purchaseState)
|
||||
{
|
||||
case CatalogPurchaseState.CONFIRM:
|
||||
return <button type="button" className={ 'btn btn-warning ' + className } onClick={ purchase }>{ LocalizeText('catalog.marketplace.confirm_title') }</button>;
|
||||
return <button type="button" className={ 'btn btn-warning ' + className } onClick={ attemptPurchase }>{ LocalizeText('catalog.marketplace.confirm_title') }</button>;
|
||||
case CatalogPurchaseState.PURCHASE:
|
||||
return <button type="button" className={ 'btn btn-primary ' + className } disabled><LoadingSpinnerView /></button>;
|
||||
case CatalogPurchaseState.SOLD_OUT:
|
||||
|
@ -7,6 +7,8 @@ export interface CatalogPurchaseButtonViewProps
|
||||
pageId: number;
|
||||
extra?: string;
|
||||
quantity?: number;
|
||||
isPurchaseAllowed?: boolean;
|
||||
beforePurchase?: () => void;
|
||||
}
|
||||
|
||||
export class CatalogPurchaseState
|
||||
|
Loading…
Reference in New Issue
Block a user