Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/components/UI/components/TabPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Box } from '@mui/material';

const TabPanel = (props) => {
const { children, value, index, ...other } = props;

return (
<div
role="tabpanel"
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && <Box sx={{ p: 3 }}>{children}</Box>}
</div>
);
}

export default TabPanel;
136 changes: 83 additions & 53 deletions src/pages/SendTokens/SendTokens.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext, useState } from 'react';
import { Paper } from '@mui/material';
import { useContext, useState } from 'react';
import { Paper, Tab, Tabs } from '@mui/material';
import {
ContentContainer,
LoaderContainer,
Expand All @@ -10,23 +10,36 @@ import SendTokensForm from './SendTokensForm/SendTokensForm';
import Message, {
MessageType,
} from '../../components/UI/components/Message/Message';
import apiClient from '../../utils/apiClient';
import { Loader } from '../../components/UI/components/Loader/Loader';
import TokenInfoBlock from './TokenInfoBlock/TokenInfoBlock';
import { formatWithCommas } from '../../utils/formatting';
import SendToUntrustedWalletsForm from './SendTokensForm/SendToUntrustedWallets';
import AuthContext from '../../store/auth-context';
import TabPanel from '../../components/UI/components/TabPanel'
import { handleCreateWallet } from './helpers/walletHandlers';
import { formatWithCommas } from '../../utils/formatting';
import { handleSendToUntrustedWallets } from './helpers/sendTokenHandlers';
import apiClient from '../../utils/apiClient';



const SendTokens = () => {
const [createdWalletName, setCreatedWalletName] = useState();
const [errorMessage, setErrorMessage] = useState();
const [successMessage, setSuccessMessage] = useState();
const [isLoading, setIsLoading] = useState(false);
const [tabValue, setTabValue] = useState(0);

const [senderWalletName, setSenderWalletName] = useState();
const [senderWalletTokens, setSenderWalletTokens] = useState(0);

const authContext = useContext(AuthContext);

const handleTabChange = (event, newValue) => {
setTabValue(newValue);
};



// TODO: uncomment when API is ready: is should have a totalTokens value
// const [totalTokensAmount, setTotalTokensAmount] = useState();

Expand Down Expand Up @@ -101,34 +114,14 @@ const SendTokens = () => {
});
};

const handleCreateWalled = (name) => {
if (!name) return;

setIsLoading(true);


apiClient
.setAuthHeader(authContext.token)
.post('/wallets', {
wallet: name,
})
.then(() => {
setErrorMessage('');
setSuccessMessage(`Wallet ${name} created successfully!`);
setCreatedWalletName(name);
})
.catch((error) => {
console.error(error);
setSuccessMessage('');
const errorMessage =
error.response.status === 403 &&
error.response.data.message.includes('already exists')
? 'Wallet with this name already exists.'
: 'An error occurred while creating a wallet.';
setErrorMessage(errorMessage);
})
.finally(() => {
setIsLoading(false);
});
const callbacks = {
setIsLoading,
setErrorMessage,
setSuccessMessage,
setSenderWalletTokens,
setCreatedWalletName
};

return (
Expand Down Expand Up @@ -158,38 +151,75 @@ const SendTokens = () => {
width: '100%',
height: '60vh',
display: 'flex',
justifyContent: 'space-between',
flexDirection: 'column',
}}
>
<Tabs value={tabValue} onChange={handleTabChange} aria-label="wallet tabs">
<Tab label="Managed Wallets" />
<Tab label="Trusted Wallets" />
<Tab label="Untrusted Wallets" />
</Tabs>

{isLoading && (
<LoaderContainer>
<Loader />
</LoaderContainer>
)}
<SendTokensForm
onSubmit={handleSendTokenForm}
onCreateWallet={handleCreateWalled}
createdWalletName={createdWalletName}
onSenderWalletSelected={(wallet) => {
if (!wallet) {
setSenderWalletName(null);
setSenderWalletTokens(null);
return;
}

setSenderWalletName(wallet.name);
setSenderWalletTokens(wallet.tokensInWallet);
}}
/>
<TokenInfoBlock
// totalTokens={formatWithCommas(totalTokensAmount)}
senderWalletName={senderWalletName}
senderWalletTokens={formatWithCommas(senderWalletTokens)}
/>

<TabPanel value={tabValue} index={0} style={{ flex: 1 }}>
<div style={{ display: 'flex', height: '100%' }}>
<SendTokensForm
onSubmit={(data) => handleSendTokenForm(data, authContext, callbacks)}
createdWalletName={createdWalletName}
onCreateWallet={(name) => handleCreateWallet(name, authContext, callbacks)}
onSenderWalletSelected={(wallet) => {
if (!wallet) {
setSenderWalletName(null);
setSenderWalletTokens(null);
return;
}
setSenderWalletName(wallet.name);
setSenderWalletTokens(wallet.tokensInWallet);
}}
/>
<TokenInfoBlock
senderWalletName={senderWalletName}
senderWalletTokens={formatWithCommas(senderWalletTokens)}
/>
</div>
</TabPanel>

<TabPanel value={tabValue} index={1} style={{ flex: 1 }}>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<h2>Under development</h2>
{/* To be implemented */}
</div>
</TabPanel>

<TabPanel value={tabValue} index={2} style={{ flex: 1 }}>
<div style={{ display: 'flex', height: '100%' }}>
<SendToUntrustedWalletsForm
onSubmit={(data) => handleSendToUntrustedWallets(data, authContext, callbacks)}
onSenderWalletSelected={(wallet) => {
if (!wallet) {
setSenderWalletName(null);
setSenderWalletTokens(null);
return;
}
setSenderWalletName(wallet?.name);
setSenderWalletTokens(wallet?.tokensInWallet);
}}
/>
<TokenInfoBlock
senderWalletName={senderWalletName}
senderWalletTokens={formatWithCommas(senderWalletTokens)}
/>
</div>
</TabPanel>
</Paper>
</ContentContainer>
</StyledGrid>
);
};

export default SendTokens;
export default SendTokens;
137 changes: 137 additions & 0 deletions src/pages/SendTokens/SendTokensForm/SendToUntrustedWallets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Grid, TextField } from '@mui/material';
import SelectWallet from './SelectWallet';
import { StyledBox, StyledButton } from './SendTokensFormStyled';
import ConfirmDialog from './confirmDialog/ConfirmDialog';

const SendToUntrustedWalletsForm = (props) => {
const {
onSubmit,
onSenderWalletSelected,
} = props;

const [senderWallet, setSenderWallet] = useState(null);
const [receiverWallet, setReceiverWallet] = useState('');
const tokensAmountRef = useRef(0);
const [isSubmitBtnDisabled, setIsSubmitButtonDisabled] = useState(true);
const [showConfirmationDialog, setShowConfirmationDialog] = useState(false);

useEffect(() => {
isSubmitButtonDisabled();
}, [receiverWallet, senderWallet]);

const handleConfirmationDialogOpen = e => {
e.preventDefault();
setShowConfirmationDialog(true);
};

const handleConfirmationDialogClose = () => {
setShowConfirmationDialog(false);
};

const handleConfirmSubmit = () => {
handleSubmit();
handleConfirmationDialogClose();
};

const handleChangeSenderWallet = useCallback((wallet) => {
if (!wallet) {
setSenderWallet(null);
onSenderWalletSelected(null);
return;
}

setSenderWallet(wallet.name);
onSenderWalletSelected(wallet);

if (tokensAmountRef.current.value > wallet.tokensInWallet) {
tokensAmountRef.current.value = wallet.tokensInWallet;
}
tokensAmountRef.current.setAttribute('max', wallet.tokensInWallet);
}, []);

const handleReceiverWalletChange = (e) => {
setReceiverWallet(e.target.value);
};

const handleSubmit = () => {
const tokensAmount = tokensAmountRef.current.value;

onSubmit({
senderWallet,
receiverWallet,
tokensAmount,
});

// reset form
tokensAmountRef.current.value = 1;
};

const isSubmitButtonDisabled = () => {
const isDisabled =
!senderWallet ||
!receiverWallet ||
tokensAmountRef.current.value <= 0;
setIsSubmitButtonDisabled(isDisabled);
};

return (
<>
<StyledBox>
<form onSubmit={handleConfirmationDialogOpen}>
<Grid container spacing={8}>
<Grid item xs={6}>
<SelectWallet
wallet={senderWallet}
onChangeWallet={handleChangeSenderWallet}
label={'Sender Wallet'}
/>
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={6}>
<TextField
label="Receiver Wallet Address"
value={receiverWallet}
onChange={handleReceiverWalletChange}
fullWidth
required
/>
</Grid>
<Grid item xs={6}></Grid>
<Grid item xs={12}>
<TextField
id="token-amount"
label="Token Amount"
type="number"
InputProps={{ inputProps: { min: 0, max: 10000 } }}
defaultValue={1}
inputRef={tokensAmountRef}
onChange={() => isSubmitButtonDisabled()}
/>
</Grid>
<Grid item xs={12}>
<StyledButton
type="submit"
variant="contained"
color="primary"
disabled={isSubmitBtnDisabled}
>
Submit
</StyledButton>
</Grid>
</Grid>
</form>
</StyledBox>
<ConfirmDialog
open={showConfirmationDialog}
onClose={handleConfirmationDialogClose}
onConfirm={handleConfirmSubmit}
senderWallet={senderWallet}
receiverWallet={receiverWallet}
tokensAmount={tokensAmountRef}
/>
</>
);
};

export default React.memo(SendToUntrustedWalletsForm);
Loading