2024-09-23 10:49:54 -05:00
|
|
|
import {
|
2024-10-14 10:40:23 -05:00
|
|
|
createDefaultSkills,
|
2024-10-05 16:44:07 -05:00
|
|
|
fetchEquipmentDefinitions,
|
|
|
|
|
fetchModelDefinitions,
|
|
|
|
|
fetchProvisionDefinitions,
|
2024-10-14 10:40:23 -05:00
|
|
|
fetchSkillDefinitions,
|
2024-10-18 11:30:33 -05:00
|
|
|
fetchTankDefinitions,
|
2024-09-23 10:49:54 -05:00
|
|
|
} from '@blitzkit/core';
|
|
|
|
|
import { PlusIcon } from '@radix-ui/react-icons';
|
|
|
|
|
import { Box, Flex, Heading, IconButton, Text } from '@radix-ui/themes';
|
2024-10-18 11:30:33 -05:00
|
|
|
import { useEffect, useMemo, useState } from 'react';
|
2024-09-23 10:49:54 -05:00
|
|
|
import { CompareTable } from '../../../components/Compare/CompareTable';
|
|
|
|
|
import { Controls } from '../../../components/Compare/Controls';
|
|
|
|
|
import { DamageWarning } from '../../../components/DamageWarning';
|
|
|
|
|
import { PageWrapper } from '../../../components/PageWrapper';
|
|
|
|
|
import { tankCharacteristics } from '../../../core/blitzkit/tankCharacteristics';
|
2024-10-18 11:30:33 -05:00
|
|
|
import { tankToCompareMember } from '../../../core/blitzkit/tankToCompareMember';
|
2024-10-13 20:14:32 -05:00
|
|
|
import { App } from '../../../stores/app';
|
2024-09-23 10:49:54 -05:00
|
|
|
import { CompareEphemeral } from '../../../stores/compareEphemeral';
|
|
|
|
|
import { ComparePersistent } from '../../../stores/comparePersistent';
|
|
|
|
|
|
2024-10-05 16:44:07 -05:00
|
|
|
const modelDefinitions = await fetchModelDefinitions();
|
|
|
|
|
const equipmentDefinitions = await fetchEquipmentDefinitions();
|
|
|
|
|
const provisionDefinitions = await fetchProvisionDefinitions();
|
2024-10-14 10:40:23 -05:00
|
|
|
const skillDefinitions = await fetchSkillDefinitions();
|
2024-10-18 11:30:33 -05:00
|
|
|
const tankDefinitions = await fetchTankDefinitions();
|
2024-09-23 10:49:54 -05:00
|
|
|
|
|
|
|
|
export function Page() {
|
|
|
|
|
return (
|
2024-10-13 20:14:32 -05:00
|
|
|
<App.Provider>
|
|
|
|
|
<ComparePersistent.Provider>
|
2024-10-14 10:40:23 -05:00
|
|
|
<CompareEphemeral.Provider data={createDefaultSkills(skillDefinitions)}>
|
2024-10-13 20:14:32 -05:00
|
|
|
<Content />
|
|
|
|
|
</CompareEphemeral.Provider>
|
|
|
|
|
</ComparePersistent.Provider>
|
|
|
|
|
</App.Provider>
|
2024-09-23 10:49:54 -05:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Content() {
|
|
|
|
|
const members = CompareEphemeral.use((state) => state.members);
|
|
|
|
|
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
|
|
|
|
|
const crewSkills = CompareEphemeral.use((state) => state.crewSkills);
|
|
|
|
|
const stats = useMemo<ReturnType<typeof tankCharacteristics>[]>(
|
|
|
|
|
() =>
|
|
|
|
|
members.map((thisMember) =>
|
|
|
|
|
tankCharacteristics(
|
|
|
|
|
{
|
|
|
|
|
...thisMember,
|
|
|
|
|
crewSkills,
|
|
|
|
|
stockEngine: thisMember.tank.engines[0],
|
|
|
|
|
stockGun: thisMember.tank.turrets[0].guns[0],
|
|
|
|
|
stockTrack: thisMember.tank.tracks[0],
|
|
|
|
|
stockTurret: thisMember.tank.turrets[0],
|
|
|
|
|
applyReactiveArmor: members.some(
|
|
|
|
|
(member) =>
|
|
|
|
|
member.key !== thisMember.key &&
|
|
|
|
|
member.consumables.includes(33),
|
|
|
|
|
),
|
|
|
|
|
applyDynamicArmor: members.some(
|
|
|
|
|
(member) =>
|
|
|
|
|
member.key !== thisMember.key &&
|
|
|
|
|
member.consumables.includes(73),
|
|
|
|
|
),
|
|
|
|
|
applySpallLiner: members.some(
|
|
|
|
|
(member) =>
|
|
|
|
|
member.key !== thisMember.key &&
|
|
|
|
|
member.provisions.includes(101),
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-10-05 16:44:07 -05:00
|
|
|
equipmentDefinitions: equipmentDefinitions,
|
|
|
|
|
provisionDefinitions: provisionDefinitions,
|
|
|
|
|
tankModelDefinition: modelDefinitions.models[thisMember.tank.id],
|
2024-09-23 10:49:54 -05:00
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
[members, crewSkills],
|
|
|
|
|
);
|
2024-10-18 11:30:33 -05:00
|
|
|
const mutateCompareEphemeral = CompareEphemeral.useMutation();
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const search = new URLSearchParams(window.location.search);
|
|
|
|
|
const tanksQuery = search.get('tanks');
|
|
|
|
|
|
|
|
|
|
if (tanksQuery === null) return;
|
|
|
|
|
|
|
|
|
|
const tanks = tanksQuery.split(',').map(Number);
|
|
|
|
|
|
|
|
|
|
mutateCompareEphemeral((draft) => {
|
|
|
|
|
tanks.forEach((id) => {
|
|
|
|
|
const tank = tankDefinitions.tanks[id];
|
|
|
|
|
|
|
|
|
|
if (tank === undefined) return;
|
|
|
|
|
|
|
|
|
|
draft.members.push(tankToCompareMember(tank, provisionDefinitions));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}, []);
|
2024-09-23 10:49:54 -05:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<PageWrapper color="crimson" size="100%">
|
|
|
|
|
<Flex justify="center" gap="4" align="center" direction="column">
|
|
|
|
|
<DamageWarning />
|
|
|
|
|
<Controls
|
|
|
|
|
addTankDialogOpen={addTankDialogOpen}
|
|
|
|
|
onAddTankDialogOpenChange={setAddTankDialogOpen}
|
|
|
|
|
/>
|
|
|
|
|
</Flex>
|
|
|
|
|
|
|
|
|
|
{members.length > 0 && (
|
|
|
|
|
<Flex justify="center">
|
|
|
|
|
<Box maxWidth="100%" position="relative">
|
|
|
|
|
<CompareTable stats={stats} />
|
|
|
|
|
|
|
|
|
|
<IconButton
|
|
|
|
|
style={{
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
right: 0,
|
|
|
|
|
top: 73,
|
|
|
|
|
transform: 'translate(50%, -50%)',
|
|
|
|
|
zIndex: 1,
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => setAddTankDialogOpen(true)}
|
|
|
|
|
>
|
|
|
|
|
<PlusIcon />
|
|
|
|
|
</IconButton>
|
|
|
|
|
</Box>
|
|
|
|
|
</Flex>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{members.length === 0 && (
|
|
|
|
|
<Flex
|
|
|
|
|
align="center"
|
|
|
|
|
justify="center"
|
|
|
|
|
direction="column"
|
|
|
|
|
style={{ flex: 1 }}
|
|
|
|
|
>
|
|
|
|
|
<Heading color="gray">No tanks selected</Heading>
|
|
|
|
|
<Text color="gray">
|
|
|
|
|
Press the <PlusIcon /> Add button to get started
|
|
|
|
|
</Text>
|
|
|
|
|
</Flex>
|
|
|
|
|
)}
|
|
|
|
|
</PageWrapper>
|
|
|
|
|
);
|
|
|
|
|
}
|