feat: translate tank search

This commit is contained in:
tresabhi committed 2025-01-07 13:50:06 -06:00
1 parent c7856364ad
commit 5a65fee1d1
9 files changed
+231 -355

No files matched your search

+80 -1
View File
@@ -716,6 +716,68 @@
"common": {
"copy_button": {
"copied": "Copied!"
},
"tank_search": {
"search_bar_hint": "Search tanks...",
"recent": "Recently viewed",
"select_all": "Select all",
"count_singular": "1 tank",
"count_plural": "%s1 tanks",
"sorting_by": "Sorting by %s1",
"sort": {
"meta.none": "none",
"survivability.health": "health",
"survivability.viewRange": "view range",
"survivability.camouflageStill": "camouflage still",
"survivability.camouflageMoving": "camouflage moving",
"survivability.camouflageShooting": "camouflage shooting",
"survivability.volume": "volume",
"survivability.length": "length",
"fire.dpm": "standard DPM",
"fire.dpmPremium": "premium DPM",
"fire.reload": "reload",
"fire.caliber": "caliber",
"fire.standardPenetration": "standard penetration",
"fire.premiumPenetration": "premium penetration",
"fire.damage": "damage",
"fire.moduleDamage": "module damage",
"fire.shellVelocity": "shell velocity",
"fire.shellRange": "shell range",
"fire.shellCapacity": "shell capacity",
"fire.aimTime": "aim time",
"fire.dispersionStill": "dispersion still",
"fire.dispersionMoving": "dispersion moving",
"fire.gunDepression": "gun depression",
"fire.gunElevation": "gun elevation",
"maneuverability.forwardsSpeed": "forwards speed",
"maneuverability.backwardsSpeed": "backwards speed",
"maneuverability.power": "power",
"maneuverability.powerToWeight": "power to weight",
"maneuverability.weight": "weight",
"maneuverability.traverseSpeed": "traverse speed"
},
"sort_dropdown": {
"label": "Sort",
"groups": {
"sort": {
"no_sort": "No sort",
"label": "Sort by",
"fire": "Fire",
"maneuverability": "Maneuverability",
"survivability": "Survivability"
},
"direction": {
"label": "Direction",
"ascending": "Ascending",
"descending": "Descending"
}
}
}
},
"warnings": {
"test": "Tanks in testing are subject to change and may not represent the final product."
}
},
@@ -743,7 +805,24 @@
"name": "Compare",
"button": "Compare tanks",
"description": "Compare tank statistics",
"seo_description": "Compare tanks statistics and loadouts in World of Tanks Blitz"
"seo_description": "Compare tanks statistics and loadouts in World of Tanks Blitz",
"actions": {
"add": {
"button": "Add",
"title": "Add tanks",
"description": "Select tanks to add to comparison"
},
"clear": "Clear",
"deltas": {
"none": "No deltas",
"percentage": "Percentage",
"absolute": "Absolute"
}
},
"no_tanks": {
"title": "No tanks selected",
"body": "Press the Add button to get started"
}
},
"performance": {
"name": "Performance",
@@ -2,6 +2,7 @@ import { PlusIcon, TrashIcon } from '@radix-ui/react-icons';
import { Button, Dialog, Flex, SegmentedControl } from '@radix-ui/themes';
import { awaitableProvisionDefinitions } from '../../core/awaitables/provisionDefinitions';
import { tankToCompareMember } from '../../core/blitzkit/tankToCompareMember';
import { useLocale } from '../../hooks/useLocale';
import { CompareEphemeral } from '../../stores/compareEphemeral';
import {
ComparePersistent,
@@ -23,6 +24,7 @@ export function Controls({
const deltaMode = ComparePersistent.use((state) => state.deltaMode);
const mutateCompareEphemeral = CompareEphemeral.useMutation();
const mutateComparePersistent = ComparePersistent.useMutation();
const { strings } = useLocale();
return (
<Flex gap="2" wrap="wrap" justify="center">
@@ -32,14 +34,16 @@ export function Controls({
>
<Dialog.Trigger>
<Button variant="soft">
<PlusIcon /> Add
<PlusIcon /> {strings.website.tools.compare.actions.add.button}
</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title align="center">Add tanks</Dialog.Title>
<Dialog.Title align="center">
{strings.website.tools.compare.actions.add.title}
</Dialog.Title>
<Dialog.Description align="center">
Select tanks to add to comparison
{strings.website.tools.compare.actions.add.description}
</Dialog.Description>
<Flex gap="4" direction="column">
@@ -87,7 +91,7 @@ export function Controls({
});
}}
>
<TrashIcon /> Clear
<TrashIcon /> {strings.website.tools.compare.actions.clear}
</Button>
<SegmentedControl.Root
@@ -99,13 +103,13 @@ export function Controls({
}}
>
<SegmentedControl.Item value={'none' satisfies DeltaMode}>
No deltas
{strings.website.tools.compare.actions.deltas.none}
</SegmentedControl.Item>
<SegmentedControl.Item value={'percentage' satisfies DeltaMode}>
Percentage
{strings.website.tools.compare.actions.deltas.percentage}
</SegmentedControl.Item>
<SegmentedControl.Item value={'absolute' satisfies DeltaMode}>
Absolute
{strings.website.tools.compare.actions.deltas.absolute}
</SegmentedControl.Item>
</SegmentedControl.Root>
</Flex>
@@ -4,6 +4,7 @@ import { MagnifyingGlassIcon } from '@radix-ui/react-icons';
import { Flex, Spinner, TextField } from '@radix-ui/themes';
import { debounce } from 'lodash-es';
import { type KeyboardEventHandler, useCallback, useRef } from 'react';
import { useLocale } from '../../../hooks/useLocale';
import { $tankFilters } from '../../../stores/tankFilters';
import { QuickLink } from './QuickLink';
import { Sort } from './Sort';
@@ -14,6 +15,7 @@ interface SearchBarProps {
}
export function SearchBar({ topResult, onSelect }: SearchBarProps) {
const { strings } = useLocale();
const tankFilters = useStore($tankFilters);
const input = useRef<HTMLInputElement>(null);
const performSearch = useCallback(
@@ -67,7 +69,7 @@ export function SearchBar({ topResult, onSelect }: SearchBarProps) {
defaultValue={tankFilters.search}
style={{ flex: 1 }}
ref={input}
placeholder="Search tanks..."
placeholder={strings.website.common.tank_search.search_bar_hint}
onChange={handleChange}
onKeyDown={handleKeyDown}
>
@@ -1,308 +1,122 @@
import { useStore } from '@nanostores/react';
import { CaretDownIcon } from '@radix-ui/react-icons';
import { Button, DropdownMenu } from '@radix-ui/themes';
import type { TankopediaSortDirection } from '../../../stores/tankopediaPersistent';
import { useLocale } from '../../../hooks/useLocale';
import type {
TankopediaSortBy,
TankopediaSortDirection,
} from '../../../stores/tankopediaPersistent';
import { $tankopediaSort } from '../../../stores/tankopediaSort';
interface ItemProps {
by: TankopediaSortBy;
}
interface ItemProps {
by: TankopediaSortBy;
}
function Item({ by }: ItemProps) {
const { strings } = useLocale();
const tankopediaSort = useStore($tankopediaSort);
return (
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === by}
onClick={() => {
$tankopediaSort.setKey('by', by);
}}
>
{strings.website.common.tank_search.sort[by]}
</DropdownMenu.CheckboxItem>
);
}
export function Sort() {
const tankopediaSort = useStore($tankopediaSort);
const { strings } = useLocale();
return (
<DropdownMenu.Root modal={false}>
<DropdownMenu.Trigger>
<Button variant="surface" color="gray">
Sort
{strings.website.common.tank_search.sort_dropdown.label}
<CaretDownIcon />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content align="end">
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'meta.none'}
onClick={() => {
// mutateTankopediaSort((draft) => {
// draft.by = 'meta.none';
// });
$tankopediaSort.setKey('by', 'meta.none');
}}
>
No sort
</DropdownMenu.CheckboxItem>
<DropdownMenu.Label>
{strings.website.common.tank_search.sort_dropdown.groups.sort.label}
</DropdownMenu.Label>
<DropdownMenu.Label>Sort by</DropdownMenu.Label>
<Item by="meta.none" />
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>Fire</DropdownMenu.SubTrigger>
<DropdownMenu.SubTrigger>
{strings.website.common.tank_search.sort_dropdown.groups.sort.fire}
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.dpm'}
onClick={() => {
// mutateTankopediaSort((draft) => {
// draft.by = 'fire.dpm';
// });
$tankopediaSort.setKey('by', 'fire.dpm');
}}
>
Standard DPM
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.dpmPremium'}
onClick={() => {
// mutateTankopediaSort((draft) => {
// draft.by = 'fire.dpmPremium';
// });
$tankopediaSort.setKey('by', 'fire.dpmPremium');
}}
>
Premium DPM
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.reload'}
onClick={() => {
// mutateTankopediaSort((draft) => {
// draft.by = 'fire.reload';
// });
$tankopediaSort.setKey('by', 'fire.reload');
}}
>
Reload
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.caliber'}
onClick={() => {
// mutateTankopediaSort((draft) => {
// draft.by = 'fire.caliber';
// });
$tankopediaSort.setKey('by', 'fire.caliber');
}}
>
Caliber
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.standardPenetration'}
onClick={() => {
// mutateTankopediaSort((draft) => {
// draft.by = 'fire.standardPenetration';
// });
$tankopediaSort.setKey('by', 'fire.standardPenetration');
}}
>
Standard penetration
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.premiumPenetration'}
onClick={() => {
// mutateTankopediaSort((draft) => {
// draft.by = 'fire.premiumPenetration';
// });
$tankopediaSort.setKey('by', 'fire.premiumPenetration');
}}
>
Premium penetration
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.damage'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.damage');
}}
>
Damage
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.moduleDamage'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.moduleDamage');
}}
>
Module damage
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.shellVelocity'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.shellVelocity');
}}
>
Shell velocity
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.shellRange'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.shellRange');
}}
>
Shell range
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.shellCapacity'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.shellCapacity');
}}
>
Shell capacity
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.aimTime'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.aimTime');
}}
>
Aim time
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.dispersionStill'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.dispersionStill');
}}
>
Dispersion still
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.dispersionMoving'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.dispersionMoving');
}}
>
Dispersion moving
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.gunDepression'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.gunDepression');
}}
>
Gun depression
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'fire.gunElevation'}
onClick={() => {
$tankopediaSort.setKey('by', 'fire.gunElevation');
}}
>
Gun elevation
</DropdownMenu.CheckboxItem>
<Item by="fire.dpm" />
<Item by="fire.dpmPremium" />
<Item by="fire.reload" />
<Item by="fire.caliber" />
<Item by="fire.standardPenetration" />
<Item by="fire.premiumPenetration" />
<Item by="fire.damage" />
<Item by="fire.moduleDamage" />
<Item by="fire.shellVelocity" />
<Item by="fire.shellRange" />
<Item by="fire.shellCapacity" />
<Item by="fire.aimTime" />
<Item by="fire.dispersionStill" />
<Item by="fire.dispersionMoving" />
<Item by="fire.gunDepression" />
<Item by="fire.gunElevation" />
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>Maneuverability</DropdownMenu.SubTrigger>
<DropdownMenu.SubTrigger>
{
strings.website.common.tank_search.sort_dropdown.groups.sort
.maneuverability
}
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'maneuverability.forwardsSpeed'}
onClick={() => {
$tankopediaSort.setKey('by', 'maneuverability.forwardsSpeed');
}}
>
Forwards speed
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'maneuverability.backwardsSpeed'}
onClick={() => {
$tankopediaSort.setKey('by', 'maneuverability.backwardsSpeed');
}}
>
Backwards speed
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'maneuverability.power'}
onClick={() => {
$tankopediaSort.setKey('by', 'maneuverability.power');
}}
>
Power
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'maneuverability.powerToWeight'}
onClick={() => {
$tankopediaSort.setKey('by', 'maneuverability.powerToWeight');
}}
>
Power to weight
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'maneuverability.weight'}
onClick={() => {
$tankopediaSort.setKey('by', 'maneuverability.weight');
}}
>
Weight
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'maneuverability.traverseSpeed'}
onClick={() => {
$tankopediaSort.setKey('by', 'maneuverability.traverseSpeed');
}}
>
Traverse speed
</DropdownMenu.CheckboxItem>
<Item by="maneuverability.forwardsSpeed" />
<Item by="maneuverability.backwardsSpeed" />
<Item by="maneuverability.power" />
<Item by="maneuverability.powerToWeight" />
<Item by="maneuverability.weight" />
<Item by="maneuverability.traverseSpeed" />
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>Survivability</DropdownMenu.SubTrigger>
<DropdownMenu.SubTrigger>
{
strings.website.common.tank_search.sort_dropdown.groups.sort
.survivability
}
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'survivability.health'}
onClick={() => {
$tankopediaSort.setKey('by', 'survivability.health');
}}
>
Health
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'survivability.viewRange'}
onClick={() => {
$tankopediaSort.setKey('by', 'survivability.viewRange');
}}
>
View range
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'survivability.camouflageStill'}
onClick={() => {
$tankopediaSort.setKey('by', 'survivability.camouflageStill');
}}
>
Camouflage
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'survivability.camouflageMoving'}
onClick={() => {
$tankopediaSort.setKey('by', 'survivability.camouflageMoving');
}}
>
Camouflage moving
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'survivability.camouflageShooting'}
onClick={() => {
$tankopediaSort.setKey(
'by',
'survivability.camouflageShooting',
);
}}
>
Camouflage shooting
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'survivability.volume'}
onClick={() => {
$tankopediaSort.setKey('by', 'survivability.volume');
}}
>
Volume
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={tankopediaSort.by === 'survivability.length'}
onClick={() => {
$tankopediaSort.setKey('by', 'survivability.length');
}}
>
Length
</DropdownMenu.CheckboxItem>
<Item by="survivability.health" />
<Item by="survivability.viewRange" />
<Item by="survivability.camouflageStill" />
<Item by="survivability.camouflageMoving" />
<Item by="survivability.camouflageShooting" />
<Item by="survivability.volume" />
<Item by="survivability.length" />
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Label>Direction</DropdownMenu.Label>
<DropdownMenu.Label>
{
strings.website.common.tank_search.sort_dropdown.groups.direction
.label
}
</DropdownMenu.Label>
<DropdownMenu.RadioGroup
value={tankopediaSort.direction}
onValueChange={(value) => {
@@ -313,10 +127,16 @@ export function Sort() {
}}
>
<DropdownMenu.RadioItem value="ascending">
Ascending
{
strings.website.common.tank_search.sort_dropdown.groups.direction
.ascending
}
</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem value="descending">
Descending
{
strings.website.common.tank_search.sort_dropdown.groups.direction
.descending
}
</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.Content>
@@ -16,12 +16,11 @@ import { awaitableTankDefinitions } from '../../core/awaitables/tankDefinitions'
import { awaitableTankNames } from '../../core/awaitables/tankNames';
import { filterTank } from '../../core/blitzkit/filterTank';
import { resolveReload } from '../../core/blitzkit/resolveReload';
import { literals } from '../../core/i18n/literals';
import { useLocale } from '../../hooks/useLocale';
import { $tankFilters } from '../../stores/tankFilters';
import { TankopediaPersistent } from '../../stores/tankopediaPersistent';
import {
SORT_NAMES,
SORT_UNITS,
} from '../../stores/tankopediaPersistent/constants';
import { SORT_UNITS } from '../../stores/tankopediaPersistent/constants';
import { $tankopediaSort } from '../../stores/tankopediaSort';
import { ExperimentIcon } from '../ExperimentIcon';
import { TankSearchCard } from './components/Card';
@@ -52,6 +51,7 @@ const [gameDefinitions, modelDefinitions, tankDefinitions, tankNames] =
export const TankSearch = memo<TankSearchProps>(
({ compact, onSelect, onSelectAll, ...props }) => {
const { strings, locale } = useLocale();
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const awaitedTanksDefinitionsArray = Object.values(tankDefinitions.tanks);
const tankFilters = useStore($tankFilters);
@@ -438,8 +438,11 @@ export const TankSearch = memo<TankSearchProps>(
<Flex mt="2" gap="1" align="center" justify="center" direction="column">
<Flex gap="2">
<Text color="gray">
{tanksFiltered.length} tank
{tanksFiltered.length === 1 ? '' : 's'}
{tanksFiltered.length === 1
? strings.website.common.tank_search.count_singular
: literals(strings.website.common.tank_search.count_plural, [
`${tanksFiltered.length.toLocaleString(locale)}`,
])}
</Text>
{onSelectAll && (
@@ -457,14 +460,16 @@ export const TankSearch = memo<TankSearchProps>(
});
}}
>
Select all
{strings.website.common.tank_search.select_all}
</Link>
)}
</Flex>
{tankopediaSort.by !== 'meta.none' && (
<Text color="gray">
Sorting by {SORT_NAMES[tankopediaSort.by]}
{literals(strings.website.common.tank_search.sorting_by, [
strings.website.common.tank_search.sort[tankopediaSort.by],
])}
{SORT_UNITS[tankopediaSort.by] === undefined
? ''
: ` (${SORT_UNITS[tankopediaSort.by]})`}
@@ -480,8 +485,7 @@ export const TankSearch = memo<TankSearchProps>(
<ExperimentIcon style={{ width: '1em', height: '1em' }} />
</Callout.Icon>
<Callout.Text>
Tanks in testing are subject to change and may not represent the
final product.
{strings.website.common.warnings.test}
</Callout.Text>
</Callout.Root>
</Flex>
@@ -1,5 +1,4 @@
import { createDefaultSkills } from '@blitzkit/core';
import { PlusIcon } from '@radix-ui/react-icons';
import { Flex, Heading, Text } from '@radix-ui/themes';
import { useEffect, useMemo, useState } from 'react';
import { CompareTable } from '../../../../components/Compare/CompareTable';
@@ -13,6 +12,11 @@ import { awaitableSkillDefinitions } from '../../../../core/awaitables/skillDefi
import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions';
import { tankCharacteristics } from '../../../../core/blitzkit/tankCharacteristics';
import { tankToCompareMember } from '../../../../core/blitzkit/tankToCompareMember';
import {
LocaleProvider,
useLocale,
type LocaleAcceptorProps,
} from '../../../../hooks/useLocale';
import { App } from '../../../../stores/app';
import { CompareEphemeral } from '../../../../stores/compareEphemeral';
import { ComparePersistent } from '../../../../stores/comparePersistent';
@@ -32,19 +36,21 @@ const [
awaitableTankDefinitions,
]);
export function Page() {
export function Page({ locale }: LocaleAcceptorProps) {
return (
<App.Provider>
<TankopediaPersistent.Provider>
<ComparePersistent.Provider>
<CompareEphemeral.Provider
data={createDefaultSkills(skillDefinitions)}
>
<Content />
</CompareEphemeral.Provider>
</ComparePersistent.Provider>
</TankopediaPersistent.Provider>
</App.Provider>
<LocaleProvider locale={locale}>
<App.Provider>
<TankopediaPersistent.Provider>
<ComparePersistent.Provider>
<CompareEphemeral.Provider
data={createDefaultSkills(skillDefinitions)}
>
<Content />
</CompareEphemeral.Provider>
</ComparePersistent.Provider>
</TankopediaPersistent.Provider>
</App.Provider>
</LocaleProvider>
);
}
@@ -52,6 +58,7 @@ function Content() {
const members = CompareEphemeral.use((state) => state.members);
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
const crewSkills = CompareEphemeral.use((state) => state.crewSkills);
const { strings } = useLocale();
const stats = useMemo<ReturnType<typeof tankCharacteristics>[]>(
() =>
members.map((thisMember) =>
@@ -136,19 +143,6 @@ function Content() {
{members.length > 0 && (
<Flex justify="center" flexGrow="1" position="relative">
<CompareTable stats={stats} />
{/* <IconButton
style={{
position: 'absolute',
right: 0,
top: 73,
transform: 'translate(50%, -50%)',
zIndex: 1,
}}
onClick={() => setAddTankDialogOpen(true)}
>
<PlusIcon />
</IconButton> */}
</Flex>
)}
@@ -159,9 +153,11 @@ function Content() {
direction="column"
style={{ flex: 1 }}
>
<Heading color="gray">No tanks selected</Heading>
<Heading color="gray">
{strings.website.tools.compare.no_tanks.title}
</Heading>
<Text color="gray">
Press the <PlusIcon /> Add button to get started
{strings.website.tools.compare.no_tanks.body}
</Text>
</Flex>
)}
@@ -5,10 +5,12 @@ import BaseLayout from '../../../../layouts/BaseLayout.astro';
import { Page } from './_index';
export { getStaticPaths } from '../../index.astro';
const { locale } = Astro.params;
---
<ToolOpenGraph tool={compareTool} />
<BaseLayout noFooter>
<Page client:load />
<Page {locale} client:load />
</BaseLayout>
@@ -32,38 +32,7 @@ export const SORT_UNITS: Record<TankopediaSortBy, string | undefined> = {
'survivability.viewRange': 'm',
'survivability.volume': 'm^3',
};
export const SORT_NAMES = {
'meta.none': 'none',
'survivability.health': 'health',
'survivability.viewRange': 'view range',
'survivability.camouflageStill': 'camouflage still',
'survivability.camouflageMoving': 'camouflage moving',
'survivability.camouflageShooting': 'camouflage shooting',
'survivability.volume': 'volume',
'survivability.length': 'length',
'fire.dpm': 'standard DPM',
'fire.dpmPremium': 'premium DPM',
'fire.reload': 'reload',
'fire.caliber': 'caliber',
'fire.standardPenetration': 'standard penetration',
'fire.premiumPenetration': 'premium penetration',
'fire.damage': 'damage',
'fire.moduleDamage': 'module damage',
'fire.shellVelocity': 'shell velocity',
'fire.shellRange': 'shell range',
'fire.shellCapacity': 'shell capacity',
'fire.aimTime': 'aim time',
'fire.dispersionStill': 'dispersion still',
'fire.dispersionMoving': 'dispersion moving',
'fire.gunDepression': 'gun depression',
'fire.gunElevation': 'gun elevation',
'maneuverability.forwardsSpeed': 'forwards speed',
'maneuverability.backwardsSpeed': 'backwards speed',
'maneuverability.power': 'power',
'maneuverability.powerToWeight': 'power to weight',
'maneuverability.weight': 'weight',
'maneuverability.traverseSpeed': 'traverse speed',
} as const;
export enum TankopediaDisplay {
Model,
DynamicArmor,
@@ -1,10 +1,10 @@
import type en from '@blitzkit/core/lang/en.json';
import * as lodash from 'lodash-es';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
import { createContextualStore } from '../../core/zustand/createContextualStore';
import { SORT_NAMES } from './constants';
export type TankopediaSortBy = keyof typeof SORT_NAMES;
export type TankopediaSortBy = keyof typeof en.website.common.tank_search.sort;
export type TankopediaSortDirection = 'ascending' | 'descending';
export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';