mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: some button functionality
This commit is contained in:
1 parent
753804b8cf
commit
d25da724e1
2 files changed
+185
-63
No files matched your search
+132
-18
@@ -1,10 +1,26 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { PlusIcon } from '@radix-ui/react-icons';
|
import {
|
||||||
import { Button, Dialog, Flex, Table, Text } from '@radix-ui/themes';
|
CaretLeftIcon,
|
||||||
|
CaretRightIcon,
|
||||||
|
PlusIcon,
|
||||||
|
ShuffleIcon,
|
||||||
|
TrashIcon,
|
||||||
|
} from '@radix-ui/react-icons';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
Flex,
|
||||||
|
IconButton,
|
||||||
|
Table,
|
||||||
|
Text,
|
||||||
|
} from '@radix-ui/themes';
|
||||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { use, useCallback, useEffect, useMemo, useState } from 'react';
|
import { use, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import PageWrapper from '../../../components/PageWrapper';
|
import PageWrapper from '../../../components/PageWrapper';
|
||||||
|
import { equipmentDefinitions } from '../../../core/blitzkrieg/equipmentDefinitions';
|
||||||
|
import { modelDefinitions } from '../../../core/blitzkrieg/modelDefinitions';
|
||||||
|
import { provisionDefinitions } from '../../../core/blitzkrieg/provisionDefinitions';
|
||||||
import { tankCharacteristics } from '../../../core/blitzkrieg/tankCharacteristics';
|
import { tankCharacteristics } from '../../../core/blitzkrieg/tankCharacteristics';
|
||||||
import { tankDefinitions } from '../../../core/blitzkrieg/tankDefinitions';
|
import { tankDefinitions } from '../../../core/blitzkrieg/tankDefinitions';
|
||||||
import { tankIcon } from '../../../core/blitzkrieg/tankIcon';
|
import { tankIcon } from '../../../core/blitzkrieg/tankIcon';
|
||||||
@@ -22,22 +38,29 @@ export default function Page() {
|
|||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const tanks = useCompare((state) => state.tanks);
|
const tanks = useCompare((state) => state.tanks);
|
||||||
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
|
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
|
||||||
const statsPromise = useMemo(
|
const awaitedModelDefinitions = use(modelDefinitions);
|
||||||
|
const awaitedEquipmentDefinitions = use(equipmentDefinitions);
|
||||||
|
const awaitedProvisionDefinitions = use(provisionDefinitions);
|
||||||
|
const stats = useMemo(
|
||||||
() =>
|
() =>
|
||||||
Promise.all(
|
tanks.map((item) =>
|
||||||
tanks.map((item) =>
|
tankCharacteristics(
|
||||||
tankCharacteristics({
|
{
|
||||||
...item,
|
...item,
|
||||||
stockEngine: item.tank.engines[0],
|
stockEngine: item.tank.engines[0],
|
||||||
stockGun: item.tank.turrets[0].guns[0],
|
stockGun: item.tank.turrets[0].guns[0],
|
||||||
stockTrack: item.tank.tracks[0],
|
stockTrack: item.tank.tracks[0],
|
||||||
stockTurret: item.tank.turrets[0],
|
stockTurret: item.tank.turrets[0],
|
||||||
}),
|
},
|
||||||
|
{
|
||||||
|
equipmentDefinitions: awaitedEquipmentDefinitions,
|
||||||
|
modelDefinitions: awaitedModelDefinitions,
|
||||||
|
provisionDefinitions: awaitedProvisionDefinitions,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
[tanks],
|
[tanks],
|
||||||
);
|
);
|
||||||
const stats = use(statsPromise);
|
|
||||||
const createQueryString = useCallback(
|
const createQueryString = useCallback(
|
||||||
(name: string, value: string) => {
|
(name: string, value: string) => {
|
||||||
const params = new URLSearchParams(searchParams.toString());
|
const params = new URLSearchParams(searchParams.toString());
|
||||||
@@ -50,6 +73,13 @@ export default function Page() {
|
|||||||
|
|
||||||
const hasNonRegularGun = tanks.some(({ gun }) => gun.type !== 'regular');
|
const hasNonRegularGun = tanks.some(({ gun }) => gun.type !== 'regular');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
router.push(
|
||||||
|
pathname +
|
||||||
|
'?' +
|
||||||
|
createQueryString('tanks', tanks.map(({ tank }) => tank.id).join(',')),
|
||||||
|
);
|
||||||
|
}, [tanks]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tanksParam = searchParams.get('tanks');
|
const tanksParam = searchParams.get('tanks');
|
||||||
|
|
||||||
@@ -164,15 +194,6 @@ export default function Page() {
|
|||||||
...tankToDuelMember(tank),
|
...tankToDuelMember(tank),
|
||||||
crewSkills: {},
|
crewSkills: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
router.push(
|
|
||||||
pathname +
|
|
||||||
'?' +
|
|
||||||
createQueryString(
|
|
||||||
'tanks',
|
|
||||||
draft.tanks.map(({ tank }) => tank.id).join(','),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setAddTankDialogOpen(false);
|
setAddTankDialogOpen(false);
|
||||||
@@ -192,6 +213,93 @@ export default function Page() {
|
|||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Table.Header>
|
||||||
|
<Table.Row>
|
||||||
|
<Table.ColumnHeaderCell />
|
||||||
|
|
||||||
|
{tanks.map(({ tank }, index) => {
|
||||||
|
return (
|
||||||
|
<Table.ColumnHeaderCell width="0" key={tank.id}>
|
||||||
|
<Flex gap="4" style={{ padding: '0 4px' }}>
|
||||||
|
{index !== 0 && (
|
||||||
|
<IconButton
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
mutateCompare((draft) => {
|
||||||
|
const item = draft.tanks[index];
|
||||||
|
draft.tanks.splice(index, 1);
|
||||||
|
draft.tanks.splice(index - 1, 0, item);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CaretLeftIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
<IconButton
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
mutateCompare((draft) => {
|
||||||
|
draft.tanks.splice(index, 1);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TrashIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Dialog.Root
|
||||||
|
open={addTankDialogOpen}
|
||||||
|
onOpenChange={setAddTankDialogOpen}
|
||||||
|
>
|
||||||
|
<Dialog.Trigger>
|
||||||
|
<IconButton variant="ghost">
|
||||||
|
<ShuffleIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Dialog.Trigger>
|
||||||
|
|
||||||
|
<Dialog.Content>
|
||||||
|
<Flex gap="4" direction="column">
|
||||||
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
gap="4"
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
justify="center"
|
||||||
|
>
|
||||||
|
<TankSearch
|
||||||
|
compact
|
||||||
|
onSelect={(tank) => {
|
||||||
|
mutateCompare((draft) => {
|
||||||
|
draft.tanks[index] = {
|
||||||
|
...tankToDuelMember(tank),
|
||||||
|
crewSkills: {},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setAddTankDialogOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Root>
|
||||||
|
{index !== tanks.length - 1 && (
|
||||||
|
<IconButton
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
mutateCompare((draft) => {
|
||||||
|
const item = draft.tanks[index];
|
||||||
|
draft.tanks.splice(index, 1);
|
||||||
|
draft.tanks.splice(index + 1, 0, item);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CaretRightIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Table.ColumnHeaderCell>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Table.Row>
|
||||||
|
</Table.Header>
|
||||||
|
|
||||||
<Table.Header>
|
<Table.Header>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.ColumnHeaderCell />
|
<Table.ColumnHeaderCell />
|
||||||
@@ -199,7 +307,13 @@ export default function Page() {
|
|||||||
{tanks.map(({ tank }) => {
|
{tanks.map(({ tank }) => {
|
||||||
return (
|
return (
|
||||||
<Table.ColumnHeaderCell width="0" key={tank.id}>
|
<Table.ColumnHeaderCell width="0" key={tank.id}>
|
||||||
<Flex direction="column" align="center">
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
align="center"
|
||||||
|
justify="between"
|
||||||
|
gap="2"
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src={tankIcon(tank.id)}
|
src={tankIcon(tank.id)}
|
||||||
width={64}
|
width={64}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { isExplosive } from '../blitz/isExplosive';
|
|||||||
import { resolveNearPenetration } from '../blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../blitz/resolveNearPenetration';
|
||||||
import { coefficient } from './coefficient';
|
import { coefficient } from './coefficient';
|
||||||
import { degressiveStat } from './degressiveStat';
|
import { degressiveStat } from './degressiveStat';
|
||||||
import { equipmentDefinitions } from './equipmentDefinitions';
|
import { EquipmentDefinitions } from './equipmentDefinitions';
|
||||||
import { modelDefinitions } from './modelDefinitions';
|
import { ModelDefinitions } from './modelDefinitions';
|
||||||
import { normalizeBoundingBox } from './normalizeBoundingBox';
|
import { normalizeBoundingBox } from './normalizeBoundingBox';
|
||||||
import { progressiveStat } from './progressiveStat';
|
import { progressiveStat } from './progressiveStat';
|
||||||
import { provisionDefinitions } from './provisionDefinitions';
|
import { ProvisionDefinitions } from './provisionDefinitions';
|
||||||
import { resolveDpm } from './resolveDpm';
|
import { resolveDpm } from './resolveDpm';
|
||||||
import { sum } from './sum';
|
import { sum } from './sum';
|
||||||
import {
|
import {
|
||||||
@@ -20,46 +20,54 @@ import {
|
|||||||
} from './tankDefinitions';
|
} from './tankDefinitions';
|
||||||
import { unionBoundingBox } from './unionBoundingBox';
|
import { unionBoundingBox } from './unionBoundingBox';
|
||||||
|
|
||||||
export async function tankCharacteristics({
|
export function tankCharacteristics(
|
||||||
tank,
|
{
|
||||||
turret,
|
tank,
|
||||||
gun,
|
turret,
|
||||||
shell,
|
gun,
|
||||||
consumables,
|
shell,
|
||||||
equipmentMatrix,
|
consumables,
|
||||||
crewMastery,
|
equipmentMatrix,
|
||||||
provisions,
|
crewMastery,
|
||||||
engine,
|
provisions,
|
||||||
crewSkills,
|
engine,
|
||||||
camouflage,
|
crewSkills,
|
||||||
track,
|
camouflage,
|
||||||
stockEngine,
|
track,
|
||||||
stockTrack,
|
stockEngine,
|
||||||
stockTurret,
|
stockTrack,
|
||||||
stockGun,
|
stockTurret,
|
||||||
}: {
|
stockGun,
|
||||||
tank: TankDefinition;
|
}: {
|
||||||
turret: TurretDefinition;
|
tank: TankDefinition;
|
||||||
gun: GunDefinition;
|
turret: TurretDefinition;
|
||||||
shell: ShellDefinition;
|
gun: GunDefinition;
|
||||||
track: TrackDefinition;
|
shell: ShellDefinition;
|
||||||
engine: EngineDefinition;
|
track: TrackDefinition;
|
||||||
stockEngine: EngineDefinition;
|
engine: EngineDefinition;
|
||||||
stockTrack: TrackDefinition;
|
stockEngine: EngineDefinition;
|
||||||
stockTurret: TurretDefinition;
|
stockTrack: TrackDefinition;
|
||||||
stockGun: GunDefinition;
|
stockTurret: TurretDefinition;
|
||||||
consumables: number[];
|
stockGun: GunDefinition;
|
||||||
equipmentMatrix: EquipmentMatrix;
|
consumables: number[];
|
||||||
crewMastery: number;
|
equipmentMatrix: EquipmentMatrix;
|
||||||
provisions: number[];
|
crewMastery: number;
|
||||||
crewSkills: Record<string, number>;
|
provisions: number[];
|
||||||
camouflage: boolean;
|
crewSkills: Record<string, number>;
|
||||||
}) {
|
camouflage: boolean;
|
||||||
const awaitedModelDefinitions = await modelDefinitions;
|
},
|
||||||
const awaitedEquipmentDefinitions = await equipmentDefinitions;
|
{
|
||||||
const awaitedProvisionDefinitions = await provisionDefinitions;
|
modelDefinitions,
|
||||||
const presetRows = awaitedEquipmentDefinitions.presets[tank.equipment];
|
equipmentDefinitions,
|
||||||
const tankModelDefinition = awaitedModelDefinitions[tank.id];
|
provisionDefinitions,
|
||||||
|
}: {
|
||||||
|
modelDefinitions: ModelDefinitions;
|
||||||
|
equipmentDefinitions: EquipmentDefinitions;
|
||||||
|
provisionDefinitions: ProvisionDefinitions;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const presetRows = equipmentDefinitions.presets[tank.equipment];
|
||||||
|
const tankModelDefinition = modelDefinitions[tank.id];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
|
|
||||||
@@ -115,8 +123,8 @@ export async function tankCharacteristics({
|
|||||||
const provisionCrewBonus =
|
const provisionCrewBonus =
|
||||||
provisions.reduce(
|
provisions.reduce(
|
||||||
(total, provision) =>
|
(total, provision) =>
|
||||||
awaitedProvisionDefinitions[provision].crew
|
provisionDefinitions[provision].crew
|
||||||
? total + awaitedProvisionDefinitions[provision].crew! / 100
|
? total + provisionDefinitions[provision].crew! / 100
|
||||||
: total,
|
: total,
|
||||||
0,
|
0,
|
||||||
) + (hasImprovedVentilation ? 0.05 : 0);
|
) + (hasImprovedVentilation ? 0.05 : 0);
|
||||||
|
|||||||
Reference in new issue
Block a user