import { html, LitElement, nothing, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators.js"; import { Flag, Pack, Pattern, Skin, Subscription, } from "../../core/CosmeticSchemas"; import { PlayerPattern } from "../../core/Schemas"; import { PaymentMethod, ResolvedCosmetic, translateCosmetic, } from "../Cosmetics"; import { translateText } from "../Utils"; import "./CapIcon"; import "./CosmeticContainer"; import "./CosmeticInfo"; import { renderPatternPreview } from "./PatternPreview"; import "./PlutoniumIcon"; import { DEFAULT_DOLLAR_LABEL_KEY } from "./PurchaseButton"; @customElement("cosmetic-button") export class CosmeticButton extends LitElement { @property({ type: Object }) resolved!: ResolvedCosmetic; @property({ type: Boolean }) selected: boolean = false; @property({ type: Function }) onSelect?: (resolved: ResolvedCosmetic) => void; @property({ type: Function }) onPurchase?: (resolved: ResolvedCosmetic, method: PaymentMethod) => void; /** True if the user already has a subscription (any tier). */ @property({ type: Boolean }) userHasSubscription: boolean = false; createRenderRoot() { return this; } private handleClick() { this.onSelect?.(this.resolved); } private get displayName(): string { const c = this.resolved.cosmetic; if (c === null) { return translateText("territory_patterns.pattern.default"); } if (this.resolved.type === "pattern" || this.resolved.type === "skin") { return translateCosmetic("territory_patterns.pattern", c.name); } if (this.resolved.type === "pack") { return (c as Pack).displayName; } if (this.resolved.type === "subscription") { return translateCosmetic("subscriptions", c.name); } return translateCosmetic("flags", c.name); } private renderPreview(): TemplateResult { if (this.resolved.type === "pattern") { const c = this.resolved.cosmetic; const playerPattern: PlayerPattern | null = c === null ? null : { name: c.name, patternData: (c as Pattern).pattern, colorPalette: this.resolved.colorPalette ?? undefined, }; return renderPatternPreview(playerPattern, 150, 150); } if (this.resolved.type === "skin") { const c = this.resolved.cosmetic as Skin | null; if (c === null) { // "Default" tile — visually consistent with pattern's default tile. return html`
${translateText("territory_patterns.pattern.default")}
`; } return html`${c.name}`; } if (this.resolved.type === "pack") { const pack = this.resolved.cosmetic as Pack; const isHard = pack.currency === "hard"; const icon = isHard ? html`` : html``; const colorClass = isHard ? "text-green-400" : "text-amber-700"; const currencyKey = isHard ? "cosmetics.hard" : "cosmetics.soft"; return html`
${icon} ${pack.amount.toLocaleString()} ${translateText(currencyKey)} ${pack.bonusAmount > 0 ? html`
${translateText("cosmetics.free", { numFree: pack.bonusAmount.toLocaleString(), })}
` : nothing}
`; } if (this.resolved.type === "subscription") { const sub = this.resolved.cosmetic as Subscription; return html`
${sub.description}
${sub.dailyHardCurrency.toLocaleString()} ${translateText("cosmetics.per_day")}
${sub.dailySoftCurrency.toLocaleString()} ${translateText("cosmetics.per_day")}
`; } const c = this.resolved.cosmetic as Flag; return html`${c.name} { const img = e.currentTarget as HTMLImageElement; const fallback = "/flags/xx.svg"; if (img.src && !img.src.endsWith(fallback)) { img.src = fallback; } }} />`; } render() { const c = this.resolved.cosmetic; const priced = c as Pattern | Skin | Flag | Pack | null; const priceHard = priced?.priceHard; const priceSoft = priced?.priceSoft; const artist = priced?.artist; const isPurchasable = this.resolved.relationship === "purchasable"; const type = this.resolved.type; const isPattern = type === "pattern"; const isSkin = type === "skin"; const isOwnedSubscription = type === "subscription" && this.resolved.relationship === "owned"; const dollarLabelKey = type === "subscription" ? this.userHasSubscription ? "store.switch_button" : "store.subscribe_button" : DEFAULT_DOLLAR_LABEL_KEY; const priceSuffix = type === "subscription" ? translateText("store.price_per_month") : ""; const sizeClass = type === "flag" ? "gap-1 p-1.5 w-36" : "gap-2 p-3 w-48"; const crazygamesClass = isPattern || isSkin ? "no-crazygames " : ""; return html` this.onPurchase?.(this.resolved, "dollar") : undefined} .onPurchaseHard=${isPurchasable && priceHard !== undefined ? () => this.onPurchase?.(this.resolved, "hard") : undefined} .onPurchaseSoft=${isPurchasable && priceSoft !== undefined ? () => this.onPurchase?.(this.resolved, "soft") : undefined} .name=${this.displayName} > ${isOwnedSubscription ? html`
${translateText("store.current_plan")}
` : nothing}
`; } }