mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-01-19 05:46: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 { UserCurrencyComposer } from 'nitro-renderer';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { FC, useEffect, useMemo, useReducer } from 'react';
|
||||||
import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event';
|
import { SendMessageHook } from '../../hooks/messages/message-event';
|
||||||
import { TransitionAnimation } from '../../transitions/TransitionAnimation';
|
|
||||||
import { TransitionAnimationTypes } from '../../transitions/TransitionAnimation.types';
|
|
||||||
import { GetConfiguration } from '../../utils/GetConfiguration';
|
import { GetConfiguration } from '../../utils/GetConfiguration';
|
||||||
import { CurrencySet } from './currency/CurrencySet';
|
import { PurseContextProvider } from './context/PurseContext';
|
||||||
import { CurrencyView } from './currency/CurrencyView';
|
import { CurrencyView } from './currency/CurrencyView';
|
||||||
|
import { PurseMessageHandler } from './PurseMessageHandler';
|
||||||
import { PurseViewProps } from './PurseView.types';
|
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 [ purseState, dispatchPurseState ] = useReducer(PurseReducer, initialPurse);
|
||||||
const [ isReady, setIsReady ] = useState(false);
|
const { currencies = [] } = purseState;
|
||||||
|
|
||||||
const displayedCurrencies = GetConfiguration<number[]>('system.currency.types', []);
|
const displayedCurrencies = useMemo(() =>
|
||||||
|
|
||||||
const onUserCreditsEvent = useCallback((event: UserCreditsEvent) =>
|
|
||||||
{
|
{
|
||||||
const parser = event.getParser();
|
return GetConfiguration<number[]>('system.currency.types', []);
|
||||||
|
|
||||||
updateCurrency(-1, parseFloat(parser.credits));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
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(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
SendMessageHook(new UserCurrencyComposer());
|
SendMessageHook(new UserCurrencyComposer());
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
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">
|
<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>
|
</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
|
export function CurrencyView(props: CurrencyViewProps): JSX.Element
|
||||||
{
|
{
|
||||||
const { currencySet = null } = props;
|
const { currency = null } = props;
|
||||||
|
|
||||||
const [ firstRender, setFirstRender ] = useState(true);
|
const [ firstRender, setFirstRender ] = useState(true);
|
||||||
const [ isAnimating, setIsAnimating ] = useState(false);
|
const [ isAnimating, setIsAnimating ] = useState(false);
|
||||||
@ -22,22 +22,20 @@ export function CurrencyView(props: CurrencyViewProps): JSX.Element
|
|||||||
|
|
||||||
setIsAnimating(true);
|
setIsAnimating(true);
|
||||||
|
|
||||||
let timeout = setTimeout(() =>
|
const timeout = setTimeout(() => setIsAnimating(false), 305);
|
||||||
|
|
||||||
|
return () =>
|
||||||
{
|
{
|
||||||
setIsAnimating(false)
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
timeout = null
|
}, [ firstRender, currency ]);
|
||||||
}, 300);
|
|
||||||
|
|
||||||
return () => clearTimeout(timeout);
|
|
||||||
}, [ firstRender, currencySet ]);
|
|
||||||
|
|
||||||
return (
|
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="col pe-1 pb-1">
|
||||||
<div className="d-flex bg-primary rounded border overflow-hidden">
|
<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="d-flex flex-grow-1 align-items-center justify-content-end pe-1">{ !isAnimating && currency.amount }</div>
|
||||||
<div className="bg-secondary"><CurrencyIcon type={ currencySet.type } /></div>
|
<div className="bg-secondary"><CurrencyIcon type={ currency.type } /></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TransitionAnimation>
|
</TransitionAnimation>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { CurrencySet } from './CurrencySet';
|
import { Currency } from '../utils/Currency';
|
||||||
|
|
||||||
export interface CurrencyViewProps
|
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