mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 11:39:50 +02:00
aliases
This commit is contained in:
1 parent
13cda7aec0
commit
b26c5137f3
53 files changed
+236
-932
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { Flex, Heading, IconButton, Table } from "@radix-ui/themes";
|
||||
import type { TankCharacteristics } from "../../core/blitzkit/tankCharacteristics";
|
||||
import { useLocale } from "../../hooks/useLocale";
|
||||
@@ -57,7 +58,10 @@ export function Body({ stats }: BodyProps) {
|
||||
alt={unwrap(thisShell.name!)}
|
||||
width={16}
|
||||
height={16}
|
||||
src={`/api/icons/shells/${thisShell.icon}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/shells/${thisShell.icon}.webp`,
|
||||
)}
|
||||
/>
|
||||
</IconButton>
|
||||
))}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { availableProvisions, permanentSkills } from "@blitzkit/core";
|
||||
import { alias, availableProvisions, permanentSkills } from "@blitzkit/core";
|
||||
import { checkConsumableProvisionInclusivity } from "@blitzkit/core/src/blitzkit/checkConsumableProvisionInclusivity";
|
||||
import { ComponentPlaceholderIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
@@ -231,7 +231,10 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
alt={module}
|
||||
width={24}
|
||||
height={24}
|
||||
src={`/api/icons/modules/${module}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/modules/${module}.webp`,
|
||||
)}
|
||||
style={{
|
||||
marginLeft: index > 0 ? -8 : 0,
|
||||
objectFit: "contain",
|
||||
@@ -320,7 +323,10 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
.name!,
|
||||
)}
|
||||
key={provision}
|
||||
src={`/api//icons/provisions/${provision}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`//icons/provisions/${provision}.webp`,
|
||||
)}
|
||||
style={{
|
||||
left: "50%",
|
||||
/**
|
||||
@@ -525,7 +531,10 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
].name!,
|
||||
)}
|
||||
key={consumable}
|
||||
src={`/api/icons/consumables/${consumable}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/consumables/${consumable}.webp`,
|
||||
)}
|
||||
style={{
|
||||
left: "50%",
|
||||
/**
|
||||
@@ -617,7 +626,7 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
variant={camouflage ? "solid" : "outline"}
|
||||
>
|
||||
<img
|
||||
src={`/api/icons/camo.webp`}
|
||||
src={alias("api", `/icons/camo.webp`)}
|
||||
style={{
|
||||
width: "1em",
|
||||
height: "1em",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { permanentSkills, romanize } from "@blitzkit/core";
|
||||
import { alias, permanentSkills, romanize } from "@blitzkit/core";
|
||||
import { Flex } from "@radix-ui/themes";
|
||||
import { api } from "../core/blitzkit/api";
|
||||
import { GenericTankComponentButton } from "./ModuleButtons/GenericTankComponentButton";
|
||||
@@ -27,7 +27,7 @@ export function CrewSkillManager({
|
||||
special={!permanentSkills.includes(skill)}
|
||||
selected={level > 0}
|
||||
discriminator={level === 0 ? undefined : romanize(level)}
|
||||
icon={`/api/icons/skills/${skill}.webp`}
|
||||
icon={alias("api", `/icons/skills/${skill}.webp`)}
|
||||
onClick={(event) => {
|
||||
if (!onChange) return;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Avatar } from "@blitzkit/core";
|
||||
import { alias, Avatar } from "@blitzkit/core";
|
||||
import { Cross1Icon, DownloadIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -18,7 +18,10 @@ type GalleryCardProps = MaybeSkeletonComponentProps<{
|
||||
}>;
|
||||
|
||||
export function GalleryCard(props: GalleryCardProps) {
|
||||
const src = `/api/gallery/avatars/${!props.skeleton && `${props.avatar.id}${props.avatar.extension}`}`;
|
||||
const src = alias(
|
||||
"api",
|
||||
`/gallery/avatars/${!props.skeleton && `${props.avatar.id}${props.avatar.extension}`}`,
|
||||
);
|
||||
const card = useRef<HTMLDivElement>(null!);
|
||||
const { unwrap } = useLocale();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
alias,
|
||||
SEARCH_KEYS,
|
||||
TankDefinition,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
@@ -149,7 +150,10 @@ export function Guesser() {
|
||||
prefix={
|
||||
<img
|
||||
style={{ width: "1em", height: "1em" }}
|
||||
src={`/api/flags/circle/${result.nation}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/flags/circle/${result.nation}.webp`,
|
||||
)}
|
||||
/>
|
||||
}
|
||||
discriminator={
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { GenericTankComponentButton } from "./GenericTankComponentButton";
|
||||
import type { TankComponentButtonProps } from "./TankComponentButton";
|
||||
|
||||
@@ -8,7 +9,7 @@ interface ModuleProps extends TankComponentButtonProps {
|
||||
export function ModuleButton({ module, ...props }: ModuleProps) {
|
||||
return (
|
||||
<GenericTankComponentButton
|
||||
icon={`/api/icons/modules/${module}.webp`}
|
||||
icon={alias("api", `/icons/modules/${module}.webp`)}
|
||||
iconStyles={{
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { api } from "../../core/blitzkit/api";
|
||||
import { useLocale } from "../../hooks/useLocale";
|
||||
import { GenericTankComponentButton } from "./GenericTankComponentButton";
|
||||
@@ -15,7 +16,7 @@ export function ProvisionButton({ provision, ...props }: ProvisionButtonProps) {
|
||||
return (
|
||||
<GenericTankComponentButton
|
||||
tooltip={unwrap(provisionDefinitions.provisions[provision].name!)}
|
||||
icon={`/api/icons/provisions/${provision}.webp`}
|
||||
icon={alias("api", `/icons/provisions/${provision}.webp`)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { GenericTankComponentButton } from "./GenericTankComponentButton";
|
||||
import type { TankComponentButtonProps } from "./TankComponentButton";
|
||||
|
||||
@@ -8,7 +9,7 @@ interface ShellButtonProps extends TankComponentButtonProps {
|
||||
export function ShellButton({ shell, ...props }: ShellButtonProps) {
|
||||
return (
|
||||
<GenericTankComponentButton
|
||||
icon={`/api/icons/shells/${shell}.webp`}
|
||||
icon={alias("api", `/icons/shells/${shell}.webp`)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
|
||||
interface SmallTankIconProps {
|
||||
id: number;
|
||||
size?: number;
|
||||
@@ -17,7 +19,7 @@ export function SmallTankIcon({ id, size = HEIGHT }: SmallTankIconProps) {
|
||||
>
|
||||
<img
|
||||
alt={`Tank ${id}`}
|
||||
src={`/api/tanks/${id}/icons/small.webp`}
|
||||
src={alias("api", `/tanks/${id}/icons/small.webp`)}
|
||||
style={{
|
||||
transform: `scale(${(size / HEIGHT) * 100}%)`,
|
||||
transformOrigin: "top left",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TankType, type TankDefinition } from "@blitzkit/core";
|
||||
import { alias, TankType, type TankDefinition } from "@blitzkit/core";
|
||||
import { Flex, Text, type TextProps } from "@radix-ui/themes";
|
||||
import { uniq } from "lodash-es";
|
||||
import { forwardRef, type ReactNode } from "react";
|
||||
@@ -60,7 +60,10 @@ export const TankCard = forwardRef<HTMLSpanElement, TankCardProps>(
|
||||
className="tank-search-card"
|
||||
data-provide-link={provideLink}
|
||||
style={{
|
||||
backgroundImage: `url(/api/flags/scratched/${tank.nation}.webp)`,
|
||||
backgroundImage: `url(${alias(
|
||||
"api",
|
||||
`/flags/scratched/${tank.nation}.webp`,
|
||||
)})`,
|
||||
...style,
|
||||
}}
|
||||
{...props}
|
||||
@@ -76,7 +79,7 @@ export const TankCard = forwardRef<HTMLSpanElement, TankCardProps>(
|
||||
>
|
||||
<img
|
||||
alt={unwrap(tank.name!)}
|
||||
src={`/api/tanks/${tank.id}/icons/big.webp`}
|
||||
src={alias("api", `/tanks/${tank.id}/icons/big.webp`)}
|
||||
className="image"
|
||||
draggable={false}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
alias,
|
||||
GunDefinition,
|
||||
ShellType,
|
||||
TANK_CLASSES,
|
||||
@@ -309,7 +310,7 @@ function NationsFilter() {
|
||||
width: "1.25em",
|
||||
height: "1.25em",
|
||||
}}
|
||||
src={`/api/flags/circle/${nation}.webp`}
|
||||
src={alias("api", `/flags/circle/${nation}.webp`)}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
@@ -346,7 +347,7 @@ function NationsFilter() {
|
||||
right="0"
|
||||
mr="-2"
|
||||
style={{
|
||||
backgroundImage: `url(${`/api/flags/scratched/${nation}.webp`})`,
|
||||
backgroundImage: `url(${alias("api", `/flags/scratched/${nation}.webp`)})`,
|
||||
backgroundSize: "100%",
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPosition: "5rem center",
|
||||
@@ -679,9 +680,10 @@ function IndividualShellFilter({
|
||||
{shells[index] !== null && (
|
||||
<img
|
||||
style={{ width: "1em", height: "1em" }}
|
||||
src={`/api/icons/shells/${shellTypeIcons[shells[index]]}${
|
||||
premium ? "_premium" : ""
|
||||
}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/shells/${shellTypeIcons[shells[index]]}${premium ? "_premium" : ""}.webp`,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</IconButton>
|
||||
@@ -712,9 +714,12 @@ function IndividualShellFilter({
|
||||
color={selected ? undefined : "gray"}
|
||||
>
|
||||
<img
|
||||
src={`/api/icons/shells/${shellTypeIcons[shellType]}${
|
||||
premium ? "_premium" : ""
|
||||
}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/shells/${shellTypeIcons[shellType]}${
|
||||
premium ? "_premium" : ""
|
||||
}.webp`,
|
||||
)}
|
||||
style={{ width: "1.25em", height: "1.25em" }}
|
||||
/>
|
||||
|
||||
@@ -883,7 +888,7 @@ function ConsumablesFilter() {
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/consumables/${consumable}.webp`}
|
||||
src={alias("api", `/icons/consumables/${consumable}.webp`)}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -928,7 +933,7 @@ function ConsumablesFilter() {
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/consumables/${consumable}.webp`}
|
||||
src={alias("api", `/icons/consumables/${consumable}.webp`)}
|
||||
/>
|
||||
|
||||
{unwrap(consumableDefinition.name!)}
|
||||
@@ -977,7 +982,7 @@ function ProvisionsFilter() {
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/provisions/${provision}.webp`}
|
||||
src={alias("api", `/icons/provisions/${provision}.webp`)}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -1022,7 +1027,7 @@ function ProvisionsFilter() {
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/provisions/${provision}.webp`}
|
||||
src={alias("api", `/icons/provisions/${provision}.webp`)}
|
||||
/>
|
||||
|
||||
{unwrap(provisionDefinition.name!)}
|
||||
@@ -1151,7 +1156,10 @@ function GameModeAbilitiesFilter() {
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/consumables/${consumable}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/consumables/${consumable}.webp`,
|
||||
)}
|
||||
/>
|
||||
|
||||
{unwrap(abilityDefinition.name!)}
|
||||
@@ -1200,7 +1208,10 @@ function GameModeAbilitiesFilter() {
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/provisions/${provision}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/provisions/${provision}.webp`,
|
||||
)}
|
||||
/>
|
||||
|
||||
{unwrap(powerDefinition.name!)}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { isExplosive } from "@blitzkit/core";
|
||||
import { alias, isExplosive } from "@blitzkit/core";
|
||||
import { literals } from "@blitzkit/i18n";
|
||||
import { Flex, Heading, IconButton, Tooltip } from "@radix-ui/themes";
|
||||
import { useLocale } from "../../../../../../hooks/useLocale";
|
||||
@@ -62,7 +62,7 @@ export function Firepower({
|
||||
alt={unwrap(thisShell.name!)}
|
||||
width={16}
|
||||
height={16}
|
||||
src={`/api/icons/shells/${thisShell.icon}.webp`}
|
||||
src={alias("api", `/icons/shells/${thisShell.icon}.webp`)}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { Flex, IconButton, Tooltip } from "@radix-ui/themes";
|
||||
import { useLocale } from "../../../../../../../../hooks/useLocale";
|
||||
import { Duel } from "../../../../../../../../stores/duel";
|
||||
@@ -37,7 +38,7 @@ export function ShellSwitcher() {
|
||||
<img
|
||||
alt={unwrap(thisShell.name!)}
|
||||
style={{ width: "1.125rem", height: "1.125rem" }}
|
||||
src={`/api/icons/shells/${thisShell.icon}.webp`}
|
||||
src={alias("api", `/icons/shells/${thisShell.icon}.webp`)}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { isExplosive } from "@blitzkit/core";
|
||||
import { alias, isExplosive } from "@blitzkit/core";
|
||||
import { literals } from "@blitzkit/i18n";
|
||||
import { Box, Flex, Text } from "@radix-ui/themes";
|
||||
import { useRef, useState } from "react";
|
||||
@@ -124,7 +124,7 @@ export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
||||
/>
|
||||
|
||||
<img
|
||||
src={`/api/icons/shells/${shell.icon}.webp`}
|
||||
src={alias("api", `/icons/shells/${shell.icon}.webp`)}
|
||||
style={{
|
||||
objectFit: "contain",
|
||||
transform: "translate(-50%, -50%) rotate(-45deg)",
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { Badge, Box, Flex, Heading, Switch, Text } from "@radix-ui/themes";
|
||||
import { useLocale } from "../../../../hooks/useLocale";
|
||||
import { Duel } from "../../../../stores/duel";
|
||||
@@ -33,7 +34,7 @@ export function Equalizer() {
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
borderRadius: "var(--radius-3)",
|
||||
backgroundImage: "url(/api/gamemodes/45/banner.webp)",
|
||||
backgroundImage: `url(${alias("api", `/gamemodes/45/banner.webp`)})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
overflow: "hidden",
|
||||
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { Flex, Heading } from "@radix-ui/themes";
|
||||
import { useLocale } from "../../../../hooks/useLocale";
|
||||
import { Duel } from "../../../../stores/duel";
|
||||
@@ -21,7 +22,7 @@ export function Miscellaneous() {
|
||||
<Flex gap="2" align="center">
|
||||
{!tank.fixed_camouflage && (
|
||||
<GenericTankComponentButton
|
||||
icon={"/api/icons/camo.webp"}
|
||||
icon={alias("api", "/icons/camo.webp")}
|
||||
selected={camouflage}
|
||||
iconStyles={{
|
||||
top: "50%",
|
||||
@@ -36,7 +37,7 @@ export function Miscellaneous() {
|
||||
/>
|
||||
)}
|
||||
<GenericTankComponentButton
|
||||
icon={"/api/icons/boosters/equipment.webp"}
|
||||
icon={alias("api", "/icons/boosters/equipment.webp")}
|
||||
selected={cooldownBooster > 0}
|
||||
banner={
|
||||
cooldownBooster === 0
|
||||
|
||||
+6
-2
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
alias,
|
||||
EngineDefinition,
|
||||
formatCompact,
|
||||
GunDefinition,
|
||||
@@ -110,7 +111,7 @@ function ModuleButton({
|
||||
|
||||
<img
|
||||
alt={unlock.cost!.type}
|
||||
src={`/api/icons/currencies/${unlock.cost!.type}.webp`}
|
||||
src={alias("api", `/icons/currencies/${unlock.cost!.type}.webp`)}
|
||||
style={{
|
||||
width: 12,
|
||||
height: 12,
|
||||
@@ -125,7 +126,10 @@ function ModuleButton({
|
||||
src={
|
||||
isTank
|
||||
? tankIcon(unlock.id)
|
||||
: `/api/icons/modules/${moduleTypeTypeIconName[unlock.type]}.webp`
|
||||
: alias(
|
||||
"api",
|
||||
`/icons/modules/${moduleTypeTypeIconName[unlock.type]}.webp`,
|
||||
)
|
||||
}
|
||||
style={{
|
||||
width: isTank ? 64 : 32,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { Box, Flex, Heading, Text } from "@radix-ui/themes";
|
||||
import { api } from "../../core/blitzkit/api";
|
||||
import { useLocale } from "../../hooks/useLocale";
|
||||
@@ -37,7 +38,10 @@ export function GameModeSection() {
|
||||
direction="column"
|
||||
style={{
|
||||
borderRadius: "var(--radius-3)",
|
||||
background: `url(/api/gamemodes/${id}/banner.webp)`,
|
||||
background: `url(${alias(
|
||||
"api",
|
||||
`/gamemodes/${id}/banner.webp`,
|
||||
)})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
}}
|
||||
@@ -45,7 +49,10 @@ export function GameModeSection() {
|
||||
<Box
|
||||
flexGrow="1"
|
||||
style={{
|
||||
background: `url(/api/gamemodes/${id}/banner.webp)`,
|
||||
background: `url(${alias(
|
||||
"api",
|
||||
`/gamemodes/${id}/banner.webp`,
|
||||
)})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
}}
|
||||
@@ -80,7 +87,7 @@ export function GameModeSection() {
|
||||
height: "1.5em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/provisions/${id}.webp`}
|
||||
src={alias("api", `/icons/provisions/${id}.webp`)}
|
||||
alt={unwrap(provisions.name!)}
|
||||
/>
|
||||
{unwrap(provisions.name!)}
|
||||
@@ -101,7 +108,7 @@ export function GameModeSection() {
|
||||
height: "1.5em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/icons/consumables/${id}.webp`}
|
||||
src={alias("api", `/icons/consumables/${id}.webp`)}
|
||||
alt={unwrap(consumable.name!)}
|
||||
/>
|
||||
{unwrap(consumable.name!)}
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { IconButton } from "@radix-ui/themes";
|
||||
import { useArmor } from "../../../../../../hooks/useArmor";
|
||||
import { Duel } from "../../../../../../stores/duel";
|
||||
@@ -37,7 +38,7 @@ export function DynamicArmorSwitcher() {
|
||||
>
|
||||
<img
|
||||
alt="Dynamic Armor"
|
||||
src={"/api/icons/consumables/73.webp"}
|
||||
src={alias("api", "/icons/consumables/73.webp")}
|
||||
style={{
|
||||
width: "50%",
|
||||
height: "50%",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
alias,
|
||||
resolvePenetrationCoefficient,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
uniqueGuns,
|
||||
@@ -139,7 +140,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
||||
|
||||
<img
|
||||
alt="Antagonist Gun"
|
||||
src={"/api/icons/modules/gun.webp"}
|
||||
src={alias("api", "/icons/modules/gun.webp")}
|
||||
style={{
|
||||
width: "65%",
|
||||
height: "65%",
|
||||
@@ -208,7 +209,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
||||
>
|
||||
<img
|
||||
alt={unwrap(thisShell.name!)}
|
||||
src={`/api/icons/shells/${thisShell.icon}.webp`}
|
||||
src={alias("api", `/icons/shells/${thisShell.icon}.webp`)}
|
||||
style={{
|
||||
width: "50%",
|
||||
height: "50%",
|
||||
@@ -245,7 +246,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
||||
>
|
||||
<img
|
||||
alt="Calibrated Shells"
|
||||
src={"/api/icons/equipment/103.webp"}
|
||||
src={alias("api", "/icons/equipment/103.webp")}
|
||||
style={{
|
||||
width: "50%",
|
||||
height: "50%",
|
||||
@@ -270,7 +271,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
||||
>
|
||||
<img
|
||||
alt="Enhanced Armor"
|
||||
src={"/api/icons/equipment/110.webp"}
|
||||
src={alias("api", "/icons/equipment/110.webp")}
|
||||
style={{
|
||||
width: "50%",
|
||||
height: "50%",
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { Flex, type FlexProps, Progress } from "@radix-ui/themes";
|
||||
import { useProgress } from "@react-three/drei";
|
||||
|
||||
@@ -11,7 +12,7 @@ export function TankSandboxLoader({ id, ...props }: TankSandboxLoaderProps) {
|
||||
return (
|
||||
<Flex width="100%" height="100%" align="center" justify="center" {...props}>
|
||||
<img
|
||||
src={`/api/tanks/${id}/icons/big.webp`}
|
||||
src={alias("api", `/tanks/${id}/icons/big.webp`)}
|
||||
style={{ height: "75%", filter: "blur(1rem)" }}
|
||||
/>
|
||||
<Progress
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Flex, Text, type TextProps } from '@radix-ui/themes';
|
||||
import { Var } from '../../../../core/radix/var';
|
||||
import { Flex, Text, type TextProps } from "@radix-ui/themes";
|
||||
import { Var } from "../../../../core/radix/var";
|
||||
|
||||
type ListingProps = TextProps & {
|
||||
label: string;
|
||||
@@ -11,7 +11,7 @@ export function Listing({ label, ...props }: ListingProps) {
|
||||
minWidth="17rem"
|
||||
justify="between"
|
||||
gap="4"
|
||||
style={{ borderBottom: `1px solid ${Var('gray-a9')}` }}
|
||||
style={{ borderBottom: `1px solid ${Var("gray-a9")}` }}
|
||||
>
|
||||
<Text size="4">{label}</Text>
|
||||
<Text align="right" size="4" weight="medium" {...props} />
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
import { StarFilledIcon, StarIcon } from '@radix-ui/react-icons';
|
||||
import { Box, type BoxProps } from '@radix-ui/themes';
|
||||
|
||||
type PartialStarProps = BoxProps & {
|
||||
fill: number;
|
||||
};
|
||||
|
||||
export function PartialStar({ fill, ...props }: PartialStarProps) {
|
||||
return (
|
||||
<Box height="1em" width="1em" position="relative" {...props}>
|
||||
<StarIcon width="1em" height="1em" />
|
||||
{fill > 0 && (
|
||||
<Box
|
||||
top="0"
|
||||
left="0"
|
||||
width={`${fill * 100}%`}
|
||||
position="absolute"
|
||||
overflow="hidden"
|
||||
>
|
||||
<StarFilledIcon width="1em" height="1em" />
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import type { StarsInt } from '@blitzkit/core';
|
||||
import { type TextProps, Flex, Text } from '@radix-ui/themes';
|
||||
import { times } from 'lodash-es';
|
||||
import { PartialStar } from './components/PartialStar';
|
||||
|
||||
type StarsProps = TextProps & {
|
||||
stars: number | null;
|
||||
onCast?: (value: StarsInt) => void;
|
||||
};
|
||||
|
||||
export function Stars({ stars, onCast, ...props }: StarsProps) {
|
||||
let color: TextProps['color'] = 'green';
|
||||
|
||||
if (stars === null) color = 'gray';
|
||||
else if (stars < 1.5) color = 'tomato';
|
||||
else if (stars < 2.5) color = 'orange';
|
||||
else if (stars < 3.5) color = 'amber';
|
||||
else if (stars < 4.5) color = 'blue';
|
||||
|
||||
return (
|
||||
<Text color={color} {...props}>
|
||||
<Flex style={{ cursor: onCast ? 'pointer' : 'unset' }}>
|
||||
{stars !== null &&
|
||||
times(Math.floor(stars), (index) => (
|
||||
<PartialStar
|
||||
fill={1}
|
||||
key={index}
|
||||
onClick={() => onCast?.((index + 1) as StarsInt)}
|
||||
/>
|
||||
))}
|
||||
{stars !== null && stars % 1 !== 0 && <PartialStar fill={stars % 1} />}
|
||||
{times(5 - Math.ceil(stars ?? 0), (index) => (
|
||||
<PartialStar
|
||||
fill={0}
|
||||
key={index}
|
||||
onClick={() =>
|
||||
onCast?.((Math.floor(stars ?? 0) + index + 1) as StarsInt)
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
import { Flex, Text } from '@radix-ui/themes';
|
||||
import { Stars } from '../../Stars';
|
||||
|
||||
interface StarRowProps {
|
||||
stars: number | null;
|
||||
children: string;
|
||||
}
|
||||
|
||||
export function StarRow({ stars, children }: StarRowProps) {
|
||||
return (
|
||||
<Text color={stars === null ? 'gray' : undefined}>
|
||||
<Flex align="center" justify="between" width="15rem">
|
||||
{children}
|
||||
<Stars stars={stars} />
|
||||
</Flex>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
-179
@@ -1,179 +0,0 @@
|
||||
import type { BlitzkitResponse, StarsInt } from "@blitzkit/core";
|
||||
import { PaperPlaneIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
AlertDialog,
|
||||
Button,
|
||||
Dialog,
|
||||
Flex,
|
||||
Spinner,
|
||||
Text,
|
||||
} from "@radix-ui/themes";
|
||||
import { useState } from "react";
|
||||
import { useLocale } from "../../../../../../hooks/useLocale";
|
||||
import { App } from "../../../../../../stores/app";
|
||||
import { Duel } from "../../../../../../stores/duel";
|
||||
import { Stars } from "../../Stars";
|
||||
|
||||
export function VoteCaster() {
|
||||
const tank = Duel.use((state) => state.protagonist.tank);
|
||||
const [easiness, setEasiness] = useState<StarsInt | null>(null);
|
||||
const [firepower, setFirepower] = useState<StarsInt | null>(null);
|
||||
const [maneuverability, setManeuverability] = useState<StarsInt | null>(null);
|
||||
const [survivability, setSurvivability] = useState<StarsInt | null>(null);
|
||||
// true = vote successful, false = vote failed, null = hide alert
|
||||
const [postVote, setPostVote] = useState<boolean | null>(null);
|
||||
// true = open, false = closed, null = casting
|
||||
const [showDialogue, setShowDialogue] = useState<boolean | null>(false);
|
||||
const { unwrap } = useLocale();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog.Root open={showDialogue !== false} onOpenChange={setShowDialogue}>
|
||||
<Dialog.Trigger>
|
||||
<Button variant="surface">
|
||||
<PaperPlaneIcon /> Vote
|
||||
</Button>
|
||||
</Dialog.Trigger>
|
||||
|
||||
<Dialog.Content maxWidth="23rem">
|
||||
<Dialog.Title>Voting for {unwrap(tank.name!)}</Dialog.Title>
|
||||
|
||||
<Flex direction="column" mt="4">
|
||||
<Flex align="center" justify="between">
|
||||
<Text>
|
||||
Easiness{" "}
|
||||
<Text color="gray" size="2">
|
||||
{easiness === null ? "(empty)" : `(${easiness})`}
|
||||
</Text>
|
||||
</Text>
|
||||
<Stars stars={easiness} size="5" onCast={setEasiness} />
|
||||
</Flex>
|
||||
<Flex align="center" justify="between">
|
||||
<Text>
|
||||
Firepower{" "}
|
||||
<Text color="gray" size="2">
|
||||
{firepower === null ? "(empty)" : `(${firepower})`}
|
||||
</Text>
|
||||
</Text>
|
||||
<Stars stars={firepower} size="5" onCast={setFirepower} />
|
||||
</Flex>
|
||||
<Flex align="center" justify="between">
|
||||
<Text>
|
||||
Maneuverability{" "}
|
||||
<Text color="gray" size="2">
|
||||
{maneuverability === null
|
||||
? "(empty)"
|
||||
: `(${maneuverability})`}
|
||||
</Text>
|
||||
</Text>
|
||||
<Stars
|
||||
stars={maneuverability}
|
||||
size="5"
|
||||
onCast={setManeuverability}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex align="center" justify="between">
|
||||
<Text>
|
||||
Survivability{" "}
|
||||
<Text color="gray" size="2">
|
||||
{survivability === null ? "(empty)" : `(${survivability})`}
|
||||
</Text>
|
||||
</Text>
|
||||
<Stars stars={survivability} size="5" onCast={setSurvivability} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<Flex justify="end" mt="4" gap="2">
|
||||
<Dialog.Close>
|
||||
<Button variant="outline" color="red">
|
||||
Cancel
|
||||
</Button>
|
||||
</Dialog.Close>
|
||||
|
||||
<Button
|
||||
disabled={
|
||||
showDialogue === null ||
|
||||
(easiness === null &&
|
||||
firepower === null &&
|
||||
maneuverability === null &&
|
||||
survivability === null)
|
||||
}
|
||||
onClick={() => {
|
||||
const { wargaming } = App.state.logins;
|
||||
|
||||
if (!wargaming) {
|
||||
return setShowDialogue(false);
|
||||
}
|
||||
|
||||
setShowDialogue(null);
|
||||
|
||||
fetch(
|
||||
`/api/tank-voting/${tank.id}/cast?${
|
||||
easiness === null ? "" : `easiness=${easiness}&`
|
||||
}${firepower === null ? "" : `firepower=${firepower}&`}${
|
||||
maneuverability === null
|
||||
? ""
|
||||
: `maneuverability=${maneuverability}&`
|
||||
}${
|
||||
survivability === null
|
||||
? ""
|
||||
: `survivability=${survivability}&`
|
||||
}player=${wargaming.id}&token=${wargaming.token}`,
|
||||
)
|
||||
.then(
|
||||
(response) => response.json() as Promise<BlitzkitResponse>,
|
||||
)
|
||||
.then((json) => {
|
||||
setShowDialogue(false);
|
||||
setPostVote(json.status === "ok");
|
||||
|
||||
if (json.status === "error") {
|
||||
console.error("vote failed", json);
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
{showDialogue === null ? <Spinner /> : <PaperPlaneIcon />} Vote
|
||||
</Button>
|
||||
</Flex>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
|
||||
<AlertDialog.Root
|
||||
open={postVote !== null}
|
||||
onOpenChange={() => setPostVote(null)}
|
||||
>
|
||||
{postVote === true && (
|
||||
<AlertDialog.Content maxWidth="20rem">
|
||||
<AlertDialog.Title>Vote casted</AlertDialog.Title>
|
||||
<AlertDialog.Description>
|
||||
It may take a few minutes for it to show up.
|
||||
</AlertDialog.Description>
|
||||
|
||||
<Flex justify="end" mt="4">
|
||||
<AlertDialog.Cancel>
|
||||
<Button>Okay</Button>
|
||||
</AlertDialog.Cancel>
|
||||
</Flex>
|
||||
</AlertDialog.Content>
|
||||
)}
|
||||
|
||||
{postVote === false && (
|
||||
<AlertDialog.Content maxWidth="20rem">
|
||||
<AlertDialog.Title>Voting failed</AlertDialog.Title>
|
||||
<AlertDialog.Description>
|
||||
So sorry about this! If you're a nerd, feel free to check out the
|
||||
console.
|
||||
</AlertDialog.Description>
|
||||
|
||||
<Flex justify="end" mt="4">
|
||||
<AlertDialog.Cancel>
|
||||
<Button>Gotcha</Button>
|
||||
</AlertDialog.Cancel>
|
||||
</Flex>
|
||||
</AlertDialog.Content>
|
||||
)}
|
||||
</AlertDialog.Root>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
import { formatCompact } from '@blitzkit/core';
|
||||
import { Flex, Heading, Skeleton, Text } from '@radix-ui/themes';
|
||||
import { memo } from 'react';
|
||||
import { useLocale } from '../../../../../hooks/useLocale';
|
||||
import { useTankVotes } from '../../../../../hooks/useTankVotes';
|
||||
import { App } from '../../../../../stores/app';
|
||||
import { Duel } from '../../../../../stores/duel';
|
||||
import { WargamingLoginButton } from '../../../../WargamingLoginButton';
|
||||
import { StarRow } from './components/StarRow';
|
||||
import { VoteCaster } from './components/VoteCaster';
|
||||
|
||||
export const Votes = memo(
|
||||
() => {
|
||||
const id = Duel.use((state) => state.protagonist.tank.id);
|
||||
const votes = useTankVotes(id);
|
||||
const wargaming = App.use((state) => state.logins.wargaming);
|
||||
const { locale } = useLocale();
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="3">
|
||||
<Flex justify="between" align="center">
|
||||
<Heading size="4">
|
||||
{!votes && <Skeleton height="1em" width="4rem" />}
|
||||
{votes && formatCompact(locale, votes.votes)}{' '}
|
||||
{votes && (votes.votes > 1 ? 'votes' : 'vote')}
|
||||
</Heading>
|
||||
|
||||
{!wargaming && (
|
||||
<WargamingLoginButton variant="surface">
|
||||
Login to vote
|
||||
</WargamingLoginButton>
|
||||
)}
|
||||
{wargaming && <VoteCaster />}
|
||||
</Flex>
|
||||
|
||||
<Flex gap="0" direction="column">
|
||||
<Flex
|
||||
gap={{ initial: '0', sm: '6' }}
|
||||
direction={{ initial: 'column', sm: 'row' }}
|
||||
>
|
||||
<StarRow
|
||||
stars={votes?.categories.easiness ?? null}
|
||||
children="Easiness"
|
||||
/>
|
||||
<StarRow
|
||||
stars={votes?.categories.firepower ?? null}
|
||||
children="Firepower"
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
gap={{ initial: '0', sm: '6' }}
|
||||
direction={{ initial: 'column', sm: 'row' }}
|
||||
>
|
||||
<StarRow
|
||||
stars={votes?.categories.maneuverability ?? null}
|
||||
children="Maneuverability"
|
||||
/>
|
||||
<StarRow
|
||||
stars={votes?.categories.survivability ?? null}
|
||||
children="Survivability"
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Flex justify="center">
|
||||
<Text size="2" color="gray" mt="2">
|
||||
<>
|
||||
{votes ? (
|
||||
wargaming ? (
|
||||
votes.last_updated ? (
|
||||
`You voted on ${new Date(
|
||||
votes.last_updated,
|
||||
).toLocaleDateString()}`
|
||||
) : (
|
||||
`You haven't voted yet`
|
||||
)
|
||||
) : (
|
||||
'Login to vote'
|
||||
)
|
||||
) : (
|
||||
<Skeleton height="1em" width="5rem" />
|
||||
)}
|
||||
</>
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
},
|
||||
() => true,
|
||||
);
|
||||
@@ -1,4 +1,9 @@
|
||||
import { TankPriceType, TankType, TIER_ROMAN_NUMERALS } from "@blitzkit/core";
|
||||
import {
|
||||
alias,
|
||||
TankPriceType,
|
||||
TankType,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
} from "@blitzkit/core";
|
||||
import { Box, Flex } from "@radix-ui/themes";
|
||||
import { Var } from "../../../core/radix/var";
|
||||
import { useLocale } from "../../../hooks/useLocale";
|
||||
@@ -35,7 +40,7 @@ export function MetaSection() {
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
background: `url(${`/api/flags/scratched/${protagonist.nation}.webp`})`,
|
||||
background: `url(${alias("api", `/flags/scratched/${protagonist.nation}.webp`)})`,
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: "min(53rem, 80vw)",
|
||||
backgroundPosition: "-8rem 50%",
|
||||
@@ -60,7 +65,10 @@ export function MetaSection() {
|
||||
<img
|
||||
style={{ width: "1em", height: "1em" }}
|
||||
alt={protagonist.nation}
|
||||
src={`/api/flags/circle/${protagonist.nation}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/flags/circle/${protagonist.nation}.webp`,
|
||||
)}
|
||||
/>
|
||||
{
|
||||
strings.common.nations[
|
||||
@@ -130,7 +138,7 @@ export function MetaSection() {
|
||||
<img
|
||||
style={{ width: "1em", height: "1em" }}
|
||||
alt="gold"
|
||||
src={"/api/icons/currencies/gold.webp"}
|
||||
src={alias("api", "/icons/currencies/gold.webp")}
|
||||
/>
|
||||
</Flex>
|
||||
</Listing>
|
||||
@@ -147,12 +155,15 @@ export function MetaSection() {
|
||||
<img
|
||||
style={{ width: "1em", height: "1em" }}
|
||||
alt={TankPriceType[protagonist.price!.type]}
|
||||
src={`/api/icons/currencies/${
|
||||
protagonist.price!.type ===
|
||||
TankPriceType.TANK_PRICE_TYPE_GOLD
|
||||
? "gold"
|
||||
: "silver"
|
||||
}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/currencies/${
|
||||
protagonist.price!.type ===
|
||||
TankPriceType.TANK_PRICE_TYPE_GOLD
|
||||
? "gold"
|
||||
: "silver"
|
||||
}.webp`,
|
||||
)}
|
||||
/>
|
||||
</Flex>
|
||||
</Listing>
|
||||
@@ -162,12 +173,15 @@ export function MetaSection() {
|
||||
<img
|
||||
style={{ width: "1em", height: "1em" }}
|
||||
alt={TankPriceType[protagonist.price!.type]}
|
||||
src={`/api/icons/currencies/${
|
||||
protagonist.price!.type ===
|
||||
TankPriceType.TANK_PRICE_TYPE_GOLD
|
||||
? "gold"
|
||||
: "silver"
|
||||
}.webp`}
|
||||
src={alias(
|
||||
"api",
|
||||
`/icons/currencies/${
|
||||
protagonist.price!.type ===
|
||||
TankPriceType.TANK_PRICE_TYPE_GOLD
|
||||
? "gold"
|
||||
: "silver"
|
||||
}.webp`,
|
||||
)}
|
||||
/>
|
||||
</Flex>
|
||||
</Listing>
|
||||
@@ -183,7 +197,7 @@ export function MetaSection() {
|
||||
<img
|
||||
style={{ width: "1em", height: "1em" }}
|
||||
alt="xp"
|
||||
src={"/api/icons/currencies/xp.webp"}
|
||||
src={alias("api", "/icons/currencies/xp.webp")}
|
||||
/>
|
||||
</Flex>
|
||||
</Listing>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { formatCompact, TIER_ROMAN_NUMERALS } from "@blitzkit/core";
|
||||
import { alias, formatCompact, TIER_ROMAN_NUMERALS } from "@blitzkit/core";
|
||||
import { literals } from "@blitzkit/i18n/src/literals";
|
||||
import { Box, Flex, Skeleton, Text } from "@radix-ui/themes";
|
||||
import { awaitableAverageDefinitions } from "../../../../core/awaitables/averageDefinitions";
|
||||
@@ -58,7 +58,7 @@ export function Node({ id, highlight, nextIds, skeleton }: NodeProps) {
|
||||
mx={highlight ? "2" : "0"}
|
||||
style={{
|
||||
background: highlight
|
||||
? `url(${`/api/flags/fade/${tank.nation}.webp`})`
|
||||
? `url(${alias("api", `/flags/fade/${tank.nation}.webp`)})`
|
||||
: undefined,
|
||||
backgroundPosition: "center",
|
||||
backgroundSize: "cover",
|
||||
@@ -79,7 +79,7 @@ export function Node({ id, highlight, nextIds, skeleton }: NodeProps) {
|
||||
>
|
||||
<img
|
||||
alt={unwrap(tank.name!)}
|
||||
src={`/api/tanks/${id}/icons/big.webp`}
|
||||
src={alias("api", `/tanks/${id}/icons/big.webp`)}
|
||||
width={64}
|
||||
height={64}
|
||||
style={{
|
||||
@@ -99,7 +99,7 @@ export function Node({ id, highlight, nextIds, skeleton }: NodeProps) {
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="XP"
|
||||
src={"/api/icons/currencies/xp.webp"}
|
||||
src={alias("api", "/icons/currencies/xp.webp")}
|
||||
style={{
|
||||
width: "1em",
|
||||
height: "1em",
|
||||
@@ -114,7 +114,7 @@ export function Node({ id, highlight, nextIds, skeleton }: NodeProps) {
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="Silver"
|
||||
src={"/api/icons/currencies/silver.webp"}
|
||||
src={alias("api", "/icons/currencies/silver.webp")}
|
||||
style={{
|
||||
width: "1em",
|
||||
height: "1em",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TankType } from "@blitzkit/core";
|
||||
import { alias, TankType } from "@blitzkit/core";
|
||||
import { literals } from "@blitzkit/i18n/src/literals";
|
||||
import { CaretLeftIcon, CaretRightIcon, PlusIcon } from "@radix-ui/react-icons";
|
||||
import { Flex, Heading, IconButton, ScrollArea, Text } from "@radix-ui/themes";
|
||||
@@ -105,7 +105,7 @@ export function TechTreeSection({ skeleton }: MaybeSkeletonComponentProps) {
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="XP"
|
||||
src={"/api/icons/currencies/xp.webp"}
|
||||
src={alias("api", "/icons/currencies/xp.webp")}
|
||||
style={{
|
||||
width: "1em",
|
||||
height: "1em",
|
||||
@@ -121,7 +121,7 @@ export function TechTreeSection({ skeleton }: MaybeSkeletonComponentProps) {
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="Silver"
|
||||
src={"/api/icons/currencies/silver.webp"}
|
||||
src={alias("api", "/icons/currencies/silver.webp")}
|
||||
style={{
|
||||
width: "1em",
|
||||
height: "1em",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { assertSecret } from "@blitzkit/core";
|
||||
import { assertSecret, environmentConfig } from "@blitzkit/core";
|
||||
import type { GetStaticPaths } from "astro";
|
||||
|
||||
export function chunkedStaticPaths(chunk: string) {
|
||||
return function () {
|
||||
const environment = environmentConfig();
|
||||
const chunksEnv = assertSecret(import.meta.env.CHUNK);
|
||||
const chunks = chunksEnv.split(",");
|
||||
|
||||
@@ -10,6 +11,8 @@ export function chunkedStaticPaths(chunk: string) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [{ params: { [`chunk_${chunk}`]: undefined } }];
|
||||
return [
|
||||
{ params: { [`chunk_${chunk}`]: environment.paths[chunk] ?? undefined } },
|
||||
];
|
||||
} satisfies GetStaticPaths;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { useLoader } from "@react-three/fiber";
|
||||
import { Mesh, MeshStandardMaterial } from "three";
|
||||
import { GLTFLoader } from "three-stdlib";
|
||||
import { useDispose } from "./useDispose";
|
||||
|
||||
export function useModel(id: number) {
|
||||
const path = `/api/tanks/${id}/model.glb`;
|
||||
const path = alias("api", `/tanks/${id}/model.glb`);
|
||||
const gltf = useLoader(GLTFLoader, path);
|
||||
|
||||
useDispose(gltf, path);
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import {
|
||||
unwrapBlitzkitResponse,
|
||||
type BlitzkitResponse,
|
||||
type TankVotes,
|
||||
} from '@blitzkit/core';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { App } from '../stores/app';
|
||||
|
||||
const cache: Record<string, Promise<TankVotes> | TankVotes> = {};
|
||||
|
||||
export function useTankVotes(id: number) {
|
||||
const [votes, setVotes] = useState<TankVotes | null>(null);
|
||||
const wargaming = App.use((state) => state.logins.wargaming);
|
||||
|
||||
useEffect(() => {
|
||||
if (!wargaming) return;
|
||||
|
||||
if (id in cache) {
|
||||
Promise.all([cache[id]]).then(([votes]) => setVotes(votes));
|
||||
} else {
|
||||
const cacheable = fetch(
|
||||
`/api/tank-voting/${id}/average${
|
||||
wargaming ? `?player=${wargaming.id}&token=${wargaming.token}` : ''
|
||||
}`,
|
||||
)
|
||||
.then(
|
||||
(response) => response.json() as Promise<BlitzkitResponse<TankVotes>>,
|
||||
)
|
||||
.then(unwrapBlitzkitResponse);
|
||||
cacheable.then(setVotes);
|
||||
cache[id] = cacheable;
|
||||
}
|
||||
}, [id, wargaming]);
|
||||
|
||||
return votes;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
alias,
|
||||
GunDefinition,
|
||||
TankDefinition,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
@@ -110,7 +111,7 @@ function ModuleChooser({
|
||||
height: "4em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={`/api/tanks/${tank}/icons/big.webp`}
|
||||
src={alias("api", `/tanks/${tank}/icons/big.webp`)}
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
import { AstroSeo } from "@astrolib/seo";
|
||||
import {
|
||||
alias,
|
||||
assertSecret,
|
||||
createDefaultProvisions,
|
||||
createDefaultSkills,
|
||||
@@ -51,7 +52,7 @@ const title = literals(strings.website.tools.tankopedia.tank_seo_title, {
|
||||
});
|
||||
const url = import.meta.env.SITE + Astro.url.pathname;
|
||||
|
||||
const icon = `/api/tanks/${id}/icons/big.webp`;
|
||||
const icon = alias("api", `/tanks/${id}/icons/big.webp`);
|
||||
const turret = tank.turrets.at(-1)!;
|
||||
const gun = turret.guns.at(-1)!;
|
||||
const shell = gun.shells[0];
|
||||
|
||||
Reference in new issue
Block a user