diff --git a/web/components/analytics/charts.tsx b/web/components/analytics/charts.tsx
new file mode 100644
index 00000000..c628c071
--- /dev/null
+++ b/web/components/analytics/charts.tsx
@@ -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 (
+
= 800 ? 400 : 250 }}
+ >
+ 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 }}
+ />
+
+ )
+}
diff --git a/web/lib/firebase/bets.ts b/web/lib/firebase/bets.ts
index f03b293b..4056e114 100644
--- a/web/lib/firebase/bets.ts
+++ b/web/lib/firebase/bets.ts
@@ -103,3 +103,24 @@ export function withoutAnteBets(contract: Contract, bets?: Bet[]) {
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(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
+}
diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts
index eb1b65e1..e75a34fb 100644
--- a/web/lib/firebase/contracts.ts
+++ b/web/lib/firebase/contracts.ts
@@ -209,3 +209,32 @@ export async function getClosingSoonContracts() {
(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(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
+}
diff --git a/web/pages/analytics.tsx b/web/pages/analytics.tsx
index 7f905a46..e4ce95fc 100644
--- a/web/pages/analytics.tsx
+++ b/web/pages/analytics.tsx
@@ -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 { Title } from '../components/title'
+import { getDailyBets } from '../lib/firebase/bets'
+import { getDailyContracts } from '../lib/firebase/contracts'
-export default function Analytics() {
- // Edit dashboard at https://datastudio.google.com/u/0/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3/edit
+export async function getStaticProps() {
+ 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 (
-
+
+
)
}
+
+function CustomAnalytics(props: {
+ startDate: number
+ dailyBetCounts: number[]
+ dailyContractCounts: number[]
+}) {
+ const { startDate, dailyBetCounts, dailyContractCounts } = props
+ return (
+
+
+
+
+
+
+
+ )
+}
+
+function FirebaseAnalytics() {
+ // Edit dashboard at https://datastudio.google.com/u/0/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3/edit
+ return (
+
+ )
+}