mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-01-18 21:36:27 +01:00
Update purse
This commit is contained in:
parent
1cf02c53d7
commit
4ef0a1d6d0
56
src/views/purse/PurseMessageHandler.tsx
Normal file
56
src/views/purse/PurseMessageHandler.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import { UserCreditsEvent, UserCurrencyEvent, UserCurrencyUpdateEvent } from 'nitro-renderer';
|
||||
import { FC, useCallback } from 'react';
|
||||
import { CreateMessageHook } from '../../hooks/messages/message-event';
|
||||
import { usePurseContext } from './context/PurseContext';
|
||||
import { PurseMessageHandlerProps } from './PurseMessageHandler.types';
|
||||
import { PurseActions } from './reducers/PurseReducer';
|
||||
import { Currency } from './utils/Currency';
|
||||
|
||||
export const PurseMessageHandler: FC<PurseMessageHandlerProps> = props =>
|
||||
{
|
||||
const { dispatchPurseState = null } = usePurseContext();
|
||||
|
||||
const onUserCreditsEvent = useCallback((event: UserCreditsEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
dispatchPurseState({
|
||||
type: PurseActions.SET_CURRENCY,
|
||||
payload: {
|
||||
currency: { type: -1, amount: parseFloat(parser.credits) }
|
||||
}
|
||||
});
|
||||
}, [ dispatchPurseState ]);
|
||||
|
||||
const onUserCurrencyEvent = useCallback((event: UserCurrencyEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
const currencies: Currency[] = [];
|
||||
|
||||
for(const [ key, value ] of parser.currencies.entries()) currencies.push({ type: key, amount: value });
|
||||
|
||||
dispatchPurseState({
|
||||
type: PurseActions.SET_CURRENCIES,
|
||||
payload: { currencies }
|
||||
});
|
||||
}, [ dispatchPurseState ]);
|
||||
|
||||
const onUserCurrencyUpdateEvent = useCallback((event: UserCurrencyUpdateEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
dispatchPurseState({
|
||||
type: PurseActions.SET_CURRENCY,
|
||||
payload: {
|
||||
currency: { type: parser.type, amount: parser.amount }
|
||||
}
|
||||
});
|
||||
}, [ dispatchPurseState ]);
|
||||
|
||||
CreateMessageHook(UserCreditsEvent, onUserCreditsEvent);
|
||||
CreateMessageHook(UserCurrencyEvent, onUserCurrencyEvent);
|
||||
CreateMessageHook(UserCurrencyUpdateEvent, onUserCurrencyUpdateEvent);
|
||||
|
||||
return null;
|
||||
}
|
4
src/views/purse/PurseMessageHandler.types.ts
Normal file
4
src/views/purse/PurseMessageHandler.types.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface PurseMessageHandlerProps
|
||||
{
|
||||
|
||||
}
|
@ -1,90 +1,39 @@
|
||||
import { UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserCurrencyUpdateEvent } from 'nitro-renderer';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event';
|
||||
import { TransitionAnimation } from '../../transitions/TransitionAnimation';
|
||||
import { TransitionAnimationTypes } from '../../transitions/TransitionAnimation.types';
|
||||
import { UserCurrencyComposer } from 'nitro-renderer';
|
||||
import { FC, useEffect, useMemo, useReducer } from 'react';
|
||||
import { SendMessageHook } from '../../hooks/messages/message-event';
|
||||
import { GetConfiguration } from '../../utils/GetConfiguration';
|
||||
import { CurrencySet } from './currency/CurrencySet';
|
||||
import { PurseContextProvider } from './context/PurseContext';
|
||||
import { CurrencyView } from './currency/CurrencyView';
|
||||
import { PurseMessageHandler } from './PurseMessageHandler';
|
||||
import { PurseViewProps } from './PurseView.types';
|
||||
import { initialPurse, PurseReducer } from './reducers/PurseReducer';
|
||||
|
||||
export function PurseView(props: PurseViewProps): JSX.Element
|
||||
export const PurseView: FC<PurseViewProps> = props =>
|
||||
{
|
||||
const [ currencies, setCurrencies ] = useState<CurrencySet[]>([ new CurrencySet(-1, 0) ]);
|
||||
const [ isReady, setIsReady ] = useState(false);
|
||||
|
||||
const displayedCurrencies = GetConfiguration<number[]>('system.currency.types', []);
|
||||
|
||||
const onUserCreditsEvent = useCallback((event: UserCreditsEvent) =>
|
||||
const [ purseState, dispatchPurseState ] = useReducer(PurseReducer, initialPurse);
|
||||
const { currencies = [] } = purseState;
|
||||
|
||||
const displayedCurrencies = useMemo(() =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
updateCurrency(-1, parseFloat(parser.credits));
|
||||
return GetConfiguration<number[]>('system.currency.types', []);
|
||||
}, []);
|
||||
|
||||
const onUserCurrencyEvent = useCallback((event: UserCurrencyEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
for(const [ key, value ] of parser.currencies.entries()) updateCurrency(key, value);
|
||||
|
||||
setIsReady(true);
|
||||
}, []);
|
||||
|
||||
const onUserCurrencyUpdateEvent = useCallback((event: UserCurrencyUpdateEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
updateCurrency(parser.type, parser.amount)
|
||||
}, []);
|
||||
|
||||
function updateCurrency(type: number, amount: number): void
|
||||
{
|
||||
setCurrencies(oldState =>
|
||||
{
|
||||
const newState: CurrencySet[] = [];
|
||||
|
||||
let found = false;
|
||||
|
||||
for(const set of oldState)
|
||||
{
|
||||
if(set.type !== type)
|
||||
{
|
||||
newState.push(set);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
newState.push(new CurrencySet(set.type, amount));
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
if(!found) newState.push(new CurrencySet(type, amount));
|
||||
|
||||
return newState;
|
||||
});
|
||||
}
|
||||
|
||||
CreateMessageHook(UserCreditsEvent, onUserCreditsEvent);
|
||||
CreateMessageHook(UserCurrencyEvent, onUserCurrencyEvent);
|
||||
CreateMessageHook(UserCurrencyUpdateEvent, onUserCurrencyUpdateEvent);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
SendMessageHook(new UserCurrencyComposer());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<TransitionAnimation className="nitro-purse position-relative mb-1" type={ TransitionAnimationTypes.FADE_DOWN } inProp={ isReady } timeout={ 300 }>
|
||||
<PurseContextProvider value={ { purseState, dispatchPurseState }}>
|
||||
<PurseMessageHandler />
|
||||
<div className="row row-cols-2 g-0">
|
||||
{ currencies && currencies.map((set, index) =>
|
||||
{ currencies && currencies.map((currency, index) =>
|
||||
{
|
||||
if(displayedCurrencies.indexOf(set.type) === -1) return null;
|
||||
if(displayedCurrencies.indexOf(currency.type) === -1) return null;
|
||||
|
||||
return <CurrencyView key={ index } currencySet={ set } />
|
||||
return <CurrencyView key={ index } currency={ currency } />
|
||||
}) }
|
||||
</div>
|
||||
</TransitionAnimation>
|
||||
</PurseContextProvider>
|
||||
);
|
||||
}
|
||||
|
14
src/views/purse/context/PurseContext.tsx
Normal file
14
src/views/purse/context/PurseContext.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { createContext, FC, useContext } from 'react';
|
||||
import { IPurseContext, PurseContextProps } from './PurseContext.types';
|
||||
|
||||
const PurseContext = createContext<IPurseContext>({
|
||||
purseState: null,
|
||||
dispatchPurseState: null
|
||||
});
|
||||
|
||||
export const PurseContextProvider: FC<PurseContextProps> = props =>
|
||||
{
|
||||
return <PurseContext.Provider value={ props.value }>{ props.children }</PurseContext.Provider>
|
||||
}
|
||||
|
||||
export const usePurseContext = () => useContext(PurseContext);
|
13
src/views/purse/context/PurseContext.types.ts
Normal file
13
src/views/purse/context/PurseContext.types.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Dispatch, ProviderProps } from 'react';
|
||||
import { IPurseAction, IPurseState } from '../reducers/PurseReducer';
|
||||
|
||||
export interface IPurseContext
|
||||
{
|
||||
purseState: IPurseState;
|
||||
dispatchPurseState: Dispatch<IPurseAction>;
|
||||
}
|
||||
|
||||
export interface PurseContextProps extends ProviderProps<IPurseContext>
|
||||
{
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
export class CurrencySet
|
||||
{
|
||||
constructor(
|
||||
public type: number,
|
||||
public amount: number)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import { CurrencyViewProps } from './CurrencyView.types';
|
||||
|
||||
export function CurrencyView(props: CurrencyViewProps): JSX.Element
|
||||
{
|
||||
const { currencySet = null } = props;
|
||||
const { currency = null } = props;
|
||||
|
||||
const [ firstRender, setFirstRender ] = useState(true);
|
||||
const [ isAnimating, setIsAnimating ] = useState(false);
|
||||
@ -22,22 +22,20 @@ export function CurrencyView(props: CurrencyViewProps): JSX.Element
|
||||
|
||||
setIsAnimating(true);
|
||||
|
||||
let timeout = setTimeout(() =>
|
||||
{
|
||||
setIsAnimating(false)
|
||||
|
||||
timeout = null
|
||||
}, 300);
|
||||
const timeout = setTimeout(() => setIsAnimating(false), 305);
|
||||
|
||||
return () => clearTimeout(timeout);
|
||||
}, [ firstRender, currencySet ]);
|
||||
return () =>
|
||||
{
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}, [ firstRender, currency ]);
|
||||
|
||||
return (
|
||||
<TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ isAnimating } timeout={ 300 }>
|
||||
<TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ isAnimating }>
|
||||
<div className="col pe-1 pb-1">
|
||||
<div className="d-flex bg-primary rounded border overflow-hidden">
|
||||
<div className="d-flex flex-grow-1 align-items-center justify-content-end pe-1">{ currencySet.amount }</div>
|
||||
<div className="bg-secondary"><CurrencyIcon type={ currencySet.type } /></div>
|
||||
<div className="d-flex flex-grow-1 align-items-center justify-content-end pe-1">{ !isAnimating && currency.amount }</div>
|
||||
<div className="bg-secondary"><CurrencyIcon type={ currency.type } /></div>
|
||||
</div>
|
||||
</div>
|
||||
</TransitionAnimation>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CurrencySet } from './CurrencySet';
|
||||
import { Currency } from '../utils/Currency';
|
||||
|
||||
export interface CurrencyViewProps
|
||||
{
|
||||
currencySet: CurrencySet;
|
||||
currency: Currency;
|
||||
}
|
||||
|
67
src/views/purse/reducers/PurseReducer.tsx
Normal file
67
src/views/purse/reducers/PurseReducer.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import { Reducer } from 'react';
|
||||
import { Currency } from '../utils/Currency';
|
||||
|
||||
export interface IPurseState
|
||||
{
|
||||
currencies: Currency[];
|
||||
}
|
||||
|
||||
export interface IPurseAction
|
||||
{
|
||||
type: string;
|
||||
payload: {
|
||||
currency?: Currency;
|
||||
currencies?: Currency[];
|
||||
}
|
||||
}
|
||||
|
||||
export class PurseActions
|
||||
{
|
||||
public static SET_CURRENCY: string = 'PA_SET_CURRENCY';
|
||||
public static SET_CURRENCIES: string = 'PA_SET_CURRENCIES';
|
||||
}
|
||||
|
||||
export const initialPurse: IPurseState = {
|
||||
currencies: []
|
||||
}
|
||||
|
||||
export const PurseReducer: Reducer<IPurseState, IPurseAction> = (state, action) =>
|
||||
{
|
||||
switch(action.type)
|
||||
{
|
||||
case PurseActions.SET_CURRENCY: {
|
||||
const updated = action.payload.currency;
|
||||
|
||||
let didSet = false;
|
||||
|
||||
const currencies = state.currencies.map((existing, index) =>
|
||||
{
|
||||
if(existing.type !== updated.type) return existing;
|
||||
|
||||
didSet = true;
|
||||
|
||||
return { ...updated };
|
||||
});
|
||||
|
||||
if(!didSet) currencies.push({ ...updated });
|
||||
|
||||
return { ...state, currencies };
|
||||
}
|
||||
case PurseActions.SET_CURRENCIES: {
|
||||
const updated = action.payload.currencies;
|
||||
|
||||
const currencies = state.currencies.filter((existing, index) =>
|
||||
{
|
||||
if(existing.type !== -1) return null;
|
||||
|
||||
return existing;
|
||||
});
|
||||
|
||||
if(updated && updated.length) currencies.push(...updated);
|
||||
|
||||
return { ...state, currencies };
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
5
src/views/purse/utils/Currency.ts
Normal file
5
src/views/purse/utils/Currency.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface Currency
|
||||
{
|
||||
type: number;
|
||||
amount: number;
|
||||
}
|
Loading…
Reference in New Issue
Block a user