feat: add graphql support (#349)
* fix: eslint warnings * refactor: use ramda + sanctuary instead of lodash * refactor: use prettier-standard for formatting * feat: enable security * feat: add graphql * chore: remove trailing commas from linter * docs: new scripts on react and new-admin-server * feat: handle authentication on graphql * fix: perf improvement to date picker * chore: add insecure-dev script to run servers
This commit is contained in:
parent
49f434f1d1
commit
b8e0c2175b
182 changed files with 8827 additions and 4623 deletions
|
|
@ -1,19 +1,28 @@
|
|||
import React, { useState } from 'react'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classnames from 'classnames'
|
||||
import moment from 'moment'
|
||||
import QRCode from 'qrcode.react'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import useAxios from '@use-hooks/axios'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import React, { useState } from 'react'
|
||||
import { useQuery } from '@apollo/react-hooks'
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
import { Tr, Td, THead, TBody, Table } from '../components/fake-table/Table'
|
||||
import { H3, Info1, Info2, Info3, Mono, Label1, Label3 } from '../components/typography'
|
||||
import Title from '../components/Title'
|
||||
import TableLabel from '../components/TableLabel'
|
||||
import Sidebar from '../components/Sidebar'
|
||||
import { primaryColor } from '../styling/variables'
|
||||
import Sidebar from 'src/components/Sidebar'
|
||||
import TableLabel from 'src/components/TableLabel'
|
||||
import Title from 'src/components/Title'
|
||||
import { Tr, Td, THead, TBody, Table } from 'src/components/fake-table/Table'
|
||||
import {
|
||||
H3,
|
||||
Info1,
|
||||
Info2,
|
||||
Info3,
|
||||
Mono,
|
||||
Label1,
|
||||
Label3
|
||||
} from 'src/components/typography'
|
||||
import { primaryColor } from 'src/styling/variables'
|
||||
|
||||
import styles from './Funding.styles'
|
||||
import classnames from 'classnames'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
const sizes = {
|
||||
|
|
@ -22,53 +31,67 @@ const sizes = {
|
|||
date: 130
|
||||
}
|
||||
|
||||
const formatAddress = (address = '') => {
|
||||
return address.replace(/(.{4})/g, '$1 ')
|
||||
}
|
||||
const GET_FUNDING = gql`
|
||||
{
|
||||
funding {
|
||||
cryptoCode
|
||||
fundingAddress
|
||||
fundingAddressUrl
|
||||
confirmedBalance
|
||||
pending
|
||||
fiatConfirmedBalance
|
||||
fiatPending
|
||||
fiatCode
|
||||
display
|
||||
unitScale
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const formatAddress = (address = '') => address.replace(/(.{4})/g, '$1 ')
|
||||
const sumReducer = (acc, value) => acc.plus(value)
|
||||
|
||||
const formatNumber = it => {
|
||||
return new BigNumber(it).toFormat(2)
|
||||
}
|
||||
const formatNumber = it => new BigNumber(it).toFormat(2)
|
||||
|
||||
const getConfirmedTotal = list => {
|
||||
return formatNumber(
|
||||
list.map(it => new BigNumber(it.fiatConfirmedBalance)).reduce(sumReducer, new BigNumber(0))
|
||||
list
|
||||
.map(it => new BigNumber(it.fiatConfirmedBalance))
|
||||
.reduce(sumReducer, new BigNumber(0))
|
||||
)
|
||||
}
|
||||
|
||||
const getPendingTotal = list => {
|
||||
return formatNumber(
|
||||
list.map(it => new BigNumber(it.fiatPending)).reduce(sumReducer, new BigNumber(0))
|
||||
list
|
||||
.map(it => new BigNumber(it.fiatPending))
|
||||
.reduce(sumReducer, new BigNumber(0))
|
||||
)
|
||||
}
|
||||
|
||||
const Funding = () => {
|
||||
const [data, setData] = useState(null)
|
||||
const [selected, setSelected] = useState(null)
|
||||
const [viewHistory, setViewHistory] = useState(false)
|
||||
const [viewHistory] = useState(false)
|
||||
const classes = useStyles()
|
||||
const fundingHistory = [
|
||||
{
|
||||
cryptoAmount: 2.00,
|
||||
cryptoAmount: 2.0,
|
||||
balance: 10.23,
|
||||
fiatValue: 1000.00,
|
||||
fiatValue: 1000.0,
|
||||
date: new Date(),
|
||||
performedBy: null,
|
||||
pending: true
|
||||
},
|
||||
{
|
||||
cryptoAmount: 10.00,
|
||||
cryptoAmount: 10.0,
|
||||
balance: 12.23,
|
||||
fiatValue: 12000.00,
|
||||
fiatValue: 12000.0,
|
||||
date: new Date(),
|
||||
performedBy: null
|
||||
},
|
||||
{
|
||||
cryptoAmount: 5.00,
|
||||
balance: 5.00,
|
||||
fiatValue: 50000.00,
|
||||
cryptoAmount: 5.0,
|
||||
balance: 5.0,
|
||||
fiatValue: 50000.0,
|
||||
date: new Date(),
|
||||
performedBy: null
|
||||
}
|
||||
|
|
@ -78,25 +101,22 @@ const Funding = () => {
|
|||
return selected && selected.cryptoCode === it.cryptoCode
|
||||
}
|
||||
|
||||
useAxios({
|
||||
url: 'http://localhost:8070/api/funding',
|
||||
method: 'GET',
|
||||
trigger: [],
|
||||
customHandler: (err, res) => {
|
||||
if (err) return
|
||||
if (res) {
|
||||
setData(res.data)
|
||||
setSelected(res.data && res.data[0])
|
||||
}
|
||||
}
|
||||
})
|
||||
const { data: fundingResponse } = useQuery(GET_FUNDING)
|
||||
|
||||
const itemRender = (it) => {
|
||||
if (fundingResponse?.funding?.length && !selected) {
|
||||
setSelected(fundingResponse?.funding[0])
|
||||
}
|
||||
|
||||
const itemRender = it => {
|
||||
return (
|
||||
<div className={classes.itemWrapper}>
|
||||
<div className={classes.firstItem}>{it.display}</div>
|
||||
<div className={classes.item}>{it.fiatConfirmedBalance} {it.fiatCode}</div>
|
||||
<div className={classes.item}>{it.confirmedBalance} {it.cryptoCode}</div>
|
||||
<div className={classes.item}>
|
||||
{it.fiatConfirmedBalance} {it.fiatCode}
|
||||
</div>
|
||||
<div className={classes.item}>
|
||||
{it.confirmedBalance} {it.cryptoCode}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -105,23 +125,27 @@ const Funding = () => {
|
|||
<>
|
||||
<div>
|
||||
<Title>Funding</Title>
|
||||
{/* <button onClick={it => setViewHistory(!viewHistory)}>hehe</button> */}
|
||||
{/* <button onClick={it => setViewHistory(!viewHistory)}>history</button> */}
|
||||
</div>
|
||||
<div className={classes.wrapper}>
|
||||
<Sidebar
|
||||
data={data}
|
||||
data={fundingResponse?.funding}
|
||||
isSelected={isSelected}
|
||||
onClick={setSelected}
|
||||
displayName={it => it.display}
|
||||
itemRender={itemRender}
|
||||
>
|
||||
{data && data.length && (
|
||||
itemRender={itemRender}>
|
||||
{fundingResponse?.funding && fundingResponse?.funding?.length && (
|
||||
<div className={classes.total}>
|
||||
<Label1 className={classes.totalTitle}>Total Crypto Balance</Label1>
|
||||
<Label1 className={classes.totalTitle}>
|
||||
Total Crypto Balance
|
||||
</Label1>
|
||||
<Info1 noMargin>
|
||||
{getConfirmedTotal(data)} {data[0].fiatCode}
|
||||
{getConfirmedTotal(fundingResponse.funding)}
|
||||
{fundingResponse.funding[0].fiatCode}
|
||||
</Info1>
|
||||
<Label1 className={classes.totalPending}>(+{getPendingTotal(data)} pending)</Label1>
|
||||
<Label1 className={classes.totalPending}>
|
||||
(+{getPendingTotal(fundingResponse.funding)} pending)
|
||||
</Label1>
|
||||
</div>
|
||||
)}
|
||||
</Sidebar>
|
||||
|
|
@ -140,7 +164,9 @@ const Funding = () => {
|
|||
|
||||
<div className={classes.coinTotal}>
|
||||
<Info3 inline noMargin>
|
||||
{`= ${formatNumber(selected.fiatConfirmedBalance)} ${selected.fiatCode}`}
|
||||
{`= ${formatNumber(selected.fiatConfirmedBalance)} ${
|
||||
selected.fiatCode
|
||||
}`}
|
||||
</Info3>
|
||||
<Label3 inline noMargin className={classes.leftSpacer}>
|
||||
{`(+${formatNumber(selected.fiatPending)} pending)`}
|
||||
|
|
@ -157,30 +183,62 @@ const Funding = () => {
|
|||
|
||||
<div className={classes.secondSide}>
|
||||
<Label1>Scan to send {selected.display}</Label1>
|
||||
<QRCode size={240} fgColor={primaryColor} value={selected.fundingAddressUrl} />
|
||||
<QRCode
|
||||
size={240}
|
||||
fgColor={primaryColor}
|
||||
value={selected.fundingAddressUrl}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{selected && viewHistory && (
|
||||
<div>
|
||||
<TableLabel className={classes.tableLabel} label='Pending' color='#cacaca' />
|
||||
<TableLabel
|
||||
className={classes.tableLabel}
|
||||
label="Pending"
|
||||
color="#cacaca"
|
||||
/>
|
||||
<Table className={classes.table}>
|
||||
<THead>
|
||||
<Td header size={sizes.big}>Amount Entered</Td>
|
||||
<Td header size={sizes.big}>Balance After</Td>
|
||||
<Td header size={sizes.big}>Cash Value</Td>
|
||||
<Td header size={sizes.date}>Date</Td>
|
||||
<Td header size={sizes.time}>Time (h:m:s)</Td>
|
||||
<Td header size={sizes.big}>Performed By</Td>
|
||||
<Td header size={sizes.big}>
|
||||
Amount Entered
|
||||
</Td>
|
||||
<Td header size={sizes.big}>
|
||||
Balance After
|
||||
</Td>
|
||||
<Td header size={sizes.big}>
|
||||
Cash Value
|
||||
</Td>
|
||||
<Td header size={sizes.date}>
|
||||
Date
|
||||
</Td>
|
||||
<Td header size={sizes.time}>
|
||||
Time (h:m:s)
|
||||
</Td>
|
||||
<Td header size={sizes.big}>
|
||||
Performed By
|
||||
</Td>
|
||||
</THead>
|
||||
<TBody>
|
||||
{fundingHistory.map((it, idx) => (
|
||||
<Tr key={idx} className={classnames({ [classes.pending]: it.pending })}>
|
||||
<Td size={sizes.big}>{it.cryptoAmount} {selected.cryptoCode}</Td>
|
||||
<Td size={sizes.big}>{it.balance} {selected.cryptoCode}</Td>
|
||||
<Td size={sizes.big}>{it.fiatValue} {selected.fiatCode}</Td>
|
||||
<Td size={sizes.date}>{moment(it.date).format('YYYY-MM-DD')}</Td>
|
||||
<Td size={sizes.time}>{moment(it.date).format('hh:mm:ss')}</Td>
|
||||
<Tr
|
||||
key={idx}
|
||||
className={classnames({ [classes.pending]: it.pending })}>
|
||||
<Td size={sizes.big}>
|
||||
{it.cryptoAmount} {selected.cryptoCode}
|
||||
</Td>
|
||||
<Td size={sizes.big}>
|
||||
{it.balance} {selected.cryptoCode}
|
||||
</Td>
|
||||
<Td size={sizes.big}>
|
||||
{it.fiatValue} {selected.fiatCode}
|
||||
</Td>
|
||||
<Td size={sizes.date}>
|
||||
{moment(it.date).format('YYYY-MM-DD')}
|
||||
</Td>
|
||||
<Td size={sizes.time}>
|
||||
{moment(it.date).format('hh:mm:ss')}
|
||||
</Td>
|
||||
<Td size={sizes.big}>add</Td>
|
||||
</Tr>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue