2024-11-16 23:11:31 -06:00
|
|
|
import { asset, tankIcon, TankType, type TankDefinition } from '@blitzkit/core';
|
|
|
|
|
import { Flex, Link, Text, type TextProps } from '@radix-ui/themes';
|
2024-11-11 10:50:15 -06:00
|
|
|
import { uniq } from 'lodash-es';
|
2024-12-12 15:03:51 -06:00
|
|
|
import { forwardRef, type ReactNode } from 'react';
|
2024-11-16 22:47:12 -06:00
|
|
|
import { TankopediaPersistent } from '../../stores/tankopediaPersistent';
|
|
|
|
|
import { classIcons } from '../ClassIcon';
|
|
|
|
|
import { MAX_RECENTLY_VIEWED } from '../TankSearch/constants';
|
2024-11-02 18:23:30 -05:00
|
|
|
import './index.css';
|
2024-06-21 14:03:20 -05:00
|
|
|
|
2024-11-16 23:11:31 -06:00
|
|
|
type TankCardProps = TextProps & {
|
2024-06-21 14:03:20 -05:00
|
|
|
tank: TankDefinition;
|
2024-11-16 23:11:31 -06:00
|
|
|
onTankSelect?: (tank: TankDefinition) => void;
|
2024-12-12 21:10:50 -06:00
|
|
|
discriminator?: ReactNode;
|
2024-11-16 23:11:31 -06:00
|
|
|
noLink?: boolean;
|
|
|
|
|
};
|
2024-06-21 14:03:20 -05:00
|
|
|
|
2024-11-16 23:11:31 -06:00
|
|
|
export const TankCard = forwardRef<HTMLSpanElement, TankCardProps>(
|
|
|
|
|
(
|
|
|
|
|
{
|
|
|
|
|
tank,
|
|
|
|
|
discriminator,
|
|
|
|
|
onTankSelect: onSelect,
|
|
|
|
|
noLink,
|
|
|
|
|
style,
|
|
|
|
|
...props
|
|
|
|
|
}: TankCardProps,
|
|
|
|
|
ref,
|
|
|
|
|
) => {
|
|
|
|
|
const provideLink = !noLink && onSelect === undefined;
|
|
|
|
|
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
|
|
|
|
|
const Icon = classIcons[tank.class];
|
2024-10-05 16:44:07 -05:00
|
|
|
|
2024-11-16 23:11:31 -06:00
|
|
|
return (
|
|
|
|
|
<Text
|
|
|
|
|
ref={ref}
|
|
|
|
|
tabIndex={onSelect ? 0 : undefined}
|
|
|
|
|
size="1"
|
|
|
|
|
color={
|
|
|
|
|
tank.type === TankType.COLLECTOR
|
|
|
|
|
? 'blue'
|
|
|
|
|
: tank.type === TankType.PREMIUM
|
|
|
|
|
? 'amber'
|
|
|
|
|
: 'gray'
|
|
|
|
|
}
|
|
|
|
|
highContrast={tank.type === TankType.RESEARCHABLE}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
onSelect?.(tank);
|
|
|
|
|
mutateTankopediaPersistent((draft) => {
|
|
|
|
|
draft.recentlyViewed = uniq([
|
|
|
|
|
tank.id,
|
|
|
|
|
...draft.recentlyViewed,
|
|
|
|
|
]).slice(0, MAX_RECENTLY_VIEWED);
|
|
|
|
|
});
|
2024-10-18 10:48:19 -05:00
|
|
|
}}
|
2024-11-16 23:11:31 -06:00
|
|
|
className="tank-search-card"
|
|
|
|
|
data-provide-link={provideLink}
|
|
|
|
|
style={{
|
|
|
|
|
backgroundImage: `url(${asset(`flags/scratched/${tank.nation}.webp`)})`,
|
|
|
|
|
...style,
|
|
|
|
|
}}
|
|
|
|
|
{...props}
|
2024-06-21 14:03:20 -05:00
|
|
|
>
|
2024-11-16 23:11:31 -06:00
|
|
|
<Link
|
|
|
|
|
className="link"
|
|
|
|
|
underline="hover"
|
|
|
|
|
href={provideLink ? `/tools/tankopedia/${tank.id}` : undefined}
|
2024-06-22 16:39:31 -05:00
|
|
|
>
|
2024-11-16 23:11:31 -06:00
|
|
|
<img
|
|
|
|
|
alt={tank.name}
|
|
|
|
|
src={tankIcon(tank.id)}
|
|
|
|
|
className="image"
|
|
|
|
|
draggable={false}
|
|
|
|
|
/>
|
2024-07-12 19:23:15 -05:00
|
|
|
|
2024-11-16 23:11:31 -06:00
|
|
|
<Flex
|
|
|
|
|
justify="center"
|
|
|
|
|
gap="1"
|
2024-07-12 19:23:15 -05:00
|
|
|
align="center"
|
2024-11-16 23:11:31 -06:00
|
|
|
overflow="hidden"
|
|
|
|
|
width="100%"
|
2024-07-12 19:23:15 -05:00
|
|
|
>
|
2024-11-16 23:11:31 -06:00
|
|
|
<Icon className="class-icon" />
|
|
|
|
|
<Text align="center" className="name">
|
|
|
|
|
{tank.name}
|
|
|
|
|
</Text>
|
|
|
|
|
</Flex>
|
|
|
|
|
|
|
|
|
|
{discriminator && (
|
|
|
|
|
<Text
|
|
|
|
|
color="gray"
|
|
|
|
|
align="center"
|
|
|
|
|
style={{
|
|
|
|
|
whiteSpace: 'nowrap',
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
textOverflow: 'ellipsis',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{discriminator}
|
|
|
|
|
</Text>
|
|
|
|
|
)}
|
|
|
|
|
</Link>
|
|
|
|
|
</Text>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|