mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: migrate session
This commit is contained in:
1 parent
8d51ce2bea
commit
e234b29e16
5 files changed
+51
-89
No files matched your search
Vendored
-1
@@ -13,7 +13,6 @@
|
|||||||
"artefacts",
|
"artefacts",
|
||||||
"astrojs",
|
"astrojs",
|
||||||
"atgm",
|
"atgm",
|
||||||
"Avearges",
|
|
||||||
"AYUV",
|
"AYUV",
|
||||||
"battleresults",
|
"battleresults",
|
||||||
"bbox",
|
"bbox",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"include": [
|
"include": [
|
||||||
"src/**/*",
|
"src/**/*",
|
||||||
".next/types/**/*.ts",
|
".next/types/**/*.ts",
|
||||||
"../website/src/components/Performance/PerformanceInfo.tsx"
|
"../website/src/components/Performance/PerformanceInfo.tsx",
|
||||||
|
"../website/src/pages/tools/session/index.tsx"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
import { Page } from '.';
|
||||||
|
import ToolLayout from '../../../layouts/ToolLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<ToolLayout>
|
||||||
|
<Page client:load />
|
||||||
|
</ToolLayout>
|
||||||
+37
-82
@@ -1,12 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
AccountListWithServer,
|
|
||||||
IndividualAccountInfo,
|
|
||||||
IndividualTankStats,
|
|
||||||
STAT_KEYS,
|
STAT_KEYS,
|
||||||
STAT_NAMES,
|
STAT_NAMES,
|
||||||
Stat,
|
|
||||||
UNLOCALIZED_REGION_NAMES_SHORT,
|
UNLOCALIZED_REGION_NAMES_SHORT,
|
||||||
deltaTankStats,
|
deltaTankStats,
|
||||||
|
fetchAverageDefinitions,
|
||||||
fetchTankDefinitions,
|
fetchTankDefinitions,
|
||||||
generateStats,
|
generateStats,
|
||||||
getAccountInfo,
|
getAccountInfo,
|
||||||
@@ -15,6 +12,10 @@ import {
|
|||||||
prettifyStats,
|
prettifyStats,
|
||||||
searchPlayersAcrossRegions,
|
searchPlayersAcrossRegions,
|
||||||
sumBlitzStarsStats,
|
sumBlitzStarsStats,
|
||||||
|
type AccountListWithServer,
|
||||||
|
type IndividualAccountInfo,
|
||||||
|
type IndividualTankStats,
|
||||||
|
type Stat,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
import {
|
import {
|
||||||
ArrowDownIcon,
|
ArrowDownIcon,
|
||||||
@@ -29,22 +30,29 @@ import {
|
|||||||
Heading,
|
Heading,
|
||||||
IconButton,
|
IconButton,
|
||||||
Select,
|
Select,
|
||||||
Spinner,
|
|
||||||
Table,
|
Table,
|
||||||
Text,
|
Text,
|
||||||
TextField,
|
TextField,
|
||||||
} from '@radix-ui/themes';
|
} from '@radix-ui/themes';
|
||||||
import { debounce } from 'lodash-es';
|
import { debounce } from 'lodash-es';
|
||||||
import { use, useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import usePromise from 'react-promise-suspense';
|
||||||
|
import { PageWrapper } from '../../../components/PageWrapper';
|
||||||
|
import { TankRowHeaderCell } from '../../../components/TankRowHeaderCell';
|
||||||
|
import { Session, type SessionTracking } from '../../../stores/session';
|
||||||
|
|
||||||
const awaitedTankDefinitions = await fetchTankDefinitions();
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
|
const tankAverages = await fetchAverageDefinitions();
|
||||||
|
|
||||||
export default function Page({
|
export function Page() {
|
||||||
searchParams,
|
return (
|
||||||
}: {
|
<Session.Provider>
|
||||||
searchParams: { id?: string };
|
<Content />
|
||||||
}) {
|
</Session.Provider>
|
||||||
const [loaded, setLoaded] = useState(false);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Content() {
|
||||||
const [showSearch, setShowSearch] = useState(false);
|
const [showSearch, setShowSearch] = useState(false);
|
||||||
const [searching, setSearching] = useState(false);
|
const [searching, setSearching] = useState(false);
|
||||||
const [searchResults, setSearchResults] = useState<AccountListWithServer>([]);
|
const [searchResults, setSearchResults] = useState<AccountListWithServer>([]);
|
||||||
@@ -56,27 +64,26 @@ export default function Page({
|
|||||||
const [tankStatsB, setTankStatsB] = useState<IndividualTankStats[] | null>(
|
const [tankStatsB, setTankStatsB] = useState<IndividualTankStats[] | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
const accountInfoPromise = useMemo(
|
const accountInfo = usePromise(
|
||||||
() =>
|
(id?: number) =>
|
||||||
new Promise<IndividualAccountInfo | null>(async (resolve) => {
|
new Promise<IndividualAccountInfo | null>(async (resolve) => {
|
||||||
|
if (!id) return resolve(null);
|
||||||
|
|
||||||
resolve(
|
resolve(
|
||||||
session.tracking
|
session.tracking ? await getAccountInfo(idToRegion(id), id) : null,
|
||||||
? await getAccountInfo(session.player.region, session.player.id)
|
|
||||||
: null,
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
[session.tracking && session.player.id],
|
[session.tracking ? session.player.id : undefined],
|
||||||
);
|
);
|
||||||
const accountInfo = use(accountInfoPromise);
|
|
||||||
const delta = useMemo(
|
const delta = useMemo(
|
||||||
() =>
|
() =>
|
||||||
session.tracking && tankStatsB
|
session.tracking && tankStatsB
|
||||||
? deltaTankStats(session.player.stats, tankStatsB)
|
? deltaTankStats(session.player.stats, tankStatsB)
|
||||||
.sort((a, b) => b.last_battle_time - a.last_battle_time)
|
.sort((a, b) => b.last_battle_time - a.last_battle_time)
|
||||||
.map((entry) => {
|
.map((entry) => {
|
||||||
const tank = awaitedTankDefinitions[entry.tank_id];
|
const tank = tankDefinitions.tanks[entry.tank_id];
|
||||||
const average = awaitedTankAvearges[tank.id];
|
const average = tankAverages.averages[tank.id];
|
||||||
const stats = generateStats(entry.all, average?.all);
|
const stats = generateStats(entry.all, average.mu);
|
||||||
const statsPretty = prettifyStats(stats);
|
const statsPretty = prettifyStats(stats);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -119,7 +126,7 @@ export default function Page({
|
|||||||
if (!input.current) return;
|
if (!input.current) return;
|
||||||
|
|
||||||
draft.tracking = true;
|
draft.tracking = true;
|
||||||
(draft as Session.SessionTracking).player = {
|
(draft as SessionTracking).player = {
|
||||||
id,
|
id,
|
||||||
region,
|
region,
|
||||||
since: Date.now(),
|
since: Date.now(),
|
||||||
@@ -147,22 +154,6 @@ export default function Page({
|
|||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [session.tracking && session.player.id]);
|
}, [session.tracking && session.player.id]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setLoaded(true);
|
|
||||||
|
|
||||||
if (searchParams.id && !session.tracking) {
|
|
||||||
track(Number(searchParams.id));
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (!loaded) {
|
|
||||||
return (
|
|
||||||
<PageWrapper align="center" justify="center">
|
|
||||||
<Spinner />
|
|
||||||
</PageWrapper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper color="blue">
|
<PageWrapper color="blue">
|
||||||
<AlertDialog.Root
|
<AlertDialog.Root
|
||||||
@@ -187,39 +178,6 @@ export default function Page({
|
|||||||
</AlertDialog.Content>
|
</AlertDialog.Content>
|
||||||
</AlertDialog.Root>
|
</AlertDialog.Root>
|
||||||
|
|
||||||
{searchParams.id &&
|
|
||||||
session.tracking &&
|
|
||||||
Number(searchParams.id) !== session.player.id && (
|
|
||||||
<AlertDialog.Root
|
|
||||||
open={showLinkOverridePrompt}
|
|
||||||
onOpenChange={setShowLinkOverridePrompt}
|
|
||||||
>
|
|
||||||
<AlertDialog.Content>
|
|
||||||
<AlertDialog.Title>
|
|
||||||
You are currently tracking {accountInfo?.nickname}
|
|
||||||
</AlertDialog.Title>
|
|
||||||
<AlertDialog.Description>
|
|
||||||
Would you like to stop tracking {accountInfo?.nickname} and
|
|
||||||
start tracking a new player?
|
|
||||||
</AlertDialog.Description>
|
|
||||||
|
|
||||||
<Flex mt="4" justify="end">
|
|
||||||
<AlertDialog.Action>
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
onClick={() => {
|
|
||||||
setShowLinkOverridePrompt(false);
|
|
||||||
track(Number(searchParams.id));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Proceed
|
|
||||||
</Button>
|
|
||||||
</AlertDialog.Action>
|
|
||||||
</Flex>
|
|
||||||
</AlertDialog.Content>
|
|
||||||
</AlertDialog.Root>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!session.tracking && (
|
{!session.tracking && (
|
||||||
<Flex
|
<Flex
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
@@ -325,7 +283,7 @@ export default function Page({
|
|||||||
}
|
}
|
||||||
|
|
||||||
mutateSession((draft) => {
|
mutateSession((draft) => {
|
||||||
(draft as Session.SessionTracking).player.stats = stats;
|
(draft as SessionTracking).player.stats = stats;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -383,9 +341,9 @@ export default function Page({
|
|||||||
key={key}
|
key={key}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
mutateSession((draft) => {
|
mutateSession((draft) => {
|
||||||
(
|
(draft as SessionTracking).columns.unshift(
|
||||||
draft as Session.SessionTracking
|
key as Stat,
|
||||||
).columns.unshift(key as Stat);
|
);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -401,12 +359,9 @@ export default function Page({
|
|||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
mutateSession((draft) => {
|
mutateSession((draft) => {
|
||||||
if (value === 'remove') {
|
if (value === 'remove') {
|
||||||
(draft as Session.SessionTracking).columns.splice(
|
(draft as SessionTracking).columns.splice(index, 1);
|
||||||
index,
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
(draft as Session.SessionTracking).columns[index] =
|
(draft as SessionTracking).columns[index] =
|
||||||
value as Stat;
|
value as Stat;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IndividualTankStats, Region, Stat } from '@blitzkit/core';
|
import type { IndividualTankStats, Region, Stat } from '@blitzkit/core';
|
||||||
import lodash from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { persist } from 'zustand/middleware';
|
import { persist } from 'zustand/middleware';
|
||||||
import { createContextualStore } from '../core/zustand/createContextualStore';
|
import { createContextualStore } from '../core/zustand/createContextualStore';
|
||||||
@@ -24,15 +24,14 @@ interface SessionNotTracking extends SessionBase {
|
|||||||
|
|
||||||
type Session = SessionTracking | SessionNotTracking;
|
type Session = SessionTracking | SessionNotTracking;
|
||||||
|
|
||||||
export const { Provider, use, useMutation, useStore } = createContextualStore(
|
export const Session = createContextualStore(() =>
|
||||||
() =>
|
|
||||||
create<Session>()(
|
create<Session>()(
|
||||||
persist(
|
persist(
|
||||||
(set) => ({
|
(set) => ({
|
||||||
columns: ['battles', 'winrate', 'wn8', 'averageDamage'],
|
columns: ['battles', 'winrate', 'wn8', 'averageDamage'],
|
||||||
tracking: false,
|
tracking: false,
|
||||||
}),
|
}),
|
||||||
{ name: 'session-2', merge: (a, b) => lodash.merge(b, a) },
|
{ name: 'session-2', merge: (a, b) => merge(b, a) },
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
Reference in new issue
Block a user