getting color graphs
This commit is contained in:
parent
c15d5e9e91
commit
f916f2bd74
|
@ -15,20 +15,90 @@ export const PortfolioValueGraph = memo(function PortfolioValueGraph(props: {
|
|||
const { portfolioHistory, height, includeTime, mode } = props
|
||||
const { width } = useWindowSize()
|
||||
|
||||
const points = portfolioHistory.map((p) => {
|
||||
function getPoints(line: 'value' | 'posProfit' | 'negProfit') {
|
||||
let points = portfolioHistory.map((p) => {
|
||||
const { timestamp, balance, investmentValue, totalDeposits } = p
|
||||
const value = balance + investmentValue
|
||||
const profit = value - totalDeposits
|
||||
let posProfit = null
|
||||
let negProfit = null
|
||||
|
||||
// const profit = value - totalDeposits
|
||||
if (profit < 0) {
|
||||
negProfit = profit
|
||||
} else {
|
||||
posProfit = profit
|
||||
}
|
||||
|
||||
return {
|
||||
x: new Date(timestamp),
|
||||
y: mode === 'value' ? value : profit,
|
||||
y:
|
||||
line === 'value'
|
||||
? value
|
||||
: line === 'posProfit'
|
||||
? posProfit
|
||||
: negProfit,
|
||||
}
|
||||
})
|
||||
const data = [{ id: 'Value', data: points, color: '#11b981' }]
|
||||
return points
|
||||
}
|
||||
|
||||
let data
|
||||
|
||||
if (mode === 'value') {
|
||||
data = [{ id: 'value', data: getPoints('value'), color: '#4f46e5' }]
|
||||
} else {
|
||||
data = [
|
||||
{
|
||||
id: 'negProfit',
|
||||
data: getPoints('negProfit'),
|
||||
color: '#dc2626',
|
||||
},
|
||||
{
|
||||
id: 'posProfit',
|
||||
data: getPoints('posProfit'),
|
||||
color: '#14b8a6',
|
||||
},
|
||||
]
|
||||
}
|
||||
const firstPoints = data[0].data
|
||||
const numXTickValues = !width || width < 800 ? 2 : 5
|
||||
const numYTickValues = 4
|
||||
const endDate = last(points)?.x
|
||||
const endDate = last(firstPoints)?.x
|
||||
|
||||
const firstPointsY = firstPoints
|
||||
.filter((p) => {
|
||||
return p.y !== null
|
||||
})
|
||||
.map((p) => p.y)
|
||||
// console.log(firstPointsY)
|
||||
|
||||
console.log(
|
||||
'MIN: ',
|
||||
mode === 'value'
|
||||
? Math.min(...firstPointsY)
|
||||
: Math.min(
|
||||
...firstPointsY,
|
||||
...data[1].data
|
||||
.filter((p) => {
|
||||
return p.y !== null
|
||||
})
|
||||
.map((p) => p.y)
|
||||
),
|
||||
|
||||
'MAX: ',
|
||||
mode === 'value'
|
||||
? Math.max(...firstPointsY)
|
||||
: Math.max(
|
||||
...firstPointsY,
|
||||
...data[1].data
|
||||
.filter((p) => {
|
||||
return p.y !== null
|
||||
})
|
||||
.map((p) => p.y)
|
||||
)
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-full overflow-hidden"
|
||||
|
@ -39,16 +109,37 @@ export const PortfolioValueGraph = memo(function PortfolioValueGraph(props: {
|
|||
margin={{ top: 20, right: 28, bottom: 22, left: 60 }}
|
||||
xScale={{
|
||||
type: 'time',
|
||||
min: points[0]?.x,
|
||||
min: firstPoints[0]?.x,
|
||||
max: endDate,
|
||||
}}
|
||||
yScale={{
|
||||
type: 'linear',
|
||||
stacked: false,
|
||||
min: Math.min(...points.map((p) => p.y)),
|
||||
min:
|
||||
mode === 'value'
|
||||
? Math.min(...firstPointsY)
|
||||
: Math.min(
|
||||
...firstPointsY,
|
||||
...data[1].data
|
||||
.filter((p) => {
|
||||
return p.y !== null
|
||||
})
|
||||
.map((p) => p.y)
|
||||
),
|
||||
max:
|
||||
mode === 'value'
|
||||
? Math.max(...firstPointsY)
|
||||
: Math.max(
|
||||
...firstPointsY,
|
||||
...data[1].data
|
||||
.filter((p) => {
|
||||
return p.y !== null
|
||||
})
|
||||
.map((p) => p.y)
|
||||
),
|
||||
}}
|
||||
gridYValues={numYTickValues}
|
||||
curve="stepAfter"
|
||||
curve="linear"
|
||||
enablePoints={false}
|
||||
colors={{ datum: 'color' }}
|
||||
axisBottom={{
|
||||
|
@ -56,7 +147,7 @@ export const PortfolioValueGraph = memo(function PortfolioValueGraph(props: {
|
|||
format: (time) => formatTime(+time, !!includeTime),
|
||||
}}
|
||||
pointBorderColor="#fff"
|
||||
pointSize={points.length > 100 ? 0 : 6}
|
||||
pointSize={firstPoints.length > 100 ? 0 : 6}
|
||||
axisLeft={{
|
||||
tickValues: numYTickValues,
|
||||
format: (value) => formatMoney(value),
|
||||
|
@ -66,6 +157,21 @@ export const PortfolioValueGraph = memo(function PortfolioValueGraph(props: {
|
|||
enableSlices="x"
|
||||
animate={false}
|
||||
yFormat={(value) => formatMoney(+value)}
|
||||
// defs={[
|
||||
// {
|
||||
// id: 'purpleGradient',
|
||||
// type: 'linearGradient',
|
||||
// colors: [
|
||||
// { offset: 0, color: '#7c3aed' },
|
||||
// {
|
||||
// offset: 100,
|
||||
// color: '#inherit',
|
||||
// opacity: 0,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ]}
|
||||
enableArea={true}
|
||||
></ResponsiveLine>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@ import { last } from 'lodash'
|
|||
import { memo, useRef, useState } from 'react'
|
||||
import { usePortfolioHistory } from 'web/hooks/use-portfolio-history'
|
||||
import { Period } from 'web/lib/firebase/users'
|
||||
import { PillButton } from '../buttons/pill-button'
|
||||
import { Col } from '../layout/col'
|
||||
import { Row } from '../layout/row'
|
||||
import { Spacer } from '../layout/spacer'
|
||||
|
@ -15,6 +16,7 @@ export const PortfolioValueSection = memo(
|
|||
|
||||
const [portfolioPeriod, setPortfolioPeriod] = useState<Period>('weekly')
|
||||
const portfolioHistory = usePortfolioHistory(userId, portfolioPeriod)
|
||||
const [graphMode, setGraphMode] = useState<'profit' | 'value'>('profit')
|
||||
|
||||
// Remember the last defined portfolio history.
|
||||
const portfolioRef = useRef(portfolioHistory)
|
||||
|
@ -32,38 +34,34 @@ export const PortfolioValueSection = memo(
|
|||
|
||||
return (
|
||||
<>
|
||||
<Row className="gap-8">
|
||||
<Col className="flex-1 justify-center">
|
||||
<div className="text-sm text-gray-500">Profit</div>
|
||||
<div className="text-lg">{formatMoney(totalProfit)}</div>
|
||||
<Row className="justify-between">
|
||||
<Row className="gap-4 sm:gap-8 ">
|
||||
<Col>
|
||||
<div className="text-greyscale-4 text-xs sm:text-sm">
|
||||
Portfolio value
|
||||
</div>
|
||||
<div className="text-lg text-indigo-600 sm:text-xl">
|
||||
{formatMoney(totalValue)}
|
||||
</div>
|
||||
</Col>
|
||||
{/* <select
|
||||
className="select select-bordered self-start"
|
||||
value={portfolioPeriod}
|
||||
onChange={(e) => {
|
||||
setPortfolioPeriod(e.target.value as Period)
|
||||
}}
|
||||
<Col>
|
||||
<div className="text-greyscale-4 text-xs sm:text-sm">Profit</div>
|
||||
<div
|
||||
className={clsx(
|
||||
totalProfit > 0 ? 'text-green-500' : 'text-red-600',
|
||||
'text-lg sm:text-xl'
|
||||
)}
|
||||
>
|
||||
<option value="allTime">All time</option>
|
||||
<option value="monthly">Last Month</option>
|
||||
<option value="weekly">Last 7d</option>
|
||||
<option value="daily">Last 24h</option>
|
||||
</select> */}
|
||||
{formatMoney(totalProfit)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<GraphToggle setGraphMode={setGraphMode} graphMode={graphMode} />
|
||||
</Row>
|
||||
<PortfolioValueGraph
|
||||
portfolioHistory={currPortfolioHistory}
|
||||
includeTime={portfolioPeriod == 'daily'}
|
||||
mode="profit"
|
||||
/>
|
||||
<Spacer h={8} />
|
||||
<Col className="flex-1 justify-center">
|
||||
<div className="text-sm text-gray-500">Portfolio value</div>
|
||||
<div className="text-lg">{formatMoney(totalValue)}</div>
|
||||
</Col>
|
||||
<PortfolioValueGraph
|
||||
portfolioHistory={currPortfolioHistory}
|
||||
includeTime={portfolioPeriod == 'daily'}
|
||||
mode="value"
|
||||
includeTime={true}
|
||||
mode={graphMode}
|
||||
/>
|
||||
<PortfolioPeriodSelection
|
||||
portfolioPeriod={portfolioPeriod}
|
||||
|
@ -85,7 +83,7 @@ export function PortfolioPeriodSelection(props: {
|
|||
const { setPortfolioPeriod, portfolioPeriod, className, selectClassName } =
|
||||
props
|
||||
return (
|
||||
<Row className={className}>
|
||||
<Row className={clsx(className, 'text-greyscale-4')}>
|
||||
<button
|
||||
className={clsx(portfolioPeriod === 'daily' ? selectClassName : '')}
|
||||
onClick={() => setPortfolioPeriod('daily' as Period)}
|
||||
|
@ -113,3 +111,34 @@ export function PortfolioPeriodSelection(props: {
|
|||
</Row>
|
||||
)
|
||||
}
|
||||
|
||||
export function GraphToggle(props: {
|
||||
setGraphMode: (mode: 'profit' | 'value') => void
|
||||
graphMode: string
|
||||
}) {
|
||||
const { setGraphMode, graphMode } = props
|
||||
return (
|
||||
<Row className="relative mt-1 ml-1 items-center gap-1.5 sm:ml-0 sm:gap-2">
|
||||
<PillButton
|
||||
selected={graphMode === 'value'}
|
||||
onSelect={() => {
|
||||
setGraphMode('value')
|
||||
}}
|
||||
xs={true}
|
||||
className="z-50"
|
||||
>
|
||||
Value
|
||||
</PillButton>
|
||||
<PillButton
|
||||
selected={graphMode === 'profit'}
|
||||
onSelect={() => {
|
||||
setGraphMode('profit')
|
||||
}}
|
||||
xs={true}
|
||||
className="z-50"
|
||||
>
|
||||
Profit
|
||||
</PillButton>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user