From 4033e8618fa2978a009b2066302f5d74a2575062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sun, 30 Nov 2025 22:12:46 -0600 Subject: [PATCH] feat: useAwait --- .../src/constants/characteristicsOrder.ts | 2 +- packages/website-ue/src/core/api/client.ts | 11 ++- packages/website-ue/src/hooks/useAwait.ts | 19 +++++ .../website-ue/src/pages/api/tanks/[id].pb.ts | 14 ++++ .../src/pages/tanks/[slug]/_index.tsx | 69 ++++++++++++------- .../src/pages/tanks/[slug]/index.astro | 2 +- 6 files changed, 90 insertions(+), 27 deletions(-) create mode 100644 packages/website-ue/src/hooks/useAwait.ts create mode 100644 packages/website-ue/src/pages/api/tanks/[id].pb.ts diff --git a/packages/website-ue/src/constants/characteristicsOrder.ts b/packages/website-ue/src/constants/characteristicsOrder.ts index 30804993a..6a347bd0b 100644 --- a/packages/website-ue/src/constants/characteristicsOrder.ts +++ b/packages/website-ue/src/constants/characteristicsOrder.ts @@ -1,6 +1,6 @@ import { TankAttributeChange_AttributeName } from "@protos/blitz_static_tank_upgrade_single_stage"; -enum CharacteristicsGroup { +export enum CharacteristicsGroup { Firepower, Maneuverability, Survivability, diff --git a/packages/website-ue/src/core/api/client.ts b/packages/website-ue/src/core/api/client.ts index 0c86e6eb6..7d04d4714 100644 --- a/packages/website-ue/src/core/api/client.ts +++ b/packages/website-ue/src/core/api/client.ts @@ -1,3 +1,12 @@ +import { TankCatalogComponent } from "@protos/blitz_static_tank_component"; import { AbstractAPI } from "./abstract"; -export class ClientAPI extends AbstractAPI {} +export class ClientAPI extends AbstractAPI { + async tank(id: string) { + const response = await fetch(`/api/tanks/${id}.pb`); + const buffer = await response.arrayBuffer(); + const array = new Uint8Array(buffer); + + return TankCatalogComponent.decode(array); + } +} diff --git a/packages/website-ue/src/hooks/useAwait.ts b/packages/website-ue/src/hooks/useAwait.ts new file mode 100644 index 000000000..5783447a2 --- /dev/null +++ b/packages/website-ue/src/hooks/useAwait.ts @@ -0,0 +1,19 @@ +import { use } from "react"; + +const cache = new Map>(); + +export function useAwait( + creator: () => Promise, + discriminator: string +) { + let promise; + + if (cache.has(discriminator)) { + promise = cache.get(discriminator) as Promise; + } else { + promise = creator(); + cache.set(discriminator, promise); + } + + return use(promise); +} diff --git a/packages/website-ue/src/pages/api/tanks/[id].pb.ts b/packages/website-ue/src/pages/api/tanks/[id].pb.ts new file mode 100644 index 000000000..1cc6ce655 --- /dev/null +++ b/packages/website-ue/src/pages/api/tanks/[id].pb.ts @@ -0,0 +1,14 @@ +import { TankCatalogComponent } from "@protos/blitz_static_tank_component"; +import type { APIContext, GetStaticPaths } from "astro"; +import { api } from "../../../core/api/dynamic"; + +export const getStaticPaths = (async () => { + const { tanks } = await api.tanks(); + + return tanks.map(({ id }) => ({ params: { id } })); +}) satisfies GetStaticPaths; + +export async function GET({ params }: APIContext) { + const tank = await api.tank(params.id); + return new Response(TankCatalogComponent.encode(tank).finish()); +} diff --git a/packages/website-ue/src/pages/tanks/[slug]/_index.tsx b/packages/website-ue/src/pages/tanks/[slug]/_index.tsx index 310eb7f1c..b2a232fab 100644 --- a/packages/website-ue/src/pages/tanks/[slug]/_index.tsx +++ b/packages/website-ue/src/pages/tanks/[slug]/_index.tsx @@ -2,45 +2,66 @@ import { TankAttributeChange_AttributeName, TankAttributeChange_Modifier, } from "@protos/blitz_static_tank_upgrade_single_stage"; -import { use } from "react"; +import { Suspense, useMemo } from "react"; +import { + CharacteristicsGroup, + characteristicsOrder, +} from "../../../constants/characteristicsOrder"; import { api } from "../../../core/api/dynamic"; +import { useAwait } from "../../../hooks/useAwait"; import { Tankopedia } from "../../../stores/tankopedia"; -interface Props { - id: string; +export function Page({ id }: { id: string }) { + return ( + + + + ); } -export function Page({ id }: Props) { - const tank = use(api.tank(id)); +function Content({ id }: { id: string }) { + const tank = useAwait(() => api.tank(id), `tank-${id}`); const stage = Tankopedia.use((state) => state.stage); + const attributes = useMemo(() => { + const attributes: Partial< + Record + > = {}; + + for (const { attribute_name, value, modifier } of tank.base_stats! + .attributes) { + if (modifier !== TankAttributeChange_Modifier.MODIFIER_OVERRIDE) { + throw new Error( + `Unexpected modifier ${TankAttributeChange_Modifier[modifier]}` + ); + } + + attributes[attribute_name] = value; + } + + return attributes; + }, [stage]); + return ( <>

{tank.name?.value}

-

Base stats

+

Characteristics

- {tank.base_stats!.attributes.map((attribute) => ( -

- {TankAttributeChange_AttributeName[attribute.attribute_name]}:{" "} - {attribute.value} ({TankAttributeChange_Modifier[attribute.modifier]}) -

- ))} - -

Upgrades

- - {tank.upgrade_stages.map((stage, index) => ( + {characteristicsOrder.map((group) => ( <> -

Stage {index}

+

{CharacteristicsGroup[group.group]}

- {stage.attributes.map((attribute) => ( -

- {TankAttributeChange_AttributeName[attribute.attribute_name]}:{" "} - {attribute.value} ( - {TankAttributeChange_Modifier[attribute.modifier]}) -

- ))} + {group.attributes.map( + (attribute) => + attribute.name in attributes && ( +

+ {TankAttributeChange_AttributeName[attribute.name]}:{" "} + {attributes[attribute.name]} +

+ ) + )} ))} diff --git a/packages/website-ue/src/pages/tanks/[slug]/index.astro b/packages/website-ue/src/pages/tanks/[slug]/index.astro index 59949adf5..9bf18209b 100644 --- a/packages/website-ue/src/pages/tanks/[slug]/index.astro +++ b/packages/website-ue/src/pages/tanks/[slug]/index.astro @@ -15,4 +15,4 @@ export const getStaticPaths = (async () => { const { id } = Astro.props; --- - +