Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feature) New Summary: leo, account fees and value #716

Merged
merged 72 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
f2615af
Merge pull request #715 from bitfinexcom/staging
prdn Oct 4, 2023
1d6cb0f
Revert "Merge pull request #713 from alexstotsky/revert#709"
Oct 6, 2023
7b67098
Add timeframe selector to the app summary
Sep 26, 2023
ed85a3a
Adjust summary header positioning
Sep 26, 2023
f8bd842
Update spacing
Sep 26, 2023
84435f8
Porvide acc balance handlers to summary
Sep 27, 2023
e6d4a2d
Update app summary prop-types
Sep 27, 2023
64a11dd
Implement acc value time frame handling
Sep 27, 2023
383b33a
Actualize mapped props
Sep 27, 2023
5255481
Add unrealized profit handling flow to app summary
Sep 27, 2023
7cfce12
Actualize summary component naming
Sep 27, 2023
ccc984a
Add acc value section keys/descriptions
Sep 27, 2023
70ef0b8
[wip]App summary account value section
Sep 27, 2023
f770427
Actualize charts y-axis orientation
Sep 27, 2023
7065276
Improve chart legend positioning
Sep 27, 2023
a0d3dcd
Make chart legend representation configurable
Sep 27, 2023
01c7c27
Actualize prop-types
Sep 27, 2023
090a17f
Fix unrealized profit persisting on balance refresh
Sep 28, 2023
2429437
Add accout value refresh button
Sep 28, 2023
4318660
[wip] Account value chart section
Sep 28, 2023
92d5c26
Add account value container
Sep 28, 2023
aeda525
Add account value section to the summary
Sep 28, 2023
b66bffa
Fix data row items aligning
Sep 28, 2023
39f1acb
Actualize value section titles and chart config
Sep 28, 2023
c9f823b
Implement configurable charts aspect
Sep 28, 2023
e82e5ac
Update prop-types and defaults
Sep 28, 2023
562db68
Fix dev server overlay issue
Sep 28, 2023
5be584d
Adjusted charts spacing
Sep 28, 2023
e3c5671
Adjust chart fro mobile breakpoint
Sep 28, 2023
12f3f03
Update acc value chart config
Sep 28, 2023
05d0f62
Actualize row styling and spacing
Sep 28, 2023
9d0aed9
Place acc value on a dedicated row
Sep 28, 2023
80b2ed6
Improve no-data styling for nested chart items
Sep 28, 2023
f7c1924
Improve chart loading state representation
Sep 28, 2023
7777cbe
[wip] Rework acc summary value
Sep 29, 2023
a5443e1
Optimize acc balance handling flow
Sep 29, 2023
aeddde4
Implement getCurrentTimeFrame selector
Sep 29, 2023
60e5a14
Actualize acc value import
Sep 29, 2023
4e643e9
Cleanup
Sep 29, 2023
1942879
Improve value chart entries handling flow
Sep 29, 2023
1db66f4
Redundant container cleanup
Sep 29, 2023
85c4786
Improve no data case check, lint fix
Sep 29, 2023
865c5a4
Actualize summary mapped props
Sep 29, 2023
a31751b
Cleanup
Sep 29, 2023
637cff3
[wip]Acc value representation
Oct 2, 2023
ff47f3d
Update styling
Oct 2, 2023
dec1999
Chart last value representation
Oct 2, 2023
417e7e1
Implement getFormattedChartLastValue helper
Oct 2, 2023
71c00e9
Improve chart last value formatting and representation
Oct 2, 2023
8e12891
Memoize chart data handlers
Oct 2, 2023
756ed1f
[wip] Value changes in percents
Oct 4, 2023
f912867
Implement getChartValueChangePerc helper
Oct 4, 2023
ebf71e8
Add getFormattedPercentChange helper
Oct 4, 2023
24f77b4
Add formatted perc difference value to the chart
Oct 4, 2023
a6f26cf
Rework chart helpers with cuurrency const
Oct 4, 2023
5c4afbf
Optimize formatted perc value handler
Oct 4, 2023
56bc364
Cleanup
Oct 4, 2023
e3d1db4
Adjust chart value perc positioning
Oct 4, 2023
d2bbbb1
Memoize and reorder formattedPercValue
Oct 4, 2023
fe27203
Actualize perc value represenation
Oct 4, 2023
0aa3b10
Lint fix
Oct 4, 2023
93638ae
Adjust summary sub-sections positioning
Oct 5, 2023
01922d1
Improve getFormattedPercentChange helper flow
Oct 5, 2023
97fdf8a
Adjust chart values formatting
Oct 13, 2023
ea84ffe
Actualize chart axis colors
Oct 13, 2023
0791008
Adjust summary sub-sections titles
Oct 13, 2023
5a897fa
Update chart item elements spacing
Oct 13, 2023
eeea328
Update chart aspect
Oct 13, 2023
e1023c8
Improve sub-title positioning
Oct 13, 2023
7500c28
Update chart helpers
Oct 13, 2023
867afeb
Adjust chart values formatting
Oct 13, 2023
a9865d7
Adjust chart values positioning
Oct 14, 2023
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 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