Pet catalog updates

This commit is contained in:
Bill 2021-05-22 13:27:39 -04:00
parent b191026ba1
commit 058f8e6dcc
22 changed files with 396 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

View File

@ -603,7 +603,7 @@ $input-btn-font-family: null !default;
$input-btn-font-size: $font-size-base !default; $input-btn-font-size: $font-size-base !default;
$input-btn-line-height: $line-height-base !default; $input-btn-line-height: $line-height-base !default;
$input-btn-focus-width: .25rem !default; $input-btn-focus-width: 0 !default;
$input-btn-focus-color-opacity: .25 !default; $input-btn-focus-color-opacity: .25 !default;
$input-btn-focus-color: rgba($component-active-bg, $input-btn-focus-color-opacity) !default; $input-btn-focus-color: rgba($component-active-bg, $input-btn-focus-color-opacity) !default;
$input-btn-focus-blur: 0 !default; $input-btn-focus-blur: 0 !default;

View File

@ -8,4 +8,5 @@ export class CatalogEvent extends NitroEvent
public static PURCHASE_SUCCESS: string = 'CE_PURCHASE_SUCCESS'; public static PURCHASE_SUCCESS: string = 'CE_PURCHASE_SUCCESS';
public static PURCHASE_FAILED: string = 'CE_PURCHASE_FAILED'; public static PURCHASE_FAILED: string = 'CE_PURCHASE_FAILED';
public static SOLD_OUT: string = 'CE_SOLD_OUT'; public static SOLD_OUT: string = 'CE_SOLD_OUT';
public static APPROVE_NAME_RESULT: string = 'CE_APPROVE_NAME_RESULT';
} }

View File

@ -0,0 +1,25 @@
import { CatalogEvent } from './CatalogEvent';
export class CatalogNameResultEvent extends CatalogEvent
{
private _result: number;
private _validationInfo: string;
constructor(result: number, validationInfo: string)
{
super(CatalogEvent.APPROVE_NAME_RESULT);
this._result = result;
this._validationInfo = validationInfo;
}
public get result(): number
{
return this._result;
}
public get validationInfo(): string
{
return this._validationInfo;
}
}

View File

@ -1,4 +1,5 @@
export * from './CatalogEvent'; export * from './CatalogEvent';
export * from './CatalogNameResultEvent';
export * from './CatalogPurchasedEvent'; export * from './CatalogPurchasedEvent';
export * from './CatalogPurchaseFailureEvent'; export * from './CatalogPurchaseFailureEvent';
export * from './CatalogPurchaseSoldOutEvent'; export * from './CatalogPurchaseSoldOutEvent';

View File

@ -1,6 +1,6 @@
import { CatalogPageEvent, CatalogPagesEvent, CatalogPurchaseEvent, CatalogPurchaseFailedEvent, CatalogPurchaseUnavailableEvent, CatalogSearchEvent, CatalogSoldOutEvent } from 'nitro-renderer'; import { CatalogApproveNameResultEvent, CatalogPageEvent, CatalogPagesEvent, CatalogPurchaseEvent, CatalogPurchaseFailedEvent, CatalogPurchaseUnavailableEvent, CatalogSearchEvent, CatalogSoldOutEvent, SellablePetPalettesEvent } from 'nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { CatalogPurchaseFailureEvent } from '../../events'; import { CatalogNameResultEvent, CatalogPurchaseFailureEvent } from '../../events';
import { CatalogPurchasedEvent } from '../../events/catalog/CatalogPurchasedEvent'; import { CatalogPurchasedEvent } from '../../events/catalog/CatalogPurchasedEvent';
import { CatalogPurchaseSoldOutEvent } from '../../events/catalog/CatalogPurchaseSoldOutEvent'; import { CatalogPurchaseSoldOutEvent } from '../../events/catalog/CatalogPurchaseSoldOutEvent';
import { dispatchUiEvent } from '../../hooks/events/ui/ui-event'; import { dispatchUiEvent } from '../../hooks/events/ui/ui-event';
@ -8,6 +8,7 @@ import { CreateMessageHook } from '../../hooks/messages/message-event';
import { CatalogMessageHandlerProps } from './CatalogMessageHandler.types'; import { CatalogMessageHandlerProps } from './CatalogMessageHandler.types';
import { useCatalogContext } from './context/CatalogContext'; import { useCatalogContext } from './context/CatalogContext';
import { CatalogActions } from './reducers/CatalogReducer'; import { CatalogActions } from './reducers/CatalogReducer';
import { CatalogPetPalette } from './utils/CatalogPetPalette';
export const CatalogMessageHandler: FC<CatalogMessageHandlerProps> = props => export const CatalogMessageHandler: FC<CatalogMessageHandlerProps> = props =>
{ {
@ -75,6 +76,24 @@ export const CatalogMessageHandler: FC<CatalogMessageHandlerProps> = props =>
}); });
}, [ dispatchCatalogState ]); }, [ dispatchCatalogState ]);
const onSellablePetPalettesEvent = useCallback((event: SellablePetPalettesEvent) =>
{
const parser = event.getParser();
const petPalette = new CatalogPetPalette(parser.productCode, parser.palettes.slice());
dispatchCatalogState({
type: CatalogActions.SET_PET_PALETTE,
payload: { petPalette }
});
}, [ dispatchCatalogState ]);
const onCatalogApproveNameResultEvent = useCallback((event: CatalogApproveNameResultEvent) =>
{
const parser = event.getParser();
dispatchUiEvent(new CatalogNameResultEvent(parser.result, parser.validationInfo));
}, []);
CreateMessageHook(CatalogPagesEvent, onCatalogPagesEvent); CreateMessageHook(CatalogPagesEvent, onCatalogPagesEvent);
CreateMessageHook(CatalogPageEvent, onCatalogPageEvent); CreateMessageHook(CatalogPageEvent, onCatalogPageEvent);
CreateMessageHook(CatalogPurchaseEvent, onCatalogPurchaseEvent); CreateMessageHook(CatalogPurchaseEvent, onCatalogPurchaseEvent);
@ -82,6 +101,8 @@ export const CatalogMessageHandler: FC<CatalogMessageHandlerProps> = props =>
CreateMessageHook(CatalogPurchaseUnavailableEvent, onCatalogPurchaseUnavailableEvent); CreateMessageHook(CatalogPurchaseUnavailableEvent, onCatalogPurchaseUnavailableEvent);
CreateMessageHook(CatalogSoldOutEvent, onCatalogSoldOutEvent); CreateMessageHook(CatalogSoldOutEvent, onCatalogSoldOutEvent);
CreateMessageHook(CatalogSearchEvent, onCatalogSearchEvent); CreateMessageHook(CatalogSearchEvent, onCatalogSearchEvent);
CreateMessageHook(SellablePetPalettesEvent, onSellablePetPalettesEvent);
CreateMessageHook(CatalogApproveNameResultEvent, onCatalogApproveNameResultEvent);
return null; return null;
} }

View File

@ -1,5 +1,6 @@
import { CatalogPageOfferData, ICatalogPageData, ICatalogPageParser } from 'nitro-renderer'; import { CatalogPageOfferData, ICatalogPageData, ICatalogPageParser } from 'nitro-renderer';
import { Reducer } from 'react'; import { Reducer } from 'react';
import { CatalogPetPalette } from '../utils/CatalogPetPalette';
import { ICatalogOffers, ICatalogSearchResult, SetOffersToNodes } from '../utils/CatalogUtilities'; import { ICatalogOffers, ICatalogSearchResult, SetOffersToNodes } from '../utils/CatalogUtilities';
export interface ICatalogState export interface ICatalogState
@ -10,6 +11,7 @@ export interface ICatalogState
pageParser: ICatalogPageParser; pageParser: ICatalogPageParser;
activeOffer: CatalogPageOfferData; activeOffer: CatalogPageOfferData;
searchResult: ICatalogSearchResult; searchResult: ICatalogSearchResult;
petPalettes: CatalogPetPalette[];
} }
export interface ICatalogAction export interface ICatalogAction
@ -22,6 +24,7 @@ export interface ICatalogAction
pageParser?: ICatalogPageParser; pageParser?: ICatalogPageParser;
activeOffer?: CatalogPageOfferData; activeOffer?: CatalogPageOfferData;
searchResult?: ICatalogSearchResult; searchResult?: ICatalogSearchResult;
petPalette?: CatalogPetPalette;
} }
} }
@ -32,6 +35,7 @@ export class CatalogActions
public static SET_CATALOG_PAGE_PARSER: string = 'CA_SET_CATALOG_PAGE'; public static SET_CATALOG_PAGE_PARSER: string = 'CA_SET_CATALOG_PAGE';
public static SET_CATALOG_ACTIVE_OFFER: string = 'CA_SET_ACTIVE_OFFER'; public static SET_CATALOG_ACTIVE_OFFER: string = 'CA_SET_ACTIVE_OFFER';
public static SET_SEARCH_RESULT: string = 'CA_SET_SEARCH_RESULT'; public static SET_SEARCH_RESULT: string = 'CA_SET_SEARCH_RESULT';
public static SET_PET_PALETTE: string = 'CA_SET_PET_PALETTE';
} }
export const initialCatalog: ICatalogState = { export const initialCatalog: ICatalogState = {
@ -40,7 +44,8 @@ export const initialCatalog: ICatalogState = {
currentTab: null, currentTab: null,
pageParser: null, pageParser: null,
activeOffer: null, activeOffer: null,
searchResult: null searchResult: null,
petPalettes: []
} }
export const CatalogReducer: Reducer<ICatalogState, ICatalogAction> = (state, action) => export const CatalogReducer: Reducer<ICatalogState, ICatalogAction> = (state, action) =>
@ -64,7 +69,7 @@ export const CatalogReducer: Reducer<ICatalogState, ICatalogAction> = (state, ac
return { ...state, currentTab, searchResult }; return { ...state, currentTab, searchResult };
} }
case CatalogActions.SET_CATALOG_PAGE_PARSER: { case CatalogActions.SET_CATALOG_PAGE_PARSER: {
const pageParser = action.payload.pageParser; let pageParser = Object.create(action.payload.pageParser);
let activeOffer = null; let activeOffer = null;
if(pageParser.layoutCode === 'single_bundle') if(pageParser.layoutCode === 'single_bundle')
@ -91,6 +96,27 @@ export const CatalogReducer: Reducer<ICatalogState, ICatalogAction> = (state, ac
return { ...state, searchResult }; return { ...state, searchResult };
} }
case CatalogActions.SET_PET_PALETTE: {
const petPalette = (action.payload.petPalette || null);
let petPalettes = [ ...state.petPalettes ];
for(let i = 0; i < petPalettes.length; i++)
{
const palette = petPalettes[i];
if(palette.breed === petPalette.breed)
{
petPalettes.splice(i, 1);
break;
}
}
petPalettes.push(petPalette);
return { ...state, petPalettes };
}
default: default:
return state; return state;
} }

View File

@ -0,0 +1,9 @@
import { SellablePetPaletteData } from 'nitro-renderer';
export class CatalogPetPalette
{
constructor(
public breed: string,
public palettes: SellablePetPaletteData[]
) {}
}

View File

@ -1,4 +1,5 @@
import { CatalogPageOfferData, ICatalogPageData, ICatalogPageParser, IFurnitureData } from 'nitro-renderer'; import { CatalogPageOfferData, ICatalogPageData, ICatalogPageParser, IFurnitureData, SellablePetPaletteData } from 'nitro-renderer';
import { GetRoomEngine } from '../../../api';
import { GetProductDataForLocalization } from '../../../api/nitro/session/GetProductDataForLocalization'; import { GetProductDataForLocalization } from '../../../api/nitro/session/GetProductDataForLocalization';
import { GetConfiguration } from '../../../utils/GetConfiguration'; import { GetConfiguration } from '../../../utils/GetConfiguration';
@ -88,3 +89,65 @@ export function GetCatalogPageText(page: ICatalogPageParser, index: number = 0):
return (message || ''); return (message || '');
} }
export function GetPetIndexFromLocalization(localization: string)
{
if(!localization.length) return 0;
let index = (localization.length - 1);
while(index >= 0)
{
if(isNaN(parseInt(localization.charAt(index)))) break;
index--;
}
if(index > 0) return parseInt(localization.substring(index + 1));
return -1;
}
export function GetPetAvailableColors(petIndex: number, palettes: SellablePetPaletteData[]): number[][]
{
switch(petIndex)
{
case 0:
return [[16743226], [16750435], [16764339], [0xF59500], [16498012], [16704690], [0xEDD400], [16115545], [16513201], [8694111], [11585939], [14413767], [6664599], [9553845], [12971486], [8358322], [10002885], [13292268], [10780600], [12623573], [14403561], [12418717], [14327229], [15517403], [14515069], [15764368], [16366271], [0xABABAB], [0xD4D4D4], [0xFFFFFF], [14256481], [14656129], [15848130], [14005087], [14337152], [15918540], [15118118], [15531929], [9764857], [11258085]];
case 1:
return [[16743226], [16750435], [16764339], [0xF59500], [16498012], [16704690], [0xEDD400], [16115545], [16513201], [8694111], [11585939], [14413767], [6664599], [9553845], [12971486], [8358322], [10002885], [13292268], [10780600], [12623573], [14403561], [12418717], [14327229], [15517403], [14515069], [15764368], [16366271], [0xABABAB], [0xD4D4D4], [0xFFFFFF], [14256481], [14656129], [15848130], [14005087], [14337152], [15918540], [15118118], [15531929], [9764857], [11258085]];
case 2:
return [[16579283], [15378351], [8830016], [15257125], [9340985], [8949607], [6198292], [8703620], [9889626], [8972045], [12161285], [13162269], [8620113], [12616503], [8628101], [0xD2FF00], [9764857]];
case 3:
return [[0xFFFFFF], [0xEEEEEE], [0xDDDDDD]];
case 4:
return [[0xFFFFFF], [16053490], [15464440], [16248792], [15396319], [15007487]];
case 5:
return [[0xFFFFFF], [0xEEEEEE], [0xDDDDDD]];
case 6:
return [[0xFFFFFF], [0xEEEEEE], [0xDDDDDD], [16767177], [16770205], [16751331]];
case 7:
return [[0xCCCCCC], [0xAEAEAE], [16751331], [10149119], [16763290], [16743786]];
default: {
const colors: number[][] = [];
for(const palette of palettes)
{
const petColorResult = GetRoomEngine().getPetColorResult(petIndex, palette.paletteId);
if(!petColorResult) continue;
if(petColorResult._Str_5845 === petColorResult._Str_6659)
{
colors.push([ petColorResult._Str_5845 ]);
}
else
{
colors.push([ petColorResult._Str_5845, petColorResult._Str_6659 ]);
}
}
return colors;
}
}
}

View File

@ -1,4 +1,5 @@
@import './default/CatalogLayoutDefaultView'; @import './default/CatalogLayoutDefaultView';
@import './pets/CatalogLayoutPetView';
@import './single-bundle/CatalogLayoutSingleBundleView'; @import './single-bundle/CatalogLayoutSingleBundleView';
@import './spaces-new/CatalogLayoutSpacesView'; @import './spaces-new/CatalogLayoutSpacesView';
@import './trophies/CatalogLayoutTrophiesView'; @import './trophies/CatalogLayoutTrophiesView';

View File

@ -1,5 +1,6 @@
import { ICatalogPageParser, RoomPreviewer } from 'nitro-renderer'; import { ICatalogPageParser, RoomPreviewer } from 'nitro-renderer';
import { CatalogLayoutDefaultView } from './default/CatalogLayoutDefaultView'; import { CatalogLayoutDefaultView } from './default/CatalogLayoutDefaultView';
import { CatalogLayoutPetView } from './pets/CatalogLayoutPetView';
import { CatalogLayoutSingleBundleView } from './single-bundle/CatalogLayoutSingleBundleView'; import { CatalogLayoutSingleBundleView } from './single-bundle/CatalogLayoutSingleBundleView';
import { CatalogLayoutSpacesView } from './spaces-new/CatalogLayoutSpacesView'; import { CatalogLayoutSpacesView } from './spaces-new/CatalogLayoutSpacesView';
import { CatalogLayoutTrophiesView } from './trophies/CatalogLayoutTrophiesView'; import { CatalogLayoutTrophiesView } from './trophies/CatalogLayoutTrophiesView';
@ -13,7 +14,7 @@ export function GetCatalogLayout(pageParser: ICatalogPageParser, roomPreviewer:
case 'frontpage4': case 'frontpage4':
return null; return null;
case 'pets': case 'pets':
return null; return <CatalogLayoutPetView roomPreviewer={ roomPreviewer } pageParser={ pageParser } />;
case 'pets2': case 'pets2':
return null; return null;
case 'pets3': case 'pets3':

View File

@ -0,0 +1,10 @@
.nitro-catalog-layout-pets {
.color-button {
position: absolute;
left: 5px;
bottom: 5px;
}
@import './name-approval/CatalogPetNameApprovalView';
}

View File

@ -0,0 +1,150 @@
import { CatalogRequestPetBreedsComposer, ColorConverter, SellablePetPaletteData } from 'nitro-renderer';
import { FC, useEffect, useMemo, useState } from 'react';
import { GetProductDataForLocalization } from '../../../../../../api/nitro/session/GetProductDataForLocalization';
import { SendMessageHook } from '../../../../../../hooks/messages/message-event';
import { LocalizeText } from '../../../../../../utils/LocalizeText';
import { PetImageView } from '../../../../../pet-image/PetImageView';
import { RoomPreviewerView } from '../../../../../room-previewer/RoomPreviewerView';
import { useCatalogContext } from '../../../../context/CatalogContext';
import { CatalogActions } from '../../../../reducers/CatalogReducer';
import { GetPetAvailableColors, GetPetIndexFromLocalization } from '../../../../utils/CatalogUtilities';
import { CatalogLayoutPetViewProps } from './CatalogLayoutPetView.types';
import { CatalogLayoutPetPurchaseView } from './purchase/CatalogLayoutPetPurchaseView';
export const CatalogLayoutPetView: FC<CatalogLayoutPetViewProps> = props =>
{
const { roomPreviewer = null, pageParser = null } = props;
const { catalogState = null, dispatchCatalogState = null } = useCatalogContext();
const { activeOffer = null, petPalettes = [] } = catalogState;
const [ petIndex, setPetIndex ] = useState(-1);
const [ sellablePalettes, setSellablePalettes ] = useState<SellablePetPaletteData[]>([]);
const [ selectedPaletteIndex, setSelectedPaletteIndex ] = useState(-1);
const [ sellableColors, setSellableColors ] = useState<number[][]>([]);
const [ selectedColorIndex, setSelectedColorIndex ] = useState(-1);
const [ colorsShowing, setColorsShowing ] = useState(false);
useEffect(() =>
{
if(!pageParser || !pageParser.offers.length) return;
const offer = pageParser.offers[0];
dispatchCatalogState({
type: CatalogActions.SET_CATALOG_ACTIVE_OFFER,
payload: {
activeOffer: offer
}
});
setPetIndex(GetPetIndexFromLocalization(offer.localizationId));
setColorsShowing(false);
}, [ pageParser, dispatchCatalogState ]);
useEffect(() =>
{
if(!activeOffer) return;
const productData = GetProductDataForLocalization(activeOffer.localizationId);
if(!productData) return;
for(const paletteData of petPalettes)
{
if(paletteData.breed !== productData.type) continue;
const palettes: SellablePetPaletteData[] = [];
for(const palette of paletteData.palettes)
{
if(!palette.sellable) continue;
palettes.push(palette);
}
setSelectedPaletteIndex((palettes.length ? 0 : -1));
setSellablePalettes(palettes);
return;
}
setSelectedPaletteIndex(-1);
setSellablePalettes([]);
SendMessageHook(new CatalogRequestPetBreedsComposer(productData.type));
}, [ activeOffer, petPalettes ]);
useEffect(() =>
{
if(petIndex === -1) return;
const colors = GetPetAvailableColors(petIndex, sellablePalettes);
setSelectedColorIndex((colors.length ? 0 : -1));
setSellableColors(colors);
}, [ petIndex, sellablePalettes ]);
const getColor = useMemo(() =>
{
if(!sellableColors.length || (selectedColorIndex === -1)) return 0xFFFFFF;
return sellableColors[selectedColorIndex][0];
}, [ sellableColors, selectedColorIndex ]);
useEffect(() =>
{
if(!roomPreviewer) return;
roomPreviewer && roomPreviewer.reset(false);
if((petIndex === -1) || !sellablePalettes.length || (selectedPaletteIndex === -1)) return;
let petFigureString = `${ petIndex } ${ sellablePalettes[selectedPaletteIndex].paletteId }`;
if(petIndex <= 7) petFigureString += ` ${ getColor.toString(16) }`;
roomPreviewer.addPetIntoRoom(petFigureString);
}, [ roomPreviewer, petIndex, sellablePalettes, selectedPaletteIndex, getColor ]);
const petBreedName = useMemo(() =>
{
if((petIndex === -1) || !sellablePalettes.length || (selectedPaletteIndex === -1)) return '';
return LocalizeText(`pet.breed.${ petIndex }.${ sellablePalettes[selectedPaletteIndex].breedId }`);
}, [ petIndex, sellablePalettes, selectedPaletteIndex ]);
if(!activeOffer) return null;
return (
<div className="row h-100 nitro-catalog-layout-pets">
<div className="col-7">
<div className="row row-cols-5 align-content-start g-0 mb-n1 w-100 catalog-offers-container single-bundle-items-container">
{ colorsShowing && (sellableColors.length > 0) && sellableColors.map((colorSet, index) =>
{
return <div key={ index } className="col pe-1 pb-1 catalog-offer-item-container">
<div className={ 'position-relative border border-2 rounded catalog-offer-item cursor-pointer ' + ((selectedColorIndex === index) ? 'active ' : '') } style={ { backgroundColor: ColorConverter.int2rgb(colorSet[0]) } } onClick={ event => setSelectedColorIndex(index) }>
</div>
</div>;
})}
{ !colorsShowing && (sellablePalettes.length > 0) && sellablePalettes.map((palette, index) =>
{
return <div key={ index } className="col pe-1 pb-1 catalog-offer-item-container">
<div className={ 'position-relative border border-2 rounded catalog-offer-item cursor-pointer ' + ((selectedPaletteIndex === index) ? 'active ' : '') } onClick={ event => setSelectedPaletteIndex(index) }>
<PetImageView typeId={ petIndex } paletteId={ palette.paletteId } direction={ 2 } headOnly={ true } />
</div>
</div>;
}) }
</div>
</div>
<div className="position-relative d-flex flex-column col-5">
<RoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 }>
{ (petIndex > -1 && petIndex <= 7) &&
<button type="button" className= { 'btn btn-primary btn-sm color-button ' + (colorsShowing ? 'active ' : '') } onClick={ event => setColorsShowing(!colorsShowing) }>
<i className="fas fa-fill-drip" />
</button> }
</RoomPreviewerView>
<div className="fs-6 text-black mt-1 overflow-hidden">{ petBreedName }</div>
<CatalogLayoutPetPurchaseView offer={ activeOffer } pageId={ pageParser.pageId } />
</div>
</div>
);
}

View File

@ -0,0 +1,6 @@
import { CatalogLayoutProps } from '../CatalogLayout.types';
export interface CatalogLayoutPetViewProps extends CatalogLayoutProps
{
}

View File

@ -0,0 +1,12 @@
import { FC } from 'react';
import { LocalizeText } from '../../../../../../../utils/LocalizeText';
import { CatalogPetNameApprovalViewProps } from './CatalogPetNameApprovalView.types';
export const CatalogPetNameApprovalView: FC<CatalogPetNameApprovalViewProps> = props =>
{
const { petNameValue = null, setPetNameValue = null } = props;
return (
<input type="text" className="form-control form-control-sm" placeholder={ LocalizeText('widgets.petpackage.name.title') } value={ petNameValue } onChange={ event => setPetNameValue(event.target.value) } />
);
}

View File

@ -0,0 +1,7 @@
import { Dispatch, SetStateAction } from 'react';
export interface CatalogPetNameApprovalViewProps
{
petNameValue: string;
setPetNameValue: Dispatch<SetStateAction<string>>;
}

View File

@ -0,0 +1,44 @@
import { FC, useState } from 'react';
import { CurrencyIcon } from '../../../../../../../utils/currency-icon/CurrencyIcon';
import { LocalizeText } from '../../../../../../../utils/LocalizeText';
import { CatalogPurchaseButtonView } from '../../../purchase/purchase-button/CatalogPurchaseButtonView';
import { CatalogPetNameApprovalView } from '../name-approval/CatalogPetNameApprovalView';
import { CatalogLayoutPetPurchaseViewProps } from './CatalogLayoutPetPurchaseView.types';
export const CatalogLayoutPetPurchaseView: FC<CatalogLayoutPetPurchaseViewProps> = props =>
{
const { offer = null, pageId = -1, extra = '' } = props;
const [ petNameValue, setPetNameValue ] = useState('');
const extraData = ((extra && extra.length) ? extra : (offer?.products[0]?.extraParam || null));
return (
<>
<div className="d-flex flex-grow-1 justify-content-center align-items-center">
<CatalogPetNameApprovalView petNameValue={ petNameValue } setPetNameValue={ setPetNameValue } />
</div>
<div className="d-flex flex-column flex-grow-1 justify-content-end w-100">
<div className="d-flex align-items-end">
<div className="flex-grow-1 align-items-end">
<span className="text-black">{ LocalizeText('catalog.bundlewidget.price') }</span>
</div>
<div className="d-flex flex-column">
{ (offer.priceCredits > 0) &&
<div className="d-flex align-items-center justify-content-end">
<span className="text-black ms-1">{ offer.priceCredits }</span>
<CurrencyIcon type={ -1 } />
</div> }
{ (offer.priceActivityPoints > 0) &&
<div className="d-flex align-items-center justify-content-end">
<span className="text-black ms-1">{ offer.priceActivityPoints }</span>
<CurrencyIcon type={ offer.priceActivityPointsType } />
</div> }
</div>
</div>
<div className="d-flex flex-column mt-1">
<CatalogPurchaseButtonView className="btn-sm w-100" offer={ offer } pageId={ pageId } extra={ extraData } quantity={ 1 } />
</div>
</div>
</>
);
}

View File

@ -0,0 +1,8 @@
import { CatalogPageOfferData } from 'nitro-renderer';
export interface CatalogLayoutPetPurchaseViewProps
{
offer: CatalogPageOfferData;
pageId: number;
extra?: string;
}

View File

@ -6,14 +6,14 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
border-color: $grid-border-color !important; border-color: $grid-border-color !important;
background-color: $grid-bg-color !important; background-color: $grid-bg-color;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
overflow: hidden; overflow: hidden;
&.active { &.active {
border-color: $grid-active-border-color !important; border-color: $grid-active-border-color !important;
background-color: $grid-active-bg-color !important; background-color: $grid-active-bg-color;
} }
.badge { .badge {

View File

@ -113,7 +113,7 @@ export const CatalogSearchView: FC<CatalogSearchViewProps> = props =>
return ( return (
<div className="d-flex mb-1"> <div className="d-flex mb-1">
<div className="d-flex flex-grow-1 me-1"> <div className="d-flex flex-grow-1 me-1">
<input type="text" className="form-control form-control-sm" placeholder="search" value={ searchValue } onChange={ event => setSearchValue(event.target.value) } /> <input type="text" className="form-control form-control-sm" placeholder={ LocalizeText('generic.search') } value={ searchValue } onChange={ event => setSearchValue(event.target.value) } />
</div> </div>
<div className="d-flex"> <div className="d-flex">
<button type="button" className="btn btn-primary btn-sm"> <button type="button" className="btn btn-primary btn-sm">

View File

@ -57,5 +57,5 @@ export const PetImageView: FC<PetImageViewProps> = props =>
const url = `url('${ petUrl }')`; const url = `url('${ petUrl }')`;
return <div className={ 'pet-image scale-' + scale } style={ (petUrl && url.length) ? { backgroundImage: url } : {} }></div>; return <div className={ 'pet-image scale-' + scale.toString().replace('.', '-') } style={ (petUrl && url.length) ? { backgroundImage: url } : {} }></div>;
} }