From d2b4cc3e7d71bc7dd8de98121578589e6b4669c8 Mon Sep 17 00:00:00 2001
From: tresabhi <43380238+tresabhi@users.noreply.github.com>
Date: Thu, 28 May 2026 13:14:38 -0500
Subject: [PATCH] consumable prices
---
packages/i18n/strings/en.json | 4 +
.../website-ue/src/components/Price/index.tsx | 26 +++--
.../TankopediaLoadout/index.module.css | 35 +++---
.../components/TankopediaLoadout/index.tsx | 110 +++++++++++-------
4 files changed, 113 insertions(+), 62 deletions(-)
diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json
index efc5aae71..3aa611c5d 100644
--- a/packages/i18n/strings/en.json
+++ b/packages/i18n/strings/en.json
@@ -1,4 +1,8 @@
{
+ "price": {
+ "free": "Free"
+ },
+
"nations": {
"0": "Unspecified",
"1": "USSR",
diff --git a/packages/website-ue/src/components/Price/index.tsx b/packages/website-ue/src/components/Price/index.tsx
index b7f6a86e9..0bc72ccda 100644
--- a/packages/website-ue/src/components/Price/index.tsx
+++ b/packages/website-ue/src/components/Price/index.tsx
@@ -6,23 +6,35 @@ import { useLocale } from "../../hooks/useLocale";
import { classNames } from "../../ui/classNames";
import { Text } from "../Text";
import styles from "./index.module.css";
+import { useStrings } from "../../hooks/useStrings";
interface PriceProps extends ComponentProps<"div"> {
- price: StandardPrice;
+ price?: StandardPrice;
}
export function Price({ price, className, ...props }: PriceProps) {
+ const strings = useStrings();
+ const normalized =
+ price === undefined
+ ? []
+ : price.price_list.filter(
+ (entry) =>
+ entry.currency_price === undefined ||
+ entry.currency_price.amount !== 0,
+ );
+
return (
- {price.price_list.map((entry, index) => (
+ {normalized.map((entry, index) => (
))}
- {price.price_list.length === 0 && (
-
- Free
-
- )}
+ {price === undefined ||
+ (normalized.length === 0 && (
+
+ {strings.price.free}
+
+ ))}
);
}
diff --git a/packages/website-ue/src/components/TankopediaLoadout/index.module.css b/packages/website-ue/src/components/TankopediaLoadout/index.module.css
index 336a2e674..1ca654c48 100644
--- a/packages/website-ue/src/components/TankopediaLoadout/index.module.css
+++ b/packages/website-ue/src/components/TankopediaLoadout/index.module.css
@@ -18,25 +18,32 @@
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: var(--space-3);
- .consumable {
- font-size: var(--space-5);
+ .consumable-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--space-2);
- img {
- width: 1em;
- height: 1em;
- }
+ .consumable {
+ font-size: var(--space-5);
- .info {
- display: flex;
- flex-direction: column;
+ img {
+ width: 1em;
+ height: 1em;
+ }
- .entry {
+ .info {
display: flex;
- gap: var(--space-2);
+ flex-direction: column;
- svg {
- width: 1em;
- height: 1em;
+ .entry {
+ display: flex;
+ gap: var(--space-2);
+
+ svg {
+ width: 1em;
+ height: 1em;
+ }
}
}
}
diff --git a/packages/website-ue/src/components/TankopediaLoadout/index.tsx b/packages/website-ue/src/components/TankopediaLoadout/index.tsx
index cc316fa9c..34f7ec1a0 100644
--- a/packages/website-ue/src/components/TankopediaLoadout/index.tsx
+++ b/packages/website-ue/src/components/TankopediaLoadout/index.tsx
@@ -43,6 +43,7 @@ import { TankopediaCollapsible } from "../TankopediaCollapsible";
import type { ConsumableComponent } from "@protos/blitz_static_consumable_component";
import { Tank } from "@protos/tank";
import { select } from "three/src/nodes/math/ConditionalNode.js";
+import type { BlitzStaticPurchaseComponent } from "@protos/blitz_static_purchase_component";
interface TankopediaLoadoutProps {
characteristics: ComputedCharacteristics;
@@ -95,7 +96,13 @@ function Consumables({ characteristics }: ConsumablesProps) {
{Object.entries(consumables.consumables).map(
([id, { compatibility, consumable, purchase }]) => {
if (!isCompatible(compatibility!)) return null;
- return ;
+ return (
+
+ );
},
)}
@@ -106,51 +113,72 @@ function Consumables({ characteristics }: ConsumablesProps) {
interface ConsumableProps {
id: string;
consumable: ConsumableComponent;
+ purchase: BlitzStaticPurchaseComponent;
}
-function Consumable({ id, consumable }: ConsumableProps) {
+function Consumable({ id, consumable, purchase }: ConsumableProps) {
const gameStrings = useGameStrings("ConsumableEntity");
const isSelected = Tankopedia.use((state) =>
state.protagonist.consumables.includes(id),
);
+ const tank = useProtagonist();
+ const tierPrices = useTierPrices();
+
+ const price = useMemo(() => {
+ const { prices } = tierPrices.prices[purchase.price_per_tier_catalog_id];
+
+ for (const { tier_catalog_id, unlock_price } of prices) {
+ if (tier_catalog_id === tank.tank!.tier_catalog_id) {
+ return unlock_price;
+ }
+ }
+
+ throw new Error(
+ `No price found for tier catalog id ${tank.tank!.tier_catalog_id}`,
+ );
+ }, [tank.id, purchase.price_per_tier_catalog_id]);
return (
-
-