Show bonus amount on currency packs (#3907)

Show bonus amount on currency packs

- Add `bonusAmount` field to `PackSchema` (non-negative int)
- Render a rotated green corner ribbon (`+X FREE!`) on pack tiles when
`bonusAmount > 0`
- Add `cosmetics.free` translation key with `numFree` param

<img width="720" height="359" alt="Screenshot 2026-05-12 at 7 40 12 AM"
src="https://github.com/user-attachments/assets/3dd70fc4-c922-47f4-aee6-055047b58563"
/>

Describe the PR.

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

regression is found:

evan
This commit is contained in:
Evan
2026-05-12 07:44:44 -07:00
committed by Josh Harris
parent 450f2944c9
commit 712b2bc473
3 changed files with 13 additions and 2 deletions
+2 -1
View File
@@ -1271,7 +1271,8 @@
"adfree": "ad-free for life!",
"hard": "Plutonium",
"soft": "Caps",
"per_day": "/day"
"per_day": "/day",
"free": "+{numFree} BONUS!"
},
"flag_input": {
"title": "Select Flag",
+10 -1
View File
@@ -112,7 +112,7 @@ export class CosmeticButton extends LitElement {
const colorClass = isHard ? "text-green-400" : "text-amber-700";
const currencyKey = isHard ? "cosmetics.hard" : "cosmetics.soft";
return html`<div
class="flex flex-col items-center justify-end h-full w-full text-center gap-1 pb-1"
class="relative flex flex-col items-center justify-end h-full w-full text-center gap-1 pb-1"
>
${icon}
<span class="text-lg font-black ${colorClass}"
@@ -121,6 +121,15 @@ export class CosmeticButton extends LitElement {
<span class="text-[10px] font-bold text-white/50 uppercase"
>${translateText(currencyKey)}</span
>
${pack.bonusAmount > 0
? html`<div
class="absolute top-3 -right-8 bg-green-500 text-white text-[10px] font-black px-8 py-0.5 rotate-45 shadow-md uppercase tracking-wide pointer-events-none"
>
${translateText("cosmetics.free", {
numFree: pack.bonusAmount.toLocaleString(),
})}
</div>`
: nothing}
</div>`;
}
+1
View File
@@ -89,6 +89,7 @@ export const PackSchema = CosmeticSchema.extend({
displayName: z.string(),
currency: z.enum(["hard", "soft"]),
amount: z.number().int().positive(),
bonusAmount: z.number().int().nonnegative(),
});
export const SubscriptionSchema = CosmeticSchema.extend({