diff --git a/packages/website/src/components/TankSearch/components/RecentlyViewed.tsx b/packages/website/src/components/TankSearch/components/RecentlyViewed.tsx
new file mode 100644
index 000000000..22bdb3aec
--- /dev/null
+++ b/packages/website/src/components/TankSearch/components/RecentlyViewed.tsx
@@ -0,0 +1,30 @@
+import { fetchTankDefinitions } from '@blitzkit/core';
+import { Flex, Separator, Text } from '@radix-ui/themes';
+import { TankopediaPersistent } from '../../../stores/tankopediaPersistent';
+import { TankCard } from './TankCard';
+import { TankCardWrapper } from './TankCardWrapper';
+
+const tankDefinitions = await fetchTankDefinitions();
+
+export function RecentlyViewed() {
+ const tankopediaPersistentStore = TankopediaPersistent.useStore();
+ // non-reactive because it is a little weird that it updates instantly even before the page loads
+ const recentlyViewed = tankopediaPersistentStore.getState().recentlyViewed;
+
+ if (recentlyViewed.length === 0) return null;
+
+ return (
+
+
+ Recently viewed
+
+
+ {recentlyViewed.map((id) => (
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/packages/website/src/components/TankSearch/components/TankCard/index.tsx b/packages/website/src/components/TankSearch/components/TankCard/index.tsx
index 984b2717e..54f16ac28 100644
--- a/packages/website/src/components/TankSearch/components/TankCard/index.tsx
+++ b/packages/website/src/components/TankSearch/components/TankCard/index.tsx
@@ -10,10 +10,13 @@ import {
} from '@blitzkit/core';
import { useStore } from '@nanostores/react';
import { Flex, Link, Text } from '@radix-ui/themes';
+import { uniq } from 'lodash-es';
import { useMemo } from 'react';
import { resolveReload } from '../../../../core/blitzkit/resolveReload';
+import { TankopediaPersistent } from '../../../../stores/tankopediaPersistent';
import { $tankopediaSort } from '../../../../stores/tankopediaSort';
import { classIcons } from '../../../ClassIcon';
+import { MAX_RECENTLY_VIEWED } from '../../constants';
import './index.css';
interface TankCardProps {
@@ -24,6 +27,7 @@ interface TankCardProps {
const modelDefinitions = await fetchModelDefinitions();
export function TankCard({ tank, onSelect }: TankCardProps) {
+ const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const Icon = classIcons[tank.class];
const tankopediaSort = useStore($tankopediaSort);
const discriminator = useMemo(() => {
@@ -155,7 +159,15 @@ export function TankCard({ tank, onSelect }: TankCardProps) {
: 'gray'
}
highContrast={tank.type === TankType.RESEARCHABLE}
- onClick={onSelect ? () => onSelect(tank) : undefined}
+ onClick={() => {
+ onSelect?.(tank);
+ mutateTankopediaPersistent((draft) => {
+ draft.recentlyViewed = uniq([tank.id, ...draft.recentlyViewed]).slice(
+ 0,
+ MAX_RECENTLY_VIEWED,
+ );
+ });
+ }}
className="tank-search-card"
style={{
backgroundImage: `url(${asset(`flags/scratched/${tank.nation}.webp`)})`,
diff --git a/packages/website/src/components/TankSearch/constants.tsx b/packages/website/src/components/TankSearch/constants.tsx
index b5c31148f..5dbcbb450 100644
--- a/packages/website/src/components/TankSearch/constants.tsx
+++ b/packages/website/src/components/TankSearch/constants.tsx
@@ -5,3 +5,5 @@ export const treeTypeOrder = [
TankType.PREMIUM,
TankType.COLLECTOR,
];
+
+export const MAX_RECENTLY_VIEWED = 9;
diff --git a/packages/website/src/components/TankSearch/index.tsx b/packages/website/src/components/TankSearch/index.tsx
index cc2db5552..6e37b7bfc 100644
--- a/packages/website/src/components/TankSearch/index.tsx
+++ b/packages/website/src/components/TankSearch/index.tsx
@@ -12,11 +12,12 @@ import {
import { useStore } from '@nanostores/react';
import { Callout, Flex, Link, Text, type FlexProps } from '@radix-ui/themes';
import fuzzysort from 'fuzzysort';
-import { times } from 'lodash-es';
+import { times, uniq } from 'lodash-es';
import { memo, useEffect, useMemo, useState } from 'react';
import { filterTank } from '../../core/blitzkit/filterTank';
import { resolveReload } from '../../core/blitzkit/resolveReload';
import { $tankFilters } from '../../stores/tankFilters';
+import { TankopediaPersistent } from '../../stores/tankopediaPersistent';
import {
SORT_NAMES,
SORT_UNITS,
@@ -25,11 +26,12 @@ import { $tankopediaSort } from '../../stores/tankopediaSort';
import { ExperimentIcon } from '../ExperimentIcon';
import { FilterControl } from './components/FilterControl';
import { NoResults } from './components/NoResults';
+import { RecentlyViewed } from './components/RecentlyViewed';
import { SearchBar } from './components/SearchBar';
import { SkeletonTankCard } from './components/SkeletonTankCard';
import { TankCard } from './components/TankCard';
import { TankCardWrapper } from './components/TankCardWrapper';
-import { treeTypeOrder } from './constants';
+import { MAX_RECENTLY_VIEWED, treeTypeOrder } from './constants';
type TankSearchProps = Omit & {
compact?: boolean;
@@ -47,10 +49,10 @@ const tankNames = await fetchTankNames();
export const TankSearch = memo(
({ compact, onSelect, onSelectAll, ...props }) => {
+ const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const awaitedTanksDefinitionsArray = Object.values(tankDefinitions.tanks);
const tankFilters = useStore($tankFilters);
const tankopediaSort = useStore($tankopediaSort);
-
const tanksFiltered = useMemo(() => {
if (tankFilters.search === undefined) {
const filtered = awaitedTanksDefinitionsArray.filter((tank) =>
@@ -443,6 +445,8 @@ export const TankSearch = memo(
)}
+
+
@@ -457,6 +461,12 @@ export const TankSearch = memo(
onClick={(event) => {
event.preventDefault();
onSelectAll(tanksFiltered);
+ mutateTankopediaPersistent((draft) => {
+ draft.recentlyViewed = uniq([
+ ...tanksFiltered.map(({ id }) => id),
+ ...draft.recentlyViewed,
+ ]).slice(0, MAX_RECENTLY_VIEWED);
+ });
}}
>
Select all
diff --git a/packages/website/src/pages/index.astro b/packages/website/src/pages/index.astro
index e4b365a98..ae1a31e75 100644
--- a/packages/website/src/pages/index.astro
+++ b/packages/website/src/pages/index.astro
@@ -34,7 +34,7 @@ const testTanks = tanks
const mostPlayedTanks = tankAverages
.sort((a, b) => b.samples.d_1 - a.samples.d_1)
.map(({ id }) => tankDefinitions.tanks[id])
- .filter(Boolean);
+ .filter((tank) => tank !== undefined && !tank.testing);
const popularTanks = [...testTanks, ...mostPlayedTanks].slice(0, 8);
---
diff --git a/packages/website/src/pages/tools/compare/_index.tsx b/packages/website/src/pages/tools/compare/_index.tsx
index d993ba14b..104247bed 100644
--- a/packages/website/src/pages/tools/compare/_index.tsx
+++ b/packages/website/src/pages/tools/compare/_index.tsx
@@ -18,6 +18,7 @@ import { tankToCompareMember } from '../../../core/blitzkit/tankToCompareMember'
import { App } from '../../../stores/app';
import { CompareEphemeral } from '../../../stores/compareEphemeral';
import { ComparePersistent } from '../../../stores/comparePersistent';
+import { TankopediaPersistent } from '../../../stores/tankopediaPersistent';
const modelDefinitions = await fetchModelDefinitions();
const equipmentDefinitions = await fetchEquipmentDefinitions();
@@ -28,11 +29,15 @@ const tankDefinitions = await fetchTankDefinitions();
export function Page() {
return (
-
-
-
-
-
+
+
+
+
+
+
+
);
}
diff --git a/packages/website/src/pages/tools/tankopedia/_index.tsx b/packages/website/src/pages/tools/tankopedia/_index.tsx
index 016ad352d..583a884c4 100644
--- a/packages/website/src/pages/tools/tankopedia/_index.tsx
+++ b/packages/website/src/pages/tools/tankopedia/_index.tsx
@@ -1,13 +1,16 @@
import { PageWrapper } from '../../../components/PageWrapper';
import { TankSearch } from '../../../components/TankSearch';
import { App } from '../../../stores/app';
+import { TankopediaPersistent } from '../../../stores/tankopediaPersistent';
export function Page() {
return (
-
-
-
+
+
+
+
+
);
}
diff --git a/packages/website/src/pages/tools/tankopedia/index.astro b/packages/website/src/pages/tools/tankopedia/index.astro
index 5238d6985..6e2055143 100644
--- a/packages/website/src/pages/tools/tankopedia/index.astro
+++ b/packages/website/src/pages/tools/tankopedia/index.astro
@@ -5,5 +5,7 @@ import { Page } from './_index';
---
-
+
+
+
diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts
index 032a135d7..770f95dd7 100644
--- a/packages/website/src/stores/tankopediaPersistent/index.ts
+++ b/packages/website/src/stores/tankopediaPersistent/index.ts
@@ -19,6 +19,7 @@ export interface TankopediaPersistentStore {
showSpacedArmor: boolean;
showExternalModules: boolean;
showPrimaryArmor: boolean;
+ recentlyViewed: number[];
sort: {
by: TankopediaSortBy;
@@ -41,6 +42,7 @@ export const TankopediaPersistent = createContextualStore(() =>
showSpacedArmor: true,
showExternalModules: true,
showPrimaryArmor: true,
+ recentlyViewed: [],
sort: {
by: 'meta.none',
direction: 'ascending',