From 64d346ccb6363f742ac935ec79a8bc0188c8f0d9 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Tue, 15 Apr 2025 16:54:36 -0500 Subject: [PATCH] feat: in-hero controls --- .../Tankopedia/HeroSection/index.tsx | 141 +++++++++++++++--- .../Tankopedia/MetaSection/index.tsx | 79 +--------- 2 files changed, 120 insertions(+), 100 deletions(-) diff --git a/packages/website/src/components/Tankopedia/HeroSection/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/index.tsx index 1d9504392..d99e68206 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/index.tsx @@ -1,9 +1,13 @@ -import { TankType } from '@blitzkit/core'; -import { Box, Flex, Heading, Spinner, Text } from '@radix-ui/themes'; +import { assertSecret, TankType } from '@blitzkit/core'; +import { CaretLeftIcon, MixIcon, UpdateIcon } from '@radix-ui/react-icons'; +import { Box, Dialog, Flex, Heading, Link, Spinner } from '@radix-ui/themes'; import { times } from 'lodash-es'; -import { Suspense, useEffect, useMemo, useRef } from 'react'; +import { Suspense, useEffect, useMemo, useRef, useState } from 'react'; import { NAVBAR_HEIGHT } from '../../../constants/navbar'; +import { awaitableModelDefinitions } from '../../../core/awaitables/modelDefinitions'; +import { awaitableProvisionDefinitions } from '../../../core/awaitables/provisionDefinitions'; import { awaitableTankDefinitions } from '../../../core/awaitables/tankDefinitions'; +import { tankToDuelMember } from '../../../core/blitzkit/tankToDuelMember'; import { Var } from '../../../core/radix/var'; import { useFullScreen } from '../../../hooks/useFullScreen'; import { useLocale } from '../../../hooks/useLocale'; @@ -12,18 +16,27 @@ import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; import type { MaybeSkeletonComponentProps } from '../../../types/maybeSkeletonComponentProps'; import type { ThicknessRange } from '../../Armor/components/StaticArmor'; import { classIcons } from '../../ClassIcon'; +import { ScienceIcon } from '../../ScienceIcon'; +import { TankSearch } from '../../TankSearch'; import { Options } from './components/Options'; import { TankSandbox } from './components/TankSandbox'; -const tankDefinitions = await awaitableTankDefinitions; +const [provisionDefinitions, modelDefinitions, tankDefinitions] = + await Promise.all([ + awaitableProvisionDefinitions, + awaitableModelDefinitions, + awaitableTankDefinitions, + ]); export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { + const [showSwapDialog, setShowSwapDialog] = useState(false); const revealed = TankopediaEphemeral.use((state) => state.revealed); const disturbed = TankopediaEphemeral.use((state) => state.disturbed); - const { unwrap } = useLocale(); + const { unwrap, strings } = useLocale(); const canvas = useRef(null); const isFullScreen = useFullScreen(); const protagonist = Duel.use((state) => state.protagonist.tank); + const antagonist = Duel.use((state) => state.antagonist.tank); const Icon = classIcons[protagonist.class]; const treeColor = protagonist.type === TankType.COLLECTOR @@ -31,6 +44,10 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { : protagonist.type === TankType.PREMIUM ? 'amber' : undefined; + const compareTanks = + protagonist.id === antagonist.id + ? [protagonist.id] + : [protagonist.id, antagonist.id]; const thicknessRange = useMemo(() => { const entries = Object.values(tankDefinitions.tanks); const filtered = entries.filter( @@ -152,10 +169,10 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { userSelect: 'none', }} direction="column" - align={{ initial: 'center', md: 'start' }} - gap={disturbed ? '0' : { initial: '0', md: '2' }} + align={{ initial: 'center', md: 'center' }} + gap="1" > - + - - + + + + {strings.website.tools.tankopedia.meta.back} + + + + - BlitzKit Tankopedia - - + + + {strings.website.tools.tankopedia.meta.compare} + + + + + + { + event.preventDefault(); + setShowSwapDialog(true); + }} + > + + + {strings.website.tools.tankopedia.meta.swap.button} + + + + + + + {strings.website.tools.tankopedia.meta.swap.title} + + + { + const model = modelDefinitions.models[tank.id]; + + setShowSwapDialog(false); + mutateTankopediaEphemeral((draft) => { + draft.model = modelDefinitions.models[tank.id]; + }); + mutateDuel((draft) => { + draft.protagonist = tankToDuelMember( + tank, + model, + provisionDefinitions, + ); + }); + + window.history.replaceState( + null, + '', + `/tools/tankopedia/${tank.id}`, + ); + }} + /> + + + + {assertSecret(import.meta.env.PUBLIC_PROMOTE_OPENTEST) === + 'true' && ( + + + + {assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH) === + 'opentest' + ? strings.website.tools.tankopedia.meta.vanilla + : strings.website.tools.tankopedia.meta.opentest} + + + )} + diff --git a/packages/website/src/components/Tankopedia/MetaSection/index.tsx b/packages/website/src/components/Tankopedia/MetaSection/index.tsx index 0a0f6e0b8..88f4b6b70 100644 --- a/packages/website/src/components/Tankopedia/MetaSection/index.tsx +++ b/packages/website/src/components/Tankopedia/MetaSection/index.tsx @@ -29,8 +29,8 @@ const [provisionDefinitions, modelDefinitions] = await Promise.all([ export function MetaSection() { const developerMode = App.useDeferred((state) => state.developerMode, false); const protagonist = Duel.use((state) => state.protagonist.tank); - const ClassIcon = classIcons[protagonist.class]; const antagonist = Duel.use((state) => state.antagonist.tank); + const ClassIcon = classIcons[protagonist.class]; const compareTanks = protagonist.id === antagonist.id ? [protagonist.id] @@ -43,82 +43,7 @@ export function MetaSection() { return ( - - - - - - - - - - {assertSecret(import.meta.env.PUBLIC_PROMOTE_OPENTEST) === 'true' && ( - - - - )} - - - - - - - - - {strings.website.tools.tankopedia.meta.swap.title} - - - { - const model = modelDefinitions.models[tank.id]; - - setShowSwapDialog(false); - mutateTankopediaEphemeral((draft) => { - draft.model = modelDefinitions.models[tank.id]; - }); - mutateDuel((draft) => { - draft.protagonist = tankToDuelMember( - tank, - model, - provisionDefinitions, - ); - }); - - window.history.replaceState( - null, - '', - `/tools/tankopedia/${tank.id}`, - ); - }} - /> - - - +