import { ResponsiveLine } from '@nivo/line' import { PortfolioMetrics } from 'common/user' import { filterDefined } from 'common/util/array' import { formatMoney } from 'common/util/format' import dayjs from 'dayjs' import { last } from 'lodash' import { memo } from 'react' import { useWindowSize } from 'web/hooks/use-window-size' import { Col } from '../layout/col' export const PortfolioValueGraph = memo(function PortfolioValueGraph(props: { portfolioHistory: PortfolioMetrics[] mode: 'value' | 'profit' handleGraphDisplayChange: (arg0: string | number | null) => void height?: number }) { const { portfolioHistory, height, mode, handleGraphDisplayChange } = props const { width } = useWindowSize() const valuePoints = getPoints('value', portfolioHistory) const posProfitPoints = getPoints('posProfit', portfolioHistory) const negProfitPoints = getPoints('negProfit', portfolioHistory) const valuePointsY = valuePoints.map((p) => p.y) const posProfitPointsY = posProfitPoints.map((p) => p.y) const negProfitPointsY = negProfitPoints.map((p) => p.y) let data if (mode === 'value') { data = [{ id: 'value', data: valuePoints, color: '#4f46e5' }] } else { data = [ { id: 'negProfit', data: negProfitPoints, color: '#dc2626', }, { id: 'posProfit', data: posProfitPoints, color: '#14b8a6', }, ] } const numYTickValues = 2 const endDate = last(data[0].data)?.x const yMin = mode === 'value' ? Math.min(...filterDefined(valuePointsY)) : Math.min( ...filterDefined(negProfitPointsY), ...filterDefined(posProfitPointsY) ) const yMax = mode === 'value' ? Math.max(...filterDefined(valuePointsY)) : Math.max( ...filterDefined(negProfitPointsY), ...filterDefined(posProfitPointsY) ) return (
= 800 ? 200 : 100) }} onMouseLeave={() => handleGraphDisplayChange(null)} > 100 ? 0 : 6} axisLeft={{ tickValues: numYTickValues, format: '.3s', }} enableGridX={false} enableGridY={true} gridYValues={numYTickValues} enableSlices="x" animate={false} yFormat={(value) => formatMoney(+value)} enableArea={true} areaOpacity={0.1} sliceTooltip={({ slice }) => { handleGraphDisplayChange(slice.points[0].data.yFormatted) return (
{dayjs(slice.points[0].data.xFormatted).format('MMM/D/YY')}
{dayjs(slice.points[0].data.xFormatted).format('h:mm A')}
{/* ))} */}
) }} >
) }) export function getPoints( line: 'value' | 'posProfit' | 'negProfit', portfolioHistory: PortfolioMetrics[] ) { const points = portfolioHistory.map((p) => { const { timestamp, balance, investmentValue, totalDeposits } = p const value = balance + investmentValue const profit = value - totalDeposits let posProfit = null let negProfit = null if (profit < 0) { negProfit = profit } else { posProfit = profit } return { x: new Date(timestamp), y: line === 'value' ? value : line === 'posProfit' ? posProfit : negProfit, } }) return points }