feat: skeleton loading

This commit is contained in:
TrèsAbhi committed 2024-06-30 19:59:32 -05:00
1 parent 6c6cf6b76d
commit 574c789233
11 files changed
+160 -84

No files matched your search

File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,13 @@
import { Table } from '@radix-ui/themes';
import { times } from 'lodash';
import { RowLoader } from './RowLoader';
export function BodyLoader() {
return (
<Table.Body>
{times(10, (index) => (
<RowLoader key={index} />
))}
</Table.Body>
);
}
@@ -0,0 +1,53 @@
import { Table } from '@radix-ui/themes';
export function Header() {
return (
<Table.Header>
<Table.Row align="end">
<Table.ColumnHeaderCell>Tank</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Winrate
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Players
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Damage
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Survival
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
XP
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Kills
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Spots
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Accuracy
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Shots
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Hits
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Damage ratio
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Damage received
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Capture points
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Dropped capture points
</Table.ColumnHeaderCell>
</Table.Row>
</Table.Header>
);
}
@@ -0,0 +1,29 @@
'use client';
import { InfoCircledIcon } from '@radix-ui/react-icons';
import { Callout, Flex } from '@radix-ui/themes';
import { use, useMemo } from 'react';
import { averageDefinitionsArray } from '../../../../core/blitzkit/averageDefinitions';
export function Info() {
const awaitedAverageDefinitionsArray = use(averageDefinitionsArray);
const samples = useMemo(
() => awaitedAverageDefinitionsArray.reduce((a, b) => a + b.samples, 0),
[],
);
return (
<Flex justify="center">
<Callout.Root style={{ width: 'fit-content' }}>
<Callout.Icon>
<InfoCircledIcon />
</Callout.Icon>
<Callout.Text>
Based on {samples.toLocaleString()} players with at least 5,000 career
battles and 1 battle in the past 120 days. Stats displayed as an
average per battle. Updated daily.
</Callout.Text>
</Callout.Root>
</Flex>
);
}
@@ -0,0 +1,18 @@
import { Skeleton, Table } from '@radix-ui/themes';
import { times } from 'lodash';
export function RowLoader() {
return (
<Table.Row>
<Table.RowHeaderCell>
<Skeleton height="100%" width="128px" />
</Table.RowHeaderCell>
{times(14, (index) => (
<Table.Cell key={index}>
<Skeleton height="1em" width="32px" />
</Table.Cell>
))}
</Table.Row>
);
}
@@ -0,0 +1,30 @@
'use client';
import { Table } from '@radix-ui/themes';
import { Suspense, use, useMemo } from 'react';
import { averageDefinitionsArray } from '../../../../core/blitzkit/averageDefinitions';
import { tankDefinitions } from '../../../../core/blitzkit/tankDefinitions';
import { RowLoader } from './RowLoader';
import { TankRow } from './TankRow';
export function Tanks() {
const awaitedTankDefinitions = use(tankDefinitions);
const awaitedAverageDefinitionsArray = use(averageDefinitionsArray);
const tankAverages = useMemo(
() => awaitedAverageDefinitionsArray.sort((a, b) => b.mu.wins - a.mu.wins),
[],
);
return (
<Table.Body>
{tankAverages.map((averages) => {
const tank = awaitedTankDefinitions[averages.id];
return (
<Suspense key={tank.id} fallback={<RowLoader />}>
<TankRow tank={tank} />
</Suspense>
);
})}
</Table.Body>
);
}
+11 -82
View File
@@ -1,94 +1,23 @@
import { InfoCircledIcon } from '@radix-ui/react-icons';
import { Callout, Flex, Table } from '@radix-ui/themes';
import { use, useMemo } from 'react';
import { Flex, Table } from '@radix-ui/themes';
import { Suspense } from 'react';
import PageWrapper from '../../../components/PageWrapper';
import { averageDefinitionsArray } from '../../../core/blitzkit/averageDefinitions';
import { tankDefinitions } from '../../../core/blitzkit/tankDefinitions';
import { TankRow } from './components/TankRow';
import { Header } from './components/Header';
import { Info } from './components/Info';
import { Tanks } from './components/Tanks';
import { BodyLoader } from './components/BodyLoader';
export default function Page() {
const awaitedTankDefinitions = use(tankDefinitions);
const awaitedAverageDefinitionsArray = use(averageDefinitionsArray);
const tankAverages = useMemo(
() => awaitedAverageDefinitionsArray.sort((a, b) => b.mu.wins - a.mu.wins),
[],
);
const samples = useMemo(
() => awaitedAverageDefinitionsArray.reduce((a, b) => a + b.samples, 0),
[],
);
return (
<PageWrapper color="jade" noMaxWidth>
<Flex justify="center">
<Callout.Root style={{ width: 'fit-content' }}>
<Callout.Icon>
<InfoCircledIcon />
</Callout.Icon>
<Callout.Text>
Based on {samples.toLocaleString()} players with at least 5,000
career battles and 1 battle in the past 120 days. Stats displayed as
an average per battle. Updated daily.
</Callout.Text>
</Callout.Root>
</Flex>
<Info />
<Flex justify="center">
<Table.Root variant="surface" style={{ maxWidth: '100%' }}>
<Table.Header>
<Table.Row align="end">
<Table.ColumnHeaderCell>Tank</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Winrate
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Players
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Damage
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Survival
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
XP
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Kills
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Spots
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Accuracy
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Shots
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Hits
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Damage ratio
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Damage received
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Capture points
</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell width="0" justify="center">
Dropped capture points
</Table.ColumnHeaderCell>
</Table.Row>
</Table.Header>
<Header />
<Table.Body>
{tankAverages.map((averages) => {
const tank = awaitedTankDefinitions[averages.id];
return <TankRow tank={tank} key={tank.id} />;
})}
</Table.Body>
<Suspense fallback={<BodyLoader />}>
<Tanks />
</Suspense>
</Table.Root>
</Flex>
</PageWrapper>
+1 -1
View File
@@ -11,7 +11,7 @@ interface TankRowHeaderCellProps {
export function TankRowHeaderCell({ tank }: TankRowHeaderCellProps) {
return (
<Table.RowHeaderCell style={{ display: 'flex' }}>
<Link href={`/tools/tankopedia/${tank.id}`}>
<Link href={`/tools/tankopedia/${tank.id}`} tabIndex={-1}>
<img
alt={tank.name}
draggable={false}
+5 -1
View File
@@ -1,8 +1,12 @@
import { Root } from 'protobufjs';
import { context } from '../blitzkit/context';
export async function lookup(proto: string) {
const name = proto.split('.')[0];
const root = await new Root().load(
`src/protos/${proto.split('.')[0]}.proto`,
context === 'server'
? `public/protos/${name}.proto`
: `/protos/${name}.proto`,
{ keepCase: true },
);