"use client"; import { useState } from "react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; const UNLIMITED = -1; const FIELDS = [ { key: "maxRecipes", label: "Max Recipes" }, { key: "aiCallsPerMonth", label: "AI Calls / Month" }, { key: "storageMb", label: "Storage (MB)" }, { key: "maxPublicRecipes", label: "Max Public Recipes" }, ] as const; type TierDefinition = { tier: string; maxRecipes: number; aiCallsPerMonth: number; storageMb: number; maxPublicRecipes: number; }; export function TierLimitsForm({ tierDefinition }: { tierDefinition: TierDefinition }) { const [values, setValues] = useState>({ maxRecipes: tierDefinition.maxRecipes, aiCallsPerMonth: tierDefinition.aiCallsPerMonth, storageMb: tierDefinition.storageMb, maxPublicRecipes: tierDefinition.maxPublicRecipes, }); // Remembers the last finite value per field so toggling "Unlimited" off restores it. const [lastFinite, setLastFinite] = useState>({ maxRecipes: tierDefinition.maxRecipes === UNLIMITED ? 0 : tierDefinition.maxRecipes, aiCallsPerMonth: tierDefinition.aiCallsPerMonth === UNLIMITED ? 0 : tierDefinition.aiCallsPerMonth, storageMb: tierDefinition.storageMb === UNLIMITED ? 0 : tierDefinition.storageMb, maxPublicRecipes: tierDefinition.maxPublicRecipes === UNLIMITED ? 0 : tierDefinition.maxPublicRecipes, }); const [saving, setSaving] = useState(false); async function handleSave() { setSaving(true); try { const res = await fetch(`/api/v1/admin/tiers/${tierDefinition.tier}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(values), }); if (!res.ok) { const data = await res.json().catch(() => ({})); throw new Error((data as { error?: string }).error ?? "Save failed"); } toast.success(`${tierDefinition.tier} tier limits saved`); } catch (err) { toast.error(err instanceof Error ? err.message : "Failed to save"); } finally { setSaving(false); } } return (

{tierDefinition.tier}

{FIELDS.map(({ key, label }) => { const isUnlimited = values[key] === UNLIMITED; return (
{ if (checked) { setLastFinite((prev) => ({ ...prev, [key]: values[key] ?? 0 })); setValues((prev) => ({ ...prev, [key]: UNLIMITED })); } else { setValues((prev) => ({ ...prev, [key]: lastFinite[key] ?? 0 })); } }} />
setValues((prev) => ({ ...prev, [key]: Number(e.target.value) })) } />
); })}
); }