Show region stats on home page
This commit is contained in:
parent
382db5a11e
commit
7ae4ebebb6
83
frontend/src/components/RegionStats/index.tsx
Normal file
83
frontend/src/components/RegionStats/index.tsx
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import React, { useState, useCallback } from "react";
|
||||||
|
import { pickBy } from "lodash";
|
||||||
|
import {
|
||||||
|
Loader,
|
||||||
|
Statistic,
|
||||||
|
Pagination,
|
||||||
|
Segment,
|
||||||
|
Header,
|
||||||
|
Menu,
|
||||||
|
Table,
|
||||||
|
Icon,
|
||||||
|
} from "semantic-ui-react";
|
||||||
|
import { useObservable } from "rxjs-hooks";
|
||||||
|
import { of, from, concat, combineLatest } from "rxjs";
|
||||||
|
import { map, switchMap, distinctUntilChanged } from "rxjs/operators";
|
||||||
|
import { Duration, DateTime } from "luxon";
|
||||||
|
|
||||||
|
import api from "api";
|
||||||
|
|
||||||
|
function formatDuration(seconds) {
|
||||||
|
return (
|
||||||
|
Duration.fromMillis((seconds ?? 0) * 1000)
|
||||||
|
.as("hours")
|
||||||
|
.toFixed(1) + " h"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Stats() {
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const PER_PAGE = 10;
|
||||||
|
const stats = useObservable(
|
||||||
|
() =>
|
||||||
|
of(null).pipe(
|
||||||
|
switchMap(() => concat(of(null), from(api.get("/stats/regions"))))
|
||||||
|
),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
const pageCount = stats ? Math.ceil(stats.length / PER_PAGE) : 1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header as="h2">Top Regions</Header>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Loader active={stats == null} />
|
||||||
|
|
||||||
|
<Table celled>
|
||||||
|
<Table.Header>
|
||||||
|
<Table.Row>
|
||||||
|
<Table.HeaderCell>Region name</Table.HeaderCell>
|
||||||
|
<Table.HeaderCell>Event count</Table.HeaderCell>
|
||||||
|
</Table.Row>
|
||||||
|
</Table.Header>
|
||||||
|
|
||||||
|
<Table.Body>
|
||||||
|
{stats
|
||||||
|
?.slice((page - 1) * PER_PAGE, page * PER_PAGE)
|
||||||
|
?.map((area) => (
|
||||||
|
<Table.Row key={area.id}>
|
||||||
|
<Table.Cell>{area.name}</Table.Cell>
|
||||||
|
<Table.Cell>{area.overtaking_event_count}</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
|
))}
|
||||||
|
</Table.Body>
|
||||||
|
|
||||||
|
{pageCount > 1 && <Table.Footer>
|
||||||
|
<Table.Row>
|
||||||
|
<Table.HeaderCell colSpan="2">
|
||||||
|
<Pagination
|
||||||
|
floated="right"
|
||||||
|
activePage={page}
|
||||||
|
totalPages={pageCount}
|
||||||
|
onPageChange={(e, data) => setPage(data.activePage as number)}
|
||||||
|
/>
|
||||||
|
</Table.HeaderCell>
|
||||||
|
</Table.Row>
|
||||||
|
</Table.Footer>}
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import {map, switchMap} from 'rxjs/operators'
|
||||||
import {useTranslation} from 'react-i18next'
|
import {useTranslation} from 'react-i18next'
|
||||||
|
|
||||||
import api from 'api'
|
import api from 'api'
|
||||||
import {Stats, Page} from 'components'
|
import {RegionStats, Stats, Page} from 'components'
|
||||||
import type {Track} from 'types'
|
import type {Track} from 'types'
|
||||||
|
|
||||||
import {TrackListItem, NoPublicTracksMessage} from './TracksPage'
|
import {TrackListItem, NoPublicTracksMessage} from './TracksPage'
|
||||||
|
@ -46,9 +46,10 @@ export default function HomePage() {
|
||||||
<Grid.Row>
|
<Grid.Row>
|
||||||
<Grid.Column width={8}>
|
<Grid.Column width={8}>
|
||||||
<Stats />
|
<Stats />
|
||||||
|
<MostRecentTrack />
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
<Grid.Column width={8}>
|
<Grid.Column width={8}>
|
||||||
<MostRecentTrack />
|
<RegionStats />
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
</Grid.Row>
|
</Grid.Row>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
Loading…
Reference in a new issue