feat: swap button

This commit is contained in:
TrèsAbhi committed 2024-09-01 18:00:15 -05:00
1 parent ee9dbdaf74
commit 13faad0977
3 files changed
+81 -31

No files matched your search

@@ -12,11 +12,7 @@ import { TankSandbox } from './TankSandbox';
import { TankSandboxLoader } from './TankSandboxLoader'; import { TankSandboxLoader } from './TankSandboxLoader';
import { Options } from './components/Options'; import { Options } from './components/Options';
interface HeroSectionProps { export function HeroSection() {
id: number;
}
export function HeroSection({ id }: HeroSectionProps) {
const canvas = useRef<HTMLCanvasElement>(null); const canvas = useRef<HTMLCanvasElement>(null);
const isFullScreen = useFullScreen(); const isFullScreen = useFullScreen();
const protagonist = Duel.use((state) => state.protagonist.tank); const protagonist = Duel.use((state) => state.protagonist.tank);
@@ -29,10 +25,11 @@ export function HeroSection({ id }: HeroSectionProps) {
? 'amber' ? 'amber'
: undefined; : undefined;
const awaitedTankDefinitions = use(tankDefinitions); const awaitedTankDefinitions = use(tankDefinitions);
const tank = awaitedTankDefinitions[id];
const thicknessRange = useMemo(() => { const thicknessRange = useMemo(() => {
const entries = Object.values(awaitedTankDefinitions); const entries = Object.values(awaitedTankDefinitions);
const filtered = entries.filter((thisTank) => thisTank.tier === tank.tier); const filtered = entries.filter(
(thisTank) => thisTank.tier === protagonist.tier,
);
const value = const value =
(filtered.reduce((accumulator, thisTank) => { (filtered.reduce((accumulator, thisTank) => {
return ( return (
@@ -46,7 +43,7 @@ export function HeroSection({ id }: HeroSectionProps) {
(3 / 4); (3 / 4);
return { value } satisfies ThicknessRange; return { value } satisfies ThicknessRange;
}, [tank.tier]); }, [protagonist]);
useEffect(() => { useEffect(() => {
setDummyLoader(false); setDummyLoader(false);
@@ -90,7 +87,7 @@ export function HeroSection({ id }: HeroSectionProps) {
> >
<Flex align="center" gap="3"> <Flex align="center" gap="3">
<Icon width="0.8em" height="0.8em" /> <Icon width="0.8em" height="0.8em" />
{tank.name} {protagonist.name}
</Flex> </Flex>
</Heading> </Heading>
@@ -114,14 +111,14 @@ export function HeroSection({ id }: HeroSectionProps) {
<Box width="100%" height="100%" position="absolute"> <Box width="100%" height="100%" position="absolute">
<Box width="100%" height="100%"> <Box width="100%" height="100%">
<TankSandboxLoader <TankSandboxLoader
id={id} id={protagonist.id}
display={dummyLoader ? 'flex' : 'none'} display={dummyLoader ? 'flex' : 'none'}
/> />
<Suspense <Suspense
fallback={ fallback={
<TankSandboxLoader <TankSandboxLoader
id={id} id={protagonist.id}
display={dummyLoader ? 'none' : 'flex'} display={dummyLoader ? 'none' : 'flex'}
/> />
} }
@@ -1,11 +1,17 @@
import { ChevronLeftIcon, MixIcon } from '@radix-ui/react-icons'; import { ChevronLeftIcon, MixIcon, UpdateIcon } from '@radix-ui/react-icons';
import { Button, Code, Flex } from '@radix-ui/themes'; import { Button, Code, Dialog, Flex } from '@radix-ui/themes';
import { use, useState } from 'react';
import { classIcons } from '../../../../../../../components/ClassIcon'; import { classIcons } from '../../../../../../../components/ClassIcon';
import { Link } from '../../../../../../../components/Link'; import { Link } from '../../../../../../../components/Link';
import { asset } from '../../../../../../../core/blitzkit/asset'; import { asset } from '../../../../../../../core/blitzkit/asset';
import { modelDefinitions } from '../../../../../../../core/blitzkit/modelDefinitions';
import { provisionDefinitions } from '../../../../../../../core/blitzkit/provisionDefinitions';
import { tankToDuelMember } from '../../../../../../../core/blitzkit/tankToDuelMember';
import strings from '../../../../../../../lang/en-US.json'; import strings from '../../../../../../../lang/en-US.json';
import * as App from '../../../../../../../stores/app'; import * as App from '../../../../../../../stores/app';
import * as Duel from '../../../../../../../stores/duel'; import * as Duel from '../../../../../../../stores/duel';
import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral';
import { TankSearch } from '../../../../components/TankSearch';
import { Listing } from './components/Listing'; import { Listing } from './components/Listing';
import { Votes } from './components/Votes'; import { Votes } from './components/Votes';
@@ -18,6 +24,11 @@ export function MetaSection() {
protagonist.id === antagonist.id protagonist.id === antagonist.id
? [protagonist.id] ? [protagonist.id]
: [protagonist.id, antagonist.id]; : [protagonist.id, antagonist.id];
const mutateDuel = Duel.useMutation();
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const awaitedProvisionDefinitions = use(provisionDefinitions);
const [showSwapDialog, setShowSwapDialog] = useState(false);
const awaitedModelDefinitions = use(modelDefinitions);
return ( return (
<Flex justify="center" align="center"> <Flex justify="center" align="center">
@@ -31,11 +42,44 @@ export function MetaSection() {
</Link> </Link>
<Link href={`/tools/compare?tanks=${compareTanks.join('%2C')}`}> <Link href={`/tools/compare?tanks=${compareTanks.join('%2C')}`}>
<Button> <Button variant="outline">
<MixIcon /> <MixIcon />
Compare Compare
</Button> </Button>
</Link> </Link>
<Dialog.Root open={showSwapDialog} onOpenChange={setShowSwapDialog}>
<Dialog.Trigger>
<Button>
<UpdateIcon />
Swap
</Button>
</Dialog.Trigger>
<Dialog.Content>
<TankSearch
compact
onSelect={(tank) => {
setShowSwapDialog(false);
mutateTankopediaEphemeral((draft) => {
draft.model = awaitedModelDefinitions[tank.id];
});
mutateDuel((draft) => {
draft.protagonist = tankToDuelMember(
tank,
awaitedProvisionDefinitions,
);
});
window.history.replaceState(
null,
'',
`/tools/tankopedia/${tank.id}`,
);
}}
/>
</Dialog.Content>
</Dialog.Root>
</Flex> </Flex>
<Flex <Flex
+26 -17
View File
@@ -4,7 +4,9 @@ import { invalidate } from '@react-three/fiber';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { AdMidSectionResponsive } from '../../../../components/AdMidSectionResponsive'; import { AdMidSectionResponsive } from '../../../../components/AdMidSectionResponsive';
import PageWrapper from '../../../../components/PageWrapper'; import PageWrapper from '../../../../components/PageWrapper';
import { TIER_ROMAN_NUMERALS } from '../../../../core/blitzkit/tankDefinitions/constants';
import { useAdExempt } from '../../../../hooks/useAdExempt'; import { useAdExempt } from '../../../../hooks/useAdExempt';
import strings from '../../../../lang/en-US.json';
import * as Duel from '../../../../stores/duel'; import * as Duel from '../../../../stores/duel';
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral'; import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
import { CalloutsSection } from './components/CalloutsSection'; import { CalloutsSection } from './components/CalloutsSection';
@@ -14,14 +16,18 @@ import { GameModeSection } from './components/Model/GameModeSection';
import { HeroSection } from './components/Model/HeroSection'; import { HeroSection } from './components/Model/HeroSection';
import { MetaSection } from './components/Model/MetaSection'; import { MetaSection } from './components/Model/MetaSection';
import { TechTreeSection } from './components/Model/TechTreeSection'; import { TechTreeSection } from './components/Model/TechTreeSection';
import { ShotDisplaySection } from './components/ShotDisplaySection';
import { VideoSection } from './components/VideoSection'; import { VideoSection } from './components/VideoSection';
export default function Page({ params }: { params: { id: string } }) { export default function Page() {
const id = Number(params.id);
const exempt = useAdExempt(); const exempt = useAdExempt();
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const duelStore = Duel.useStore(); const duelStore = Duel.useStore();
const tank = Duel.use((state) => state.protagonist.tank);
const title = `${tank.name} - Tier ${TIER_ROMAN_NUMERALS[tank.tier]} ${
(strings.common.nations_adjectives as Record<string, string>)[tank.nation]
} ${strings.common.tank_class_short[tank.class]}`;
useEffect(() => { useEffect(() => {
function handleKeyDown(event: KeyboardEvent) { function handleKeyDown(event: KeyboardEvent) {
@@ -79,20 +85,23 @@ export default function Page({ params }: { params: { id: string } }) {
}, []); }, []);
return ( return (
<PageWrapper p="0" noMaxWidth color="purple" size={1600} gap="9"> <>
<HeroSection id={id} /> <title>{title}</title>
<CalloutsSection />
<MetaSection /> <PageWrapper p="0" noMaxWidth color="purple" size={1600} gap="9">
{/* <VotingSection /> */} <HeroSection />
{/* <ShotDisplaySection /> */} <MetaSection />
<TechTreeSection /> <ShotDisplaySection />
{!exempt && <AdMidSectionResponsive />} <TechTreeSection />
<CharacteristicsSection /> {!exempt && <AdMidSectionResponsive />}
{!exempt && <AdMidSectionResponsive />} <CalloutsSection />
<GameModeSection /> <CharacteristicsSection />
<VideoSection /> {!exempt && <AdMidSectionResponsive />}
<HistorySection /> <GameModeSection />
{!exempt && <AdMidSectionResponsive mb="6" />} <VideoSection />
</PageWrapper> <HistorySection />
{!exempt && <AdMidSectionResponsive mb="6" />}
</PageWrapper>
</>
); );
} }