mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-25 03:29:51 +01:00
feat: added options
This commit is contained in:
1 parent
8264f19ad4
commit
7f431b07e1
7 files changed
+305
-142
No files matched your search
@@ -37,6 +37,7 @@
|
|||||||
"esbuild": "^0.19.3",
|
"esbuild": "^0.19.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"fuzzysort": "^2.0.4",
|
"fuzzysort": "^2.0.4",
|
||||||
|
"immer": "^10.0.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-escape": "^2.0.0",
|
"markdown-escape": "^2.0.0",
|
||||||
"next": "^13.5.2",
|
"next": "^13.5.2",
|
||||||
|
|||||||
+156
-122
@@ -12,6 +12,7 @@ import { TankopediaEntry, tankopedia } from '../../../core/blitz/tankopedia';
|
|||||||
import { tankAverages } from '../../../core/blitzstars/tankAverages';
|
import { tankAverages } from '../../../core/blitzstars/tankAverages';
|
||||||
import { useSession } from '../../../stores/session';
|
import { useSession } from '../../../stores/session';
|
||||||
import { IndividualTankStats, TanksStats } from '../../../types/tanksStats';
|
import { IndividualTankStats, TanksStats } from '../../../types/tanksStats';
|
||||||
|
import { CustomColumnDisplay } from '../../tools/session/components/CustomColumn';
|
||||||
|
|
||||||
const REFRESH_RATE = 1 / 5;
|
const REFRESH_RATE = 1 / 5;
|
||||||
|
|
||||||
@@ -139,136 +140,169 @@ export default function SessionPage() {
|
|||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [session]);
|
}, [session]);
|
||||||
|
|
||||||
|
const totalRowStats: Record<
|
||||||
|
CustomColumnDisplay,
|
||||||
|
Breakdown.RowStat | undefined
|
||||||
|
> = {
|
||||||
|
battles: {
|
||||||
|
title: 'Battles',
|
||||||
|
current: sessionBattles?.toLocaleString(),
|
||||||
|
career: tankStatsArray
|
||||||
|
.reduce((accumulator, stats) => accumulator + stats.all.battles, 0)
|
||||||
|
.toLocaleString(),
|
||||||
|
},
|
||||||
|
winrate: {
|
||||||
|
title: 'Winrate',
|
||||||
|
current: sessionBattles ? `${(100 * sessionWinrate).toFixed(2)}%` : '--',
|
||||||
|
career: `${(100 * careerWinrate).toFixed(2)}%`,
|
||||||
|
delta: sessionBattles === 0 ? 0 : sessionWinrate - careerWinrate,
|
||||||
|
},
|
||||||
|
wn8: (() => {
|
||||||
|
if (!diff) return undefined;
|
||||||
|
|
||||||
|
const battlesWithWN8 = diff.list.reduce(
|
||||||
|
(accumulator, { currentWN8, stats }) =>
|
||||||
|
(currentWN8 === undefined ? 0 : stats.all.battles) + accumulator,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
const currentWN8 =
|
||||||
|
diff.list.reduce(
|
||||||
|
(accumulator, { currentWN8, stats }) =>
|
||||||
|
stats.all.battles * (currentWN8 ?? 0) + accumulator,
|
||||||
|
0,
|
||||||
|
) / battlesWithWN8!;
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: 'WN8',
|
||||||
|
current: battlesWithWN8
|
||||||
|
? Math.round(currentWN8!).toLocaleString()
|
||||||
|
: '--',
|
||||||
|
percentile: battlesWithWN8 ? getWN8Percentile(currentWN8!) : undefined,
|
||||||
|
career: Math.round(diff.careerWN8).toLocaleString(),
|
||||||
|
};
|
||||||
|
})(),
|
||||||
|
damage: {
|
||||||
|
title: 'Damage',
|
||||||
|
delta: sessionBattles === 0 ? 0 : currentDamage - careerDamage,
|
||||||
|
current: sessionBattles
|
||||||
|
? Math.round(currentDamage).toLocaleString()
|
||||||
|
: '--',
|
||||||
|
career: Math.round(careerDamage).toLocaleString(),
|
||||||
|
},
|
||||||
|
none: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Breakdown.Root>
|
<Breakdown.Root>
|
||||||
{session.isTracking && since !== undefined && diff !== undefined && (
|
{session.showTotal &&
|
||||||
<Breakdown.Row
|
session.isTracking &&
|
||||||
title={`Since ${since.toLocaleString(undefined, {
|
since !== undefined &&
|
||||||
hour: 'numeric',
|
diff !== undefined && (
|
||||||
minute: 'numeric',
|
<Breakdown.Row
|
||||||
hour12: true,
|
title={`Since ${since.toLocaleString(undefined, {
|
||||||
month: 'short',
|
hour: 'numeric',
|
||||||
year: 'numeric',
|
minute: 'numeric',
|
||||||
day: 'numeric',
|
hour12: true,
|
||||||
})}`}
|
month: 'short',
|
||||||
stats={[
|
year: 'numeric',
|
||||||
{
|
day: 'numeric',
|
||||||
title: 'Battles',
|
})}`}
|
||||||
current: sessionBattles!.toLocaleString(),
|
stats={session.customColumns.map((customColumn) => {
|
||||||
career: tankStatsArray
|
const rowStat = totalRowStats[customColumn.display];
|
||||||
.reduce(
|
|
||||||
(accumulator, stats) => accumulator + stats.all.battles,
|
if (!rowStat) return undefined;
|
||||||
0,
|
|
||||||
)
|
|
||||||
.toLocaleString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Winrate',
|
|
||||||
current: sessionBattles
|
|
||||||
? `${(100 * sessionWinrate).toFixed(2)}%`
|
|
||||||
: '--',
|
|
||||||
career: `${(100 * careerWinrate).toFixed(2)}%`,
|
|
||||||
delta: sessionBattles === 0 ? 0 : sessionWinrate - careerWinrate,
|
|
||||||
},
|
|
||||||
(() => {
|
|
||||||
const battlesWithWN8 = diff.list.reduce(
|
|
||||||
(accumulator, { currentWN8, stats }) =>
|
|
||||||
(currentWN8 === undefined ? 0 : stats.all.battles) +
|
|
||||||
accumulator,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
const currentWN8 =
|
|
||||||
diff.list.reduce(
|
|
||||||
(accumulator, { currentWN8, stats }) =>
|
|
||||||
stats.all.battles * (currentWN8 ?? 0) + accumulator,
|
|
||||||
0,
|
|
||||||
) / battlesWithWN8;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: 'WN8',
|
...rowStat,
|
||||||
current: battlesWithWN8
|
delta:
|
||||||
? Math.round(currentWN8).toLocaleString()
|
customColumn.showDelta && rowStat.percentile === undefined
|
||||||
: '--',
|
? rowStat.delta
|
||||||
percentile: battlesWithWN8
|
: undefined,
|
||||||
? getWN8Percentile(currentWN8)
|
|
||||||
: undefined,
|
|
||||||
career: Math.round(diff.careerWN8).toLocaleString(),
|
|
||||||
};
|
};
|
||||||
})(),
|
})}
|
||||||
{
|
/>
|
||||||
title: 'Damage',
|
)}
|
||||||
delta: sessionBattles === 0 ? 0 : currentDamage - careerDamage,
|
|
||||||
current: sessionBattles
|
|
||||||
? Math.round(currentDamage).toLocaleString()
|
|
||||||
: '--',
|
|
||||||
career: Math.round(careerDamage).toLocaleString(),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{diff?.list
|
{diff?.list
|
||||||
.sort((a, b) => b.stats.last_battle_time - a.stats.last_battle_time)
|
.sort((a, b) => b.stats.last_battle_time - a.stats.last_battle_time)
|
||||||
.map(({ stats, tankopedia, career, careerWN8, currentWN8 }) => (
|
.map(({ stats, tankopedia, career, careerWN8, currentWN8 }) => {
|
||||||
<Breakdown.Row
|
const rowStats: Record<
|
||||||
key={stats.tank_id}
|
CustomColumnDisplay,
|
||||||
title={tankopedia?.name ?? `Unknown tank ${stats.tank_id}`}
|
Breakdown.RowStat | undefined
|
||||||
type="tank"
|
> = {
|
||||||
tankType={tankopedia?.type}
|
battles: {
|
||||||
treeType={(() => {
|
title: 'Battles',
|
||||||
if (tankopedia?.is_collectible) return TreeTypeEnum.Collector;
|
current: stats.all.battles.toLocaleString(),
|
||||||
if (tankopedia?.is_premium) return TreeTypeEnum.Premium;
|
career: career.all.battles.toLocaleString(),
|
||||||
})()}
|
},
|
||||||
stats={[
|
winrate: {
|
||||||
{
|
title: 'Winrate',
|
||||||
title: 'Battles',
|
current: `${(100 * (stats.all.wins / stats.all.battles)).toFixed(
|
||||||
current: stats.all.battles.toLocaleString(),
|
2,
|
||||||
career: career.all.battles.toLocaleString(),
|
)}%`,
|
||||||
},
|
career: `${(100 * (career.all.wins / career.all.battles)).toFixed(
|
||||||
{
|
2,
|
||||||
title: 'Winrate',
|
)}%`,
|
||||||
current: `${(
|
delta:
|
||||||
100 *
|
stats.all.wins / stats.all.battles -
|
||||||
(stats.all.wins / stats.all.battles)
|
career.all.wins / career.all.battles,
|
||||||
).toFixed(2)}%`,
|
},
|
||||||
career: `${(
|
wn8: {
|
||||||
100 *
|
title: 'WN8',
|
||||||
(career.all.wins / career.all.battles)
|
current:
|
||||||
).toFixed(2)}%`,
|
currentWN8 === undefined
|
||||||
delta:
|
? undefined
|
||||||
stats.all.wins / stats.all.battles -
|
: Math.round(currentWN8).toLocaleString(),
|
||||||
career.all.wins / career.all.battles,
|
career:
|
||||||
},
|
careerWN8 === undefined
|
||||||
{
|
? undefined
|
||||||
title: 'WN8',
|
: Math.round(careerWN8).toLocaleString(),
|
||||||
current:
|
percentile:
|
||||||
currentWN8 === undefined
|
currentWN8 === undefined
|
||||||
? undefined
|
? undefined
|
||||||
: Math.round(currentWN8).toLocaleString(),
|
: getWN8Percentile(currentWN8),
|
||||||
career:
|
},
|
||||||
careerWN8 === undefined
|
damage: {
|
||||||
? undefined
|
title: 'Damage',
|
||||||
: Math.round(careerWN8).toLocaleString(),
|
current: Math.round(
|
||||||
percentile:
|
stats.all.damage_dealt / stats.all.battles,
|
||||||
currentWN8 === undefined
|
).toLocaleString(),
|
||||||
? undefined
|
career: Math.round(
|
||||||
: getWN8Percentile(currentWN8),
|
career.all.damage_dealt / career.all.battles,
|
||||||
},
|
).toLocaleString(),
|
||||||
{
|
delta:
|
||||||
title: 'Damage',
|
stats.all.damage_dealt / stats.all.battles -
|
||||||
current: Math.round(
|
career.all.damage_dealt / career.all.battles,
|
||||||
stats.all.damage_dealt / stats.all.battles,
|
},
|
||||||
).toLocaleString(),
|
none: undefined,
|
||||||
career: Math.round(
|
};
|
||||||
career.all.damage_dealt / career.all.battles,
|
|
||||||
).toLocaleString(),
|
return (
|
||||||
delta:
|
<Breakdown.Row
|
||||||
stats.all.damage_dealt / stats.all.battles -
|
key={stats.tank_id}
|
||||||
career.all.damage_dealt / career.all.battles,
|
title={tankopedia?.name ?? `Unknown tank ${stats.tank_id}`}
|
||||||
},
|
type="tank"
|
||||||
]}
|
tankType={tankopedia?.type}
|
||||||
/>
|
treeType={(() => {
|
||||||
))}
|
if (tankopedia?.is_collectible) return TreeTypeEnum.Collector;
|
||||||
|
if (tankopedia?.is_premium) return TreeTypeEnum.Premium;
|
||||||
|
})()}
|
||||||
|
stats={session.customColumns.map((customColumn) => {
|
||||||
|
const rowStat = rowStats[customColumn.display];
|
||||||
|
|
||||||
|
if (!rowStat) return undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rowStat,
|
||||||
|
delta:
|
||||||
|
customColumn.showDelta && rowStat.percentile === undefined
|
||||||
|
? rowStat.delta
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</Breakdown.Root>
|
</Breakdown.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import { DropdownMenu } from '@radix-ui/themes';
|
||||||
|
import mutateSession, { useSession } from '../../../../stores/session';
|
||||||
|
|
||||||
|
export type CustomColumnDisplay =
|
||||||
|
| 'battles'
|
||||||
|
| 'winrate'
|
||||||
|
| 'wn8'
|
||||||
|
| 'damage'
|
||||||
|
| 'none';
|
||||||
|
|
||||||
|
const NO_DELTA: CustomColumnDisplay[] = ['battles', 'wn8', 'none'];
|
||||||
|
|
||||||
|
interface CustomColumn {
|
||||||
|
column: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CustomColumn({ column }: CustomColumn) {
|
||||||
|
const customColumn = useSession((state) => state.customColumns[column]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu.Sub>
|
||||||
|
<DropdownMenu.SubTrigger>Column {column + 1}</DropdownMenu.SubTrigger>
|
||||||
|
|
||||||
|
<DropdownMenu.SubContent>
|
||||||
|
<DropdownMenu.Label>Display</DropdownMenu.Label>
|
||||||
|
|
||||||
|
<DropdownMenu.RadioGroup
|
||||||
|
value={customColumn.display}
|
||||||
|
onValueChange={(event) =>
|
||||||
|
mutateSession((draft) => {
|
||||||
|
draft.customColumns[column].display =
|
||||||
|
event as CustomColumnDisplay;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<DropdownMenu.RadioItem value="battles">
|
||||||
|
Battles
|
||||||
|
</DropdownMenu.RadioItem>
|
||||||
|
<DropdownMenu.RadioItem value="winrate">
|
||||||
|
Winrate
|
||||||
|
</DropdownMenu.RadioItem>
|
||||||
|
<DropdownMenu.RadioItem value="wn8">WN8</DropdownMenu.RadioItem>
|
||||||
|
<DropdownMenu.RadioItem value="damage">Damage</DropdownMenu.RadioItem>
|
||||||
|
<DropdownMenu.RadioItem value="none">None</DropdownMenu.RadioItem>
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
|
||||||
|
{!NO_DELTA.includes(customColumn.display) && (
|
||||||
|
<>
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
|
||||||
|
<DropdownMenu.CheckboxItem
|
||||||
|
checked={customColumn.showDelta}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
mutateSession((draft) => {
|
||||||
|
draft.customColumns[column].showDelta = checked;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Show delta
|
||||||
|
</DropdownMenu.CheckboxItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DropdownMenu.SubContent>
|
||||||
|
</DropdownMenu.Sub>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { CopyIcon, PersonIcon, ReloadIcon } from '@radix-ui/react-icons';
|
import {
|
||||||
|
CaretDownIcon,
|
||||||
|
CopyIcon,
|
||||||
|
PersonIcon,
|
||||||
|
ReloadIcon,
|
||||||
|
} from '@radix-ui/react-icons';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
Button,
|
Button,
|
||||||
@@ -23,10 +28,9 @@ import listPlayers, {
|
|||||||
import { useSession } from '../../../stores/session';
|
import { useSession } from '../../../stores/session';
|
||||||
import { NormalizedTankStats, TanksStats } from '../../../types/tanksStats';
|
import { NormalizedTankStats, TanksStats } from '../../../types/tanksStats';
|
||||||
import SessionPage from '../../embeds/session/page';
|
import SessionPage from '../../embeds/session/page';
|
||||||
|
import { CustomColumn } from './components/CustomColumn';
|
||||||
import * as styles from './page.css';
|
import * as styles from './page.css';
|
||||||
|
|
||||||
// 1 once per 5 seconds
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const input = useRef<HTMLInputElement>(null);
|
const input = useRef<HTMLInputElement>(null);
|
||||||
const [searchResults, setSearchResults] = useState<
|
const [searchResults, setSearchResults] = useState<
|
||||||
@@ -150,6 +154,7 @@ export default function Page() {
|
|||||||
<AlertDialog.Root>
|
<AlertDialog.Root>
|
||||||
<AlertDialog.Trigger>
|
<AlertDialog.Trigger>
|
||||||
<Button
|
<Button
|
||||||
|
variant="soft"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (!session.promptBeforeReset) {
|
if (!session.promptBeforeReset) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -206,6 +211,7 @@ export default function Page() {
|
|||||||
|
|
||||||
<Tooltip content="Copy to clipboard">
|
<Tooltip content="Copy to clipboard">
|
||||||
<Button
|
<Button
|
||||||
|
variant="soft"
|
||||||
className={styles.toolbarButton}
|
className={styles.toolbarButton}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigator.clipboard.writeText(
|
navigator.clipboard.writeText(
|
||||||
@@ -216,6 +222,33 @@ export default function Page() {
|
|||||||
<CopyIcon width="16" height="16" /> Embed
|
<CopyIcon width="16" height="16" /> Embed
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<Button variant="soft" className={styles.toolbarButton}>
|
||||||
|
Options
|
||||||
|
<CaretDownIcon />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
<CustomColumn column={0} />
|
||||||
|
<CustomColumn column={1} />
|
||||||
|
<CustomColumn column={2} />
|
||||||
|
<CustomColumn column={3} />
|
||||||
|
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
|
||||||
|
<DropdownMenu.CheckboxItem
|
||||||
|
checked={session.showTotal}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
useSession.setState({ showTotal: checked })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Show total
|
||||||
|
</DropdownMenu.CheckboxItem>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ import { theme } from '../../../stitches.config';
|
|||||||
import { TREE_TYPE_ICONS, TreeTypeEnum } from '../../Tanks';
|
import { TREE_TYPE_ICONS, TreeTypeEnum } from '../../Tanks';
|
||||||
import { RowStat } from './RowStat';
|
import { RowStat } from './RowStat';
|
||||||
|
|
||||||
|
export interface RowStat {
|
||||||
|
title: string;
|
||||||
|
current?: number | string;
|
||||||
|
career?: number | string;
|
||||||
|
delta?: number;
|
||||||
|
percentile?: Percentile;
|
||||||
|
}
|
||||||
|
|
||||||
interface RowProps {
|
interface RowProps {
|
||||||
type?: 'tank' | 'summary';
|
type?: 'tank' | 'summary';
|
||||||
title: string;
|
title: string;
|
||||||
@@ -11,13 +19,7 @@ interface RowProps {
|
|||||||
treeType?: TreeTypeEnum;
|
treeType?: TreeTypeEnum;
|
||||||
tankType?: TankType;
|
tankType?: TankType;
|
||||||
|
|
||||||
stats: {
|
stats: (RowStat | undefined)[];
|
||||||
title: string;
|
|
||||||
current?: number | string;
|
|
||||||
career?: number | string;
|
|
||||||
delta?: number;
|
|
||||||
percentile?: Percentile;
|
|
||||||
}[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Row(props: RowProps) {
|
export function Row(props: RowProps) {
|
||||||
@@ -77,16 +79,19 @@ export function Row(props: RowProps) {
|
|||||||
paddingBottom: 8,
|
paddingBottom: 8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.stats.map((row, index) => (
|
{props.stats.map(
|
||||||
<RowStat
|
(row, index) =>
|
||||||
minimized={props.minimized}
|
row && (
|
||||||
key={index}
|
<RowStat
|
||||||
name={`${row.title} • ${row.career ?? '--'}`}
|
minimized={props.minimized}
|
||||||
value={row.current ?? '--'}
|
key={index}
|
||||||
delta={row.delta}
|
name={`${row.title} • ${row.career ?? '--'}`}
|
||||||
percentile={row.percentile}
|
value={row.current ?? '--'}
|
||||||
/>
|
delta={row.delta}
|
||||||
))}
|
percentile={row.percentile}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
import { produce } from 'immer';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { devtools, persist } from 'zustand/middleware';
|
import { devtools, persist } from 'zustand/middleware';
|
||||||
|
import { CustomColumnDisplay } from '../app/tools/session/components/CustomColumn';
|
||||||
import { Region } from '../constants/regions';
|
import { Region } from '../constants/regions';
|
||||||
import { NormalizedTankStats } from '../types/tanksStats';
|
import { NormalizedTankStats } from '../types/tanksStats';
|
||||||
|
|
||||||
@@ -18,6 +20,11 @@ type Session = (
|
|||||||
}
|
}
|
||||||
) & {
|
) & {
|
||||||
promptBeforeReset: boolean;
|
promptBeforeReset: boolean;
|
||||||
|
customColumns: {
|
||||||
|
display: CustomColumnDisplay;
|
||||||
|
showDelta: boolean;
|
||||||
|
}[] & { length: 4 };
|
||||||
|
showTotal: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSession = create<Session>()(
|
export const useSession = create<Session>()(
|
||||||
@@ -26,6 +33,14 @@ export const useSession = create<Session>()(
|
|||||||
(set) => ({
|
(set) => ({
|
||||||
isTracking: false,
|
isTracking: false,
|
||||||
promptBeforeReset: true,
|
promptBeforeReset: true,
|
||||||
|
showTotal: true,
|
||||||
|
|
||||||
|
customColumns: [
|
||||||
|
{ display: 'battles', showDelta: false },
|
||||||
|
{ display: 'winrate', showDelta: true },
|
||||||
|
{ display: 'wn8', showDelta: false },
|
||||||
|
{ display: 'damage', showDelta: true },
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: 'session',
|
name: 'session',
|
||||||
@@ -33,3 +48,7 @@ export const useSession = create<Session>()(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export default function mutateSession(recipe: (draft: Session) => void) {
|
||||||
|
useSession.setState(produce(recipe));
|
||||||
|
}
|
||||||
@@ -3078,6 +3078,11 @@ ignore@^5.1.8, ignore@^5.2.4:
|
|||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
|
||||||
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
|
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
|
||||||
|
|
||||||
|
immer@^10.0.2:
|
||||||
|
version "10.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/immer/-/immer-10.0.2.tgz#11636c5b77acf529e059582d76faf338beb56141"
|
||||||
|
integrity sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==
|
||||||
|
|
||||||
indent-string@^4.0.0:
|
indent-string@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||||
|
|||||||
Reference in new issue
Block a user