Merge pull request #1161 from 0xProject/feature/instant/order-details-loading-state
[instant] Order details loading state
This commit is contained in:
32
packages/instant/src/components/amount_placeholder.tsx
Normal file
32
packages/instant/src/components/amount_placeholder.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { ColorOption } from '../style/theme';
|
||||
|
||||
import { Pulse } from './animations/pulse';
|
||||
|
||||
import { Text } from './ui';
|
||||
|
||||
interface PlainPlaceholder {
|
||||
color: ColorOption;
|
||||
}
|
||||
const PlainPlaceholder: React.StatelessComponent<PlainPlaceholder> = props => (
|
||||
<Text fontWeight="bold" fontColor={props.color}>
|
||||
—
|
||||
</Text>
|
||||
);
|
||||
|
||||
export interface AmountPlaceholderProps {
|
||||
color: ColorOption;
|
||||
isPulsating: boolean;
|
||||
}
|
||||
export const AmountPlaceholder: React.StatelessComponent<AmountPlaceholderProps> = props => {
|
||||
if (props.isPulsating) {
|
||||
return (
|
||||
<Pulse>
|
||||
<PlainPlaceholder color={props.color} />
|
||||
</Pulse>
|
||||
);
|
||||
} else {
|
||||
return <PlainPlaceholder color={props.color} />;
|
||||
}
|
||||
};
|
15
packages/instant/src/components/animations/pulse.tsx
Normal file
15
packages/instant/src/components/animations/pulse.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { keyframes, styled } from '../../style/theme';
|
||||
|
||||
const pulsingKeyframes = keyframes`
|
||||
0%, 100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 100;
|
||||
}
|
||||
`;
|
||||
export const Pulse = styled.div`
|
||||
animation-name: ${pulsingKeyframes}
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
`;
|
@@ -7,79 +7,81 @@ import { ColorOption } from '../style/theme';
|
||||
import { AsyncProcessState } from '../types';
|
||||
import { format } from '../util/format';
|
||||
|
||||
import { AmountPlaceholder } from './amount_placeholder';
|
||||
import { Container, Flex, Text } from './ui';
|
||||
|
||||
export interface InstantHeadingProps {
|
||||
selectedAssetAmount?: BigNumber;
|
||||
totalEthBaseAmount?: BigNumber;
|
||||
ethUsdPrice?: BigNumber;
|
||||
quoteState: AsyncProcessState;
|
||||
quoteRequestState: AsyncProcessState;
|
||||
}
|
||||
|
||||
const Placeholder = () => (
|
||||
<Text fontWeight="bold" fontColor={ColorOption.white}>
|
||||
—
|
||||
</Text>
|
||||
);
|
||||
const displaytotalEthBaseAmount = ({
|
||||
selectedAssetAmount,
|
||||
totalEthBaseAmount,
|
||||
}: InstantHeadingProps): React.ReactNode => {
|
||||
if (_.isUndefined(selectedAssetAmount)) {
|
||||
return '0 ETH';
|
||||
}
|
||||
return format.ethBaseAmount(totalEthBaseAmount, 4, <Placeholder />);
|
||||
};
|
||||
|
||||
const displayUsdAmount = ({
|
||||
totalEthBaseAmount,
|
||||
selectedAssetAmount,
|
||||
ethUsdPrice,
|
||||
}: InstantHeadingProps): React.ReactNode => {
|
||||
if (_.isUndefined(selectedAssetAmount)) {
|
||||
return '$0.00';
|
||||
}
|
||||
return format.ethBaseAmountInUsd(totalEthBaseAmount, ethUsdPrice, 2, <Placeholder />);
|
||||
};
|
||||
|
||||
const loadingOrAmount = (quoteState: AsyncProcessState, amount: React.ReactNode): React.ReactNode => {
|
||||
if (quoteState === AsyncProcessState.PENDING) {
|
||||
const placeholderColor = ColorOption.white;
|
||||
export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
||||
public render(): React.ReactNode {
|
||||
return (
|
||||
<Text fontWeight="bold" fontColor={ColorOption.white}>
|
||||
…loading
|
||||
</Text>
|
||||
);
|
||||
} else {
|
||||
return amount;
|
||||
}
|
||||
};
|
||||
|
||||
export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = props => (
|
||||
<Container backgroundColor={ColorOption.primaryColor} padding="20px" width="100%" borderRadius="3px 3px 0px 0px">
|
||||
<Container marginBottom="5px">
|
||||
<Text
|
||||
letterSpacing="1px"
|
||||
fontColor={ColorOption.white}
|
||||
opacity={0.7}
|
||||
fontWeight={500}
|
||||
textTransform="uppercase"
|
||||
fontSize="12px"
|
||||
<Container
|
||||
backgroundColor={ColorOption.primaryColor}
|
||||
padding="20px"
|
||||
width="100%"
|
||||
borderRadius="3px 3px 0px 0px"
|
||||
>
|
||||
I want to buy
|
||||
</Text>
|
||||
</Container>
|
||||
<Flex direction="row" justify="space-between">
|
||||
<SelectedAssetAmountInput fontSize="45px" />
|
||||
<Flex direction="column" justify="space-between">
|
||||
<Container marginBottom="5px">
|
||||
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
|
||||
{loadingOrAmount(props.quoteState, displaytotalEthBaseAmount(props))}
|
||||
<Text
|
||||
letterSpacing="1px"
|
||||
fontColor={ColorOption.white}
|
||||
opacity={0.7}
|
||||
fontWeight={500}
|
||||
textTransform="uppercase"
|
||||
fontSize="12px"
|
||||
>
|
||||
I want to buy
|
||||
</Text>
|
||||
</Container>
|
||||
<Text fontSize="16px" fontColor={ColorOption.white} opacity={0.7}>
|
||||
{loadingOrAmount(props.quoteState, displayUsdAmount(props))}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Container>
|
||||
);
|
||||
<Flex direction="row" justify="space-between">
|
||||
<SelectedAssetAmountInput fontSize="45px" />
|
||||
<Flex direction="column" justify="space-between">
|
||||
<Container marginBottom="5px">{this._placeholderOrAmount(this._ethAmount)}</Container>
|
||||
<Container opacity={0.7}>{this._placeholderOrAmount(this._dollarAmount)}</Container>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
private _placeholderOrAmount(amountFunction: () => React.ReactNode): React.ReactNode {
|
||||
if (this.props.quoteRequestState === AsyncProcessState.PENDING) {
|
||||
return <AmountPlaceholder isPulsating={true} color={placeholderColor} />;
|
||||
}
|
||||
if (_.isUndefined(this.props.selectedAssetAmount)) {
|
||||
return <AmountPlaceholder isPulsating={false} color={placeholderColor} />;
|
||||
}
|
||||
return amountFunction();
|
||||
}
|
||||
|
||||
private readonly _ethAmount = (): React.ReactNode => {
|
||||
return (
|
||||
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
|
||||
{format.ethBaseAmount(
|
||||
this.props.totalEthBaseAmount,
|
||||
4,
|
||||
<AmountPlaceholder isPulsating={false} color={placeholderColor} />,
|
||||
)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
private readonly _dollarAmount = (): React.ReactNode => {
|
||||
return (
|
||||
<Text fontSize="16px" fontColor={ColorOption.white}>
|
||||
{format.ethBaseAmountInUsd(
|
||||
this.props.totalEthBaseAmount,
|
||||
this.props.ethUsdPrice,
|
||||
2,
|
||||
<AmountPlaceholder isPulsating={false} color={ColorOption.white} />,
|
||||
)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@@ -7,13 +7,14 @@ import { oc } from 'ts-optchain';
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { format } from '../util/format';
|
||||
|
||||
import { AmountPlaceholder } from './amount_placeholder';
|
||||
import { Container, Flex, Text } from './ui';
|
||||
|
||||
export interface OrderDetailsProps {
|
||||
buyQuoteInfo?: BuyQuoteInfo;
|
||||
ethUsdPrice?: BigNumber;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export class OrderDetails extends React.Component<OrderDetailsProps> {
|
||||
public render(): React.ReactNode {
|
||||
const { buyQuoteInfo, ethUsdPrice } = this.props;
|
||||
@@ -39,13 +40,20 @@ export class OrderDetails extends React.Component<OrderDetailsProps> {
|
||||
ethAmount={ethAssetPrice}
|
||||
ethUsdPrice={ethUsdPrice}
|
||||
isEthAmountInBaseUnits={false}
|
||||
isLoading={this.props.isLoading}
|
||||
/>
|
||||
<EthAmountRow
|
||||
rowLabel="Fee"
|
||||
ethAmount={ethTokenFee}
|
||||
ethUsdPrice={ethUsdPrice}
|
||||
isLoading={this.props.isLoading}
|
||||
/>
|
||||
<EthAmountRow rowLabel="Fee" ethAmount={ethTokenFee} ethUsdPrice={ethUsdPrice} />
|
||||
<EthAmountRow
|
||||
rowLabel="Total Cost"
|
||||
ethAmount={totalEthAmount}
|
||||
ethUsdPrice={ethUsdPrice}
|
||||
shouldEmphasize={true}
|
||||
isLoading={this.props.isLoading}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
@@ -58,43 +66,50 @@ export interface EthAmountRowProps {
|
||||
isEthAmountInBaseUnits?: boolean;
|
||||
ethUsdPrice?: BigNumber;
|
||||
shouldEmphasize?: boolean;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export const EthAmountRow: React.StatelessComponent<EthAmountRowProps> = ({
|
||||
rowLabel,
|
||||
ethAmount,
|
||||
isEthAmountInBaseUnits,
|
||||
ethUsdPrice,
|
||||
shouldEmphasize,
|
||||
}) => {
|
||||
const fontWeight = shouldEmphasize ? 700 : 400;
|
||||
const usdFormatter = isEthAmountInBaseUnits ? format.ethBaseAmountInUsd : format.ethUnitAmountInUsd;
|
||||
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseAmount : format.ethUnitAmount;
|
||||
const usdPriceSection = _.isUndefined(ethUsdPrice) ? null : (
|
||||
<Container marginRight="3px" display="inline-block">
|
||||
<Text fontColor={ColorOption.lightGrey}>({usdFormatter(ethAmount, ethUsdPrice)})</Text>
|
||||
</Container>
|
||||
);
|
||||
return (
|
||||
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
|
||||
<Flex justify="space-between">
|
||||
<Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
|
||||
{rowLabel}
|
||||
</Text>
|
||||
<Container>
|
||||
{usdPriceSection}
|
||||
export class EthAmountRow extends React.Component<EthAmountRowProps> {
|
||||
public static defaultProps = {
|
||||
shouldEmphasize: false,
|
||||
isEthAmountInBaseUnits: true,
|
||||
};
|
||||
public render(): React.ReactNode {
|
||||
const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props;
|
||||
|
||||
const fontWeight = shouldEmphasize ? 700 : 400;
|
||||
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseAmount : format.ethUnitAmount;
|
||||
return (
|
||||
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
|
||||
<Flex justify="space-between">
|
||||
<Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
|
||||
{ethFormatter(ethAmount)}
|
||||
{rowLabel}
|
||||
</Text>
|
||||
</Container>
|
||||
</Flex>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
EthAmountRow.defaultProps = {
|
||||
shouldEmphasize: false,
|
||||
isEthAmountInBaseUnits: true,
|
||||
};
|
||||
|
||||
EthAmountRow.displayName = 'EthAmountRow';
|
||||
<Container>
|
||||
{this._renderUsdSection()}
|
||||
<Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
|
||||
{ethFormatter(
|
||||
ethAmount,
|
||||
4,
|
||||
<Container opacity={0.5}>
|
||||
<AmountPlaceholder color={ColorOption.lightGrey} isPulsating={isLoading} />
|
||||
</Container>,
|
||||
)}
|
||||
</Text>
|
||||
</Container>
|
||||
</Flex>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
private _renderUsdSection(): React.ReactNode {
|
||||
const usdFormatter = this.props.isEthAmountInBaseUnits ? format.ethBaseAmountInUsd : format.ethUnitAmountInUsd;
|
||||
const shouldHideUsdPriceSection = _.isUndefined(this.props.ethUsdPrice) || _.isUndefined(this.props.ethAmount);
|
||||
return shouldHideUsdPriceSection ? null : (
|
||||
<Container marginRight="3px" display="inline-block">
|
||||
<Text fontColor={ColorOption.lightGrey}>
|
||||
({usdFormatter(this.props.ethAmount, this.props.ethUsdPrice)})
|
||||
</Text>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ export interface ContainerProps {
|
||||
backgroundColor?: ColorOption;
|
||||
hasBoxShadow?: boolean;
|
||||
zIndex?: number;
|
||||
opacity?: number;
|
||||
}
|
||||
|
||||
const PlainContainer: React.StatelessComponent<ContainerProps> = ({ children, className }) => (
|
||||
@@ -54,6 +55,7 @@ export const Container = styled(PlainContainer)`
|
||||
${props => cssRuleIfExists(props, 'border-top')}
|
||||
${props => cssRuleIfExists(props, 'border-bottom')}
|
||||
${props => cssRuleIfExists(props, 'z-index')}
|
||||
${props => cssRuleIfExists(props, 'opacity')}
|
||||
${props => (props.hasBoxShadow ? `box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)` : '')};
|
||||
background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
|
||||
border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
|
||||
|
@@ -8,18 +8,21 @@ import { oc } from 'ts-optchain';
|
||||
import { State } from '../redux/reducer';
|
||||
|
||||
import { OrderDetails } from '../components/order_details';
|
||||
import { AsyncProcessState } from '../types';
|
||||
|
||||
export interface LatestBuyQuoteOrderDetailsProps {}
|
||||
|
||||
interface ConnectedState {
|
||||
buyQuoteInfo?: BuyQuoteInfo;
|
||||
ethUsdPrice?: BigNumber;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({
|
||||
// use the worst case quote info
|
||||
buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(),
|
||||
ethUsdPrice: state.ethUsdPrice,
|
||||
isLoading: state.quoteRequestState === AsyncProcessState.PENDING,
|
||||
});
|
||||
|
||||
export const LatestBuyQuoteOrderDetails: React.ComponentClass<LatestBuyQuoteOrderDetailsProps> = connect(
|
||||
|
@@ -3,7 +3,8 @@ import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { SlidingError } from '../components/sliding_error';
|
||||
import { LatestErrorDisplay, State } from '../redux/reducer';
|
||||
import { State } from '../redux/reducer';
|
||||
import { DisplayStatus } from '../types';
|
||||
import { errorUtil } from '../util/error';
|
||||
|
||||
export interface LatestErrorComponentProps {
|
||||
@@ -29,7 +30,7 @@ export interface LatestErrorProps {}
|
||||
const mapStateToProps = (state: State, _ownProps: LatestErrorProps): ConnectedState => ({
|
||||
assetData: state.selectedAssetData,
|
||||
latestError: state.latestError,
|
||||
slidingDirection: state.latestErrorDisplay === LatestErrorDisplay.Present ? 'up' : 'down',
|
||||
slidingDirection: state.latestErrorDisplay === DisplayStatus.Present ? 'up' : 'down',
|
||||
});
|
||||
|
||||
export const LatestError = connect(mapStateToProps)(LatestErrorComponent);
|
||||
|
@@ -44,13 +44,13 @@ const updateBuyQuoteAsync = async (
|
||||
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, zrxDecimals);
|
||||
|
||||
// mark quote as pending
|
||||
dispatch(actions.updateBuyQuoteStatePending());
|
||||
dispatch(actions.setQuoteRequestStatePending());
|
||||
|
||||
let newBuyQuote: BuyQuote | undefined;
|
||||
try {
|
||||
newBuyQuote = await assetBuyer.getBuyQuoteAsync(assetData, baseUnitValue);
|
||||
} catch (error) {
|
||||
dispatch(actions.updateBuyQuoteStateFailure());
|
||||
dispatch(actions.setQuoteRequestStateFailure());
|
||||
errorUtil.errorFlasher.flashNewError(dispatch, error);
|
||||
return;
|
||||
}
|
||||
@@ -72,11 +72,11 @@ const mapDispatchToProps = (
|
||||
// invalidate the last buy quote.
|
||||
dispatch(actions.updateLatestBuyQuote(undefined));
|
||||
// reset our buy state
|
||||
dispatch(actions.updatebuyOrderState(AsyncProcessState.NONE));
|
||||
dispatch(actions.updateBuyOrderState(AsyncProcessState.NONE));
|
||||
|
||||
if (!_.isUndefined(value) && !_.isUndefined(assetData)) {
|
||||
// even if it's debounced, give them the illusion it's loading
|
||||
dispatch(actions.updateBuyQuoteStatePending());
|
||||
dispatch(actions.setQuoteRequestStatePending());
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
debouncedUpdateBuyQuoteAsync(dispatch, assetData, value);
|
||||
}
|
||||
|
@@ -44,9 +44,9 @@ const mapStateToProps = (state: State, _ownProps: SelectedAssetBuyButtonProps):
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch<Action>, ownProps: SelectedAssetBuyButtonProps): ConnectedDispatch => ({
|
||||
onClick: buyQuote => dispatch(actions.updatebuyOrderState(AsyncProcessState.PENDING)),
|
||||
onBuySuccess: buyQuote => dispatch(actions.updatebuyOrderState(AsyncProcessState.SUCCESS)),
|
||||
onBuyFailure: buyQuote => dispatch(actions.updatebuyOrderState(AsyncProcessState.FAILURE)),
|
||||
onClick: buyQuote => dispatch(actions.updateBuyOrderState(AsyncProcessState.PENDING)),
|
||||
onBuySuccess: buyQuote => dispatch(actions.updateBuyOrderState(AsyncProcessState.SUCCESS)),
|
||||
onBuyFailure: buyQuote => dispatch(actions.updateBuyOrderState(AsyncProcessState.FAILURE)),
|
||||
});
|
||||
|
||||
export const SelectedAssetBuyButton: React.ComponentClass<SelectedAssetBuyButtonProps> = connect(
|
||||
|
@@ -15,14 +15,14 @@ interface ConnectedState {
|
||||
selectedAssetAmount?: BigNumber;
|
||||
totalEthBaseAmount?: BigNumber;
|
||||
ethUsdPrice?: BigNumber;
|
||||
quoteState: AsyncProcessState;
|
||||
quoteRequestState: AsyncProcessState;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({
|
||||
selectedAssetAmount: state.selectedAssetAmount,
|
||||
totalEthBaseAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(),
|
||||
ethUsdPrice: state.ethUsdPrice,
|
||||
quoteState: state.quoteState,
|
||||
quoteRequestState: state.quoteRequestState,
|
||||
});
|
||||
|
||||
export const SelectedAssetInstantHeading: React.ComponentClass<InstantHeadingProps> = connect(mapStateToProps)(
|
||||
|
@@ -25,8 +25,8 @@ export enum ActionTypes {
|
||||
UPDATE_SELECTED_ASSET_AMOUNT = 'UPDATE_SELECTED_ASSET_AMOUNT',
|
||||
UPDATE_SELECTED_ASSET_BUY_STATE = 'UPDATE_SELECTED_ASSET_BUY_STATE',
|
||||
UPDATE_LATEST_BUY_QUOTE = 'UPDATE_LATEST_BUY_QUOTE',
|
||||
UPDATE_BUY_QUOTE_STATE_PENDING = 'UPDATE_BUY_QUOTE_STATE_PENDING',
|
||||
UPDATE_BUY_QUOTE_STATE_FAILURE = 'UPDATE_BUY_QUOTE_STATE_FAILURE',
|
||||
SET_QUOTE_REQUEST_STATE_PENDING = 'SET_QUOTE_REQUEST_STATE_PENDING',
|
||||
SET_QUOTE_REQUEST_STATE_FAILURE = 'SET_QUOTE_REQUEST_STATE_FAILURE',
|
||||
SET_ERROR = 'SET_ERROR',
|
||||
HIDE_ERROR = 'HIDE_ERROR',
|
||||
CLEAR_ERROR = 'CLEAR_ERROR',
|
||||
@@ -35,11 +35,11 @@ export enum ActionTypes {
|
||||
export const actions = {
|
||||
updateEthUsdPrice: (price?: BigNumber) => createAction(ActionTypes.UPDATE_ETH_USD_PRICE, price),
|
||||
updateSelectedAssetAmount: (amount?: BigNumber) => createAction(ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT, amount),
|
||||
updatebuyOrderState: (buyState: AsyncProcessState) =>
|
||||
updateBuyOrderState: (buyState: AsyncProcessState) =>
|
||||
createAction(ActionTypes.UPDATE_SELECTED_ASSET_BUY_STATE, buyState),
|
||||
updateLatestBuyQuote: (buyQuote?: BuyQuote) => createAction(ActionTypes.UPDATE_LATEST_BUY_QUOTE, buyQuote),
|
||||
updateBuyQuoteStatePending: () => createAction(ActionTypes.UPDATE_BUY_QUOTE_STATE_PENDING),
|
||||
updateBuyQuoteStateFailure: () => createAction(ActionTypes.UPDATE_BUY_QUOTE_STATE_FAILURE),
|
||||
setQuoteRequestStatePending: () => createAction(ActionTypes.SET_QUOTE_REQUEST_STATE_PENDING),
|
||||
setQuoteRequestStateFailure: () => createAction(ActionTypes.SET_QUOTE_REQUEST_STATE_FAILURE),
|
||||
setError: (error?: any) => createAction(ActionTypes.SET_ERROR, error),
|
||||
hideError: () => createAction(ActionTypes.HIDE_ERROR),
|
||||
clearError: () => createAction(ActionTypes.CLEAR_ERROR),
|
||||
|
@@ -3,23 +3,19 @@ import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { zrxAssetData } from '../constants';
|
||||
import { AsyncProcessState } from '../types';
|
||||
import { AsyncProcessState, DisplayStatus } from '../types';
|
||||
|
||||
import { Action, ActionTypes } from './actions';
|
||||
|
||||
export enum LatestErrorDisplay {
|
||||
Present,
|
||||
Hidden,
|
||||
}
|
||||
export interface State {
|
||||
selectedAssetData?: string;
|
||||
selectedAssetAmount?: BigNumber;
|
||||
buyOrderState: AsyncProcessState;
|
||||
ethUsdPrice?: BigNumber;
|
||||
latestBuyQuote?: BuyQuote;
|
||||
quoteState: AsyncProcessState;
|
||||
quoteRequestState: AsyncProcessState;
|
||||
latestError?: any;
|
||||
latestErrorDisplay: LatestErrorDisplay;
|
||||
latestErrorDisplay: DisplayStatus;
|
||||
}
|
||||
|
||||
export const INITIAL_STATE: State = {
|
||||
@@ -30,8 +26,8 @@ export const INITIAL_STATE: State = {
|
||||
ethUsdPrice: undefined,
|
||||
latestBuyQuote: undefined,
|
||||
latestError: undefined,
|
||||
latestErrorDisplay: LatestErrorDisplay.Hidden,
|
||||
quoteState: AsyncProcessState.NONE,
|
||||
latestErrorDisplay: DisplayStatus.Hidden,
|
||||
quoteRequestState: AsyncProcessState.NONE,
|
||||
};
|
||||
|
||||
export const reducer = (state: State = INITIAL_STATE, action: Action): State => {
|
||||
@@ -50,19 +46,19 @@ export const reducer = (state: State = INITIAL_STATE, action: Action): State =>
|
||||
return {
|
||||
...state,
|
||||
latestBuyQuote: action.data,
|
||||
quoteState: AsyncProcessState.SUCCESS,
|
||||
quoteRequestState: AsyncProcessState.SUCCESS,
|
||||
};
|
||||
case ActionTypes.UPDATE_BUY_QUOTE_STATE_PENDING:
|
||||
case ActionTypes.SET_QUOTE_REQUEST_STATE_PENDING:
|
||||
return {
|
||||
...state,
|
||||
latestBuyQuote: undefined,
|
||||
quoteState: AsyncProcessState.PENDING,
|
||||
quoteRequestState: AsyncProcessState.PENDING,
|
||||
};
|
||||
case ActionTypes.UPDATE_BUY_QUOTE_STATE_FAILURE:
|
||||
case ActionTypes.SET_QUOTE_REQUEST_STATE_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
latestBuyQuote: undefined,
|
||||
quoteState: AsyncProcessState.FAILURE,
|
||||
quoteRequestState: AsyncProcessState.FAILURE,
|
||||
};
|
||||
case ActionTypes.UPDATE_SELECTED_ASSET_BUY_STATE:
|
||||
return {
|
||||
@@ -73,18 +69,18 @@ export const reducer = (state: State = INITIAL_STATE, action: Action): State =>
|
||||
return {
|
||||
...state,
|
||||
latestError: action.data,
|
||||
latestErrorDisplay: LatestErrorDisplay.Present,
|
||||
latestErrorDisplay: DisplayStatus.Present,
|
||||
};
|
||||
case ActionTypes.HIDE_ERROR:
|
||||
return {
|
||||
...state,
|
||||
latestErrorDisplay: LatestErrorDisplay.Hidden,
|
||||
latestErrorDisplay: DisplayStatus.Hidden,
|
||||
};
|
||||
case ActionTypes.CLEAR_ERROR:
|
||||
return {
|
||||
...state,
|
||||
latestError: undefined,
|
||||
latestErrorDisplay: LatestErrorDisplay.Hidden,
|
||||
latestErrorDisplay: DisplayStatus.Hidden,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
|
@@ -7,6 +7,10 @@ export enum AsyncProcessState {
|
||||
SUCCESS = 'Success',
|
||||
FAILURE = 'Failure',
|
||||
}
|
||||
export enum DisplayStatus {
|
||||
Present,
|
||||
Hidden,
|
||||
}
|
||||
|
||||
export type FunctionType = (...args: any[]) => any;
|
||||
export type ActionCreatorsMapObject = ObjectMap<FunctionType>;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false,
|
||||
"semicolon": [true, "always", "ignore-bound-class-methods"]
|
||||
"semicolon": [true, "always", "ignore-bound-class-methods"],
|
||||
"max-classes-per-file": false
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user