Files
Arnaud f6975e98a9 fix: recipe/storage tier limits are lifetime totals, not monthly (v0.58.0)
Recipe count and storage usage shared the monthly user_usage bucket with
AI calls, so both incorrectly reset every month even though nothing was
deleted. Only AI calls should be monthly.

Recipe count and storage are now derived live from real data (recipes,
recipe/review photos, avatar) instead of a counter — deleting a photo or
recipe is itself the "decrement", no extra wiring needed. Storage size is
tracked per-row (recipePhotos.sizeMb, ratings.photoSizeMb, users.avatarSizeMb)
and threaded through presign -> upload -> save.

Also fixes avatar removal silently no-oping (client sent a field the PATCH
schema didn't recognize).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 20:32:31 +02:00

39 lines
1.1 KiB
TypeScript

"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export function ResetUsageButton({ userId }: { userId: string }) {
const router = useRouter();
const [resetting, setResetting] = useState(false);
async function handleReset() {
if (!confirm("Reset this user's AI call count for the current month?")) return;
setResetting(true);
try {
const res = await fetch(`/api/v1/admin/users/${userId}/usage`, { method: "PATCH" });
if (!res.ok) throw new Error("Reset failed");
toast.success("AI call count reset");
router.refresh();
} catch {
toast.error("Failed to reset usage");
} finally {
setResetting(false);
}
}
return (
<Button
variant="outline"
size="sm"
onClick={() => { void handleReset(); }}
disabled={resetting}
className="text-destructive hover:text-destructive"
>
{resetting ? "Resetting…" : "Reset AI Calls"}
</Button>
);
}