feat: more layout

This commit is contained in:
TrèsAbhi committed 2024-06-12 14:35:10 -05:00
1 parent c900af6e33
commit 9d0abdb135
4 files changed
+265 -218

No files matched your search

@@ -1,11 +0,0 @@
import { style } from '@vanilla-extract/css';
export const bkniIndicator = style({
scale: 0.8,
'@media': {
'screen and (min-width: 1024px)': {
scale: 1,
},
},
});
+205 -95
View File
@@ -1,24 +1,31 @@
'use client'; 'use client';
import { TimerIcon } from '@radix-ui/react-icons';
import { import {
Box, Box,
Button,
Flex, Flex,
Heading, Heading,
Link, Link,
Popover, Popover,
SegmentedControl,
Text, Text,
Theme, Theme,
} from '@radix-ui/themes'; } from '@radix-ui/themes';
import { useState } from 'react'; import { useState } from 'react';
import { BkniIndicator } from '../../../../components/BkniIndicator';
import { DatePicker } from '../../../../components/DatePicker'; import { DatePicker } from '../../../../components/DatePicker';
import { Speedometer } from '../../../../components/Speedometer';
import { getAccountInfo } from '../../../../core/blitz/getAccountInfo'; import { getAccountInfo } from '../../../../core/blitz/getAccountInfo';
import { getClanAccountInfo } from '../../../../core/blitz/getClanAccountInfo'; import { getClanAccountInfo } from '../../../../core/blitz/getClanAccountInfo';
import { idToRegion } from '../../../../core/blitz/idToRegion'; import { idToRegion } from '../../../../core/blitz/idToRegion';
import { parseBkni } from '../../../../core/blitzkit/parseBkni'; import { parseBkni } from '../../../../core/blitzkit/parseBkni';
import { PeriodType } from '../../../../core/discord/addPeriodSubCommands';
import {
BKNI_COLORS,
BKNI_PERCENTILES,
} from '../../../../core/statistics/getBkniPercentile';
import { useAwait } from '../../../../hooks/useAwait'; import { useAwait } from '../../../../hooks/useAwait';
import strings from '../../../../lang/en-US.json'; import strings from '../../../../lang/en-US.json';
import * as styles from './page.css';
export default function Page({ params }: { params: { id: string } }) { export default function Page({ params }: { params: { id: string } }) {
const id = parseInt(params.id); const id = parseInt(params.id);
@@ -26,18 +33,18 @@ export default function Page({ params }: { params: { id: string } }) {
const accountInfo = useAwait(getAccountInfo(region, id)); const accountInfo = useAwait(getAccountInfo(region, id));
const clanAccountInfo = useAwait(getClanAccountInfo(region, id, ['clan'])); const clanAccountInfo = useAwait(getClanAccountInfo(region, id, ['clan']));
// const bkni = ((Math.round(Date.now() / 1000 / 60) / 100) % 2) - 1; // const bkni = ((Math.round(Date.now() / 1000 / 60) / 100) % 2) - 1;
const bkni = 2 * Math.random() - 1; const bkni = 0.81;
const [period, setPeriod] = useState<'custom' | number>(30); const winrate = 0.6;
const { bkniColor } = parseBkni(bkni); const [period, setPeriod] = useState<PeriodType>('30');
const isTracking = false; const { bkniColor, bkniMetric, bkniFraction, bkniPercentile } =
parseBkni(bkni);
const [customFrom, setCustomFrom] = useState<Date>( const [customFrom, setCustomFrom] = useState<Date>(
new Date(Date.now() - 29 * 24 * 60 * 60 * 1000), new Date(Date.now() - 29 * 24 * 60 * 60 * 1000),
); );
const stats = [ const stats = [
['Winrate', '70%'],
['Survival', '70%'],
['Damage', '3,203'], ['Damage', '3,203'],
['Tier', '9.83'], ['Tier', '9.83'],
['Survival', '70%'],
['Kills', '1.54'], ['Kills', '1.54'],
['Damage ratio', '2.45'], ['Damage ratio', '2.45'],
['Accuracy', '91%'], ['Accuracy', '91%'],
@@ -52,110 +59,213 @@ export default function Page({ params }: { params: { id: string } }) {
<Flex <Flex
direction="column" direction="column"
align="center" align="center"
p="8" justify="center"
gap="8" py="8"
gap="6"
style={{ style={{
background: `linear-gradient(var(--${bkniColor}-a2), var(--${bkniColor}-a1))`, background: `linear-gradient(var(--${bkniColor}-a3), var(--${bkniColor}-a1))`,
}} }}
> >
<Flex width="100%" maxWidth="1600px" align="center"> <Flex direction="column" align="center">
<Flex style={{ flex: 1 }} direction="column" align="start" gap="4"> <Heading
<Heading size="9">{accountInfo.nickname}</Heading> size={{
initial: '8',
<Text color="gray"> sm: '9',
{clanAccountInfo?.clan && `[${clanAccountInfo.clan.tag}] • `} }}
{ align="center"
(clanAccountInfo?.clan >
? strings.common.regions.short {accountInfo.nickname}
: strings.common.regions.normal)[region] </Heading>
} <Text color="gray" align="center">
</Text> {clanAccountInfo?.clan && `[${clanAccountInfo.clan.tag}] • `}
{
{/* <Flex gap="4" mt="-1"> (clanAccountInfo?.clan
<Link href="/tools/tankopedia"> ? strings.common.regions.short
<Button variant="ghost" size="1" ml="-1"> : strings.common.regions.normal)[region]
<ChevronLeftIcon /> }
Back </Text>
</Button>
</Link>
</Flex> */}
</Flex>
<Flex style={{ flex: 1 }} justify="center">
<BkniIndicator bkni={bkni} className={styles.bkniIndicator} />
</Flex>
<Flex style={{ flex: 1 }} wrap="wrap" gap="2" justify="center">
{stats.map((stat) => (
<Flex minWidth="96px" direction="column" align="center">
<Text size="7">{stat[1]}</Text>
<Text color="gray" size="2">
{stat[0]}
</Text>
</Flex>
))}
</Flex>
</Flex> </Flex>
{period === 'custom' && ( <Flex direction="column" align="center" gap="3">
<Text> <SegmentedControl.Root
From{' '} value={period}
<Popover.Root onValueChange={(value) => setPeriod(value as PeriodType)}
open={fromSelectorOpen} >
onOpenChange={setFromSelectorOpen} <SegmentedControl.Item value={'today' satisfies PeriodType}>
> Today
</SegmentedControl.Item>
<SegmentedControl.Item value={'30' satisfies PeriodType}>
30 days
</SegmentedControl.Item>
<SegmentedControl.Item value={'career' satisfies PeriodType}>
Career
</SegmentedControl.Item>
<SegmentedControl.Item value={'custom' satisfies PeriodType}>
Custom
</SegmentedControl.Item>
</SegmentedControl.Root>
{period === 'custom' && (
<Text>
From{' '}
<Popover.Root
open={fromSelectorOpen}
onOpenChange={setFromSelectorOpen}
>
<Popover.Trigger>
<Link underline="always" href="#">
{customFrom.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
})}
</Link>
</Popover.Trigger>
<Popover.Content>
<DatePicker
defaultDate={customFrom}
onDateChange={(date) => {
setCustomFrom(date);
setFromSelectorOpen(false);
}}
/>
</Popover.Content>
</Popover.Root>{' '}
to{' '}
<Popover.Root
open={toSelectorOpen}
onOpenChange={setToSelectorOpen}
>
<Popover.Trigger>
<Link underline="always" href="#">
{customTo.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
})}
</Link>
</Popover.Trigger>
<Popover.Content>
<DatePicker
defaultDate={customTo}
onDateChange={(date) => {
setCustomTo(date);
setToSelectorOpen(false);
}}
/>
</Popover.Content>
</Popover.Root>
</Text>
)}
</Flex>
</Flex>
<Flex justify="center" py="8" gap="6">
<Speedometer
value={`${bkniMetric}`}
color={bkniColor}
fill={bkniFraction}
label={
<Popover.Root>
<Popover.Trigger> <Popover.Trigger>
<Link underline="always" href="#"> <Button
{customFrom.toLocaleString(undefined, { style={{ position: 'relative' }}
month: 'short', color="gray"
day: 'numeric', size="2"
year: 'numeric', variant="ghost"
})} >
</Link> <TimerIcon />
{strings.common.bkni_percentile[bkniPercentile]}
</Button>
</Popover.Trigger> </Popover.Trigger>
<Popover.Content> <Popover.Content align="center">
<DatePicker <Flex
defaultDate={customFrom} direction="column"
onDateChange={(date) => { style={{
setCustomFrom(date); width: 'fit-content',
setFromSelectorOpen(false);
}} }}
/> >
</Popover.Content> <Flex direction="column" mb="3" align="center">
</Popover.Root>{' '} <Heading weight="bold" size="5">
to{' '} BkNI
<Popover.Root </Heading>
open={toSelectorOpen} <Text size="2" color="gray" wrap="wrap">
onOpenChange={setToSelectorOpen} A next generation performance metric
> </Text>
<Popover.Trigger> </Flex>
<Link underline="always" href="#">
{customTo.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
})}
</Link>
</Popover.Trigger>
<Popover.Content> {BKNI_PERCENTILES.map(({ percentile, min }, index) => (
<DatePicker <Button
defaultDate={customTo} radius="none"
onDateChange={(date) => { color={BKNI_COLORS[percentile]}
setCustomTo(date); key={percentile}
setToSelectorOpen(false); >
}} <Flex
/> align="center"
justify="between"
width="100%"
gap="2"
>
<Text>
{strings.common.bkni_percentile[percentile]}
</Text>
<Text size="1">
{min} - {BKNI_PERCENTILES[index + 1]?.min ?? 200}
</Text>
</Flex>
</Button>
))}
</Flex>
</Popover.Content> </Popover.Content>
</Popover.Root> </Popover.Root>
</Text> }
)} />
<Speedometer
value={
<Flex align="center" gap="1">
{(winrate * 100).toFixed(0)}
<Text size="3" color="gray">
%
</Text>
</Flex>
}
color="green"
fill={0.5 * (Math.cbrt(2 * winrate - 1) + 1)}
label={<Text color="gray">Winrate</Text>}
/>
</Flex>
<Flex style={{ flex: 1 }} wrap="wrap" gap="2" justify="center">
{stats.map((stat) => (
<Flex minWidth="96px" direction="column" align="center">
<Text size="6">{stat[1]}</Text>
<Text color="gray" size="2">
{stat[0]}
</Text>
</Flex>
))}
</Flex> </Flex>
</Theme> </Theme>
<Box flexGrow="1" /> <Box flexGrow="1" />
{/* <Flex gap="4">
<Link href="/tools/tankopedia">
<Button variant="ghost" size="1" ml="-1">
<ChevronLeftIcon />
Back
</Button>
</Link>
</Flex> */}
{/* <Flex style={{ flex: 1 }} justify="center">
</Flex>
*/}
{/* <PageWrapper {/* <PageWrapper
p="6" p="6"
pt="9" pt="9"
-112
View File
@@ -1,112 +0,0 @@
import { TimerIcon } from '@radix-ui/react-icons';
import {
Button,
Flex,
FlexProps,
Heading,
Popover,
Text,
} from '@radix-ui/themes';
import { parseBkni } from '../core/blitzkit/parseBkni';
import {
BKNI_COLORS,
BKNI_PERCENTILES,
} from '../core/statistics/getBkniPercentile';
import strings from '../lang/en-US.json';
type BkniIndicatorProps = FlexProps & {
bkni: number;
};
export function BkniIndicator({ bkni, ...props }: BkniIndicatorProps) {
const { bkniColor, bkniFraction, bkniMetric, bkniPercentile } =
parseBkni(bkni);
return (
<Flex direction="column" align="center" {...props}>
<svg
width={180}
height={100}
style={{
transform: 'scaleX(-1)',
}}
>
<circle
cx={90}
cy={90}
r={80}
strokeLinecap="round"
fill="none"
stroke="var(--color-surface)"
strokeWidth={20}
strokeDasharray={80 * Math.PI}
strokeDashoffset={80 * Math.PI}
/>
<circle
cx={90}
cy={90}
r={80}
strokeLinecap="round"
fill="none"
stroke={`var(--${bkniColor}-indicator)`}
strokeWidth={20}
strokeDasharray={(160 - 80 * bkniFraction) * Math.PI}
strokeDashoffset={(160 - 80 * bkniFraction) * Math.PI}
/>
</svg>
<Flex direction="column" align="center" mt="-8">
<Text weight="bold" size="8">
{bkniMetric}
</Text>
<Popover.Root>
<Popover.Trigger>
<Button
style={{ position: 'relative' }}
color="gray"
size="2"
variant="ghost"
>
<TimerIcon />
{strings.common.bkni_percentile[bkniPercentile]}
</Button>
</Popover.Trigger>
<Popover.Content align="center">
<Flex
direction="column"
style={{
width: 'fit-content',
}}
>
<Flex direction="column" mb="3" align="center">
<Heading weight="bold" size="5">
BkNI
</Heading>
<Text size="2" color="gray" wrap="wrap">
A next generation performance metric
</Text>
</Flex>
{BKNI_PERCENTILES.map(({ percentile, min }, index) => (
<Button
radius="none"
color={BKNI_COLORS[percentile]}
key={percentile}
>
<Flex align="center" justify="between" width="100%" gap="2">
<Text>{strings.common.bkni_percentile[percentile]}</Text>
<Text size="1">
{min} - {BKNI_PERCENTILES[index + 1]?.min ?? 200}
</Text>
</Flex>
</Button>
))}
</Flex>
</Popover.Content>
</Popover.Root>
</Flex>
</Flex>
);
}
+60
View File
@@ -0,0 +1,60 @@
import { Flex, FlexProps, Text } from '@radix-ui/themes';
import { ReactNode } from 'react';
type SpeedometerProps = FlexProps & {
value: ReactNode;
color: string;
fill: number;
label: ReactNode;
};
export function Speedometer({
value,
color,
fill,
label,
...props
}: SpeedometerProps) {
return (
<Flex direction="column" align="center" {...props}>
<svg
width={180}
height={98}
style={{
transform: 'scaleX(-1)',
}}
>
<circle
cx={90}
cy={90}
r={80}
strokeLinecap="round"
fill="none"
stroke={`var(--${color}-3)`}
strokeWidth={16}
strokeDasharray={80 * Math.PI}
strokeDashoffset={80 * Math.PI}
/>
<circle
cx={90}
cy={90}
r={80}
strokeLinecap="round"
fill="none"
stroke={`var(--${color}-indicator)`}
strokeWidth={16}
strokeDasharray={(160 - 80 * fill) * Math.PI}
strokeDashoffset={(160 - 80 * fill) * Math.PI}
/>
</svg>
<Flex direction="column" align="center" mt="-8">
<Text weight="bold" size="8" mt="-1">
{value}
</Text>
{label}
</Flex>
</Flex>
);
}