diff --git a/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx b/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx
index 1de00a426..8e3a0c9a5 100644
--- a/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx
+++ b/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx
@@ -56,7 +56,7 @@ export function HeroSection() {
}}
>
- {protagonistTank.name}
+ {protagonistTank.nameFull ?? protagonistTank.name}
diff --git a/src/app/tools/tankopedia/components/TankSearch/constants.tsx b/src/app/tools/tankopedia/components/TankSearch/constants.tsx
new file mode 100644
index 000000000..116569014
--- /dev/null
+++ b/src/app/tools/tankopedia/components/TankSearch/constants.tsx
@@ -0,0 +1,7 @@
+import { TreeType } from '../../../../../components/Tanks';
+
+export const treeTypeOrder: TreeType[] = [
+ 'researchable',
+ 'premium',
+ 'collector',
+];
diff --git a/src/app/tools/tankopedia/components/TankSearch/index.tsx b/src/app/tools/tankopedia/components/TankSearch/index.tsx
index 471498dd5..9ab494bce 100644
--- a/src/app/tools/tankopedia/components/TankSearch/index.tsx
+++ b/src/app/tools/tankopedia/components/TankSearch/index.tsx
@@ -14,7 +14,6 @@ import {
import { go } from 'fuzzysort';
import { use, useEffect, useMemo, useRef, useState } from 'react';
import { isMobileOnly } from 'react-device-detect';
-import { TreeType } from '../../../../../components/Tanks';
import { TANK_CLASSES } from '../../../../../components/Tanks/components/Item/constants';
import { resolveNearPenetration } from '../../../../../core/blitz/resolveNearPenetration';
import { modelDefinitions } from '../../../../../core/blitzkit/modelDefinitions';
@@ -35,6 +34,7 @@ import { PageTurner } from '../PageTurner';
import { Options } from './components/Options';
import { Results } from './components/Results';
import { Sort } from './components/Sort';
+import { treeTypeOrder } from './constants';
interface TankSearchProps {
compact?: boolean;
@@ -42,8 +42,6 @@ interface TankSearchProps {
onSelectAll?: (tanks: TankDefinition[]) => void;
}
-const treeTypeOrder: TreeType[] = ['researchable', 'premium', 'collector'];
-
export function TankSearch({
compact,
onSelect = () => {},
diff --git a/src/app/tools/tankopedia/page.tsx b/src/app/tools/tankopedia/page.tsx
index 99d25801b..091efb55c 100644
--- a/src/app/tools/tankopedia/page.tsx
+++ b/src/app/tools/tankopedia/page.tsx
@@ -1,32 +1,160 @@
-'use client';
-
-import { Flex } from '@radix-ui/themes';
-import { times } from 'lodash';
-import { useRouter } from 'next/navigation';
-import { Ad, AdType } from '../../../components/Ad';
+import { CaretRightIcon } from '@radix-ui/react-icons';
+import { Button, Flex, Heading, Text, TextField } from '@radix-ui/themes';
+import { range } from 'lodash';
+import { use } from 'react';
+import { classIcons } from '../../../components/ClassIcon';
+import { Link } from '../../../components/Link';
import PageWrapper from '../../../components/PageWrapper';
-import { useAdExempt } from '../../../hooks/useAdExempt';
-import { TankSearch } from './components/TankSearch';
+import { TANK_CLASSES } from '../../../components/Tanks/components/Item/constants';
+import { asset } from '../../../core/blitzkit/asset';
+import {
+ NATIONS,
+ Tier,
+ tanksDefinitionsArray,
+} from '../../../core/blitzkit/tankDefinitions';
+import { TIER_ROMAN_NUMERALS } from '../../../core/blitzkit/tankDefinitions/constants';
+import { tankIcon } from '../../../core/blitzkit/tankIcon';
+import { treeTypeOrder } from './components/TankSearch/constants';
export default function Page() {
- const router = useRouter();
- const exempt = useAdExempt();
+ const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
+ const awaitedNations = use(NATIONS);
return (
-
- {
- router.push(`./tankopedia/${tank.id}`);
- }}
- />
+
+
+
- {!exempt && (
-
- {times(2, (index) => (
-
- ))}
-
- )}
+
+
+
+
+
+
+ {range(10, 0).map((tierUntyped) => {
+ const tier = tierUntyped as Tier;
+ const tierTanks = awaitedTanksDefinitionsArray.filter(
+ (tank) => tank.tier === tier,
+ );
+
+ return (
+
+ Tier {TIER_ROMAN_NUMERALS[tier]}
+
+
+ {awaitedNations.map((nation, nationIndex) => {
+ const nationTanks = tierTanks
+ .filter((tank) => tank.nation === nation)
+ .sort(
+ (a, b) =>
+ treeTypeOrder.indexOf(a.treeType) -
+ treeTypeOrder.indexOf(b.treeType),
+ )
+ .sort(
+ (a, b) =>
+ TANK_CLASSES.indexOf(a.class) -
+ TANK_CLASSES.indexOf(b.class),
+ );
+
+ if (nationTanks.length === 0) return null;
+
+ return (
+ <>
+ {nationIndex > 0 && (
+
+ )}
+
+
+
+
+ {nationTanks.map((tank) => {
+ const Icon = classIcons[tank.class];
+
+ return (
+
+
+
+
+
+
+
+ {tank.name}
+
+
+
+
+ );
+ })}
+
+
+ >
+ );
+ })}
+
+
+ );
+ })}
+
);
}
diff --git a/src/components/ClassIcon/components/ClassHeavy.tsx b/src/components/ClassIcon/components/ClassHeavy.tsx
new file mode 100644
index 000000000..6b6c64dbc
--- /dev/null
+++ b/src/components/ClassIcon/components/ClassHeavy.tsx
@@ -0,0 +1,58 @@
+import { ComponentProps } from 'react';
+
+export function ClassHeavy(props: ComponentProps<'svg'>) {
+ return (
+
+ );
+}
diff --git a/src/components/ClassIcon/components/ClassLight.tsx b/src/components/ClassIcon/components/ClassLight.tsx
new file mode 100644
index 000000000..39c2e6916
--- /dev/null
+++ b/src/components/ClassIcon/components/ClassLight.tsx
@@ -0,0 +1,23 @@
+import { ComponentProps } from 'react';
+
+export function ClassLight(props: ComponentProps<'svg'>) {
+ return (
+
+ );
+}
diff --git a/src/components/ClassIcon/components/ClassMedium.tsx b/src/components/ClassIcon/components/ClassMedium.tsx
new file mode 100644
index 000000000..1a3fa2153
--- /dev/null
+++ b/src/components/ClassIcon/components/ClassMedium.tsx
@@ -0,0 +1,49 @@
+import { ComponentProps } from 'react';
+
+export function ClassMedium(props: ComponentProps<'svg'>) {
+ return (
+
+ );
+}
diff --git a/src/components/ClassIcon/components/ClassTankDestroyer.tsx b/src/components/ClassIcon/components/ClassTankDestroyer.tsx
new file mode 100644
index 000000000..b908dce03
--- /dev/null
+++ b/src/components/ClassIcon/components/ClassTankDestroyer.tsx
@@ -0,0 +1,19 @@
+import { ComponentProps } from 'react';
+
+export function ClassTankDestroyer(props: ComponentProps<'svg'>) {
+ return (
+
+ );
+}
diff --git a/src/components/ClassIcon/index.ts b/src/components/ClassIcon/index.ts
new file mode 100644
index 000000000..fd05da0c1
--- /dev/null
+++ b/src/components/ClassIcon/index.ts
@@ -0,0 +1,16 @@
+import { ComponentProps, ReactNode } from 'react';
+import { TankClass } from '../Tanks';
+import { ClassHeavy } from './components/ClassHeavy';
+import { ClassLight } from './components/ClassLight';
+import { ClassMedium } from './components/ClassMedium';
+import { ClassTankDestroyer } from './components/ClassTankDestroyer';
+
+export const classIcons: Record<
+ TankClass,
+ (props: ComponentProps<'svg'>) => ReactNode
+> = {
+ 'AT-SPG': ClassTankDestroyer,
+ heavyTank: ClassHeavy,
+ lightTank: ClassLight,
+ mediumTank: ClassMedium,
+};
diff --git a/src/core/blitzkit/tankDefinitions/constants.ts b/src/core/blitzkit/tankDefinitions/constants.ts
index b7f928d6c..3d49f6330 100644
--- a/src/core/blitzkit/tankDefinitions/constants.ts
+++ b/src/core/blitzkit/tankDefinitions/constants.ts
@@ -19,18 +19,27 @@ export const GUN_TYPE_NAMES: Record = {
autoLoader: 'Auto loader',
autoReloader: 'Auto reloader',
};
+/**
+ * @deprecated use svg
+ */
export const TANK_ICONS: Record = {
'AT-SPG': 'https://i.imgur.com/BIHSEH0.png',
lightTank: 'https://i.imgur.com/CSNha5V.png',
mediumTank: 'https://i.imgur.com/wvf3ltm.png',
heavyTank: 'https://i.imgur.com/ECeqlZa.png',
};
+/**
+ * @deprecated use svg
+ */
export const TANK_ICONS_PREMIUM: Record = {
'AT-SPG': 'https://i.imgur.com/TCu3EdR.png',
lightTank: 'https://i.imgur.com/zdkpTRb.png',
mediumTank: 'https://i.imgur.com/3z7eHX6.png',
heavyTank: 'https://i.imgur.com/P3vbmyA.png',
};
+/**
+ * @deprecated use svg
+ */
export const TANK_ICONS_COLLECTOR: Record = {
'AT-SPG': 'https://i.imgur.com/WTjeirB.png',
lightTank: 'https://i.imgur.com/EwhtKkU.png',