import { useEffect, useRef, useState } from "react"; import { Link } from "react-router-dom"; import type { BillingCycle } from "../api/endpoints"; import type { Meter, PlanInfo } from "../api/types"; import { useUpgrade } from "../hooks/useUpgrade"; import { CheckIcon } from "./icons/Icons"; import { annualMonthly, annualTotal, money } from "./PricingTiers"; const ORDER = ["free", "writer", "studio"]; const LIMIT_TITLES: Record = { audio_minutes: "Out of audio fuel", video_minutes: "Out of render fuel", launch_kits: "Launch Kits used up", sources: "Your station is full", voice_cloning: "Voice cloning is locked", }; /** What the plan adds over the current one, as short boost chips ("20x audio minutes"). */ function boosts(plan: PlanInfo, current: PlanInfo): string[] { const out: string[] = []; const times = (a: number, b: number, label: string) => { if (a < 0 && b >= 0) out.push(`Unlimited ${label}`); else if (b > 0 && a > b) out.push(`${Math.round(a / b)}x ${label}`); }; if (plan.sources > current.sources) out.push(`${plan.sources} sources`); times(plan.audio_minutes, current.audio_minutes, "audio minutes"); times(plan.video_minutes, current.video_minutes, "video minutes"); times(plan.launch_kits, current.launch_kits, "Launch Kits"); if (plan.voice_cloning && !current.voice_cloning) out.push("Voice cloning"); if (plan.brand_kit && !current.brand_kit) out.push("Brand kit"); return out; } function resetDate(since: string | undefined): string { const d = since ? new Date(since) : new Date(); const next = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1)); return next.toLocaleDateString(undefined, { month: "long", day: "numeric" }); } function Scene({ mode }: { mode: "explore" | "limit" | "welcome" }) { return (