Skip to content

Commit

Permalink
Merge pull request #716 from alexstotsky/new-summary-1
Browse files Browse the repository at this point in the history
(feature) New Summary: leo, account fees and value
  • Loading branch information
ezewer authored Oct 16, 2023
2 parents e87ef9b + a9865d7 commit 8bcff88
Show file tree
Hide file tree
Showing 24 changed files with 850 additions and 22 deletions.
19 changes: 19 additions & 0 deletions public/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,25 @@
"use_api_key": "Use API key",
"name_updated": "Accounts group name updated"
},
"summary": {
"title": "Summary",
"leo_level": "LEO level",
"avg_amount": "Avg.Amount",
"fees": {
"title": "Account Fees",
"sub_title": "Based on your trading volume",
"maker": "Maker Fees",
"taker_crypto": "Taker Fees Crypto",
"taker_fiat": "Taker Fees Fiat",
"taker_stables": "Taker Fees Stablecoins",
"deriv_maker": "Derivatives Maker Fees",
"deriv_taker": "Derivatives Taker Fees"
},
"value": {
"title": "Account Value",
"sub_title": "Total Balance including Deposits/Withdrawals"
}
},
"symbols": {
"title": "Get symbols",
"clear_symbols": "Clear Symbols"
Expand Down
47 changes: 47 additions & 0 deletions src/components/AppSummary/AppSummary.container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { compose } from 'redux'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { withTranslation } from 'react-i18next'

import {
refresh,
fetchData,
} from 'state/accountSummary/actions'
import {
setParams,
refresh as refreshBalance,
} from 'state/accountBalance/actions'
import {
getData,
getPageLoading,
getDataReceived,
} from 'state/accountSummary/selectors'
import {
getTimeframe,
getIsUnrealizedProfitExcluded,
} from 'state/accountBalance/selectors'
import { getIsTurkishSite } from 'state/base/selectors'

import AppSummary from './AppSummary'

const mapStateToProps = state => ({
data: getData(state),
pageLoading: getPageLoading(state),
dataReceived: getDataReceived(state),
currentTimeFrame: getTimeframe(state),
isTurkishSite: getIsTurkishSite(state),
isUnrealizedProfitExcluded: getIsUnrealizedProfitExcluded(state),
})

const mapDispatchToProps = {
refresh,
fetchData,
setParams,
refreshBalance,
}

export default compose(
connect(mapStateToProps, mapDispatchToProps),
withTranslation('translations'),
withRouter,
)(AppSummary)
138 changes: 138 additions & 0 deletions src/components/AppSummary/AppSummary.fees.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import React, { memo } from 'react'
import PropTypes from 'prop-types'
import { Cell } from '@blueprintjs/table'

import { formatFee } from 'ui/utils'
import CollapsedTable from 'ui/CollapsedTable'

const getColumns = ({
makerFee,
isTurkishSite,
derivTakerFee,
takerFeeToFiat,
takerFeeToStable,
takerFeeToCrypto,
derivMakerRebate,
}) => [
{
id: 'makerFee',
name: 'summary.fees.maker',
width: 100,
renderer: () => (
<Cell>
{formatFee(makerFee)}
%
</Cell>
),
},
{
id: 'takerFeeCrypto',
name: 'summary.fees.taker_crypto',
width: 140,
renderer: () => (
<Cell>
{formatFee(takerFeeToCrypto)}
%
</Cell>
),
},
{
id: 'takerFeeFiat',
name: 'summary.fees.taker_fiat',
width: 140,
renderer: () => (
<Cell>
{formatFee(takerFeeToFiat)}
%
</Cell>
),
},
{
id: 'takerFeeStable',
name: 'summary.fees.taker_stables',
width: 140,
renderer: () => (
<Cell>
{formatFee(takerFeeToStable)}
%
</Cell>
),
},
...(!isTurkishSite ? [{
id: 'derivMakerRebate',
name: 'summary.fees.deriv_maker',
width: 140,
renderer: () => (
<Cell>
{formatFee(derivMakerRebate)}
%
</Cell>
),
},
{
id: 'derivTakerFee',
name: 'summary.fees.deriv_taker',
width: 140,
renderer: () => (
<Cell>
{formatFee(derivTakerFee)}
%
</Cell>
),
}] : []),
]

const AppSummaryFees = ({
t,
data,
isTurkishSite,
}) => {
const {
makerFee = 0,
derivTakerFee = 0,
takerFeeToFiat = 0,
takerFeeToStable = 0,
takerFeeToCrypto = 0,
derivMakerRebate = 0,
} = data

const columns = getColumns({
makerFee,
isTurkishSite,
derivTakerFee,
takerFeeToFiat,
takerFeeToStable,
takerFeeToCrypto,
derivMakerRebate,
})

return (
<div className='app-summary-item'>
<div className='app-summary-item-title'>
{t('summary.fees.title')}
</div>
<div className='app-summary-item-sub-title'>
{t('summary.fees.sub_title')}
</div>
<CollapsedTable
numRows={1}
tableColumns={columns}
/>
</div>
)
}

AppSummaryFees.propTypes = {
data: PropTypes.shape({
derivMakerRebate: PropTypes.number,
derivTakerFee: PropTypes.number,
makerFee: PropTypes.number,
takerFeeToCrypto: PropTypes.number,
takerFeeToFiat: PropTypes.number,
takerFeeToStable: PropTypes.number,
}).isRequired,
t: PropTypes.func.isRequired,
isTurkishSite: PropTypes.bool.isRequired,
}

export default memo(AppSummaryFees)
149 changes: 149 additions & 0 deletions src/components/AppSummary/AppSummary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import React, { memo, useEffect } from 'react'
import PropTypes from 'prop-types'
import _isEmpty from 'lodash/isEmpty'
import { Card, Elevation } from '@blueprintjs/core'

import NoData from 'ui/NoData'
import Loading from 'ui/Loading'
import {
SectionHeader,
SectionHeaderRow,
SectionHeaderItem,
SectionHeaderTitle,
SectionHeaderItemLabel,
} from 'ui/SectionHeader'
import TimeRange from 'ui/TimeRange'
import RefreshButton from 'ui/RefreshButton'
import TimeFrameSelector from 'ui/TimeFrameSelector'
import UnrealizedProfitSelector from 'ui/UnrealizedProfitSelector'

import Leo from './AppSummary.leo'
import Fees from './AppSummary.fees'
import Value from './AppSummary.value'

const AppSummary = ({
t,
data,
refresh,
fetchData,
setParams,
pageLoading,
dataReceived,
isTurkishSite,
refreshBalance,
currentTimeFrame,
isUnrealizedProfitExcluded,
}) => {
useEffect(() => {
if (!dataReceived && !pageLoading) fetchData()
}, [])

const handleTimeFrameChange = (timeframe) => {
setParams({ timeframe })
}

const handleUnrealizedProfitChange = (value) => {
setParams({ isUnrealizedProfitExcluded: value })
}

let showContent
if (!dataReceived && pageLoading) {
showContent = <Loading />
} else if (_isEmpty(data)) {
showContent = <NoData refresh={refresh} />
} else {
showContent = (
<>
<div className='app-summary-data-row'>
<Value />
<Fees
t={t}
data={data}
isTurkishSite={isTurkishSite}
/>
</div>
</>
)
}
return (
<Card
elevation={Elevation.ZERO}
className='app-summary-card col-lg-12 col-md-12 col-sm-12 col-xs-12 no-table-scroll'
>
<div className='app-summary-wrapper'>
<SectionHeader>
<SectionHeaderTitle>
<div className='app-summary-title-row'>
<div className='app-summary-title-item'>
{t('summary.title')}
</div>
<div className='app-summary-title-item'>
<Leo
data={data}
isLoading={pageLoading}
/>
</div>
</div>
</SectionHeaderTitle>
<SectionHeaderRow>
<SectionHeaderItem>
<SectionHeaderItemLabel>
{t('selector.filter.date')}
</SectionHeaderItemLabel>
<TimeRange className='section-header-time-range' />
</SectionHeaderItem>
<SectionHeaderItem>
<SectionHeaderItemLabel>
{t('selector.select')}
</SectionHeaderItemLabel>
<TimeFrameSelector
value={currentTimeFrame}
onChange={handleTimeFrameChange}
/>
</SectionHeaderItem>
<SectionHeaderItem>
<SectionHeaderItemLabel>
{t('selector.unrealized-profits.title')}
</SectionHeaderItemLabel>
<UnrealizedProfitSelector
value={isUnrealizedProfitExcluded}
onChange={handleUnrealizedProfitChange}
/>
</SectionHeaderItem>
<RefreshButton onClick={refreshBalance} />
</SectionHeaderRow>
</SectionHeader>
{showContent}
</div>
</Card>
)
}

AppSummary.propTypes = {
data: PropTypes.shape({
derivMakerRebate: PropTypes.number,
derivTakerFee: PropTypes.number,
leoAmountAvg: PropTypes.number,
leoLev: PropTypes.number,
makerFee: PropTypes.number,
takerFeeToCrypto: PropTypes.number,
takerFeeToFiat: PropTypes.number,
takerFeeToStable: PropTypes.number,
}),
dataReceived: PropTypes.bool.isRequired,
fetchData: PropTypes.func.isRequired,
isTurkishSite: PropTypes.bool.isRequired,
pageLoading: PropTypes.bool.isRequired,
refresh: PropTypes.func.isRequired,
refreshBalance: PropTypes.func.isRequired,
setParams: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
currentTimeFrame: PropTypes.string.isRequired,
isUnrealizedProfitExcluded: PropTypes.bool.isRequired,
}

AppSummary.defaultProps = {
data: {},
}

export default memo(AppSummary)
Loading

0 comments on commit 8bcff88

Please sign in to comment.