From d93b202ee8e4f832ba18f7b2f5a6cd69e1deb807 Mon Sep 17 00:00:00 2001 From: Mark Greene Date: Thu, 8 Oct 2026 18:36:17 +1300 Subject: [PATCH] Feature: Switch all shells in Compare --- packages/i18n/strings/en.json | 3 +- .../website/src/components/Compare/Body.tsx | 8 +++- .../src/components/Compare/Controls.tsx | 37 ++++++++++++++++++- .../website/src/stores/compareEphemeral.ts | 10 +++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index 04125f138..0377c9e62 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -742,7 +742,8 @@ "none": "No deltas", "percentage": "Percentage", "absolute": "Absolute" - } + }, + "sync_shells": "Sync shells" }, "no_tanks": { diff --git a/packages/website/src/components/Compare/Body.tsx b/packages/website/src/components/Compare/Body.tsx index ee88cd4e4..e9648106e 100644 --- a/packages/website/src/components/Compare/Body.tsx +++ b/packages/website/src/components/Compare/Body.tsx @@ -2,7 +2,7 @@ import { alias } from "@blitzkit/core"; import { Flex, Heading, IconButton, Table } from "@radix-ui/themes"; import type { TankCharacteristics } from "../../core/blitzkit/tankCharacteristics"; import { useLocale } from "../../hooks/useLocale"; -import { CompareEphemeral } from "../../stores/compareEphemeral"; +import { CompareEphemeral, syncShellSlot } from "../../stores/compareEphemeral"; import { CompareCellDirection } from "../CompareCell"; import { StickyColumnHeaderCell } from "../StickyColumnHeaderCell"; import { CompareRow } from "./CompareRow"; @@ -50,7 +50,11 @@ export function Body({ stats }: BodyProps) { }} onClick={() => { CompareEphemeral.mutate((draft) => { - draft.members[index].shell = thisShell; + if (draft.syncShells) { + syncShellSlot(draft.members, shellIndex); + } else { + draft.members[index].shell = thisShell; + } }); }} > diff --git a/packages/website/src/components/Compare/Controls.tsx b/packages/website/src/components/Compare/Controls.tsx index 1bb45c6cb..25d71d7f0 100644 --- a/packages/website/src/components/Compare/Controls.tsx +++ b/packages/website/src/components/Compare/Controls.tsx @@ -1,9 +1,16 @@ import { PlusIcon, TrashIcon } from "@radix-ui/react-icons"; -import { Button, Dialog, Flex, SegmentedControl } from "@radix-ui/themes"; +import { + Button, + Checkbox, + Dialog, + Flex, + SegmentedControl, + Text, +} from "@radix-ui/themes"; import { api } from "../../core/blitzkit/api"; import { tankToCompareMember } from "../../core/blitzkit/tankToCompareMember"; import { useLocale } from "../../hooks/useLocale"; -import { CompareEphemeral } from "../../stores/compareEphemeral"; +import { CompareEphemeral, syncShellSlot } from "../../stores/compareEphemeral"; import { ComparePersistent, type DeltaMode, @@ -22,6 +29,7 @@ export function Controls({ onAddTankDialogOpenChange, }: ControlsProps) { const deltaMode = ComparePersistent.use((state) => state.deltaMode); + const syncShells = CompareEphemeral.use((state) => state.syncShells); const { strings } = useLocale(); return ( @@ -111,6 +119,31 @@ export function Controls({ {strings.website.tools.compare.actions.deltas.absolute} + + { + CompareEphemeral.mutate((draft) => { + draft.syncShells = !draft.syncShells; + + if (!draft.syncShells || draft.members.length === 0) return; + + const [first] = draft.members; + + syncShellSlot( + draft.members, + first.gun.shells.findIndex(({ id }) => id === first.shell.id), + ); + }); + }} + > + + + {strings.website.tools.compare.actions.sync_shells} + + ); } diff --git a/packages/website/src/stores/compareEphemeral.ts b/packages/website/src/stores/compareEphemeral.ts index 2c5a2a6e3..80fcdb6e0 100644 --- a/packages/website/src/stores/compareEphemeral.ts +++ b/packages/website/src/stores/compareEphemeral.ts @@ -8,6 +8,7 @@ export interface CompareMember extends DuelMember { export interface CompareEphemeral { crewSkills: Record; equalize: boolean; + syncShells: boolean; members: CompareMember[]; sorting?: { direction: "ascending" | "descending"; @@ -21,5 +22,14 @@ export const CompareEphemeral = new Varuna< >((crewSkills) => ({ crewSkills, equalize: false, + syncShells: false, members: [], })); + +export function syncShellSlot(members: CompareMember[], slot: number) { + for (const member of members) { + const shell = member.gun.shells[slot]; + + if (shell) member.shell = shell; + } +}