Changeset View
Changeset View
Standalone View
Standalone View
web/cashtab/src/components/Send/Send.js
import React, { useState, useEffect } from 'react'; | import React, { useState, useEffect } from 'react'; | ||||
import styled from 'styled-components'; | import styled from 'styled-components'; | ||||
import { WalletContext } from '@utils/context'; | import { WalletContext } from '@utils/context'; | ||||
import { Form, notification, message, Spin } from 'antd'; | import { Form, notification, message, Spin, Modal } from 'antd'; | ||||
import { CashLoader, CashLoadingIcon } from '@components/Common/CustomIcons'; | import { CashLoader, CashLoadingIcon } from '@components/Common/CustomIcons'; | ||||
import { Row, Col } from 'antd'; | import { Row, Col } from 'antd'; | ||||
import Paragraph from 'antd/lib/typography/Paragraph'; | import Paragraph from 'antd/lib/typography/Paragraph'; | ||||
import PrimaryButton, { | import PrimaryButton, { | ||||
SecondaryButton, | SecondaryButton, | ||||
} from '@components/Common/PrimaryButton'; | } from '@components/Common/PrimaryButton'; | ||||
import { | import { | ||||
SendBchInput, | SendBchInput, | ||||
FormItemWithQRCodeAddon, | FormItemWithQRCodeAddon, | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | const [formData, setFormData] = useState({ | ||||
dirty: true, | dirty: true, | ||||
value: '', | value: '', | ||||
address: filledAddress || '', | address: filledAddress || '', | ||||
}); | }); | ||||
const [loading, setLoading] = useState(false); | const [loading, setLoading] = useState(false); | ||||
const [sendBchAmountError, setSendBchAmountError] = useState(false); | const [sendBchAmountError, setSendBchAmountError] = useState(false); | ||||
const [selectedCurrency, setSelectedCurrency] = useState(currency.ticker); | const [selectedCurrency, setSelectedCurrency] = useState(currency.ticker); | ||||
// Support cashtab button from web pages | |||||
const [txInfoFromUrl, setTxInfoFromUrl] = useState(false); | |||||
// Show a confirmation modal on transactions created by populating form from web page button | |||||
const [isModalVisible, setIsModalVisible] = useState(false); | |||||
const showModal = () => { | |||||
setIsModalVisible(true); | |||||
}; | |||||
const handleOk = () => { | |||||
setIsModalVisible(false); | |||||
submit(); | |||||
}; | |||||
const handleCancel = () => { | |||||
setIsModalVisible(false); | |||||
}; | |||||
const { getBCH, getRestUrl, sendBch, calcFee } = useBCH(); | const { getBCH, getRestUrl, sendBch, calcFee } = useBCH(); | ||||
const BCH = getBCH(); | const BCH = getBCH(); | ||||
// If the balance has changed, unlock the UI | // If the balance has changed, unlock the UI | ||||
// This is redundant, if backend has refreshed in 1.75s timeout below, UI will already be unlocked | // This is redundant, if backend has refreshed in 1.75s timeout below, UI will already be unlocked | ||||
useEffect(() => { | useEffect(() => { | ||||
setLoading(false); | setLoading(false); | ||||
}, [balances.totalBalance]); | }, [balances.totalBalance]); | ||||
useEffect(() => { | |||||
// Manually parse for txInfo object on page load when Send.js is loaded with a query string | |||||
// Do not set txInfo in state if query strings are not present | |||||
if ( | |||||
!window.location || | |||||
!window.location.hash || | |||||
window.location.hash === '#/send' | |||||
) { | |||||
console.log(`No tx info in URL`); | |||||
return; | |||||
} | |||||
const txInfoArr = window.location.hash.split('?')[1].split('&'); | |||||
// Iterate over this to create object | |||||
const txInfo = {}; | |||||
for (let i = 0; i < txInfoArr.length; i += 1) { | |||||
let txInfoKeyValue = txInfoArr[i].split('='); | |||||
let key = txInfoKeyValue[0]; | |||||
let value = txInfoKeyValue[1]; | |||||
txInfo[key] = value; | |||||
} | |||||
console.log(`txInfo from page params`, txInfo); | |||||
setTxInfoFromUrl(txInfo); | |||||
populateFormsFromUrl(txInfo); | |||||
}, []); | |||||
function populateFormsFromUrl(txInfo) { | |||||
if (txInfo && txInfo.address && txInfo.value) { | |||||
setFormData({ address: txInfo.address, value: txInfo.value }); | |||||
} | |||||
} | |||||
async function submit() { | async function submit() { | ||||
setFormData({ | setFormData({ | ||||
...formData, | ...formData, | ||||
dirty: false, | dirty: false, | ||||
}); | }); | ||||
if ( | if ( | ||||
!formData.address || | !formData.address || | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | if (fiatPrice !== null && !isNaN(formData.value)) { | ||||
fiatPriceString = `${(Number(formData.value) / fiatPrice).toFixed( | fiatPriceString = `${(Number(formData.value) / fiatPrice).toFixed( | ||||
8, | 8, | ||||
)} ${currency.ticker}`; | )} ${currency.ticker}`; | ||||
} | } | ||||
} | } | ||||
return ( | return ( | ||||
<> | <> | ||||
<Modal | |||||
title="Confirm Send" | |||||
visible={isModalVisible} | |||||
onOk={handleOk} | |||||
onCancel={handleCancel} | |||||
> | |||||
<p> | |||||
Are you sure you want to send {formData.value}{' '} | |||||
{currency.ticker} to {formData.address}? | |||||
</p> | |||||
</Modal> | |||||
{!balances.totalBalance ? ( | {!balances.totalBalance ? ( | ||||
<ZeroBalanceHeader> | <ZeroBalanceHeader> | ||||
You currently have 0 {currency.ticker} | You currently have 0 {currency.ticker} | ||||
<br /> | <br /> | ||||
Deposit some funds to use this feature | Deposit some funds to use this feature | ||||
</ZeroBalanceHeader> | </ZeroBalanceHeader> | ||||
) : ( | ) : ( | ||||
<> | <> | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | return ( | ||||
></SendBchInput> | ></SendBchInput> | ||||
<ConvertAmount>= {fiatPriceString}</ConvertAmount> | <ConvertAmount>= {fiatPriceString}</ConvertAmount> | ||||
<div style={{ paddingTop: '12px' }}> | <div style={{ paddingTop: '12px' }}> | ||||
{!balances.totalBalance || | {!balances.totalBalance || | ||||
apiError || | apiError || | ||||
sendBchAmountError ? ( | sendBchAmountError ? ( | ||||
<SecondaryButton>Send</SecondaryButton> | <SecondaryButton>Send</SecondaryButton> | ||||
) : ( | ) : ( | ||||
<PrimaryButton onClick={() => submit()}> | <> | ||||
{txInfoFromUrl ? ( | |||||
<PrimaryButton | |||||
onClick={() => showModal()} | |||||
> | |||||
Send | |||||
</PrimaryButton> | |||||
) : ( | |||||
<PrimaryButton | |||||
onClick={() => submit()} | |||||
> | |||||
Send | Send | ||||
</PrimaryButton> | </PrimaryButton> | ||||
)} | )} | ||||
</> | |||||
)} | |||||
</div> | </div> | ||||
{apiError && ( | {apiError && ( | ||||
<> | <> | ||||
<CashLoader /> | <CashLoader /> | ||||
<p style={{ color: 'red' }}> | <p style={{ color: 'red' }}> | ||||
<b> | <b> | ||||
An error occured on our end. | An error occured on our end. | ||||
Reconnecting... | Reconnecting... | ||||
Show All 13 Lines |