import type { Plan, PlanLimits } from "@/types" export const PLAN_LIMITS: Record = { starter: { maxProperties: 1, maxTenants: 3, maxAiCalls: 0, maxStorageMB: 100, hasTeamAccess: false, hasWhiteLabel: false, }, pro: { maxProperties: 10, maxTenants: Infinity, maxAiCalls: 50, maxStorageMB: 5120, hasTeamAccess: false, hasWhiteLabel: false, }, landlord: { maxProperties: Infinity, maxTenants: Infinity, maxAiCalls: 200, maxStorageMB: 25600, hasTeamAccess: true, hasWhiteLabel: true, }, lifetime: { maxProperties: Infinity, maxTenants: Infinity, maxAiCalls: 200, maxStorageMB: 25600, hasTeamAccess: true, hasWhiteLabel: true, }, } // Single source of truth for DISPLAYED prices (USD). Client-safe (plain numbers, // no env). Billing always charges the Stripe Price ID, so a mismatch here only // affects what the marketing/billing UI shows — keep these in sync with the // amounts configured on the Stripe Prices referenced below. export const PLAN_AMOUNTS = { starter: 0, pro: 29, landlord: 59, lifetime: 199 } as const // Plan metadata (client-safe — no env, no price IDs). The actual Stripe price // is resolved at runtime by lib/stripe/prices.ts using stable lookup keys, so // the same code works in test and live with ONLY an API-key swap. export const PLAN_PRICES: Record = { pro: { plan: "pro", amount: PLAN_AMOUNTS.pro, interval: "month" }, landlord: { plan: "landlord", amount: PLAN_AMOUNTS.landlord, interval: "month" }, lifetime: { plan: "lifetime", amount: PLAN_AMOUNTS.lifetime, interval: "one_time" }, } // Annual billing is always offered; the yearly price is resolved (and // auto-provisioned if missing) at checkout time by lib/stripe/prices.ts. export function annualEnabled(): boolean { return true } export function checkLimit( plan: Plan, resource: keyof PlanLimits, currentCount: number ): boolean { const limit = PLAN_LIMITS[plan][resource] if (typeof limit === "boolean") return limit return currentCount < (limit as number) } export function getPlanLabel(plan: Plan): string { const labels: Record = { starter: "Starter", pro: "Pro", landlord: "Landlord", lifetime: "Lifetime", } return labels[plan] }