"use client"; import { useState } from "react"; import { useTranslations } from "next-intl"; import { Plus, Trash2, AlertTriangle } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; type PantryItem = { id: string; rawName: string; quantity: string | null; unit: string | null; expiresAt: string | null; }; function daysUntilExpiry(dateStr: string): number { const diff = new Date(dateStr).getTime() - Date.now(); return Math.ceil(diff / (1000 * 60 * 60 * 24)); } export function PantryManager({ initialItems }: { initialItems: PantryItem[] }) { const t = useTranslations("pantry"); const [items, setItems] = useState(initialItems); const [name, setName] = useState(""); const [quantity, setQuantity] = useState(""); const [unit, setUnit] = useState(""); const [expiresAt, setExpiresAt] = useState(""); const [adding, setAdding] = useState(false); async function add() { if (!name.trim()) return; setAdding(true); try { const res = await fetch("/api/v1/pantry", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ rawName: name.trim(), quantity: quantity.trim() || undefined, unit: unit.trim() || undefined, expiresAt: expiresAt ? new Date(expiresAt).toISOString() : undefined, }), }); if (!res.ok) { toast.error(t("addFailed")); return; } const { id } = await res.json() as { id: string }; setItems((prev) => [...prev, { id, rawName: name.trim(), quantity: quantity || null, unit: unit || null, expiresAt: expiresAt ? new Date(expiresAt).toISOString() : null }]); setName(""); setQuantity(""); setUnit(""); setExpiresAt(""); } finally { setAdding(false); } } async function remove(id: string) { const res = await fetch(`/api/v1/pantry/${id}`, { method: "DELETE" }); if (res.ok) setItems((prev) => prev.filter((i) => i.id !== id)); else toast.error(t("removeFailed")); } const sorted = [...items].sort((a, b) => { if (a.expiresAt && b.expiresAt) return new Date(a.expiresAt).getTime() - new Date(b.expiresAt).getTime(); if (a.expiresAt) return -1; if (b.expiresAt) return 1; return a.rawName.localeCompare(b.rawName); }); return (
{/* Add form */}
setName(e.target.value)} placeholder={t("itemNamePlaceholder")} className="flex-1 min-w-[160px]" onKeyDown={(e) => e.key === "Enter" && add()} /> setQuantity(e.target.value)} placeholder={t("qtyPlaceholder")} className="w-20" /> setUnit(e.target.value)} placeholder={t("unitPlaceholder")} className="w-20" /> setExpiresAt(e.target.value)} className="w-36" />
{/* Item list */} {items.length === 0 ? (

{t("empty")}

) : (
{sorted.map((item) => { const days = item.expiresAt ? daysUntilExpiry(item.expiresAt) : null; const expiring = days !== null && days <= 3; const expired = days !== null && days < 0; return (
{item.rawName} {item.quantity && {item.quantity}{item.unit ? ` ${item.unit}` : ""}} {expired && {t("expired")}} {expiring && !expired && {t("expiresInDays", { days })}}
{item.expiresAt && !expired && !expiring && (

{t("expiresOn", { date: new Date(item.expiresAt).toLocaleDateString() })}

)}
); })}
)}
); }