Subscription upgrade/downgrade + tier management (#3927)

## Summary

- Tier upgrade/downgrade in the Store. The Subscriptions tab now shows
all tiers including the user's current one. Other tiers swap "Subscribe"
→ "Switch" when the user already has a sub, and clicking them calls the
new `POST /subscriptions/@me/change-tier` endpoint with a
direction-aware confirm (upgrade charges prorated diff now, downgrade
gives account credit).
- Owned-tier card renders a **Current Plan** badge in place of the
purchase button. Resolution logic in `resolveCosmetics` now reads
`userMeResponse.player.subscription.tier` (with flare fallback) and
marks that tier as `owned`.
- AccountModal's `<subscription-panel>` reworked into a proper
two-column layout:
- **Left**: tier name, `$X.XX/mo` price, description, daily Pu/Caps
amounts.
- **Right**: status badge (Active / Renews date / Cancels date),
`[Manage] [Change Tier]` button row, `[Cancel]` centered underneath.
When `cancelAtPeriodEnd === true`, the row collapses to a single
`[Reactivate]` button (opens the Stripe portal).
- New `<o-button size="xs">` variant (`py-2 px-3 text-xs`) for the
compact panel buttons.
- Store dollar-purchase price label now supports an optional suffix
(`/mo` for subs only) via a `priceSuffix` prop plumbed through
`CosmeticContainer` → `PurchaseButton`.
- `Api.ts` gains `changeSubscriptionTier(tierName)` with the same
401-handling pattern as the existing subscription helpers.


<img width="1114" height="728" alt="Screenshot 2026-05-14 at 7 09 20 PM"
src="https://github.com/user-attachments/assets/688f83d5-4010-4580-9214-6885af8ec98e"
/>

<img width="1038" height="276" alt="Screenshot 2026-05-14 at 7 09 33 PM"
src="https://github.com/user-attachments/assets/458197f5-a0d4-4c32-bc55-31e5679629b5"
/>

<img width="887" height="286" alt="Screenshot 2026-05-14 at 7 09 55 PM"
src="https://github.com/user-attachments/assets/8149ed82-89cc-4bbe-83de-3614f886b331"
/>

## Discord

evan
This commit is contained in:
Evan
2026-05-15 12:01:31 -07:00
committed by GitHub
parent 7dc5d472a7
commit ca565eaa1a
9 changed files with 228 additions and 53 deletions
+8 -1
View File
@@ -175,7 +175,9 @@ export class StoreModal extends BaseModal {
this.userMeResponse,
this.affiliateCode,
).filter(
(r) => r.type === "subscription" && r.relationship === "purchasable",
(r) =>
r.type === "subscription" &&
(r.relationship === "purchasable" || r.relationship === "owned"),
);
if (items.length === 0) {
@@ -186,6 +188,10 @@ export class StoreModal extends BaseModal {
</div>`;
}
const userHasSubscription =
this.userMeResponse !== false &&
this.userMeResponse.player.subscription !== null;
return html`
<div
class="flex flex-wrap gap-4 p-8 justify-center items-stretch content-start"
@@ -195,6 +201,7 @@ export class StoreModal extends BaseModal {
<cosmetic-button
.resolved=${r}
.onPurchase=${purchaseCosmetic}
.userHasSubscription=${userHasSubscription}
></cosmetic-button>
`,
)}