mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 03:29:51 +02:00
feat: recently veiwed tanks
This commit is contained in:
1 parent
ea013c4df8
commit
387a67266f
9 files changed
+80
-14
No files matched your search
@@ -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 (
|
||||
<Flex direction="column" gap="2" mt="2" mb="6">
|
||||
<Text color="gray" align="center">
|
||||
Recently viewed
|
||||
</Text>
|
||||
<TankCardWrapper>
|
||||
{recentlyViewed.map((id) => (
|
||||
<TankCard tank={tankDefinitions.tanks[id]} key={id} />
|
||||
))}
|
||||
</TankCardWrapper>
|
||||
|
||||
<Separator size="4" />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -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`)})`,
|
||||
|
||||
@@ -5,3 +5,5 @@ export const treeTypeOrder = [
|
||||
TankType.PREMIUM,
|
||||
TankType.COLLECTOR,
|
||||
];
|
||||
|
||||
export const MAX_RECENTLY_VIEWED = 9;
|
||||
@@ -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<FlexProps, 'onSelect'> & {
|
||||
compact?: boolean;
|
||||
@@ -47,10 +49,10 @@ const tankNames = await fetchTankNames();
|
||||
|
||||
export const TankSearch = memo<TankSearchProps>(
|
||||
({ 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<TankSearchProps>(
|
||||
<FilterControl compact={compact} />
|
||||
)}
|
||||
|
||||
<RecentlyViewed />
|
||||
|
||||
<Flex mt="2" gap="1" align="center" justify="center" direction="column">
|
||||
<Flex gap="2">
|
||||
<Text color="gray">
|
||||
@@ -457,6 +461,12 @@ export const TankSearch = memo<TankSearchProps>(
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
onSelectAll(tanksFiltered);
|
||||
mutateTankopediaPersistent((draft) => {
|
||||
draft.recentlyViewed = uniq([
|
||||
...tanksFiltered.map(({ id }) => id),
|
||||
...draft.recentlyViewed,
|
||||
]).slice(0, MAX_RECENTLY_VIEWED);
|
||||
});
|
||||
}}
|
||||
>
|
||||
Select all
|
||||
|
||||
Reference in new issue
Block a user