Create bet count and market count charts in our analytics
This commit is contained in:
parent
4d8af33c85
commit
c30962bf80
48
web/components/analytics/charts.tsx
Normal file
48
web/components/analytics/charts.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { ResponsiveLine } from '@nivo/line'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import { useWindowSize } from '../../hooks/use-window-size'
|
||||||
|
|
||||||
|
export function DailyCountChart(props: {
|
||||||
|
startDate: number
|
||||||
|
dailyCounts: number[]
|
||||||
|
}) {
|
||||||
|
const { dailyCounts, startDate } = props
|
||||||
|
const { width } = useWindowSize()
|
||||||
|
|
||||||
|
const dates = dailyCounts.map((_, i) =>
|
||||||
|
dayjs(startDate).add(i, 'day').toDate()
|
||||||
|
)
|
||||||
|
|
||||||
|
const points = _.zip(dates, dailyCounts).map(([date, betCount]) => ({
|
||||||
|
x: date,
|
||||||
|
y: betCount,
|
||||||
|
}))
|
||||||
|
const data = [{ id: 'Yes', data: points, color: '#11b981' }]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="w-full"
|
||||||
|
style={{ height: !width || width >= 800 ? 400 : 250 }}
|
||||||
|
>
|
||||||
|
<ResponsiveLine
|
||||||
|
data={data}
|
||||||
|
yScale={{ type: 'linear' }}
|
||||||
|
xScale={{
|
||||||
|
type: 'time',
|
||||||
|
}}
|
||||||
|
axisBottom={{
|
||||||
|
format: (date) => dayjs(date).format('MMM DD'),
|
||||||
|
}}
|
||||||
|
colors={{ datum: 'color' }}
|
||||||
|
pointSize={10}
|
||||||
|
pointBorderWidth={1}
|
||||||
|
pointBorderColor="#fff"
|
||||||
|
enableSlices="x"
|
||||||
|
enableGridX={!!width && width >= 800}
|
||||||
|
enableArea
|
||||||
|
margin={{ top: 20, right: 28, bottom: 22, left: 40 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -103,3 +103,24 @@ export function withoutAnteBets(contract: Contract, bets?: Bet[]) {
|
||||||
|
|
||||||
return bets?.filter((bet) => !bet.isAnte) ?? []
|
return bets?.filter((bet) => !bet.isAnte) ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getBetsQuery = (startTime: number, endTime: number) =>
|
||||||
|
query(
|
||||||
|
collectionGroup(db, 'bets'),
|
||||||
|
where('createdTime', '>=', startTime),
|
||||||
|
where('createdTime', '<', endTime),
|
||||||
|
orderBy('createdTime', 'asc')
|
||||||
|
)
|
||||||
|
|
||||||
|
export async function getDailyBets(startTime: number, numberOfDays: number) {
|
||||||
|
const query = getBetsQuery(startTime, startTime + DAY_IN_MS * numberOfDays)
|
||||||
|
const bets = await getValues<Bet>(query)
|
||||||
|
|
||||||
|
const betsByDay = _.range(0, numberOfDays).map(() => [] as Bet[])
|
||||||
|
for (const bet of bets) {
|
||||||
|
const dayIndex = Math.floor((bet.createdTime - startTime) / DAY_IN_MS)
|
||||||
|
betsByDay[dayIndex].push(bet)
|
||||||
|
}
|
||||||
|
|
||||||
|
return betsByDay
|
||||||
|
}
|
||||||
|
|
|
@ -209,3 +209,32 @@ export async function getClosingSoonContracts() {
|
||||||
(contract) => contract.closeTime
|
(contract) => contract.closeTime
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getContractsQuery = (startTime: number, endTime: number) =>
|
||||||
|
query(
|
||||||
|
collection(db, 'contracts'),
|
||||||
|
where('createdTime', '>=', startTime),
|
||||||
|
where('createdTime', '<', endTime),
|
||||||
|
orderBy('createdTime', 'asc')
|
||||||
|
)
|
||||||
|
|
||||||
|
const DAY_IN_MS = 24 * 60 * 60 * 1000
|
||||||
|
|
||||||
|
export async function getDailyContracts(
|
||||||
|
startTime: number,
|
||||||
|
numberOfDays: number
|
||||||
|
) {
|
||||||
|
const query = getContractsQuery(
|
||||||
|
startTime,
|
||||||
|
startTime + DAY_IN_MS * numberOfDays
|
||||||
|
)
|
||||||
|
const contracts = await getValues<Contract>(query)
|
||||||
|
|
||||||
|
const contractsByDay = _.range(0, numberOfDays).map(() => [] as Contract[])
|
||||||
|
for (const contract of contracts) {
|
||||||
|
const dayIndex = Math.floor((contract.createdTime - startTime) / DAY_IN_MS)
|
||||||
|
contractsByDay[dayIndex].push(contract)
|
||||||
|
}
|
||||||
|
|
||||||
|
return contractsByDay
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,81 @@
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import { DailyCountChart } from '../components/analytics/charts'
|
||||||
|
import { Col } from '../components/layout/col'
|
||||||
import { Page } from '../components/page'
|
import { Page } from '../components/page'
|
||||||
|
import { Title } from '../components/title'
|
||||||
|
import { getDailyBets } from '../lib/firebase/bets'
|
||||||
|
import { getDailyContracts } from '../lib/firebase/contracts'
|
||||||
|
|
||||||
export default function Analytics() {
|
export async function getStaticProps() {
|
||||||
// Edit dashboard at https://datastudio.google.com/u/0/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3/edit
|
const numberOfDays = 80
|
||||||
|
const today = dayjs(dayjs().format('YYYY-MM-DD'))
|
||||||
|
const startDate = today.subtract(numberOfDays, 'day')
|
||||||
|
|
||||||
|
const dailyBets = await getDailyBets(startDate.valueOf(), numberOfDays)
|
||||||
|
const dailyBetCounts = dailyBets.map((bets) => bets.length)
|
||||||
|
|
||||||
|
const dailyContracts = await getDailyContracts(
|
||||||
|
startDate.valueOf(),
|
||||||
|
numberOfDays
|
||||||
|
)
|
||||||
|
const dailyContractCounts = dailyContracts.map(
|
||||||
|
(contracts) => contracts.length
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
startDate: startDate.valueOf(),
|
||||||
|
dailyBetCounts,
|
||||||
|
dailyContractCounts,
|
||||||
|
},
|
||||||
|
revalidate: 12 * 60 * 60, // regenerate after half a day
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Analytics(props: {
|
||||||
|
startDate: number
|
||||||
|
dailyBetCounts: number[]
|
||||||
|
dailyContractCounts: number[]
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<iframe
|
<CustomAnalytics {...props} />
|
||||||
className="w-full"
|
<FirebaseAnalytics />
|
||||||
height={2200}
|
|
||||||
src="https://datastudio.google.com/embed/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3"
|
|
||||||
frameBorder="0"
|
|
||||||
style={{ border: 0 }}
|
|
||||||
allowFullScreen
|
|
||||||
></iframe>
|
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CustomAnalytics(props: {
|
||||||
|
startDate: number
|
||||||
|
dailyBetCounts: number[]
|
||||||
|
dailyContractCounts: number[]
|
||||||
|
}) {
|
||||||
|
const { startDate, dailyBetCounts, dailyContractCounts } = props
|
||||||
|
return (
|
||||||
|
<Col className="mb-8">
|
||||||
|
<Title text="Bets count" />
|
||||||
|
<DailyCountChart dailyCounts={dailyBetCounts} startDate={startDate} />
|
||||||
|
|
||||||
|
<Title text="Markets count" />
|
||||||
|
<DailyCountChart
|
||||||
|
dailyCounts={dailyContractCounts}
|
||||||
|
startDate={startDate}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function FirebaseAnalytics() {
|
||||||
|
// Edit dashboard at https://datastudio.google.com/u/0/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3/edit
|
||||||
|
return (
|
||||||
|
<iframe
|
||||||
|
className="w-full"
|
||||||
|
height={2200}
|
||||||
|
src="https://datastudio.google.com/embed/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3"
|
||||||
|
frameBorder="0"
|
||||||
|
style={{ border: 0 }}
|
||||||
|
allowFullScreen
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user