diff --git a/packages/website-legacy/src/app/tools/compare/layout.tsx b/packages/website-legacy/src/app/tools/compare/layout.tsx deleted file mode 100644 index 6f918444a..000000000 --- a/packages/website-legacy/src/app/tools/compare/layout.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ReactNode } from 'react'; -import * as CompareEphemeral from '../../../stores/compareEphemeral'; -import * as ComparePersistent from '../../../stores/comparePersistent'; -import * as TankFilters from '../../../stores/tankFilters'; -import * as TankopediaSort from '../../../stores/tankopediaSort'; - -export default function Layout({ children }: { children: ReactNode }) { - return ( - - - - {children} - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/compare/page.tsx b/packages/website-legacy/src/app/tools/compare/page.tsx deleted file mode 100644 index ef040ba35..000000000 --- a/packages/website-legacy/src/app/tools/compare/page.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { createDefaultSkills } from '@blitzkit/core'; -import { PlusIcon } from '@radix-ui/react-icons'; -import { Box, Flex, Heading, IconButton, Text } from '@radix-ui/themes'; -import { usePathname, useRouter, useSearchParams } from 'next/navigation'; -import { use, useCallback, useEffect, useMemo, useState } from 'react'; - -export default function Page() { - const pathname = usePathname(); - const router = useRouter(); - const awaitedTankDefinitions = use(tankDefinitions); - const awaitedSkillDefinitions = use(skillDefinitions); - const searchParams = useSearchParams(); - const members = CompareEphemeral.use((state) => state.members); - const [addTankDialogOpen, setAddTankDialogOpen] = useState(false); - const awaitedModelDefinitions = use(modelDefinitions); - const awaitedEquipmentDefinitions = use(equipmentDefinitions); - const awaitedProvisionDefinitions = use(provisionDefinitions); - const crewSkills = CompareEphemeral.use((state) => state.crewSkills); - const mutateCompareEphemeral = CompareEphemeral.useMutation(); - const stats = useMemo[]>( - () => - members.map((thisMember) => - tankCharacteristics( - { - ...thisMember, - crewSkills, - stockEngine: thisMember.tank.engines[0], - stockGun: thisMember.tank.turrets[0].guns[0], - stockTrack: thisMember.tank.tracks[0], - stockTurret: thisMember.tank.turrets[0], - applyReactiveArmor: members.some( - (member) => - member.key !== thisMember.key && - member.consumables.includes(33), - ), - applyDynamicArmor: members.some( - (member) => - member.key !== thisMember.key && - member.consumables.includes(73), - ), - applySpallLiner: members.some( - (member) => - member.key !== thisMember.key && - member.provisions.includes(101), - ), - }, - { - equipmentDefinitions: awaitedEquipmentDefinitions, - provisionDefinitions: awaitedProvisionDefinitions, - tankModelDefinition: awaitedModelDefinitions[thisMember.tank.id], - }, - ), - ), - [members, crewSkills], - ); - const createQueryString = useCallback( - (name: string, value: string) => { - const params = new URLSearchParams(searchParams.toString()); - params.set(name, value); - - return params.toString(); - }, - [searchParams], - ); - - useEffect(() => { - router.push( - pathname + - '?' + - createQueryString( - 'tanks', - members.map(({ tank }) => tank.id).join(','), - ), - ); - }, [members]); - - useEffect(() => { - const tanksParam = searchParams.get('tanks'); - - if (tanksParam) { - mutateCompareEphemeral((draft) => { - draft.members = tanksParam - .split(',') - .map(Number) - .map((id) => - tankToCompareMember( - awaitedTankDefinitions[id], - awaitedProvisionDefinitions, - ), - ); - }); - } - - if (Object.keys(crewSkills).length === 0) { - mutateCompareEphemeral((draft) => { - draft.crewSkills = createDefaultSkills(awaitedSkillDefinitions); - }); - } - }, []); - - return ( - - - - - - - {members.length > 0 && ( - - - - - setAddTankDialogOpen(true)} - > - - - - - )} - - {members.length === 0 && ( - - No tanks selected - - Press the Add button to get started - - - )} - - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Boolean.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Boolean.tsx deleted file mode 100644 index 9d5544f4c..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Boolean.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Switch } from '@radix-ui/themes'; -import * as EmbedState from '../../../../../stores/embedState'; -import { EmbedPreviewControllerProps } from '../page'; - -export function Boolean({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - - return ( - state[configKey] as boolean)} - onCheckedChange={() => { - mutateEmbedState((draft) => { - draft[configKey] = !draft[configKey]; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Color/components/ColorControllerRaw.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Color/components/ColorControllerRaw.tsx deleted file mode 100644 index c547720a6..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Color/components/ColorControllerRaw.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Slider } from '@radix-ui/themes'; - -interface ColorControllerRawProps { - value: string; - onValueChange: (value: string) => void; -} - -export function ColorControllerRaw({ - value, - onValueChange, -}: ColorControllerRawProps) { - const tintString = value.slice(0, 7); - const alphaString = value.slice(7, 9); - const alpha = alphaString.length === 0 ? 255 : parseInt(alphaString, 16); - - return ( - <> - { - let alpha = value.slice(7, 9); - if (alpha.length === 0) alpha = 'ff'; - onValueChange(`${event.target.value}${alpha}`); - }} - /> - { - onValueChange(`${tintString}${value.toString(16)}`); - }} - /> - > - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Color/index.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Color/index.tsx deleted file mode 100644 index e3af73a7b..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Color/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as EmbedState from '../../../../../../stores/embedState'; -import { EmbedPreviewControllerProps } from '../../page'; -import { ColorControllerRaw } from './components/ColorControllerRaw'; - -export function Color({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - const color = EmbedState.use((state) => state[configKey] as string); - - return ( - { - mutateEmbedState((draft) => { - draft[configKey] = value; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Enum.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Enum.tsx deleted file mode 100644 index 08f3ae402..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Enum.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Select } from '@radix-ui/themes'; -import * as EmbedState from '../../../../../stores/embedState'; -import { - EmbedConfigItemType, - EmbedItemType, -} from '../../../../../stores/embedState/constants'; -import { EmbedPreviewControllerProps } from '../page'; - -export function Enum({ - configKey, - config, -}: EmbedPreviewControllerProps & { - config: EmbedConfigItemType; -}) { - const mutateEmbedState = EmbedState.useMutation(); - - return ( - state[configKey] as string)} - onValueChange={(value) => { - mutateEmbedState((draft) => { - draft[configKey] = value; - }); - }} - > - - - {config.options.map((option) => ( - - {option.label} - - ))} - - - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Import.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Import.tsx deleted file mode 100644 index 373a0251b..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Import.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { - AlertDialog, - Button, - Flex, - Heading, - Text, - TextField, - Tooltip, -} from '@radix-ui/themes'; -import { useRef, useState } from 'react'; -import * as EmbedState from '../../../../../stores/embedState'; - -export function Import() { - const importInput = useRef(null); - const [showInvalidURLPrompt, setShowInvalidURLPrompt] = useState(false); - const [showConfirmation, setConfirmation] = useState(false); - const mutateEmbedState = EmbedState.useMutation(); - - return ( - <> - Import - - Paste your current URL if you have one already to import your settings - - - - - Invalid URL - - Try pasting the URL that BlitzKit previously generated, you silly - goose! - - - - - Okay, my bad - - - - - - - - - { - if (!importInput.current) return; - - try { - const url = new URL(importInput.current.value); - const state = url.searchParams.get('state'); - if (state === null) throw undefined; - const json = JSON.parse(state); - - mutateEmbedState((draft) => { - Object.assign(draft, json); - }); - - importInput.current.value = ''; - setConfirmation(true); - setTimeout(() => setConfirmation(false), 2000); - } catch { - setShowInvalidURLPrompt(true); - } - }} - > - Apply - - - - > - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/PreviewWrapper/index.css.ts b/packages/website-legacy/src/app/tools/embed/[embed]/components/PreviewWrapper/index.css.ts deleted file mode 100644 index 8f6c18989..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/PreviewWrapper/index.css.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { keyframes, style } from '@vanilla-extract/css'; - -const fadeOutBorder = keyframes({ - from: { - outline: '1rem solid #ff0000ff', - }, - to: { - outline: '1rem solid #ff000000', - }, -}); - -export const wrapper = style({ - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - overflow: 'hidden', -}); - -export const animated = style({ - animation: `${fadeOutBorder} 0.5s linear`, - - ':hover': { - outline: '1rem solid #ff000080', - }, -}); diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/PreviewWrapper/index.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/PreviewWrapper/index.tsx deleted file mode 100644 index 65932bdc5..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/PreviewWrapper/index.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Box } from '@radix-ui/themes'; -import { useEffect, useRef } from 'react'; -import { previews } from '../../../../../../../../website/src/constants/embeds'; -import { useEmbedStateCurry } from '../../../../../../stores/embedState/utilities'; -import * as styles from './index.css'; - -interface PreviewWrapperProps { - name: keyof typeof previews; -} - -export function PreviewWrapper({ name }: PreviewWrapperProps) { - const { useState } = useEmbedStateCurry(); - const width = useState('width'); - const height = useState('height'); - const Preview = previews[name]; - const wrapper = useRef(null); - - useEffect(() => { - if (!wrapper.current) return; - - wrapper.current.classList.remove(styles.animated); - void wrapper.current.offsetWidth; - wrapper.current.classList.add(styles.animated); - }, [width, height]); - - return ( - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Radius.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Radius.tsx deleted file mode 100644 index 9f2846903..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Radius.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Slider } from '@radix-ui/themes'; -import * as EmbedState from '../../../../../stores/embedState'; -import { EmbedPreviewControllerProps } from '../page'; - -export function Radius({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - - return ( - { - const radius = state[configKey] as EmbedState.RadixRadius; - return radius === 'full' ? 5 : parseInt(radius); - }), - ]} - onValueChange={([value]) => { - mutateEmbedState((draft) => { - draft[configKey] = value === 5 ? 'full' : `${value}`; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/RichText.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/RichText.tsx deleted file mode 100644 index dd5a5e92a..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/RichText.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import * as EmbedState from '../../../../../stores/embedState'; -import { - EmbedConfigItemType, - EmbedItemType, -} from '../../../../../stores/embedState/constants'; -import { EmbedPreviewControllerProps } from '../page'; -import { ColorControllerRaw } from './Color/components/ColorControllerRaw'; - -export function RichText({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - const state = EmbedState.use( - (state) => - state[ - configKey - ] as EmbedConfigItemType['default'], - ); - - return ( - { - mutateEmbedState((draft) => { - ( - draft[ - configKey - ] as EmbedConfigItemType['default'] - ).color = value; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Size.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Size.tsx deleted file mode 100644 index 889450d19..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Size.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Slider } from '@radix-ui/themes'; -import * as EmbedState from '../../../../../stores/embedState'; -import { EmbedPreviewControllerProps } from '../page'; - -export function Size({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - - return ( - - parseInt(state[configKey] as EmbedState.RadixSize), - ), - ]} - onValueChange={([value]) => { - mutateEmbedState((draft) => { - draft[configKey] = `${value}`; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/SizeWithout0.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/SizeWithout0.tsx deleted file mode 100644 index fb7344d1a..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/SizeWithout0.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Slider } from '@radix-ui/themes'; -import * as EmbedState from '../../../../../stores/embedState'; -import { EmbedPreviewControllerProps } from '../page'; - -export function SizeWithout0({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - - return ( - - parseInt(state[configKey] as EmbedState.RadixSizeWithout0), - ), - ]} - onValueChange={([value]) => { - mutateEmbedState((draft) => { - draft[configKey] = `${value}`; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Slider.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Slider.tsx deleted file mode 100644 index ef330ea9d..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Slider.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Slider as RadixSlider } from '@radix-ui/themes'; -import * as EmbedState from '../../../../../stores/embedState'; -import { - EmbedConfigItemType, - EmbedItemType, -} from '../../../../../stores/embedState/constants'; -import { EmbedPreviewControllerProps } from '../page'; - -export function Slider({ - configKey, - config, -}: EmbedPreviewControllerProps & { - config: EmbedConfigItemType; -}) { - const mutateEmbedState = EmbedState.useMutation(); - - return ( - - parseInt(state[configKey] as EmbedState.RadixSize), - ), - ]} - onValueChange={([value]) => { - mutateEmbedState((draft) => { - draft[configKey] = value; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/components/Text.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/components/Text.tsx deleted file mode 100644 index fa8594484..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/components/Text.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { TextField } from '@radix-ui/themes'; -import * as EmbedState from '../../../../../stores/embedState'; -import { EmbedPreviewControllerProps } from '../page'; - -export function Text({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - - return ( - state[configKey] as string)} - onChange={(event) => { - mutateEmbedState((draft) => { - draft[configKey] = event.target.value; - }); - }} - /> - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/host/page.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/host/page.tsx deleted file mode 100644 index 56de3c850..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/host/page.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Code, Heading } from '@radix-ui/themes'; -import { useSearchParams } from 'next/navigation'; -import { useMemo } from 'react'; -import { - configurations, - extractEmbedConfigDefaults, -} from '../../../../../../../website/src/constants/embeds'; -import { PageWrapper } from '../../../../../components/PageWrapper'; -import * as EmbedState from '../../../../../stores/embedState'; - -export interface EmbedPreviewControllerProps { - configKey: string; -} - -export default function Page({ - params, -}: { - params: { embed: keyof typeof configurations }; -}) { - const searchParams = useSearchParams(); - // TODO: check for this? idk lol - const stateParam = searchParams.get('state')!; - const config = configurations[params.embed]; - const initialState = useMemo( - () => ({ - ...extractEmbedConfigDefaults(config), - ...(JSON.parse(stateParam) as EmbedState.EmbedState), - }), - [params.embed], - ); - - return ( - - - - {params.embed} - - - - {JSON.stringify(initialState, null, 2)} - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/layout.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/layout.tsx deleted file mode 100644 index 08bdcc4e7..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/layout.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { useMemo } from 'react'; -import { - configurations, - extractEmbedConfigDefaults, -} from '../../../../../../website/src/constants/embeds'; -import * as EmbedState from '../../../../stores/embedState'; - -export function generateStaticParams() { - return Object.keys(configurations).map((embed) => ({ embed })); -} - -export default function Layout({ - params, - children, -}: { - params: { embed: keyof typeof configurations }; - children: React.ReactNode; -}) { - const config = configurations[params.embed]; - const initialState = useMemo( - () => extractEmbedConfigDefaults(config), - [params.embed], - ); - - return ( - {children} - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/[embed]/page.tsx b/packages/website-legacy/src/app/tools/embed/[embed]/page.tsx deleted file mode 100644 index c586f512c..000000000 --- a/packages/website-legacy/src/app/tools/embed/[embed]/page.tsx +++ /dev/null @@ -1,287 +0,0 @@ -import { imgur } from '@blitzkit/core'; -import { - CodeIcon, - HeightIcon, - ImageIcon, - Link2Icon, - ResetIcon, - TimerIcon, - WidthIcon, -} from '@radix-ui/react-icons'; -import { Box, Button, Flex, Heading, ScrollArea, Text } from '@radix-ui/themes'; -import { capitalize, startCase } from 'lodash-es'; -import { ReactNode, useEffect, useRef, useState } from 'react'; -import { stringify } from 'urlon'; -import { configurations } from '../../../../../../website/src/constants/embeds'; -import { CopyButton } from '../../../../components/CopyButton'; -import { PageWrapper } from '../../../../components/PageWrapper'; -import * as App from '../../../../stores/app'; -import * as EmbedState from '../../../../stores/embedState'; -import { EmbedConfig } from '../../../../stores/embedState'; -import { EmbedItemType } from '../../../../stores/embedState/constants'; -import { Boolean } from './components/Boolean'; -import { Color } from './components/Color'; -import { Enum } from './components/Enum'; -import { Import } from './components/Import'; -import { PreviewWrapper } from './components/PreviewWrapper'; -import { Radius } from './components/Radius'; -import { RichText } from './components/RichText'; -import { Size } from './components/Size'; -import { SizeWithout0 } from './components/SizeWithout0'; -import { Slider } from './components/Slider'; -import { Text as TextController } from './components/Text'; - -export interface EmbedPreviewControllerProps { - configKey: string; -} - -export default function Page({ - params, -}: { - params: { embed: keyof typeof configurations }; -}) { - const embedStateStore = EmbedState.useStore(); - const appStore = App.useStore(); - const config = configurations[params.embed] as EmbedConfig; - const [backgroundImage, setBackgroundImage] = useState(imgur('SO13zur')); - const fileInput = useRef(); - - useEffect(() => { - fileInput.current = document.createElement('input'); - fileInput.current.type = 'file'; - fileInput.current.style.display = 'none'; - fileInput.current.accept = 'image/*'; - fileInput.current.onchange = (event) => { - const file = (event.target as HTMLInputElement).files?.[0]; - if (!file) return; - setBackgroundImage(URL.createObjectURL(file)); - }; - }, []); - - return ( - - - - - - - Export - - Copy all properties for you streaming software - - - - { - const { wargaming } = appStore.getState().logins; - - if (!wargaming) return; - - const state = embedStateStore.getState(); - const initial = embedStateStore.getInitialState(); - const shallowState: EmbedState.EmbedState = {}; - - Object.entries(state).forEach(([key, value]) => { - if (value !== initial[key]) { - shallowState[key] = value; - } - }); - - const searchParams = new URLSearchParams({ - id: `${wargaming.id}`, - state: stringify(shallowState), - }); - - return `${location.origin}/tools/embed/${ - params.embed - }/host?${searchParams.toString()}`; - }} - > - - Copy URL - - - 'body { margin: 0; background-color: transparent; overflow: hidden; }' - } - > - - Copy CSS - - `${embedStateStore.getState().width}`} - > - - Copy width - - `${embedStateStore.getState().height}`} - > - - Copy height - - '`'}> - - Copy framerate - - - - - Customize - { - embedStateStore.setState( - embedStateStore.getInitialState(), - true, - ); - }} - > - Reset - - - - Bells and whistles of your embed - - - {Object.keys(config).map((configKey) => { - const item = config[configKey]; - let control: ReactNode; - let oneLiner = false; - - switch (item.type) { - case EmbedItemType.Boolean: { - control = ; - oneLiner = true; - break; - } - - case EmbedItemType.Color: { - control = ; - break; - } - - case EmbedItemType.Radius: { - control = ; - oneLiner = true; - break; - } - - case EmbedItemType.Size: { - control = ; - oneLiner = true; - break; - } - - case EmbedItemType.SizeWithout0: { - control = ; - oneLiner = true; - break; - } - - case EmbedItemType.Slider: { - control = ; - oneLiner = true; - break; - } - - case EmbedItemType.String: { - control = ; - break; - } - - case EmbedItemType.RichText: { - control = ; - break; - } - - case EmbedItemType.Enum: { - control = ; - oneLiner = true; - break; - } - } - - return ( - - {capitalize(startCase(configKey as string))} - - {control} - - - ); - })} - - - - - - - Example preview - - fileInput.current?.click()} - > - Upload test background - - - - - - - - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/embed/page.tsx b/packages/website-legacy/src/app/tools/embed/page.tsx deleted file mode 100644 index a386e73be..000000000 --- a/packages/website-legacy/src/app/tools/embed/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { PageWrapper } from '../../../components/PageWrapper'; - -export default function Page() { - return ; -} diff --git a/packages/website-legacy/src/app/tools/layout.tsx b/packages/website-legacy/src/app/tools/layout.tsx deleted file mode 100644 index 4cd6dba93..000000000 --- a/packages/website-legacy/src/app/tools/layout.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { imgur, ImgurSize } from '@blitzkit/core'; -import { Link } from '@radix-ui/themes'; -import { usePathname } from 'next/navigation'; -import { ReactNode } from 'react'; -import { TOOLS } from '../../../../website/src/constants/tools'; - -export default function Layout({ children }: { children: ReactNode }) { - const pathname = usePathname(); - const pathSplit = pathname.split('/'); - const toolId = pathSplit.at(2); - const isToolRoot = pathname === `/tools/${toolId}`; - const tool = TOOLS.find((tool) => tool.id === toolId); - - return ( - <> - {tool && ( - <> - {isToolRoot && ( - <> - {tool.title} - - - {tool.pageDescription !== undefined && ( - <> - - - > - )} - > - )} - > - )} - - {pathSplit.length === 3 && ( - - - - - {tool?.title} - - - {tool?.description} - - - )} - - {children} - > - ); -} diff --git a/packages/website-legacy/src/app/tools/performance/layout.tsx b/packages/website-legacy/src/app/tools/performance/layout.tsx deleted file mode 100644 index 21c9944c7..000000000 --- a/packages/website-legacy/src/app/tools/performance/layout.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { ReactNode } from 'react'; -import * as TankFilters from '../../../stores/tankFilters'; -import * as TankPerformancePersistent from '../../../stores/tankPerformancePersistent'; -import * as TankPerformanceSort from '../../../stores/tankPerformanceSort'; - -export default function Layout({ children }: { children: ReactNode }) { - return ( - - - {children} - - - ); -} diff --git a/packages/website-legacy/src/app/tools/performance/page.tsx b/packages/website-legacy/src/app/tools/performance/page.tsx deleted file mode 100644 index 4afddcf47..000000000 --- a/packages/website-legacy/src/app/tools/performance/page.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Controls } from '../../../../../website/src/components/Performance/Controls'; -import { Info } from '../../../../../website/src/components/Performance/PerformanceInfo'; -import { TankTable } from '../../../../../website/src/components/Performance/Table'; -import { PageWrapper } from '../../../components/PageWrapper'; - -export default function Page() { - return ( - - - {/* */} - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/rating/components/PageTurner/index.css.ts b/packages/website-legacy/src/app/tools/rating/components/PageTurner/index.css.ts deleted file mode 100644 index e7521e1c9..000000000 --- a/packages/website-legacy/src/app/tools/rating/components/PageTurner/index.css.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { keyframes, style } from '@vanilla-extract/css'; - -const spinKeyframes = keyframes({ - from: { transform: 'rotate(0deg)' }, - to: { transform: 'rotate(360deg)' }, -}); - -export const infiniteSpin = style({ - animationName: spinKeyframes, - animationIterationCount: 'infinite', - animationTimingFunction: 'linear', - animationDuration: '1s', -}); diff --git a/packages/website-legacy/src/app/tools/rating/components/PageTurner/index.tsx b/packages/website-legacy/src/app/tools/rating/components/PageTurner/index.tsx deleted file mode 100644 index 6b6566e1a..000000000 --- a/packages/website-legacy/src/app/tools/rating/components/PageTurner/index.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { - CaretLeftIcon, - CaretRightIcon, - SymbolIcon, -} from '@radix-ui/react-icons'; -import { Flex, IconButton, TextField } from '@radix-ui/themes'; -import { range } from 'lodash-es'; -import { useEffect, useRef } from 'react'; -import { infiniteSpin } from './index.css'; - -interface PageTurnerProps { - leaderboard: Record; - page: number; - rowsPerPage: number; - pages: number; - onPageChange: (page: number, isButtonClick: boolean) => void; - totalPlayers: number; -} - -export function PageTurner({ - page, - rowsPerPage, - onPageChange, - pages, - leaderboard, - totalPlayers, -}: PageTurnerProps) { - const pageInput = useRef(null); - const rightLoading = range( - page * rowsPerPage, - Math.min(totalPlayers - 1, page * rowsPerPage + rowsPerPage + 1), - ).some((index) => !(index in leaderboard)); - const leftLoading = range( - Math.max(0, page * rowsPerPage - 1), - Math.max(0, page * rowsPerPage - rowsPerPage - 1) + 1, - ).some((index) => !(index in leaderboard)); - - useEffect(() => { - if (pageInput.current) pageInput.current.value = `${page + 1}`; - }, [page]); - - return ( - - - onPageChange(Math.max(page - 1, 0), true)} - disabled={page === 0 || leftLoading} - > - {leftLoading ? ( - - ) : ( - - )} - - - { - onPageChange( - Math.max(0, Math.min(pages - 1, event.target.valueAsNumber - 1)), - false, - ); - }} - onKeyDown={(event) => { - if (event.key === 'Enter') { - (event.target as HTMLInputElement).blur(); - } - }} - > - Page - out of {pages} - - { - onPageChange(Math.min(page + 1, pages - 1), true); - }} - disabled={page === pages - 1 || rightLoading} - > - {rightLoading ? ( - - ) : ( - - )} - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/rating/page.tsx b/packages/website-legacy/src/app/tools/rating/page.tsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/website-legacy/src/app/tools/session/layout.tsx b/packages/website-legacy/src/app/tools/session/layout.tsx deleted file mode 100644 index 42dd882e5..000000000 --- a/packages/website-legacy/src/app/tools/session/layout.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { ReactNode } from 'react'; -import * as Session from '../../../stores/session'; - -export default function Layout({ children }: { children: ReactNode }) { - return {children}; -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx deleted file mode 100644 index 60ade1600..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx +++ /dev/null @@ -1,634 +0,0 @@ -import { - asset, - coefficient, - CREW_MEMBER_NAMES, - fetchEquipmentDefinitions, - fetchProvisionDefinitions, - GUN_TYPE_NAMES, - isExplosive, - resolvePenetrationCoefficient, -} from '@blitzkit/core'; -import { AccessibilityIcon, InfoCircledIcon } from '@radix-ui/react-icons'; -import { - Flex, - Heading, - IconButton, - Popover, - Slider, - Text, - TextField, - Tooltip, -} from '@radix-ui/themes'; -import { debounce } from 'lodash-es'; -import { Fragment, useEffect, useRef, useState } from 'react'; -import { Ad, AdType } from '../../../../../../../../website/src/components/Ad'; -import { InfoWithDelta } from '../../../../../../../../website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/InfoWithDelta'; -import { applyPitchYawLimits } from '../../../../../../../../website/src/core/blitz/applyPitchYawLimits'; -import { tankCharacteristics } from '../../../../../../../../website/src/core/blitzkit/tankCharacteristics'; -import { useAdExempt } from '../../../../../../../../website/src/hooks/useAdExempt'; -import { useEquipment } from '../../../../../../../../website/src/hooks/useEquipment'; -import { useTankModelDefinition } from '../../../../../../../../website/src/hooks/useTankModelDefinition'; -import { Duel } from '../../../../../../../../website/src/stores/duel'; -import { TankopediaEphemeral } from '../../../../../../../../website/src/stores/tankopediaEphemeral'; - -const equipmentDefinitions = await fetchEquipmentDefinitions(); -const provisionDefinitions = await fetchProvisionDefinitions(); - -export function Characteristics() { - const mutateDuel = Duel.useMutation(); - const exempt = useAdExempt(); - const crewSkills = TankopediaEphemeral.use((state) => state.skills); - const penetrationDistanceInput = useRef(null); - const hasImprovedVentilation = useEquipment(102); - const crewMastery = Duel.use((state) => state.protagonist.crewMastery); - const [penetrationDistance, setPenetrationDistance] = useState(250); - const setPenetrationDistanceDebounced = debounce((value: number) => { - setPenetrationDistance(value); - }, 500); - - const provisions = Duel.use((state) => state.protagonist.provisions); - const provisionCrewBonus = - provisions.reduce( - (total, provision) => - provisionDefinitions.provisions[provision].crew - ? total + provisionDefinitions.provisions[provision].crew! / 100 - : total, - 0, - ) + (hasImprovedVentilation ? 0.08 : 0); - const commanderMastery = crewMastery + provisionCrewBonus; - const consumables = Duel.use((state) => state.protagonist.consumables); - const camouflage = Duel.use((state) => state.protagonist.camouflage); - const equipmentMatrix = Duel.use( - (state) => state.protagonist.equipmentMatrix, - ); - const { tank, turret, gun, engine, track, shell } = Duel.use( - (state) => state.protagonist, - ); - const stockEngine = tank.engines[0]; - const stockTrack = tank.tracks[0]; - const stockTurret = tank.turrets[0]; - const stockGun = stockTurret.guns[0]; - const tankModelDefinition = useTankModelDefinition(); - const turretModelDefinition = tankModelDefinition.turrets[turret.id]; - const gunModelDefinition = - turretModelDefinition.guns[gun.gunType!.value.base.id]; - const stats = tankCharacteristics( - { - tank, - camouflage, - consumables, - crewMastery, - crewSkills, - engine, - equipmentMatrix, - gun, - provisions, - shell, - turret, - track, - stockEngine, - stockGun, - stockTrack, - stockTurret, - applyReactiveArmor: false, - applyDynamicArmor: false, - applySpallLiner: false, - }, - { - tankModelDefinition, - equipmentDefinitions: equipmentDefinitions, - provisionDefinitions: provisionDefinitions, - }, - ); - - const hasSupercharger = useEquipment(107); - const hasCalibratedShells = useEquipment(103); - const hasImprovedVerticalStabilizer = useEquipment(122); - const penetrationCoefficient = coefficient([ - hasCalibratedShells, - resolvePenetrationCoefficient(true, shell.type) - 1, - ]); - const penetrationLossOverDistanceCoefficient = coefficient([ - hasSupercharger, - -0.6, - ]); - - useEffect(() => { - if (penetrationDistanceInput.current) { - penetrationDistanceInput.current.value = `${penetrationDistance}`; - } - }, [penetrationDistance]); - useEffect(() => { - mutateDuel((draft) => { - [draft.protagonist.pitch, draft.protagonist.yaw] = applyPitchYawLimits( - draft.protagonist.pitch, - draft.protagonist.yaw, - gunModelDefinition.pitch, - turretModelDefinition.yaw, - hasImprovedVerticalStabilizer, - ); - }); - }, [hasImprovedVerticalStabilizer]); - - return ( - - - - - Firepower - - - {gun.gunType!.value.base.shells.map((thisShell, shellIndex) => ( - - { - mutateDuel((draft) => { - draft.protagonist.shell = thisShell; - }); - }} - > - - - - ))} - - - {GUN_TYPE_NAMES[gun.gunType!.$case]} - - {stats.dpm} - - {gun.type === 'autoReloader' && ( - - {stats.dpmEffective!} - - )} - {gun.type !== 'regular' && ( - {stats.shells} - )} - {gun.type === 'autoReloader' ? ( - <> - - {stats.mostOptimalShellIndex! + 1} - - - {stats.shellReloads!.map((reload, index) => ( - - {reload} - - ))} - > - ) : ( - - {stats.shellReload!} - - )} - {(gun.type === 'autoLoader' || gun.type === 'autoReloader') && ( - - {stats.intraClip!} - - )} - - {stats.penetration} - - {typeof shell.penetration !== 'number' && ( - <> - - {lerp( - shell.penetration[0], - shell.penetration[1], - (penetrationDistance * - penetrationLossOverDistanceCoefficient) / - 500, - ) * penetrationCoefficient} - - - Distance - { - setPenetrationDistanceDebounced(value); - - if (!penetrationDistanceInput.current) return; - - penetrationDistanceInput.current.value = value.toString(); - }} - /> - { - setPenetrationDistance( - Math.min( - parseInt(penetrationDistanceInput.current!.value), - 500, - ), - ); - }} - onKeyDown={(event) => { - if (event.key === 'Enter') { - event.currentTarget.blur(); - } - }} - > - m - - - > - )} - - {stats.damage} - - {gun.type !== 'regular' && ( - - {stats.clipDamage!} - - )} - - {stats.moduleDamage} - - {isExplosive(shell.type) && ( - - {stats.explosionRadius!} - - )} - - {stats.caliber} - - - {stats.shellNormalization} - - {!isExplosive(shell.type) && ( - - {stats.shellRicochet!} - - )} - - {stats.shellVelocity} - - - {stats.aimTime} - - - - {stats.dispersion} - - - {stats.dispersionMoving} - - - {stats.dispersionHullTraversing} - - - {stats.dispersionTurretTraversing} - - - {stats.dispersionShooting} - - - {stats.dispersionGunDamaged} - - - {stats.maxDispersion} - - - - {stats.gunDepression} - - - {stats.gunElevation} - - {gunModelDefinition.pitch.front && ( - <> - - {stats.gunFrontalDepression!} - - - {stats.gunFrontalElevation!} - - > - )} - {gunModelDefinition.pitch.back && ( - <> - - {stats.gunRearDepression!} - - - {stats.gunRearElevation!} - - > - )} - {turretModelDefinition.yaw && ( - <> - - {stats.azimuthLeft!} - - - {stats.azimuthRight!} - - > - )} - - - - Crew training - - - - - - - - - - - - - represents the other roles a crew member can take. - - - - - - - {tank.crew.map((member) => { - const count = member.count ?? 1; - - return ( - - 1 ? ` x ${count}` : '' - }`} - unit="%" - decimals={0} - > - {(member.type === 'commander' - ? commanderMastery - : commanderMastery * 1.1) * 100} - - - {member.substitute && ( - - - - {member.substitute - .map((sub, index) => - index === 0 ? CREW_MEMBER_NAMES[sub] : sub, - ) - .join(', ')} - - > - } - > - {commanderMastery * 1.05 * 100} - - )} - - ); - })} - - - - {!exempt && ( - - - - )} - - - - Maneuverability - - - {stats.speedForwards} - - - {stats.speedBackwards} - - - {stats.enginePower} - - - {stats.weight} - - - - {stats.hardTerrainCoefficient} - - - {stats.mediumTerrainCoefficient} - - - {stats.softTerrainCoefficient} - - - - {stats.hardTerrainCoefficientRaw} - - - {stats.mediumTerrainCoefficientRaw} - - - {stats.softTerrainCoefficientRaw} - - - - {stats.powerToWeightRatioHardTerrain} - - - {stats.powerToWeightRatioMediumTerrain} - - - {stats.powerToWeightRatioSoftTerrain} - - - {stats.turretTraverseSpeed} - - - - {stats.hullTraverseHardTerrain} - - - {stats.hullTraverseMediumTerrain} - - - {stats.hullTraverseSoftTerrain} - - - - Survivability - - {stats.health} - - - {stats.fireChance * 100} - - - {stats.viewRange} - - - - {stats.camouflageStill * 100} - - - {stats.camouflageMoving * 100} - - - {stats.camouflageShootingStill * 100} - - - {stats.camouflageShootingMoving * 100} - - - {stats.camouflageCaughtOnFire * 100} - - - {stats.width} - - - {stats.height} - - - {stats.length} - - - {stats.volume} - - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Content.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Content.tsx deleted file mode 100644 index 479b32a1b..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Content.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { TIER_ROMAN_NUMERALS } from '@blitzkit/core'; -import strings from '@blitzkit/core/lang/en-US.json'; -import { invalidate } from '@react-three/fiber'; -import { useEffect } from 'react'; -import { CalloutsSection } from '../../../../../../../website/src/components/Tankopedia/CalloutsSection'; -import { CharacteristicsSection } from '../../../../../../../website/src/components/Tankopedia/CharacteristicsSection'; -import { GameModeSection } from '../../../../../../../website/src/components/Tankopedia/GameModeSection'; -import { HeroSection } from '../../../../../../../website/src/components/Tankopedia/HeroSection'; -import { HistorySection } from '../../../../../../../website/src/components/Tankopedia/HistorySection'; -import { MetaSection } from '../../../../../../../website/src/components/Tankopedia/MetaSection'; -import { ShotDisplaySection } from '../../../../../../../website/src/components/Tankopedia/ShotDisplaySection'; -import { TechTreeSection } from '../../../../../../../website/src/components/Tankopedia/TechTreeSection'; -import { AdMidSectionResponsive } from '../../../../../components/AdMidSectionResponsive'; -import { PageWrapper } from '../../../../../components/PageWrapper'; -import { useAdExempt } from '../../../../../hooks/useAdExempt'; -import * as Duel from '../../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../../stores/tankopediaEphemeral'; -import { VideoSection } from '../../../../../../../website/src/components/Tankopedia/VideoSection'; - -export function Content() { - const exempt = useAdExempt(); - const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); - const mutateDuel = Duel.useMutation(); - 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)[tank.nation] - } ${strings.common.tank_class_short[tank.class]}`; - - useEffect(() => { - function handleKeyDown(event: KeyboardEvent) { - if (document.activeElement instanceof HTMLInputElement) return; - - function wipeShot() { - mutateTankopediaEphemeral((draft) => { - draft.shot = undefined; - }); - } - - if (event.key === '1') { - invalidate(); - wipeShot(); - mutateDuel((draft) => { - draft.antagonist.shell = draft.antagonist.gun.shells[0]; - }); - } else if (event.key === '2') { - invalidate(); - wipeShot(); - mutateDuel((draft) => { - if (draft.antagonist.gun.shells[1]) { - draft.antagonist.shell = draft.antagonist.gun.shells[1]; - } - }); - } else if (event.key === '3') { - invalidate(); - wipeShot(); - mutateDuel((draft) => { - if (draft.antagonist.gun.shells[2]) { - draft.antagonist.shell = draft.antagonist.gun.shells[2]; - } - }); - } - } - - window.addEventListener('keydown', handleKeyDown); - - return () => { - window.removeEventListener('keydown', handleKeyDown); - }; - }, []); - - useEffect(() => { - const unsubscribe = duelStore.subscribe( - (state) => state.protagonist?.tank.id, - () => { - mutateTankopediaEphemeral((draft) => { - draft.shot = undefined; - }); - }, - ); - - return unsubscribe; - }, []); - - return ( - <> - {title} - - - - - - - {!exempt && } - - - {!exempt && } - - - - {!exempt && } - - > - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/TankopediaSeparator.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/components/TankopediaSeparator.tsx deleted file mode 100644 index 4cbb8a161..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/TankopediaSeparator.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { Separator } from '@radix-ui/themes'; -import { PageWrapper } from '../../../../../components/PageWrapper'; - -export function TankopediaSeparator() { - return ( - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Title.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Title.tsx deleted file mode 100644 index cc7febc87..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Title.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { provisionDefinitions, TREE_TYPE_ICONS } from '@blitzkit/core'; -import { CaretRightIcon, UpdateIcon } from '@radix-ui/react-icons'; -import { Button, Dialog, Flex, Heading, Link } from '@radix-ui/themes'; -import { use, useState } from 'react'; -import { pushTankopediaPath } from '../../../../../core/blitzkit/pushTankopediaPath'; -import { tankToDuelMember } from '../../../../../core/blitzkit/tankToDuelMember'; -import * as Duel from '../../../../../stores/duel'; -import { TankSearch } from '../../components/TankSearch'; - -export function Title() { - const awaitedProvisionDefinitions = use(provisionDefinitions); - const protagonist = Duel.use((state) => state.protagonist); - const antagonist = Duel.use((state) => state.antagonist); - const compareTanks = - protagonist.tank.id === antagonist.tank.id - ? [protagonist.tank.id] - : [protagonist.tank.id, antagonist.tank.id]; - const [changeTankDialogOpen, setChangeTankDialogOpen] = useState(false); - const mutateDuel = Duel.useMutation(); - - return ( - <> - - - - - {' '} - {protagonist.tank.name} - - - - - - - - - Change - - - - - Change tank - - - - { - setChangeTankDialogOpen(false); - pushTankopediaPath(tank.id); - - mutateDuel((draft) => { - draft.protagonist = tankToDuelMember( - tank, - awaitedProvisionDefinitions, - ); - }); - }} - /> - - - - - - - - Compare - - - - - > - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/layout.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/layout.tsx deleted file mode 100644 index 71fc65331..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/layout.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { - fetchModelDefinitions, - fetchTankDefinitions, - tankIcon, - TIER_ROMAN_NUMERALS, -} from '@blitzkit/core'; -import strings from '@blitzkit/core/lang/en-US.json'; -import { ReactNode } from 'react'; - -export async function generateStaticParams() { - const tankDefinitions = await fetchTankDefinitions(); - const tanks = Object.values(tankDefinitions.tanks); - return tanks.map((tank) => ({ id: `${tank.id}` })); -} - -const tankDefinitions = await fetchTankDefinitions(); -const definitions = await fetchModelDefinitions(); - -export default async function Layout({ - children, - params, -}: { - children: ReactNode; - params: { id: string }; -}) { - const id = Number(params.id); - const tankModelDefinition = definitions[id]; - const awaitedProvisionDefinitions = await provisionDefinitions; - const tank = tankDefinitions[id]; - const title = `${tank.name} - Tier ${TIER_ROMAN_NUMERALS[tank.tier]} ${ - (strings.common.nations_adjectives as Record)[tank.nation] - } ${strings.common.tank_class_short[tank.class]}`; - const description = `Statistics, armor, and equipment for ${tank.name} in World of Tanks Blitz (WoTB)`; - - return ( - - - {title} - - - - - - {children} - - - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/page.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/page.tsx deleted file mode 100644 index 53f7d1735..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/page.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { TIER_ROMAN_NUMERALS } from '@blitzkit/core'; -import strings from '@blitzkit/core/lang/en-US.json'; -import { invalidate } from '@react-three/fiber'; -import { useEffect } from 'react'; -import { CalloutsSection } from '../../../../../../website/src/components/Tankopedia/CalloutsSection'; -import { CharacteristicsSection } from '../../../../../../website/src/components/Tankopedia/CharacteristicsSection'; -import { GameModeSection } from '../../../../../../website/src/components/Tankopedia/GameModeSection'; -import { HeroSection } from '../../../../../../website/src/components/Tankopedia/HeroSection'; -import { HistorySection } from '../../../../../../website/src/components/Tankopedia/HistorySection'; -import { MetaSection } from '../../../../../../website/src/components/Tankopedia/MetaSection'; -import { ShotDisplaySection } from '../../../../../../website/src/components/Tankopedia/ShotDisplaySection'; -import { TechTreeSection } from '../../../../../../website/src/components/Tankopedia/TechTreeSection'; -import { AdMidSectionResponsive } from '../../../../components/AdMidSectionResponsive'; -import { PageWrapper } from '../../../../components/PageWrapper'; -import { useAdExempt } from '../../../../hooks/useAdExempt'; -import * as Duel from '../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral'; -import { VideoSection } from '../../../../../../website/src/components/Tankopedia/VideoSection'; - -export default function Page() { - const exempt = useAdExempt(); - const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); - const mutateDuel = Duel.useMutation(); - 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)[tank.nation] - } ${strings.common.tank_class_short[tank.class]}`; - - useEffect(() => { - function handleKeyDown(event: KeyboardEvent) { - if (document.activeElement instanceof HTMLInputElement) return; - - function wipeShot() { - mutateTankopediaEphemeral((draft) => { - draft.shot = undefined; - }); - } - - if (event.key === '1') { - invalidate(); - wipeShot(); - mutateDuel((draft) => { - draft.antagonist.shell = draft.antagonist.gun.shells[0]; - }); - } else if (event.key === '2') { - invalidate(); - wipeShot(); - mutateDuel((draft) => { - if (draft.antagonist.gun.shells[1]) { - draft.antagonist.shell = draft.antagonist.gun.shells[1]; - } - }); - } else if (event.key === '3') { - invalidate(); - wipeShot(); - mutateDuel((draft) => { - if (draft.antagonist.gun.shells[2]) { - draft.antagonist.shell = draft.antagonist.gun.shells[2]; - } - }); - } - } - - window.addEventListener('keydown', handleKeyDown); - - return () => { - window.removeEventListener('keydown', handleKeyDown); - }; - }, []); - - useEffect(() => { - const unsubscribe = duelStore.subscribe( - (state) => state.protagonist?.tank.id, - () => { - mutateTankopediaEphemeral((draft) => { - draft.shot = undefined; - }); - }, - ); - - return unsubscribe; - }, []); - - return ( - <> - {title} - - - - - - - {!exempt && } - - - {!exempt && } - - - - {!exempt && } - - > - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/components/PageTurner.tsx b/packages/website-legacy/src/app/tools/tankopedia/components/PageTurner.tsx deleted file mode 100644 index b7f33bf44..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/components/PageTurner.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { CaretLeftIcon, CaretRightIcon } from '@radix-ui/react-icons'; -import { Flex, IconButton, TextField } from '@radix-ui/themes'; -import { useEffect, useRef } from 'react'; -import * as TankopediaPersistent from '../../../../stores/tankopediaPersistent'; -import { TankDefinition } from '@blitzkit/core'; - -interface PageTurnerProps { - searchedList: TankDefinition[]; - tanksPerPage: number; -} - -export function PageTurner({ searchedList, tanksPerPage }: PageTurnerProps) { - const page = TankopediaPersistent.use((state) => state.filters.page); - const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); - const pageInput = useRef(null); - - useEffect(() => { - if (pageInput.current) pageInput.current.value = `${page + 1}`; - }, [page]); - - return ( - - { - mutateTankopediaPersistent((draft) => { - draft.filters.page = Math.max(0, page - 1); - }); - }} - > - - - { - mutateTankopediaPersistent((draft) => { - draft.filters.page = Math.max( - 0, - Math.min( - Math.floor(searchedList.length / tanksPerPage), - event.target.valueAsNumber - 1, - ), - ); - }); - }} - onKeyDown={(event) => { - if (event.key === 'Enter') { - (event.target as HTMLInputElement).blur(); - } - }} - > - Page - - out of {Math.floor(searchedList.length / tanksPerPage) + 1} - - - { - mutateTankopediaPersistent((draft) => { - draft.filters.page = Math.min( - Math.floor(searchedList.length / tanksPerPage), - page + 1, - ); - }); - }} - > - - - - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/layout.tsx b/packages/website-legacy/src/app/tools/tankopedia/layout.tsx deleted file mode 100644 index f4cc51323..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/layout.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as TankFilters from '../../../stores/tankFilters'; -import * as TankopediaPersistent from '../../../stores/tankopediaPersistent'; -import * as TankopediaSort from '../../../stores/tankopediaSort'; - -export default function Layout({ children }: { children: React.ReactNode }) { - return ( - - - {children} - - - ); -} diff --git a/packages/website-legacy/src/app/tools/tankopedia/page.tsx b/packages/website-legacy/src/app/tools/tankopedia/page.tsx deleted file mode 100644 index 21200f5eb..000000000 --- a/packages/website-legacy/src/app/tools/tankopedia/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { PageWrapper } from '../../../components/PageWrapper'; -import { TankSearch } from './components/TankSearch'; - -export default function Page() { - return ( - - - - ); -} diff --git a/packages/website/public/assets/audio/lotta-damage.mp3 b/packages/website/public/assets/audio/lotta-damage.mp3 new file mode 100644 index 000000000..f70b11d91 Binary files /dev/null and b/packages/website/public/assets/audio/lotta-damage.mp3 differ diff --git a/packages/website-legacy/public/robots.txt b/packages/website/public/robots.txt similarity index 100% rename from packages/website-legacy/public/robots.txt rename to packages/website/public/robots.txt diff --git a/packages/website/src/pages/settings/index.astro b/packages/website/src/pages/settings/index.astro new file mode 100644 index 000000000..95d8dbf8c --- /dev/null +++ b/packages/website/src/pages/settings/index.astro @@ -0,0 +1,8 @@ +--- +import { Page } from '.'; +import RootLayout from '../../layouts/RootLayout.astro'; +--- + + + + diff --git a/packages/website/src/pages/settings/index.tsx b/packages/website/src/pages/settings/index.tsx new file mode 100644 index 000000000..d1693ebe8 --- /dev/null +++ b/packages/website/src/pages/settings/index.tsx @@ -0,0 +1,36 @@ +import { Flex, Heading, Switch, Text } from '@radix-ui/themes'; +import { PageWrapper } from '../../components/PageWrapper'; +import { App } from '../../stores/app'; + +export function Page() { + return ( + + + + ); +} + +function Content() { + const developerMode = App.useDeferred((state) => state.developerMode, false); + const appStore = App.useStore(); + + return ( + + + + Advanced + + + Developer mode + + appStore.setState({ developerMode: checked }) + } + /> + + + + + ); +}
{params.embed}
- {JSON.stringify(initialState, null, 2)} -
{JSON.stringify(initialState, null, 2)}