Use react query for portfolio history
This commit is contained in:
parent
8b1874e7bb
commit
f8888ab5e5
|
@ -1,43 +1,26 @@
|
||||||
import { PortfolioMetrics } from 'common/user'
|
|
||||||
import { formatMoney } from 'common/util/format'
|
import { formatMoney } from 'common/util/format'
|
||||||
import { last } from 'lodash'
|
import { last } from 'lodash'
|
||||||
import { memo, useEffect, useState } from 'react'
|
import { memo, useRef, useState } from 'react'
|
||||||
import { Period, getPortfolioHistory } from 'web/lib/firebase/users'
|
import { usePortfolioHistory } from 'web/hooks/use-portfolio-history'
|
||||||
|
import { Period } from 'web/lib/firebase/users'
|
||||||
import { Col } from '../layout/col'
|
import { Col } from '../layout/col'
|
||||||
import { Row } from '../layout/row'
|
import { Row } from '../layout/row'
|
||||||
import { PortfolioValueGraph } from './portfolio-value-graph'
|
import { PortfolioValueGraph } from './portfolio-value-graph'
|
||||||
import { DAY_MS } from 'common/util/time'
|
|
||||||
|
|
||||||
const periodToCutoff = (now: number, period: Period) => {
|
|
||||||
switch (period) {
|
|
||||||
case 'daily':
|
|
||||||
return now - 1 * DAY_MS
|
|
||||||
case 'weekly':
|
|
||||||
return now - 7 * DAY_MS
|
|
||||||
case 'monthly':
|
|
||||||
return now - 30 * DAY_MS
|
|
||||||
case 'allTime':
|
|
||||||
default:
|
|
||||||
return new Date(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PortfolioValueSection = memo(
|
export const PortfolioValueSection = memo(
|
||||||
function PortfolioValueSection(props: { userId: string }) {
|
function PortfolioValueSection(props: { userId: string }) {
|
||||||
const { userId } = props
|
const { userId } = props
|
||||||
|
|
||||||
const [portfolioPeriod, setPortfolioPeriod] = useState<Period>('weekly')
|
const [portfolioPeriod, setPortfolioPeriod] = useState<Period>('weekly')
|
||||||
const [portfolioHistory, setUsersPortfolioHistory] = useState<
|
const portfolioHistory = usePortfolioHistory(userId, portfolioPeriod)
|
||||||
PortfolioMetrics[]
|
|
||||||
>([])
|
|
||||||
|
|
||||||
useEffect(() => {
|
// Remember the last defined portfolio history.
|
||||||
const cutoff = periodToCutoff(Date.now(), portfolioPeriod).valueOf()
|
const portfolioRef = useRef(portfolioHistory)
|
||||||
getPortfolioHistory(userId, cutoff).then(setUsersPortfolioHistory)
|
if (portfolioHistory) portfolioRef.current = portfolioHistory
|
||||||
}, [portfolioPeriod, userId])
|
const currPortfolioHistory = portfolioRef.current
|
||||||
|
|
||||||
const lastPortfolioMetrics = last(portfolioHistory)
|
const lastPortfolioMetrics = last(currPortfolioHistory)
|
||||||
if (portfolioHistory.length === 0 || !lastPortfolioMetrics) {
|
if (!currPortfolioHistory || !lastPortfolioMetrics) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +47,7 @@ export const PortfolioValueSection = memo(
|
||||||
</select>
|
</select>
|
||||||
</Row>
|
</Row>
|
||||||
<PortfolioValueGraph
|
<PortfolioValueGraph
|
||||||
portfolioHistory={portfolioHistory}
|
portfolioHistory={currPortfolioHistory}
|
||||||
includeTime={portfolioPeriod == 'daily'}
|
includeTime={portfolioPeriod == 'daily'}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
32
web/hooks/use-portfolio-history.ts
Normal file
32
web/hooks/use-portfolio-history.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { useFirestoreQueryData } from '@react-query-firebase/firestore'
|
||||||
|
import { DAY_MS, HOUR_MS } from 'common/util/time'
|
||||||
|
import { getPortfolioHistoryQuery, Period } from 'web/lib/firebase/users'
|
||||||
|
|
||||||
|
export const usePortfolioHistory = (userId: string, period: Period) => {
|
||||||
|
const nowRounded = Math.round(Date.now() / HOUR_MS) * HOUR_MS
|
||||||
|
const cutoff = periodToCutoff(nowRounded, period).valueOf()
|
||||||
|
|
||||||
|
const result = useFirestoreQueryData(
|
||||||
|
['portfolio-history', userId, cutoff],
|
||||||
|
getPortfolioHistoryQuery(userId, cutoff),
|
||||||
|
{ subscribe: true, includeMetadataChanges: true },
|
||||||
|
// Temporary workaround for react-query bug:
|
||||||
|
// https://github.com/invertase/react-query-firebase/issues/25
|
||||||
|
{ refetchOnMount: 'always' }
|
||||||
|
)
|
||||||
|
return result.data
|
||||||
|
}
|
||||||
|
|
||||||
|
const periodToCutoff = (now: number, period: Period) => {
|
||||||
|
switch (period) {
|
||||||
|
case 'daily':
|
||||||
|
return now - 1 * DAY_MS
|
||||||
|
case 'weekly':
|
||||||
|
return now - 7 * DAY_MS
|
||||||
|
case 'monthly':
|
||||||
|
return now - 30 * DAY_MS
|
||||||
|
case 'allTime':
|
||||||
|
default:
|
||||||
|
return new Date(0)
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import {
|
||||||
deleteDoc,
|
deleteDoc,
|
||||||
collectionGroup,
|
collectionGroup,
|
||||||
onSnapshot,
|
onSnapshot,
|
||||||
|
Query,
|
||||||
} from 'firebase/firestore'
|
} from 'firebase/firestore'
|
||||||
import { getAuth } from 'firebase/auth'
|
import { getAuth } from 'firebase/auth'
|
||||||
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth'
|
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth'
|
||||||
|
@ -252,15 +253,13 @@ export async function unfollow(userId: string, unfollowedUserId: string) {
|
||||||
await deleteDoc(followDoc)
|
await deleteDoc(followDoc)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPortfolioHistory(userId: string, since: number) {
|
export function getPortfolioHistoryQuery(userId: string, since: number) {
|
||||||
return getValues<PortfolioMetrics>(
|
return query(
|
||||||
query(
|
collectionGroup(db, 'portfolioHistory'),
|
||||||
collectionGroup(db, 'portfolioHistory'),
|
where('userId', '==', userId),
|
||||||
where('userId', '==', userId),
|
where('timestamp', '>=', since),
|
||||||
where('timestamp', '>=', since),
|
orderBy('timestamp', 'asc')
|
||||||
orderBy('timestamp', 'asc')
|
) as Query<PortfolioMetrics>
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listenForFollows(
|
export function listenForFollows(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user