forked from kin-labs/kin-data
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
293 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
export interface DaySummary { | ||
date: string | ||
activeApps: number | ||
activeUserBalance: number | ||
activeCappedUserBalance: number | ||
activeUsers: number | ||
dailyTransactions: number | ||
monthlyActiveEarners: number | ||
monthlyActiveSpenders: number | ||
monthlyActiveUsers: number | ||
} | ||
|
||
export class DaysApi { | ||
static async getSummary(date?: string): Promise<DaySummary> { | ||
return fetch(`/api/stats/summary?date=${date}`).then((r) => r.json()) | ||
} | ||
|
||
static async getSummaryDates(): Promise<string[]> { | ||
return fetch('/api/stats/summary-dates').then((r) => r.json()) | ||
} | ||
} | ||
|
||
export function formatNumber(amount: number, digits = 2) { | ||
const lookup = [ | ||
{ value: 1, symbol: '' }, | ||
{ value: 1e3, symbol: 'Thousand' }, | ||
{ value: 1e6, symbol: 'Million' }, | ||
{ value: 1e9, symbol: 'Billion' }, | ||
{ value: 1e12, symbol: 'Trillion' }, | ||
] | ||
const rx = /\.0+$|(\.[0-9]*[1-9])0+$/ | ||
const item = lookup | ||
.slice() | ||
.reverse() | ||
.find(function (item) { | ||
return amount >= item.value | ||
}) | ||
return item ? `${(amount / item.value).toFixed(digits).replace(rx, '$1')} ${item.symbol}` : '0' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { Anchor, Card, Container, Flex, SimpleGrid, Stack, Text, Tooltip } from '@mantine/core' | ||
import { useQuery } from '@tanstack/react-query' | ||
import React, { useEffect } from 'react' | ||
import { Link, useParams } from 'react-router-dom' | ||
import { UiLoader } from '../../ui/loader/ui-loader' | ||
import { DaysApi, formatNumber } from './days-api' | ||
|
||
export function DaysDetail() { | ||
const { date } = useParams() | ||
const query = useQuery({ queryKey: ['date'], queryFn: () => DaysApi.getSummary(date) }) | ||
const queryDates = useQuery({ queryKey: ['dates'], queryFn: DaysApi.getSummaryDates }) | ||
|
||
useEffect(() => { | ||
query.refetch() | ||
}, [date]) | ||
|
||
return ( | ||
<Container> | ||
<Card radius="md"> | ||
<Stack> | ||
{date && queryDates?.data?.length ? <DaysStatHeader date={date} dates={queryDates.data} /> : null} | ||
{query.isFetching ? ( | ||
<UiLoader /> | ||
) : ( | ||
<Stack> | ||
<SimpleGrid cols={3}> | ||
<DaysStatBox label={'Daily Transactions'} amount={query.data?.dailyTransactions ?? 0} /> | ||
<DaysStatBox label={'Active Apps'} amount={query.data?.activeApps ?? 0} /> | ||
<DaysStatBox label={'Active User Balance'} amount={query.data?.activeUserBalance ?? 0} /> | ||
</SimpleGrid> | ||
<SimpleGrid cols={3}> | ||
<DaysStatBox label={'Monthly Active Spenders'} amount={query.data?.monthlyActiveSpenders ?? 0} /> | ||
<DaysStatBox label={'Monthly Active Earners'} amount={query.data?.monthlyActiveEarners ?? 0} /> | ||
<DaysStatBox label={'Monthly Active Users'} amount={query.data?.monthlyActiveUsers ?? 0} /> | ||
</SimpleGrid> | ||
</Stack> | ||
)} | ||
</Stack> | ||
</Card> | ||
</Container> | ||
) | ||
} | ||
|
||
export function DaysStatBox({ amount, label }: { amount: number; label: string }) { | ||
return ( | ||
<Stack> | ||
<Text size="lg" color="dimmed"> | ||
{label} | ||
</Text> | ||
<Tooltip label={amount}> | ||
<Text size="xl">{formatNumber(amount ?? 0)}</Text> | ||
</Tooltip> | ||
</Stack> | ||
) | ||
} | ||
|
||
export function DaysStatHeader({ date, dates }: { date: string; dates: string[] }) { | ||
const currentDate = dates.findIndex((d) => d === date) || 0 | ||
const previousDate = dates[currentDate + 1] || dates[0] | ||
const nextDate = dates[currentDate - 1] | ||
|
||
return ( | ||
<SimpleGrid cols={3}> | ||
<DaysStatHeaderBox date={nextDate} /> | ||
<DaysStatHeaderBox date={date} /> | ||
<DaysStatHeaderBox date={previousDate} /> | ||
</SimpleGrid> | ||
) | ||
} | ||
|
||
export function DaysStatHeaderBox({ date }: { date?: string }) { | ||
return ( | ||
<Card radius="md" withBorder> | ||
<Flex justify="center" align="center" mih={50}> | ||
{date ? ( | ||
<Anchor component={Link} color={'primary'} to={`../${date}`}> | ||
<Text align="center">{new Date(date).toLocaleDateString('en-US', { weekday: 'long' })}</Text> | ||
<Text align="center" color="dimmed"> | ||
{new Date(date).toLocaleDateString()} | ||
</Text> | ||
</Anchor> | ||
) : ( | ||
'No date selected' | ||
)} | ||
</Flex> | ||
</Card> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react' | ||
import { Route, Routes } from 'react-router-dom' | ||
import { DaysDetail } from './days-detail' | ||
import { DaysList } from './days-list' | ||
|
||
export function DaysIndex() { | ||
return ( | ||
<Routes> | ||
<Route index element={<DaysList />} /> | ||
<Route path=":date" element={<DaysDetail />} /> | ||
</Routes> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { Anchor, Card, Container, SimpleGrid, Text } from '@mantine/core' | ||
import { useQuery } from '@tanstack/react-query' | ||
import React from 'react' | ||
import { Link } from 'react-router-dom' | ||
import { UiLoader } from '../../ui/loader/ui-loader' | ||
import { DaysApi } from './days-api' | ||
|
||
export function DaysList() { | ||
const query = useQuery({ queryKey: ['dates'], queryFn: DaysApi.getSummaryDates }) | ||
|
||
return ( | ||
<Container> | ||
{query.isLoading ? ( | ||
<UiLoader /> | ||
) : ( | ||
<SimpleGrid cols={7} spacing="sm" verticalSpacing="sm"> | ||
{query.data?.map((date) => ( | ||
<Card radius="md" key={date}> | ||
<Anchor component={Link} color={'primary'} to={`./${date}`}> | ||
<Text size="sm">{new Date(date).toLocaleDateString('en-US', { weekday: 'long' })}</Text> | ||
<Text size="xs" color="dimmed"> | ||
{new Date(date).toLocaleDateString()} | ||
</Text> | ||
</Anchor> | ||
</Card> | ||
))} | ||
</SimpleGrid> | ||
)} | ||
</Container> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { createContext, ReactNode, useContext, useEffect, useState } from 'react' | ||
import { DaysApi, DaySummary } from './days-api' | ||
|
||
export interface DaysProviderContext { | ||
dates: string[] | ||
date: string | undefined | ||
previous: string | undefined | ||
next: string | undefined | ||
loading: boolean | ||
setDate: (date: string) => void | ||
summary: DaySummary | undefined | ||
} | ||
|
||
const DaysContext = createContext<DaysProviderContext>({} as DaysProviderContext) | ||
|
||
function DaysProvider({ children }: { children: ReactNode }) { | ||
const [dates, setDates] = useState<string[]>([]) | ||
const [date, setDate] = useState<string>('') | ||
const [summary, setSummary] = useState<DaySummary | undefined>() | ||
const [loading, setLoading] = useState(false) | ||
|
||
useEffect(() => { | ||
if (dates?.length || loading) return | ||
setLoading(true) | ||
DaysApi.getSummaryDates().then((res: string[]) => { | ||
setDates(res) | ||
setLoading(false) | ||
}) | ||
}, [dates, loading]) | ||
|
||
useEffect(() => { | ||
if (!date || loading || summary) return | ||
setLoading(true) | ||
DaysApi.getSummary(date).then((res) => { | ||
setSummary(res) | ||
setLoading(false) | ||
}) | ||
}, [date, summary, loading]) | ||
|
||
const previous = dates[dates.indexOf(date) + 1] | ||
const next = dates[dates.indexOf(date) - 1] | ||
|
||
const value = { | ||
dates, | ||
date, | ||
previous, | ||
next, | ||
loading, | ||
setDate: () => { | ||
setSummary(undefined) | ||
setDate(date) | ||
}, | ||
summary, | ||
} | ||
return <DaysContext.Provider value={value}>{children}</DaysContext.Provider> | ||
} | ||
|
||
const useDays = () => useContext(DaysContext) | ||
|
||
export { DaysProvider, useDays } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
export * from './days/days-index' | ||
export * from './dev/dev-index' | ||
export * from './home/home-index' | ||
export * from './kre/features/kre-detail-feature' | ||
export * from './kre/features/kre-index-feature' | ||
export * from './kre/features/kre-list-feature' | ||
export * from './kre/features/string-to-color' | ||
export { DaysDetail } from './days/days-detail' | ||
export { DaysList } from './days/days-list' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.