mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
module price rendering
This commit is contained in:
1 parent
6d2573ee95
commit
f0e0d849d5
12 files changed
+269
-91
No files matched your search
@@ -3,5 +3,5 @@
|
|||||||
|
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
|
|
||||||
font-size: 1.75em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
.price {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: var(--space-3);
|
||||||
|
|
||||||
|
.entry {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-1);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import { formatCompact } from "@blitzkit/core";
|
||||||
|
import type { StandardPrice } from "@protos/game/proto/legacy/blitz_static_standard_price";
|
||||||
|
import type { StandardSinglePrice } from "@protos/game/proto/legacy/blitz_static_standard_single_price";
|
||||||
|
import type { ComponentProps } from "react";
|
||||||
|
import { classNames } from "../../core/ui/classNames";
|
||||||
|
import { useLocale } from "../../hooks/useLocale";
|
||||||
|
import { Text } from "../Text";
|
||||||
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
|
interface PriceProps extends ComponentProps<"div"> {
|
||||||
|
price: StandardPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Price({ price, className, ...props }: PriceProps) {
|
||||||
|
return (
|
||||||
|
<div className={classNames(styles.price, className)} {...props}>
|
||||||
|
{price.price_list.map((entry, index) => (
|
||||||
|
<PriceEntry key={index} entry={entry} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PriceEntryProps {
|
||||||
|
entry: StandardSinglePrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PriceEntry({ entry }: PriceEntryProps) {
|
||||||
|
const locale = useLocale();
|
||||||
|
|
||||||
|
if (
|
||||||
|
entry.premium_time_price !== undefined ||
|
||||||
|
entry.stuff_price !== undefined ||
|
||||||
|
entry.currency_price === undefined
|
||||||
|
) {
|
||||||
|
throw new Error("Unsupported price type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text size="minor" lowContrast className={styles.entry}>
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<img
|
||||||
|
className={styles.icon}
|
||||||
|
src="https://static.vecteezy.com/system/resources/thumbnails/047/493/988/small/hairy-fluffy-cat-playing-png.png"
|
||||||
|
/>
|
||||||
|
{formatCompact(locale, entry.currency_price.amount)}
|
||||||
|
</div>
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -13,11 +13,11 @@
|
|||||||
.stage {
|
.stage {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
img {
|
.icon {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
|
|
||||||
transform: translate(var(--space-1), var(--space-1));
|
transform: translateX(var(--space-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
.tier {
|
.tier {
|
||||||
@@ -25,6 +25,13 @@
|
|||||||
left: var(--space-2);
|
left: var(--space-2);
|
||||||
top: var(--space-2);
|
top: var(--space-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: var(--space-2);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
import type { UpgradeLine } from "@blitzkit/closed/protos/game/proto/legacy/blitz_static_tank_upgrade_line";
|
|
||||||
import { romanize } from "@blitzkit/core";
|
import { romanize } from "@blitzkit/core";
|
||||||
import { Fragment, useMemo } from "react";
|
import { Grade } from "@protos/game/proto/legacy/blitz_static_standard_grades_enum";
|
||||||
import { api } from "../../core/api/dynamic";
|
import type { StandardPrice } from "@protos/game/proto/legacy/blitz_static_standard_price";
|
||||||
import { useAwait } from "../../hooks/useAwait";
|
import type { UpgradeLine } from "@protos/game/proto/legacy/blitz_static_tank_upgrade_line";
|
||||||
|
import type { StageParameters } from "@protos/game/proto/legacy/blitz_static_tank_upgrade_single_stage";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { useProtagonist } from "../../hooks/useProtagonist";
|
||||||
import { useStrings } from "../../hooks/useStrings";
|
import { useStrings } from "../../hooks/useStrings";
|
||||||
|
import { useUpgradePreset } from "../../hooks/useUpgradePreset";
|
||||||
import { Tankopedia } from "../../stores/tankopedia";
|
import { Tankopedia } from "../../stores/tankopedia";
|
||||||
import { Heading } from "../Heading";
|
import { Heading } from "../Heading";
|
||||||
import { IconButton } from "../IconButton";
|
import { IconButton } from "../IconButton";
|
||||||
|
import { Price } from "../Price";
|
||||||
import { Section } from "../Section";
|
import { Section } from "../Section";
|
||||||
import { Text } from "../Text";
|
import { Text } from "../Text";
|
||||||
import styles from "./index.module.css";
|
import styles from "./index.module.css";
|
||||||
@@ -14,8 +18,7 @@ import styles from "./index.module.css";
|
|||||||
export function TankopediaLoadout() {
|
export function TankopediaLoadout() {
|
||||||
const strings = useStrings();
|
const strings = useStrings();
|
||||||
|
|
||||||
const id = Tankopedia.use((state) => state.protagonist.id);
|
const tank = useProtagonist();
|
||||||
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section>
|
<Section>
|
||||||
@@ -25,7 +28,7 @@ export function TankopediaLoadout() {
|
|||||||
{tank.tank!.upgrade_lines.map((line) => (
|
{tank.tank!.upgrade_lines.map((line) => (
|
||||||
<Line
|
<Line
|
||||||
key={line.name}
|
key={line.name}
|
||||||
line={line.name}
|
name={line.name}
|
||||||
lines={tank.tank!.upgrade_lines}
|
lines={tank.tank!.upgrade_lines}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@@ -35,7 +38,7 @@ export function TankopediaLoadout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface LineProps {
|
interface LineProps {
|
||||||
line: string;
|
name: string;
|
||||||
lines: UpgradeLine[];
|
lines: UpgradeLine[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,107 +46,143 @@ const mergeLines = {
|
|||||||
alternative_guns: "guns",
|
alternative_guns: "guns",
|
||||||
} as Record<string, string>;
|
} as Record<string, string>;
|
||||||
|
|
||||||
function Line({ line, lines }: LineProps) {
|
function Line({ name, lines }: LineProps) {
|
||||||
const combinedLines = useMemo(() => {
|
const combinedLines = useMemo(() => {
|
||||||
const lines: string[] = [line];
|
const names: string[] = [name];
|
||||||
|
|
||||||
for (const key in mergeLines) {
|
for (const key in mergeLines) {
|
||||||
if (mergeLines[key] === line) {
|
if (mergeLines[key] === name && lines.some((line) => line.name === key)) {
|
||||||
lines.push(key);
|
names.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines;
|
return names;
|
||||||
}, [line]);
|
}, [name]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.line}>
|
<div className={styles.line}>
|
||||||
{!(line in mergeLines) &&
|
{!(name in mergeLines) &&
|
||||||
combinedLines.map((line) => <LineInner line={line} lines={lines} />)}
|
combinedLines.map((name) => (
|
||||||
|
<LineInner key={name} name={name} lines={lines} />
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LineInner({ line, lines }: LineProps) {
|
function LineInner({ name, lines }: LineProps) {
|
||||||
const id = Tankopedia.use((state) => state.protagonist.id);
|
const line = lines.find((line) => line.name === name)!;
|
||||||
const upgrades = Tankopedia.use((state) => state.protagonist.upgrades);
|
|
||||||
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
|
||||||
|
|
||||||
|
return line.stages.map((stage, index) => (
|
||||||
|
<LineElement key={index} index={index} lineName={name} stage={stage} />
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LineElementProps {
|
||||||
|
index: number;
|
||||||
|
lineName: string;
|
||||||
|
stage: StageParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
function LineElement({ index, lineName, stage }: LineElementProps) {
|
||||||
|
const upgrades = Tankopedia.use((state) => state.protagonist.upgrades);
|
||||||
|
const tank = useProtagonist();
|
||||||
const strings = useStrings();
|
const strings = useStrings();
|
||||||
|
const upgradePreset = useUpgradePreset(tank.tank!.tank_upgrade_preset);
|
||||||
|
|
||||||
|
let price: StandardPrice | undefined;
|
||||||
|
|
||||||
|
switch (stage.grade) {
|
||||||
|
case Grade.GRADE_COMMON:
|
||||||
|
price = upgradePreset.common_grade_price;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Grade.GRADE_RARE:
|
||||||
|
price = upgradePreset.rare_grade_price;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Grade.GRADE_EPIC:
|
||||||
|
price = upgradePreset.unique_grade_price;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Grade.GRADE_LEGENDARY:
|
||||||
|
price = upgradePreset.legendary_grade_price;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const override of upgradePreset.prices_overrides) {
|
||||||
|
if (override.stage_tech_name !== stage.tech_name) continue;
|
||||||
|
price = override.price;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSelected = upgrades[lineName] === index;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
color={isSelected ? undefined : "gray"}
|
||||||
|
variant={isSelected ? "surface" : "soft"}
|
||||||
|
radius="1"
|
||||||
|
className={styles.stage}
|
||||||
|
onClick={() => {
|
||||||
|
Tankopedia.mutate((draft) => {
|
||||||
|
draft.protagonist.upgrades[lineName] = index;
|
||||||
|
|
||||||
|
for (const required of stage.required_upgrades) {
|
||||||
|
for (const line of tank.tank!.upgrade_lines) {
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
return lines
|
for (const stage of line.stages) {
|
||||||
.find((l) => l.name === line)!
|
if (stage.tech_name === required) {
|
||||||
.stages.map((stage, index) => {
|
draft.protagonist.upgrades[line.name] = Math.max(
|
||||||
const isSelected = upgrades[line] === index;
|
draft.protagonist.upgrades[line.name],
|
||||||
|
i,
|
||||||
return (
|
);
|
||||||
<Fragment key={stage.tech_name}>
|
|
||||||
<IconButton
|
|
||||||
color={isSelected ? undefined : "gray"}
|
|
||||||
variant={isSelected ? "surface" : "soft"}
|
|
||||||
radius="1"
|
|
||||||
className={styles.stage}
|
|
||||||
onClick={() => {
|
|
||||||
Tankopedia.mutate((draft) => {
|
|
||||||
draft.protagonist.upgrades[line] = index;
|
|
||||||
|
|
||||||
for (const required of stage.required_upgrades) {
|
|
||||||
for (const line of tank.tank!.upgrade_lines) {
|
|
||||||
let i = 0;
|
|
||||||
|
|
||||||
for (const stage of line.stages) {
|
|
||||||
if (stage.tech_name === required) {
|
|
||||||
draft.protagonist.upgrades[line.name] = Math.max(
|
|
||||||
draft.protagonist.upgrades[line.name],
|
|
||||||
i,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const line of tank.tank!.upgrade_lines) {
|
||||||
|
let i = draft.protagonist.upgrades[line.name];
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
const currentStage = line.stages[i];
|
||||||
|
const valid = currentStage.required_upgrades.every((required) => {
|
||||||
for (const line of tank.tank!.upgrade_lines) {
|
for (const line of tank.tank!.upgrade_lines) {
|
||||||
let i = draft.protagonist.upgrades[line.name];
|
const idx = draft.protagonist.upgrades[line.name];
|
||||||
|
|
||||||
|
if (line.stages[idx]?.tech_name === required) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (i > 0) {
|
return false;
|
||||||
const currentStage = line.stages[i];
|
});
|
||||||
const valid = currentStage.required_upgrades.every(
|
|
||||||
(required) => {
|
|
||||||
for (const line of tank.tank!.upgrade_lines) {
|
|
||||||
const idx = draft.protagonist.upgrades[line.name];
|
|
||||||
|
|
||||||
if (line.stages[idx]?.tech_name === required) {
|
if (valid) break;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
i--;
|
||||||
},
|
}
|
||||||
);
|
|
||||||
|
|
||||||
if (valid) break;
|
draft.protagonist.upgrades[line.name] = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className={styles.icon}
|
||||||
|
src={`/api/tanks/modules/${stage.stage_type}.webp`}
|
||||||
|
/>
|
||||||
|
{/* {stage.display_name} */}
|
||||||
|
|
||||||
i--;
|
<Text lowContrast size="minor" className={styles.tier}>
|
||||||
}
|
{lineName in mergeLines
|
||||||
|
? strings.tanks.loadout.alternative
|
||||||
|
: romanize(stage.number)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
draft.protagonist.upgrades[line.name] = i;
|
{price && <Price className={styles.price} price={price} />}
|
||||||
}
|
</IconButton>
|
||||||
});
|
);
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img src={`/api/tanks/modules/${stage.stage_type}.webp`} />
|
|
||||||
{/* {stage.display_name} */}
|
|
||||||
{/* {stage.grade} */}
|
|
||||||
|
|
||||||
<Text lowContrast size="minor" className={styles.tier}>
|
|
||||||
{line in mergeLines
|
|
||||||
? strings.tanks.loadout.alternative
|
|
||||||
: romanize(stage.number)}
|
|
||||||
</Text>
|
|
||||||
</IconButton>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { MetadataAccessor } from "@blitzkit/closed";
|
||||||
import type { Strings } from "@blitzkit/i18n";
|
import type { Strings } from "@blitzkit/i18n";
|
||||||
import locales from "@blitzkit/i18n/locales.json";
|
import locales from "@blitzkit/i18n/locales.json";
|
||||||
import type { Avatar } from "@protos/blitzkit/avatar";
|
import type { Avatar } from "@protos/blitzkit/avatar";
|
||||||
@@ -10,12 +11,18 @@ import type { Tank } from "@protos/blitzkit/tank";
|
|||||||
import type { TankList } from "@protos/blitzkit/tank_list";
|
import type { TankList } from "@protos/blitzkit/tank_list";
|
||||||
import type { Tanks } from "@protos/blitzkit/tanks";
|
import type { Tanks } from "@protos/blitzkit/tanks";
|
||||||
import type { Tiers } from "@protos/blitzkit/tiers";
|
import type { Tiers } from "@protos/blitzkit/tiers";
|
||||||
|
import type { TankUpgradePricePresetComponent } from "@protos/game/proto/legacy/blitz_static_tank_upgrade_price_preset_component";
|
||||||
|
|
||||||
export abstract class AbstractAPI {
|
export abstract class AbstractAPI {
|
||||||
|
abstract metadata: MetadataAccessor;
|
||||||
|
|
||||||
abstract tankList(): Promise<TankList>;
|
abstract tankList(): Promise<TankList>;
|
||||||
abstract tank(id: string): Promise<Tank>;
|
abstract tank(id: string): Promise<Tank>;
|
||||||
abstract tanks(): Promise<Tanks>;
|
abstract tanks(): Promise<Tanks>;
|
||||||
abstract popularTanks(): Promise<PopularTanks>;
|
abstract popularTanks(): Promise<PopularTanks>;
|
||||||
|
abstract tankUpgradePreset(
|
||||||
|
name: string,
|
||||||
|
): Promise<TankUpgradePricePresetComponent>;
|
||||||
|
|
||||||
abstract tiers(): Promise<Tiers>;
|
abstract tiers(): Promise<Tiers>;
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,16 @@ import { PopularTanks } from "@protos/blitzkit/popular_tanks";
|
|||||||
import { TankList } from "@protos/blitzkit/tank_list";
|
import { TankList } from "@protos/blitzkit/tank_list";
|
||||||
import { Tanks } from "@protos/blitzkit/tanks";
|
import { Tanks } from "@protos/blitzkit/tanks";
|
||||||
import { Tiers } from "@protos/blitzkit/tiers";
|
import { Tiers } from "@protos/blitzkit/tiers";
|
||||||
|
import { TankUpgradePricePresetComponent } from "@protos/game/proto/legacy/blitz_static_tank_upgrade_price_preset_component";
|
||||||
import { AbstractAPI, Cache } from "./abstract";
|
import { AbstractAPI, Cache } from "./abstract";
|
||||||
|
|
||||||
const rejected = Promise.reject("Not implemented on client");
|
const rejected = Promise.reject("Not implemented on client");
|
||||||
|
|
||||||
export class ClientAPI extends AbstractAPI {
|
export class ClientAPI extends AbstractAPI {
|
||||||
|
get metadata(): never {
|
||||||
|
throw new Error("MetadataAccessor is inaccessible on the client");
|
||||||
|
}
|
||||||
|
|
||||||
@Cache()
|
@Cache()
|
||||||
tankList() {
|
tankList() {
|
||||||
return fetchPB("/api/tanks/list.pb", TankList);
|
return fetchPB("/api/tanks/list.pb", TankList);
|
||||||
@@ -31,6 +36,14 @@ export class ClientAPI extends AbstractAPI {
|
|||||||
return fetchPB("/api/tanks/popular.pb", PopularTanks);
|
return fetchPB("/api/tanks/popular.pb", PopularTanks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Cache()
|
||||||
|
tankUpgradePreset(name: string) {
|
||||||
|
return fetchPB(
|
||||||
|
`/api/tanks/presets/upgrade/${name}.pb`,
|
||||||
|
TankUpgradePricePresetComponent,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Cache()
|
@Cache()
|
||||||
tiers() {
|
tiers() {
|
||||||
return fetchPB("/api/tiers.pb", Tiers);
|
return fetchPB("/api/tiers.pb", Tiers);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ interface LocalizationConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ServerAPI extends AbstractAPI {
|
export class ServerAPI extends AbstractAPI {
|
||||||
constructor(private metadata: MetadataAccessor) {
|
constructor(public metadata: MetadataAccessor) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +174,12 @@ export class ServerAPI extends AbstractAPI {
|
|||||||
return JSON.parse(data) as PopularTanks;
|
return JSON.parse(data) as PopularTanks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Cache()
|
||||||
|
async tankUpgradePreset(id: string) {
|
||||||
|
const item = this.metadata.item(`TankUpgradePricePresetEntity.${id}`);
|
||||||
|
return item.TankUpgradePricePreset();
|
||||||
|
}
|
||||||
|
|
||||||
@Cache()
|
@Cache()
|
||||||
async tiers() {
|
async tiers() {
|
||||||
const group = this.metadata.group("TankTierEntity");
|
const group = this.metadata.group("TankTierEntity");
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { TankCatalogComponent } from "@blitzkit/closed/protos/game/proto/legacy/blitz_static_tank_component";
|
|
||||||
import { StandardSinglePrice } from "@protos/game/proto/legacy/blitz_static_standard_single_price";
|
import { StandardSinglePrice } from "@protos/game/proto/legacy/blitz_static_standard_single_price";
|
||||||
|
import type { TankCatalogComponent } from "@protos/game/proto/legacy/blitz_static_tank_component";
|
||||||
import { PenetrationGroup } from "@protos/game/proto/legacy/blitz_static_tank_penetration_group";
|
import { PenetrationGroup } from "@protos/game/proto/legacy/blitz_static_tank_penetration_group";
|
||||||
import {
|
import {
|
||||||
ModuleUpgrade,
|
ModuleUpgrade,
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { api } from "../core/api/dynamic";
|
||||||
|
import { Tankopedia } from "../stores/tankopedia";
|
||||||
|
import { useAwait } from "./useAwait";
|
||||||
|
|
||||||
|
export function useProtagonist() {
|
||||||
|
const id = Tankopedia.use((state) => state.protagonist.id);
|
||||||
|
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
||||||
|
|
||||||
|
return tank;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { api } from "../core/api/dynamic";
|
||||||
|
import { useAwait } from "./useAwait";
|
||||||
|
|
||||||
|
export function useUpgradePreset(name: string) {
|
||||||
|
const [, discriminator] = name.split(".");
|
||||||
|
const preset = useAwait(
|
||||||
|
() => api.tankUpgradePreset(discriminator),
|
||||||
|
`tank-upgrade-preset-${discriminator}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return preset;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { TankUpgradePricePresetComponent } from "@protos/game/proto/legacy/blitz_static_tank_upgrade_price_preset_component";
|
||||||
|
import type { APIContext, GetStaticPaths } from "astro";
|
||||||
|
import { api } from "../../../../../core/api/dynamic";
|
||||||
|
|
||||||
|
export const getStaticPaths = (async () => {
|
||||||
|
return api.metadata
|
||||||
|
.group("TankUpgradePricePresetEntity")
|
||||||
|
.map(({ name }) => ({ params: { id: name } }));
|
||||||
|
}) satisfies GetStaticPaths;
|
||||||
|
|
||||||
|
export async function GET({ params }: APIContext<never, { id: string }>) {
|
||||||
|
const preset = await api.tankUpgradePreset(params.id);
|
||||||
|
return new Response(TankUpgradePricePresetComponent.encode(preset).finish());
|
||||||
|
}
|
||||||
Reference in new issue
Block a user