refactor(wallet-bonding): switch to simpledialog component to keep modals consistency

This commit is contained in:
pierre
2022-07-11 15:22:12 +02:00
committed by fmtabbara
parent 352527a098
commit abf9ccb823
21 changed files with 100 additions and 294 deletions
+1 -1
View File
@@ -49,7 +49,7 @@
"string-to-color": "^2.2.2",
"use-clipboard-copy": "^0.2.0",
"uuid": "^8.3.2",
"yup": "^1.0.0-beta.4"
"yup": "^0.32.9"
},
"devDependencies": {
"@babel/core": "^7.15.0",
@@ -1,47 +0,0 @@
import * as React from 'react';
import { useState } from 'react';
import { ComponentMeta, ComponentStory } from '@storybook/react';
import { Button } from '@mui/material';
import SimpleDialog from './SimpleDialog';
export default {
title: 'Bounding/SimpleDialog',
component: SimpleDialog,
} as ComponentMeta<typeof SimpleDialog>;
const Template: ComponentStory<typeof SimpleDialog> = (args) => {
const [open, setOpen] = useState(true);
return (
<>
<Button variant="outlined" onClick={() => setOpen(true)}>
Open simple dialog
</Button>
<SimpleDialog
{...args}
open={open}
confirmButton="Confirm"
onClose={() => setOpen(false)}
onConfirm={() => setOpen(false)}
>
Dialog content.
</SimpleDialog>
</>
);
};
export const Default = Template.bind({});
Default.args = {
title: 'Simple Dialog',
subTitle: '',
fullWidth: true,
maxWidth: 'xs',
closeButton: false,
cancelButton: false,
disabled: false,
};
export const CenteredText = Template.bind({});
CenteredText.args = {
...Default.args,
sx: { textAlign: 'center' },
};
-115
View File
@@ -1,115 +0,0 @@
import React from 'react';
import {
Breakpoint,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
IconButton,
Stack,
SxProps,
Typography,
} from '@mui/material';
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import CloseIcon from '@mui/icons-material/Close';
export interface Props {
open: boolean;
onConfirm: () => void;
onClose?: () => void;
onCancel?: () => void;
closeButton?: boolean;
children?: React.ReactNode;
title: React.ReactNode | string;
subTitle?: React.ReactNode | string;
confirmButton: React.ReactNode | string;
cancelButton?: React.ReactNode | boolean;
disabled?: boolean;
sx?: SxProps;
fullWidth?: boolean;
maxWidth?: Breakpoint;
}
const SimpleDialog = ({
open,
onConfirm,
onClose,
children,
title,
subTitle,
confirmButton,
closeButton,
onCancel,
cancelButton,
disabled,
sx,
fullWidth,
maxWidth,
}: Props) => {
const titleComp = (
<DialogTitle id="responsive-dialog-title" sx={{ py: 3 }} color="black">
{title}
{subTitle &&
(typeof subTitle === 'string' ? (
<Typography fontWeight={400} variant="subtitle1" fontSize={12} color={(t) => t.palette.nym.text.muted}>
{subTitle}
</Typography>
) : (
subTitle
))}
</DialogTitle>
);
const confirmButtonComp =
typeof confirmButton === 'string' ? (
<Button onClick={onConfirm} variant="contained" fullWidth disabled={disabled} sx={{ py: 1.6 }}>
<Typography variant="button" fontSize="large">
{confirmButton}
</Typography>
</Button>
) : (
confirmButton
);
const cancelButtonComp: React.ReactNode | undefined =
cancelButton && typeof cancelButton === 'boolean' ? (
<Button onClick={onCancel} variant="outlined" color="primary" sx={{ px: 1 }}>
<ChevronLeftIcon />
</Button>
) : (
cancelButton
);
return (
<Dialog
open={open}
onClose={onClose}
aria-labelledby="responsive-dialog-title"
maxWidth={maxWidth || 'sm'}
sx={sx}
fullWidth={fullWidth}
>
{closeButton ? (
<Stack direction="row" alignItems="flex-start" justifyContent="space-between">
{titleComp}
<IconButton onClick={onClose} sx={{ mr: 2, mt: 2.6 }}>
<CloseIcon sx={{ color: 'black' }} />
</IconButton>
</Stack>
) : (
titleComp
)}
<DialogContent sx={{ pt: closeButton ? 0 : undefined }}>{children}</DialogContent>
<DialogActions sx={{ px: 3, pb: 3 }}>
{cancelButton ? (
<Stack direction="row" spacing={3} width="100%">
{cancelButtonComp}
{confirmButtonComp}
</Stack>
) : (
confirmButtonComp
)}
</DialogActions>
</Dialog>
);
};
export default SimpleDialog;
@@ -5,9 +5,10 @@ import { Box, Divider, Stack, Typography } from '@mui/material';
import { AmountData, NodeType } from '../types';
import { AppContext } from '../../../context';
import amountSchema from './amountSchema';
import { SimpleDialog, TokenPoolSelector } from '../../../components';
import { TokenPoolSelector } from '../../../components';
import { TextFieldInput, CurrencyInput } from '../components';
import { checkHasEnoughFunds, checkHasEnoughLockedTokens } from '../../../utils';
import { SimpleModal } from '../../../components/Modals/SimpleModal';
export interface Props {
nodeType: NodeType;
@@ -45,14 +46,13 @@ const AmountModal = ({ open, onClose, onSubmit, nodeType }: Props) => {
};
return (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={handleSubmit(onSubmitForm)}
title="Bond"
subTitle="Step 2/2"
confirmButton="Next"
closeButton
onOk={handleSubmit(onSubmitForm)}
header="Bond"
subHeader="Step 2/2"
okLabel="Next"
>
<Box sx={{ mt: 1 }}>
<form>
@@ -92,7 +92,7 @@ const AmountModal = ({ open, onClose, onSubmit, nodeType }: Props) => {
<Divider sx={{ my: 1 }} />
<Typography fontWeight={400}>Est. fee for this transaction will be cauculated in the next page</Typography>
</Box>
</SimpleDialog>
</SimpleModal>
);
};
@@ -6,7 +6,7 @@ import { FieldErrors } from 'react-hook-form/dist/types/errors';
import { GatewayData, MixnodeData, NodeData, NodeType } from '../types';
import { RadioInput, TextFieldInput, CheckboxInput } from '../components';
import nodeSchema from './nodeSchema';
import { SimpleDialog } from '../../../components';
import { SimpleModal } from '../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
@@ -51,14 +51,13 @@ const NodeIdentityModal = ({ open, onClose, onSubmit }: Props) => {
};
return (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={handleSubmit(onSubmitForm)}
title="Bond"
subTitle="Step 1/2"
confirmButton="Next"
closeButton
onOk={handleSubmit(onSubmitForm)}
header="Bond"
subHeader="Step 1/2"
okLabel="Next"
>
<form>
<RadioInput
@@ -215,7 +214,7 @@ const NodeIdentityModal = ({ open, onClose, onSubmit }: Props) => {
</Stack>
)}
</form>
</SimpleDialog>
</SimpleModal>
);
};
@@ -7,8 +7,8 @@ import {
simulateVestingBondMixnode,
} from '../../../requests';
import { GatewayAmount, GatewayData, MixnodeAmount, MixnodeData, NodeData } from '../types';
import { SimpleDialog } from '../../../components';
import { useGetFee } from '../../../hooks/useGetFee';
import { SimpleModal } from '../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
@@ -72,23 +72,19 @@ const SummaryModal = ({ open, onClose, onSubmit, node, amount, onCancel, onError
const onConfirm = async () => onSubmit();
return (
<SimpleDialog
<SimpleModal
open={open}
onClose={() => {
resetFeeState();
onClose();
}}
onCancel={() => {
onBack={() => {
resetFeeState();
onCancel();
}}
onConfirm={onConfirm}
title="Bond details"
confirmButton="Confirm"
maxWidth="xs"
fullWidth
cancelButton
closeButton
onOk={onConfirm}
header="Bond details"
okLabel="Confirm"
>
<Stack direction="row" justifyContent="space-between">
<Typography>Identity Key</Typography>
@@ -108,7 +104,7 @@ const SummaryModal = ({ open, onClose, onSubmit, node, amount, onCancel, onError
<Typography>{fee ? `${fee.amount?.amount} ${fee.amount?.denom}` : ''}</Typography>
)}
</Stack>
</SimpleDialog>
</SimpleModal>
);
};
@@ -3,7 +3,7 @@ import { isValidHostname, validateKey, validateLocation, validateRawPort, valida
import { NodeType } from '../types';
const nodeSchema = object().shape({
nodeType: string<NodeType>().required(),
nodeType: string().required().oneOf(['mixnode', 'gateway']),
identityKey: string()
.required('An indentity key is required')
.test('valid-id-key', 'A valid identity key is required', (value) => validateKey(value || '', 32)),
@@ -1,12 +1,12 @@
import * as React from 'react';
import { Divider, Stack, Typography } from '@mui/material';
import { MajorCurrencyAmount } from '@nymproject/types';
import { SimpleDialog } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
onClose: () => void;
onConfirm: () => void;
onConfirm: () => Promise<void>;
onCancel: () => void;
bond: MajorCurrencyAmount;
rewards?: MajorCurrencyAmount;
@@ -14,17 +14,14 @@ export interface Props {
}
const SummaryModal = ({ open, onClose, onConfirm, onCancel, bond, rewards, fee }: Props) => (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={onConfirm}
onCancel={onCancel}
title="Unbond"
subTitle="Unbond and remove your node from the mixnet"
confirmButton="Unbond"
closeButton
maxWidth="xs"
fullWidth
onOk={onConfirm}
onBack={onCancel}
header="Unbond"
subHeader="Unbond and remove your node from the mixnet"
okLabel="Unbond"
>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight={400}>Amount to unbond</Typography>
@@ -46,7 +43,7 @@ const SummaryModal = ({ open, onClose, onConfirm, onCancel, bond, rewards, fee }
</Stack>
<Divider sx={{ my: 1 }} />
<Typography fontWeight={400}>Tokens will be transferred to account you are logged in with now</Typography>
</SimpleDialog>
</SimpleModal>
);
export default SummaryModal;
@@ -70,7 +70,7 @@ const Unbond = ({ node, show, onClose }: Props) => {
fetchFee();
}, [node, isVesting]);
const submit = () => {
const submit = async () => {
if (status === 'error') {
// Fetch fee failed
return;
@@ -7,7 +7,8 @@ import { MajorCurrencyAmount } from '@nymproject/types';
import { CurrencyInput, TextFieldInput } from '../../components';
import schema from './schema';
import { AppContext } from '../../../../context';
import { TokenPoolSelector, SimpleDialog } from '../../../../components';
import { TokenPoolSelector } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
@@ -36,18 +37,17 @@ const BondModal = ({ open, onClose, onConfirm, currentBond }: Props) => {
const { userBalance, clientDetails } = useContext(AppContext);
return (
<SimpleDialog
<SimpleModal
open={open}
onClose={() => {
reset();
onClose();
}}
onConfirm={handleSubmit(async (data) => onConfirm(data.amount, data.signature))}
title="Bond more"
subTitle="Bond more tokens on your node and receive more rewards"
confirmButton="Next"
closeButton
disabled={Boolean(errors?.amount || errors?.signature)}
onOk={handleSubmit(async (data) => onConfirm(data.amount, data.signature))}
header="Bond more"
subHeader="Bond more tokens on your node and receive more rewards"
okLabel="Next"
okDisabled={Boolean(errors?.amount || errors?.signature)}
>
<Box sx={{ mt: 1 }}>
<form>
@@ -90,7 +90,7 @@ const BondModal = ({ open, onClose, onConfirm, currentBond }: Props) => {
<Divider sx={{ my: 1 }} />
<Typography fontWeight={400}>Est. fee for this transaction will be cauculated in the next page</Typography>
</Box>
</SimpleDialog>
</SimpleModal>
);
};
@@ -27,7 +27,7 @@ const BondMore = ({ mixnode, show, onClose }: Props) => {
setFee({ amount: '42', denom: 'NYM' }); // TODO fetch real fee amount
}, [addBond]);
const submit = () => {
const submit = async () => {
// TODO send request to update bond
setStep(3); // on success
// setTx(requestResult)
@@ -1,12 +1,12 @@
import * as React from 'react';
import { Divider, Stack, Typography } from '@mui/material';
import { MajorCurrencyAmount } from '@nymproject/types';
import { SimpleDialog } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
onClose: () => void;
onConfirm: () => void;
onConfirm: () => Promise<void>;
onCancel: () => void;
currentBond: MajorCurrencyAmount;
addBond: MajorCurrencyAmount;
@@ -14,17 +14,13 @@ export interface Props {
}
const SummaryModal = ({ open, onClose, onConfirm, onCancel, currentBond, addBond, fee }: Props) => (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={onConfirm}
onCancel={onCancel}
title="Bond mor details"
confirmButton="Confirm"
closeButton
cancelButton
maxWidth="xs"
fullWidth
onOk={onConfirm}
onBack={onCancel}
header="Bond mor details"
okLabel="Confirm"
>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight={400}>Current bond</Typography>
@@ -40,7 +36,7 @@ const SummaryModal = ({ open, onClose, onConfirm, onCancel, currentBond, addBond
<Typography fontWeight={400}>Fee for this operation</Typography>
<Typography fontWeight={400}>{`${fee.amount} ${fee.denom}`}</Typography>
</Stack>
</SimpleDialog>
</SimpleModal>
);
export default SummaryModal;
@@ -24,7 +24,7 @@ const CompoundRewards = ({ mixnode, show, onClose }: Props) => {
setFee({ amount: '42', denom: 'NYM' }); // TODO fetch real fee amount
}, []);
const submit = () => {
const submit = async () => {
// TODO send request to compound rewards
setStep(2); // on success
// setTx(requestResult)
@@ -1,29 +1,26 @@
import * as React from 'react';
import { Divider, Stack, Typography } from '@mui/material';
import { MajorCurrencyAmount } from '@nymproject/types';
import { SimpleDialog } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
onClose: () => void;
onConfirm: () => void;
onConfirm: () => Promise<void>;
onCancel: () => void;
rewards: MajorCurrencyAmount;
fee: MajorCurrencyAmount;
}
const SummaryModal = ({ open, onClose, onConfirm, onCancel, rewards, fee }: Props) => (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={onConfirm}
onCancel={onCancel}
title="Compound rewards"
subTitle="Get more rewards by compounding"
confirmButton="Compound"
closeButton
maxWidth="xs"
fullWidth
onOk={onConfirm}
onBack={onCancel}
header="Compound rewards"
subHeader="Get more rewards by compounding"
okLabel="Compound"
>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight={400}>Operator rewards</Typography>
@@ -36,7 +33,7 @@ const SummaryModal = ({ open, onClose, onConfirm, onCancel, rewards, fee }: Prop
</Stack>
<Divider sx={{ my: 1 }} />
<Typography fontWeight={400}>Rewards will be added to your bonding pool</Typography>
</SimpleDialog>
</SimpleModal>
);
export default SummaryModal;
@@ -29,7 +29,7 @@ const NodeSettings = ({ mixnode, show, onClose }: Props) => {
setFee({ amount: '42', denom: 'NYM' }); // TODO fetch real fee amount
}, [profitMargin]);
const submit = () => {
const submit = async () => {
// TODO send request to update profit margin
setStep(3); // on success
// setTx(requestResult)
@@ -4,9 +4,8 @@ import { yupResolver } from '@hookform/resolvers/yup';
import { Box, Divider, Stack, Tooltip, Typography } from '@mui/material';
import { MajorCurrencyAmount } from '@nymproject/types';
import { TextFieldInput } from '../../components';
import { Node as NodeIcon } from '../../../../svg-icons/node';
import getSchema from './schema';
import { SimpleDialog } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
@@ -34,23 +33,17 @@ const NodeSettingsModal = ({ open, onClose, onConfirm, estimatedOpReward, curren
});
return (
<SimpleDialog
<SimpleModal
open={open}
onClose={() => {
reset();
onClose();
}}
onConfirm={handleSubmit(async (data) => onConfirm(data.profitMargin))}
title={
<Stack direction="row" alignItems="center">
<NodeIcon sx={{ mr: 1, fontSize: 14 }} />
Node Settings
</Stack>
}
subTitle="System Variables"
confirmButton="Next"
closeButton
disabled={Boolean(errors?.profitMargin)}
onOk={handleSubmit(async (data) => onConfirm(data.profitMargin))}
header="Node Settings"
subHeader="System Variables"
okLabel="Next"
okDisabled={Boolean(errors?.profitMargin)}
>
<Box sx={{ mt: 1 }}>
<form>
@@ -84,7 +77,7 @@ const NodeSettingsModal = ({ open, onClose, onConfirm, estimatedOpReward, curren
<Divider sx={{ my: 1 }} />
<Typography fontWeight={400}>Est. fee for this transaction will be cauculated in the next page</Typography>
</Box>
</SimpleDialog>
</SimpleModal>
);
};
@@ -1,12 +1,12 @@
import * as React from 'react';
import { Divider, Stack, Typography } from '@mui/material';
import { MajorCurrencyAmount } from '@nymproject/types';
import { SimpleDialog } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
onClose: () => void;
onConfirm: () => void;
onConfirm: () => Promise<void>;
onCancel: () => void;
currentPm: number;
newPm: number;
@@ -14,18 +14,14 @@ export interface Props {
}
const SummaryModal = ({ open, onClose, onConfirm, onCancel, currentPm, newPm, fee }: Props) => (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={onConfirm}
onCancel={onCancel}
title="Profit margin change"
subTitle="System Variables"
confirmButton="Confirm"
closeButton
cancelButton
maxWidth="xs"
fullWidth
onOk={onConfirm}
onBack={onCancel}
header="Profit margin change"
subHeader="System Variables"
okLabel="Confirm"
>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight={400}>Current profit margin</Typography>
@@ -41,7 +37,7 @@ const SummaryModal = ({ open, onClose, onConfirm, onCancel, currentPm, newPm, fe
<Typography fontWeight={400}>Fee for this operation</Typography>
<Typography fontWeight={400}>{`${fee.amount} ${fee.denom}`}</Typography>
</Stack>
</SimpleDialog>
</SimpleModal>
);
export default SummaryModal;
@@ -24,7 +24,7 @@ const RedeemRewards = ({ mixnode, show, onClose }: Props) => {
setFee({ amount: '42', denom: 'NYM' }); // TODO fetch real fee amount
}, []);
const submit = () => {
const submit = async () => {
// TODO send request to redeem rewards
setStep(2); // on success
// setTx(requestResult)
@@ -1,29 +1,26 @@
import * as React from 'react';
import { Divider, Stack, Typography } from '@mui/material';
import { MajorCurrencyAmount } from '@nymproject/types';
import { SimpleDialog } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
onClose: () => void;
onConfirm: () => void;
onConfirm: () => Promise<void>;
onCancel: () => void;
rewards: MajorCurrencyAmount;
fee: MajorCurrencyAmount;
}
const SummaryModal = ({ open, onClose, onConfirm, onCancel, rewards, fee }: Props) => (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={onConfirm}
onCancel={onCancel}
title="Redeem rewards"
subTitle="Claim your rewards"
confirmButton="Redeem rewards"
closeButton
maxWidth="xs"
fullWidth
onOk={onConfirm}
onBack={onCancel}
header="Redeem rewards"
subHeader="Claim your rewards"
okLabel="Redeem rewards"
>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight={400}>Rewards to redeem</Typography>
@@ -36,7 +33,7 @@ const SummaryModal = ({ open, onClose, onConfirm, onCancel, rewards, fee }: Prop
</Stack>
<Divider sx={{ my: 1 }} />
<Typography fontWeight={400}>Rewards will be transferred to the account you are logged in with</Typography>
</SimpleDialog>
</SimpleModal>
);
export default SummaryModal;
@@ -1,12 +1,12 @@
import * as React from 'react';
import { Divider, Stack, Typography } from '@mui/material';
import { MajorCurrencyAmount } from '@nymproject/types';
import { SimpleDialog } from '../../../../components';
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
export interface Props {
open: boolean;
onClose: () => void;
onConfirm: () => void;
onConfirm: () => Promise<void>;
onCancel: () => void;
bond: MajorCurrencyAmount;
rewards?: MajorCurrencyAmount;
@@ -14,17 +14,14 @@ export interface Props {
}
const SummaryModal = ({ open, onClose, onConfirm, onCancel, bond, rewards, fee }: Props) => (
<SimpleDialog
<SimpleModal
open={open}
onClose={onClose}
onConfirm={onConfirm}
onCancel={onCancel}
title="Unbond"
subTitle="Unbond and remove your node from the mixnet"
confirmButton="Unbond"
closeButton
maxWidth="xs"
fullWidth
onOk={onConfirm}
onBack={onCancel}
header="Unbond"
subHeader="Unbond and remove your node from the mixnet"
okLabel="Unbond"
>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight={400}>Amount to unbond</Typography>
@@ -46,7 +43,7 @@ const SummaryModal = ({ open, onClose, onConfirm, onCancel, bond, rewards, fee }
</Stack>
<Divider sx={{ my: 1 }} />
<Typography fontWeight={400}>Tokens will be transferred to account you are logged in with now</Typography>
</SimpleDialog>
</SimpleModal>
);
export default SummaryModal;
@@ -70,7 +70,7 @@ const Unbond = ({ node, show, onClose }: Props) => {
fetchFee();
}, [node, isVesting]);
const submit = () => {
const submit = async () => {
if (status === 'error') {
// Fetch fee failed
return;