more storybook work for multi accounts
This commit is contained in:
@@ -44,6 +44,7 @@
|
||||
"semver": "^6.3.0",
|
||||
"string-to-color": "^2.2.2",
|
||||
"use-clipboard-copy": "^0.2.0",
|
||||
"uuid": "^8.3.2",
|
||||
"yup": "^0.32.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -72,6 +73,7 @@
|
||||
"@types/react-router": "^5.1.18",
|
||||
"@types/react-router-dom": "^5.1.8",
|
||||
"@types/semver": "^7.3.8",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
||||
"@typescript-eslint/parser": "^5.13.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||
import { Accounts } from 'src/components/Accounts';
|
||||
import { v4 as uuid4 } from 'uuid';
|
||||
|
||||
export default {
|
||||
title: 'Wallet / Multi Account',
|
||||
@@ -16,8 +17,13 @@ const Template: ComponentStory<typeof Accounts> = (args) => (
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
accounts: [
|
||||
{ name: 'Account 1', address: 'abcd1234uvw987xyz' },
|
||||
{ name: 'Account 2', address: 'cd102034u087xyz' },
|
||||
storedAccounts: [{ name: 'Account 1', address: uuid4() }],
|
||||
};
|
||||
|
||||
export const MultipleAccounts = Template.bind({});
|
||||
MultipleAccounts.args = {
|
||||
storedAccounts: [
|
||||
{ name: 'Account 1', address: uuid4() },
|
||||
{ name: 'Account 2', address: uuid4() },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Typography } from '@mui/material';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
TextField,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import stc from 'string-to-color';
|
||||
import { Add, Circle, Close, Edit } from '@mui/icons-material';
|
||||
import { NymCard } from './NymCard';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export type TAccount = {
|
||||
name: string;
|
||||
@@ -11,30 +26,35 @@ export type TAccount = {
|
||||
|
||||
const AccountColor = ({ address }: { address: string }) => <Circle sx={{ color: stc(address) }} />;
|
||||
|
||||
const AccountItem = ({ name, address }: { name: string; address: string }) => (
|
||||
<NymCard
|
||||
title={
|
||||
<Box>
|
||||
<Typography>{name}</Typography>
|
||||
<Typography variant="caption">{address}</Typography>
|
||||
</Box>
|
||||
}
|
||||
noPadding
|
||||
borderless
|
||||
Icon={
|
||||
<Box sx={{ mr: 1.5 }}>
|
||||
const AccountItem = ({ name, address, onSelect }: { name: string; address: string; onSelect: () => void }) => (
|
||||
<ListItem disablePadding disableGutters>
|
||||
<ListItemButton disableRipple onClick={onSelect}>
|
||||
<ListItemAvatar>
|
||||
<AccountColor address={address} />
|
||||
</Box>
|
||||
}
|
||||
Action={
|
||||
<IconButton size="small">
|
||||
<Edit fontSize="small" />
|
||||
</IconButton>
|
||||
}
|
||||
/>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={name} secondary={address} />
|
||||
<ListItemIcon>
|
||||
<IconButton onClick={(e) => e.stopPropagation()}>
|
||||
<Edit />
|
||||
</IconButton>
|
||||
</ListItemIcon>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
);
|
||||
|
||||
const AccountModal = ({ show, addresses, onClose }: { show: boolean; addresses: TAccount[]; onClose: () => void }) => (
|
||||
const AccountModal = ({
|
||||
show,
|
||||
accounts,
|
||||
onClose,
|
||||
onAccountSelect,
|
||||
onAddAccount,
|
||||
}: {
|
||||
show: boolean;
|
||||
accounts: TAccount[];
|
||||
onClose: () => void;
|
||||
onAccountSelect: (account: TAccount) => void;
|
||||
onAddAccount: () => void;
|
||||
}) => (
|
||||
<Dialog open={show} onClose={onClose} fullWidth>
|
||||
<DialogTitle>
|
||||
<Box display="flex" justifyContent="space-between" alignItems="center">
|
||||
@@ -43,38 +63,127 @@ const AccountModal = ({ show, addresses, onClose }: { show: boolean; addresses:
|
||||
<Close />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'grey.600' }}>
|
||||
<Typography variant="body1" sx={{ color: 'grey.600' }}>
|
||||
Switch between accounts
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
{addresses.map(({ name, address }) => (
|
||||
<AccountItem name={name} address={address} />
|
||||
<DialogContent sx={{ padding: 0 }}>
|
||||
{accounts.map(({ name, address }) => (
|
||||
<AccountItem
|
||||
name={name}
|
||||
address={address}
|
||||
onSelect={() => {
|
||||
onAccountSelect({ name, address });
|
||||
onClose();
|
||||
}}
|
||||
key={address}
|
||||
/>
|
||||
))}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button fullWidth variant="contained" size="large" startIcon={<Add fontSize="small" />}>
|
||||
<DialogActions sx={{ p: 3 }}>
|
||||
<Button
|
||||
fullWidth
|
||||
disableElevation
|
||||
variant="contained"
|
||||
size="large"
|
||||
startIcon={<Add fontSize="small" />}
|
||||
onClick={onAddAccount}
|
||||
>
|
||||
Add new account
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
export const Accounts = ({ accounts }: { accounts: TAccount[] }) => {
|
||||
const [addresses, setAddresses] = useState(accounts);
|
||||
const [selectedAddress, setSelectedAddress] = useState(accounts[0]);
|
||||
const [showDialog, setShowDialog] = useState(false);
|
||||
const AddAccountModal = ({
|
||||
show,
|
||||
onClose,
|
||||
onAdd,
|
||||
}: {
|
||||
show: boolean;
|
||||
onClose: () => void;
|
||||
onAdd: (accountName: string) => void;
|
||||
}) => {
|
||||
const [accountName, setAccountName] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (!show) setAccountName('');
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<Dialog open={show} onClose={onClose} fullWidth>
|
||||
<DialogTitle>
|
||||
<Box display="flex" justifyContent="space-between" alignItems="center">
|
||||
<Typography variant="h6">Account</Typography>
|
||||
<IconButton onClick={onClose}>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Typography variant="body1" sx={{ color: 'grey.600' }}>
|
||||
New wallet address
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ p: 0 }}>
|
||||
<Box sx={{ px: 3, mt: 1 }}>
|
||||
<TextField
|
||||
label="Account name"
|
||||
fullWidth
|
||||
value={accountName}
|
||||
onChange={(e) => setAccountName(e.target.value)}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 3 }}>
|
||||
<Button
|
||||
fullWidth
|
||||
disableElevation
|
||||
variant="contained"
|
||||
size="large"
|
||||
startIcon={<Add fontSize="small" />}
|
||||
onClick={() => onAdd(accountName)}
|
||||
disabled={!accountName.length}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export const Accounts = ({ storedAccounts }: { storedAccounts: TAccount[] }) => {
|
||||
const [accounts, setAccounts] = useState(storedAccounts);
|
||||
const [selectedAccount, setSelectedAccount] = useState(accounts[0]);
|
||||
const [showAccountsDialog, setShowAccountsDialog] = useState(false);
|
||||
const [showNewAccountsDialog, setShowNewAccountsDialog] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
startIcon={<AccountColor address={selectedAddress.address} />}
|
||||
startIcon={<AccountColor address={selectedAccount.address} />}
|
||||
color="inherit"
|
||||
onClick={() => setShowDialog(true)}
|
||||
onClick={() => setShowAccountsDialog(true)}
|
||||
>
|
||||
{selectedAddress.name}
|
||||
{selectedAccount.name}
|
||||
</Button>
|
||||
<AccountModal show={showDialog} onClose={() => setShowDialog(false)} addresses={addresses} />
|
||||
<AccountModal
|
||||
show={showAccountsDialog}
|
||||
onClose={() => setShowAccountsDialog(false)}
|
||||
accounts={accounts}
|
||||
onAccountSelect={(acc) => setSelectedAccount(acc)}
|
||||
onAddAccount={() => {
|
||||
setShowAccountsDialog(false);
|
||||
setShowNewAccountsDialog(true);
|
||||
}}
|
||||
/>
|
||||
<AddAccountModal
|
||||
show={showNewAccountsDialog}
|
||||
onClose={() => setShowNewAccountsDialog(false)}
|
||||
onAdd={(name) => {
|
||||
setAccounts((accs) => [...accs, { address: uuidv4(), name }]);
|
||||
setShowNewAccountsDialog(false);
|
||||
setShowAccountsDialog(true);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user