mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: upgrade Session
This commit is contained in:
1 parent
6d24ed92d0
commit
b3a9f0889e
3 files changed
+57
-67
No files matched your search
@@ -23,7 +23,7 @@ export class Varuna<Type, Arguments = void> {
|
|||||||
private initialize(initial: Type) {
|
private initialize(initial: Type) {
|
||||||
let data = initial;
|
let data = initial;
|
||||||
|
|
||||||
if (this.persistence) {
|
if (this.persistence && typeof localStorage !== "undefined") {
|
||||||
const dehydrated = localStorage.getItem(this.persistence);
|
const dehydrated = localStorage.getItem(this.persistence);
|
||||||
|
|
||||||
if (dehydrated) {
|
if (dehydrated) {
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ import {
|
|||||||
idToRegion,
|
idToRegion,
|
||||||
searchPlayersAcrossRegions,
|
searchPlayersAcrossRegions,
|
||||||
sumCompositeStats,
|
sumCompositeStats,
|
||||||
} from '@blitzkit/core';
|
} from "@blitzkit/core";
|
||||||
import { literals } from '@blitzkit/i18n';
|
import { literals } from "@blitzkit/i18n";
|
||||||
import {
|
import {
|
||||||
ArrowDownIcon,
|
ArrowDownIcon,
|
||||||
MagnifyingGlassIcon,
|
MagnifyingGlassIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
} from '@radix-ui/react-icons';
|
} from "@radix-ui/react-icons";
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
Button,
|
Button,
|
||||||
@@ -30,21 +30,21 @@ import {
|
|||||||
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 { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { PageWrapper } from '../../../components/PageWrapper';
|
import { PageWrapper } from "../../../components/PageWrapper";
|
||||||
import { StickyRowHeaderCell } from '../../../components/StickyRowHeaderCell';
|
import { StickyRowHeaderCell } from "../../../components/StickyRowHeaderCell";
|
||||||
import { StickyTableRoot } from '../../../components/StickyTableRoot';
|
import { StickyTableRoot } from "../../../components/StickyTableRoot";
|
||||||
import { TankRowHeaderCell } from '../../../components/TankRowHeaderCell';
|
import { TankRowHeaderCell } from "../../../components/TankRowHeaderCell";
|
||||||
import { awaitableAverageDefinitions } from '../../../core/awaitables/averageDefinitions';
|
import { awaitableAverageDefinitions } from "../../../core/awaitables/averageDefinitions";
|
||||||
import { awaitableTankDefinitions } from '../../../core/awaitables/tankDefinitions';
|
import { awaitableTankDefinitions } from "../../../core/awaitables/tankDefinitions";
|
||||||
import {
|
import {
|
||||||
type LocaleAcceptorProps,
|
type LocaleAcceptorProps,
|
||||||
LocaleProvider,
|
LocaleProvider,
|
||||||
useLocale,
|
useLocale,
|
||||||
} from '../../../hooks/useLocale';
|
} from "../../../hooks/useLocale";
|
||||||
import { Session, type SessionTracking } from '../../../stores/session';
|
import { Session, type SessionTracking } from "../../../stores/session";
|
||||||
|
|
||||||
const [tankDefinitions, averageDefinitions] = await Promise.all([
|
const [tankDefinitions, averageDefinitions] = await Promise.all([
|
||||||
awaitableTankDefinitions,
|
awaitableTankDefinitions,
|
||||||
@@ -54,9 +54,7 @@ const [tankDefinitions, averageDefinitions] = await Promise.all([
|
|||||||
export function Page({ locale }: LocaleAcceptorProps) {
|
export function Page({ locale }: LocaleAcceptorProps) {
|
||||||
return (
|
return (
|
||||||
<LocaleProvider locale={locale}>
|
<LocaleProvider locale={locale}>
|
||||||
<Session.Provider>
|
<Content />
|
||||||
<Content />
|
|
||||||
</Session.Provider>
|
|
||||||
</LocaleProvider>
|
</LocaleProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -70,9 +68,8 @@ function Content() {
|
|||||||
useState(false);
|
useState(false);
|
||||||
const input = useRef<HTMLInputElement>(null);
|
const input = useRef<HTMLInputElement>(null);
|
||||||
const session = Session.use();
|
const session = Session.use();
|
||||||
const mutateSession = Session.useMutation();
|
|
||||||
const [tankStatsB, setTankStatsB] = useState<IndividualTankStats[] | null>(
|
const [tankStatsB, setTankStatsB] = useState<IndividualTankStats[] | null>(
|
||||||
null,
|
null
|
||||||
);
|
);
|
||||||
const [accountInfo, setAccountInfo] = useState<
|
const [accountInfo, setAccountInfo] = useState<
|
||||||
IndividualAccountInfo | null | undefined
|
IndividualAccountInfo | null | undefined
|
||||||
@@ -84,7 +81,7 @@ function Content() {
|
|||||||
if (!id) return setAccountInfo(null);
|
if (!id) return setAccountInfo(null);
|
||||||
|
|
||||||
setAccountInfo(
|
setAccountInfo(
|
||||||
session.tracking ? await getAccountInfo(idToRegion(id), id) : null,
|
session.tracking ? await getAccountInfo(idToRegion(id), id) : null
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
}, [session.tracking && session.player.id]);
|
}, [session.tracking && session.player.id]);
|
||||||
@@ -98,20 +95,20 @@ function Content() {
|
|||||||
const average = averageDefinitions.averages[tank.id];
|
const average = averageDefinitions.averages[tank.id];
|
||||||
const composite = compositeStats(
|
const composite = compositeStats(
|
||||||
{ ...entry.all, battle_life_time: entry.battle_life_time },
|
{ ...entry.all, battle_life_time: entry.battle_life_time },
|
||||||
average?.mu,
|
average?.mu
|
||||||
);
|
);
|
||||||
|
|
||||||
return { tank, composite };
|
return { tank, composite };
|
||||||
})
|
})
|
||||||
: undefined,
|
: undefined,
|
||||||
[session.tracking && session.player, tankStatsB],
|
[session.tracking && session.player, tankStatsB]
|
||||||
);
|
);
|
||||||
const total = useMemo(
|
const total = useMemo(
|
||||||
() =>
|
() =>
|
||||||
delta
|
delta
|
||||||
? sumCompositeStats(delta.map(({ composite }) => composite))
|
? sumCompositeStats(delta.map(({ composite }) => composite))
|
||||||
: undefined,
|
: undefined,
|
||||||
[delta],
|
[delta]
|
||||||
);
|
);
|
||||||
const search = debounce(async () => {
|
const search = debounce(async () => {
|
||||||
if (!input.current) return;
|
if (!input.current) return;
|
||||||
@@ -131,7 +128,8 @@ function Content() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setShowSearch(false);
|
setShowSearch(false);
|
||||||
mutateSession((draft) => {
|
|
||||||
|
Session.mutate((draft) => {
|
||||||
if (!input.current) return;
|
if (!input.current) return;
|
||||||
|
|
||||||
draft.tracking = true;
|
draft.tracking = true;
|
||||||
@@ -152,7 +150,7 @@ function Content() {
|
|||||||
|
|
||||||
const tankStats = await getTankStats(
|
const tankStats = await getTankStats(
|
||||||
idToRegion(session.player.id),
|
idToRegion(session.player.id),
|
||||||
session.player.id,
|
session.player.id
|
||||||
);
|
);
|
||||||
setTankStatsB(tankStats);
|
setTankStatsB(tankStats);
|
||||||
}
|
}
|
||||||
@@ -206,8 +204,8 @@ function Content() {
|
|||||||
variant="classic"
|
variant="classic"
|
||||||
size="3"
|
size="3"
|
||||||
style={{
|
style={{
|
||||||
position: 'relative',
|
position: "relative",
|
||||||
width: '75vw',
|
width: "75vw",
|
||||||
maxWidth: 480,
|
maxWidth: 480,
|
||||||
}}
|
}}
|
||||||
ref={input}
|
ref={input}
|
||||||
@@ -272,7 +270,7 @@ function Content() {
|
|||||||
<Flex
|
<Flex
|
||||||
mt="2"
|
mt="2"
|
||||||
mb="2"
|
mb="2"
|
||||||
direction={{ initial: 'column', sm: 'row' }}
|
direction={{ initial: "column", sm: "row" }}
|
||||||
align="center"
|
align="center"
|
||||||
justify="between"
|
justify="between"
|
||||||
gap="2"
|
gap="2"
|
||||||
@@ -296,7 +294,7 @@ function Content() {
|
|||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const stats = await getTankStats(
|
const stats = await getTankStats(
|
||||||
session.player.region,
|
session.player.region,
|
||||||
session.player.id,
|
session.player.id
|
||||||
);
|
);
|
||||||
|
|
||||||
if (stats === null) {
|
if (stats === null) {
|
||||||
@@ -304,7 +302,7 @@ function Content() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutateSession((draft) => {
|
Session.mutate((draft) => {
|
||||||
(draft as SessionTracking).player.stats = stats;
|
(draft as SessionTracking).player.stats = stats;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -313,7 +311,7 @@ function Content() {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
mutateSession((draft) => {
|
Session.mutate((draft) => {
|
||||||
draft.tracking = false;
|
draft.tracking = false;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -338,7 +336,7 @@ function Content() {
|
|||||||
align="center"
|
align="center"
|
||||||
width="0"
|
width="0"
|
||||||
key={column}
|
key={column}
|
||||||
style={{ position: 'relative' }}
|
style={{ position: "relative" }}
|
||||||
>
|
>
|
||||||
{index === 0 && session.columns.length < 4 && (
|
{index === 0 && session.columns.length < 4 && (
|
||||||
<DropdownMenu.Root>
|
<DropdownMenu.Root>
|
||||||
@@ -347,10 +345,10 @@ function Content() {
|
|||||||
size="1"
|
size="1"
|
||||||
variant="surface"
|
variant="surface"
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
left: 0,
|
left: 0,
|
||||||
top: '50%',
|
top: "50%",
|
||||||
transform: 'translate(-100%, -50%)',
|
transform: "translate(-100%, -50%)",
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -365,9 +363,9 @@ function Content() {
|
|||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
key={key}
|
key={key}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
mutateSession((draft) => {
|
Session.mutate((draft) => {
|
||||||
(draft as SessionTracking).columns.unshift(
|
(draft as SessionTracking).columns.unshift(
|
||||||
key,
|
key
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -382,8 +380,8 @@ function Content() {
|
|||||||
<Select.Root
|
<Select.Root
|
||||||
value={column}
|
value={column}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
mutateSession((draft) => {
|
Session.mutate((draft) => {
|
||||||
if (value === 'remove') {
|
if (value === "remove") {
|
||||||
(draft as SessionTracking).columns.splice(index, 1);
|
(draft as SessionTracking).columns.splice(index, 1);
|
||||||
} else {
|
} else {
|
||||||
(draft as SessionTracking).columns[index] =
|
(draft as SessionTracking).columns[index] =
|
||||||
@@ -404,8 +402,7 @@ function Content() {
|
|||||||
{compositeStatsKeys
|
{compositeStatsKeys
|
||||||
.filter(
|
.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
!session.columns.includes(item) ||
|
!session.columns.includes(item) || item === column
|
||||||
item === column,
|
|
||||||
)
|
)
|
||||||
.map((key) => (
|
.map((key) => (
|
||||||
<Select.Item key={key} value={key}>
|
<Select.Item key={key} value={key}>
|
||||||
@@ -422,14 +419,14 @@ function Content() {
|
|||||||
<Table.Body>
|
<Table.Body>
|
||||||
<Table.Row
|
<Table.Row
|
||||||
style={{
|
style={{
|
||||||
overflow: 'hidden',
|
overflow: "hidden",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<StickyRowHeaderCell
|
<StickyRowHeaderCell
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: 32,
|
paddingLeft: 32,
|
||||||
position: 'relative',
|
position: "relative",
|
||||||
overflowY: 'hidden',
|
overflowY: "hidden",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{strings.website.tools.session.table.total}
|
{strings.website.tools.session.table.total}
|
||||||
@@ -446,7 +443,7 @@ function Content() {
|
|||||||
<Table.Row
|
<Table.Row
|
||||||
key={tank.id}
|
key={tank.id}
|
||||||
style={{
|
style={{
|
||||||
overflow: 'hidden',
|
overflow: "hidden",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TankRowHeaderCell tank={tank} />
|
<TankRowHeaderCell tank={tank} />
|
||||||
@@ -455,7 +452,7 @@ function Content() {
|
|||||||
{formatCompositeStat(
|
{formatCompositeStat(
|
||||||
composite[column],
|
composite[column],
|
||||||
column,
|
column,
|
||||||
composite,
|
composite
|
||||||
)}
|
)}
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -2,11 +2,8 @@ import type {
|
|||||||
CompositeStatsKey,
|
CompositeStatsKey,
|
||||||
IndividualTankStats,
|
IndividualTankStats,
|
||||||
Region,
|
Region,
|
||||||
} from '@blitzkit/core';
|
} from "@blitzkit/core";
|
||||||
import { merge } from 'lodash-es';
|
import { Varuna } from "varuna";
|
||||||
import { create } from 'zustand';
|
|
||||||
import { persist } from 'zustand/middleware';
|
|
||||||
import { createContextualStore } from '../core/zustand/createContextualStore';
|
|
||||||
|
|
||||||
interface SessionBase {
|
interface SessionBase {
|
||||||
columns: CompositeStatsKey[];
|
columns: CompositeStatsKey[];
|
||||||
@@ -28,19 +25,15 @@ interface SessionNotTracking extends SessionBase {
|
|||||||
|
|
||||||
type Session = SessionTracking | SessionNotTracking;
|
type Session = SessionTracking | SessionNotTracking;
|
||||||
|
|
||||||
export const Session = createContextualStore(() =>
|
export const Session = new Varuna<Session>(
|
||||||
create<Session>()(
|
{
|
||||||
persist(
|
columns: [
|
||||||
(_) => ({
|
"cumulative_battles",
|
||||||
columns: [
|
"normalized_wins",
|
||||||
'cumulative_battles',
|
"cumulative_wn8",
|
||||||
'normalized_wins',
|
"normalized_damage_dealt",
|
||||||
'cumulative_wn8',
|
],
|
||||||
'normalized_damage_dealt',
|
tracking: false,
|
||||||
],
|
},
|
||||||
tracking: false,
|
"session-4"
|
||||||
}),
|
|
||||||
{ name: 'session-3', merge: (a, b) => merge(b, a) },
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
Reference in new issue
Block a user