import { useQuery, gql } from '@apollo/client'
import BigNumber from 'bignumber.js'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { useState } from 'react'
import { Info2, Label1, Label2, P } from '../../../components/typography/index'
import PercentDownIcon from '../../../styling/icons/dashboard/down.svg?react'
import PercentNeutralIcon from '../../../styling/icons/dashboard/equal.svg?react'
import PercentUpIcon from '../../../styling/icons/dashboard/up.svg?react'
import { EmptyTable } from '../../../components/table'
import { java, neon } from '../../../styling/variables'
import { fromNamespace } from '../../../utils/config'
import { DAY, WEEK, MONTH } from '../../../utils/time'
import { timezones } from '../../../utils/timezone-list'
import PercentageChart from './Graphs/PercentageChart'
import LineChart from './Graphs/RefLineChart'
import Scatterplot from './Graphs/RefScatterplot'
import InfoWithLabel from './InfoWithLabel'
import Nav from './Nav'
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
const sumBNBy = by =>
R.reduce((acc, value) => acc.plus(by(value)), new BigNumber(0))
const getProfit = sumBNBy(tx => tx.profit)
const GET_DATA = gql`
query getData($excludeTestingCustomers: Boolean, $from: DateTimeISO) {
transactions(
excludeTestingCustomers: $excludeTestingCustomers
from: $from
) {
fiatCode
fiat
created
txClass
error
profit
dispense
sendConfirmed
}
fiatRates {
code
name
rate
}
config
}
`
const twoMonthsAgo = new Date()
twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - 2)
const SystemPerformance = () => {
const [selectedRange, setSelectedRange] = useState('Day')
const { data, loading } = useQuery(GET_DATA, {
variables: {
excludeTestingCustomers: true,
from: twoMonthsAgo.toISOString(),
},
})
const fiatLocale = fromNamespace('locale')(data?.config).fiatCurrency
const timezone = fromNamespace('locale')(data?.config).timezone
const allTransactions = data?.transactions ?? []
const NOW = Date.now()
const periodDomains = {
Day: [NOW - DAY, NOW],
Week: [NOW - WEEK, NOW],
Month: [NOW - MONTH, NOW],
}
const isInRangeAndNoError = getLastTimePeriod => t => {
if (t.error !== null) return false
if (t.txClass === 'cashOut' && !t.dispense) return false
if (t.txClass === 'cashIn' && !t.sendConfirmed) return false
const createdTimestamp = new Date(t.created).getTime()
const [rangeStart, rangeEnd] = periodDomains[selectedRange]
if (getLastTimePeriod) {
const duration = rangeEnd - rangeStart
return (
createdTimestamp >= rangeStart - duration &&
createdTimestamp < rangeStart
)
}
return createdTimestamp >= rangeStart && createdTimestamp <= rangeEnd
}
const convertFiatToLocale = item => {
if (item.fiatCode === fiatLocale)
return {
...item,
fiat: new BigNumber(item.fiat),
profit: new BigNumber(item.profit),
}
const itemRate = R.find(R.propEq(item.fiatCode, 'code'))(data.fiatRates)
const localeRate = R.find(R.propEq(fiatLocale, 'code'))(data.fiatRates)
const multiplier = localeRate.rate / itemRate.rate
return {
...item,
fiat: new BigNumber(item.fiat).times(multiplier),
profit: new BigNumber(item.profit).times(multiplier),
}
}
const transactionsToShow = R.map(convertFiatToLocale)(
R.filter(isInRangeAndNoError(false), allTransactions),
)
const transactionsLastTimePeriod = R.map(convertFiatToLocale)(
R.filter(isInRangeAndNoError(true), allTransactions),
)
const getNumTransactions = () => {
return R.length(transactionsToShow)
}
const getFiatVolume = () =>
sumBNBy(tx => tx.fiat)(transactionsToShow).toFormat(2)
const getPercentChange = () => {
const thisTimePeriodProfit = getProfit(transactionsToShow)
const previousTimePeriodProfit = getProfit(transactionsLastTimePeriod)
if (thisTimePeriodProfit.eq(previousTimePeriodProfit)) return 0
if (previousTimePeriodProfit.eq(0)) return 100
return thisTimePeriodProfit
.minus(previousTimePeriodProfit)
.times(100)
.div(previousTimePeriodProfit)
.toNumber()
}
const getDirectionPercent = () => {
const [cashIn, cashOut] = R.partition(R.propEq('cashIn', 'txClass'))(
transactionsToShow,
)
const totalLength = cashIn.length + cashOut.length
if (totalLength === 0) {
return { cashIn: 0, cashOut: 0 }
}
return {
cashIn: Math.round((cashIn.length / totalLength) * 100),
cashOut: Math.round((cashOut.length / totalLength) * 100),
}
}
const percentChange = getPercentChange()
const percentageClasses = {
'text-tomato': percentChange < 0,
'text-spring4': percentChange > 0,
'text-comet': percentChange === 0,
'flex items-center justify-center gap-1': true,
}
const getPercentageIcon = () => {
const className = 'w-4 h-4'
if (percentChange === 0) return
{timezones[timezone]?.short ?? timezones[timezone]?.long}{' '} timezone