v0.21.1 — Pantry: delete items with inline confirm
Trash icon on each row; clicking shows "Delete? Yes / No" inline (no dialog needed). Soft-deletes via active=false. Removed the admin-only guard on DELETE /api/pantry/[id] since anyone logged in should be able to manage their own pantry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { ItemSource } from "@prisma/client";
|
||||
import { db } from "@/lib/db";
|
||||
import { requireAuth, isAdmin } from "@/lib/auth";
|
||||
import { requireAuth } from "@/lib/auth";
|
||||
|
||||
const PANTRY_SELECT = {
|
||||
id: true, name: true, description: true, quantity: true, unit: true,
|
||||
@@ -96,7 +96,6 @@ export async function PATCH(req: Request, { params }: { params: { id: string } }
|
||||
export async function DELETE(_req: Request, { params }: { params: { id: string } }) {
|
||||
try {
|
||||
const session = await requireAuth();
|
||||
if (!isAdmin(session.user.role)) return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
await db.item.update({ where: { id: params.id }, data: { active: false } });
|
||||
await db.auditEvent.create({
|
||||
data: { action: "pantry.delete", entityId: params.id, actorId: session.user.id },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { AlertTriangle, ChevronDown, ChevronRight, UtensilsCrossed } from "lucide-react";
|
||||
import { AlertTriangle, ChevronDown, ChevronRight, Trash2, UtensilsCrossed } from "lucide-react";
|
||||
import { PantryItemDialog } from "./pantry-item-dialog";
|
||||
import { PullDialog } from "./pull-dialog";
|
||||
import { UseItemDialog } from "./use-item-dialog";
|
||||
@@ -51,6 +51,20 @@ function ExpiryBadge({ date }: { date: Date }) {
|
||||
function ItemRow({ item, locations, plants, onRefresh }: {
|
||||
item: PantryItem; locations: LocationOption[]; plants: PlantOption[]; onRefresh: () => void;
|
||||
}) {
|
||||
const [confirming, setConfirming] = useState(false);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
|
||||
async function handleDelete() {
|
||||
setDeleting(true);
|
||||
try {
|
||||
const res = await fetch(`/api/pantry/${item.id}`, { method: "DELETE" });
|
||||
if (res.ok) onRefresh();
|
||||
} finally {
|
||||
setDeleting(false);
|
||||
setConfirming(false);
|
||||
}
|
||||
}
|
||||
|
||||
const priceStr = item.pricePaid != null
|
||||
? `$${item.pricePaid.toFixed(2)}${item.priceUnit && item.priceUnit !== "package" ? `/${item.priceUnit}` : ""}`
|
||||
: null;
|
||||
@@ -83,8 +97,37 @@ function ItemRow({ item, locations, plants, onRefresh }: {
|
||||
{item.notes && <p className="text-xs text-muted-foreground mt-0.5 italic">{item.notes}</p>}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 shrink-0">
|
||||
<UseItemDialog item={item} onSuccess={onRefresh} />
|
||||
<PantryItemDialog item={item} locations={locations} plants={plants} onSuccess={onRefresh} />
|
||||
{confirming ? (
|
||||
<>
|
||||
<span className="text-xs text-muted-foreground mr-1">Delete?</span>
|
||||
<button
|
||||
onClick={handleDelete}
|
||||
disabled={deleting}
|
||||
className="text-xs text-destructive font-medium hover:underline disabled:opacity-50"
|
||||
>
|
||||
{deleting ? "…" : "Yes"}
|
||||
</button>
|
||||
<span className="text-muted-foreground text-xs">/</span>
|
||||
<button
|
||||
onClick={() => setConfirming(false)}
|
||||
className="text-xs text-muted-foreground hover:underline"
|
||||
>
|
||||
No
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<UseItemDialog item={item} onSuccess={onRefresh} />
|
||||
<PantryItemDialog item={item} locations={locations} plants={plants} onSuccess={onRefresh} />
|
||||
<button
|
||||
onClick={() => setConfirming(true)}
|
||||
className="h-8 w-8 flex items-center justify-center rounded-md hover:bg-destructive/10 hover:text-destructive text-muted-foreground transition-colors"
|
||||
title="Delete"
|
||||
>
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,13 @@ export type ChangelogEntry = {
|
||||
};
|
||||
|
||||
export const CHANGELOG: ChangelogEntry[] = [
|
||||
{
|
||||
version: "0.21.1",
|
||||
date: "2026-06-29",
|
||||
changes: [
|
||||
"Pantry: trash icon on each item — click it, confirm with Yes/No. Removes the item from the inventory.",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "0.21.0",
|
||||
date: "2026-06-29",
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// Bump on every user-visible release. Changelog entries live in `src/lib/changelog.ts`.
|
||||
export const APP_VERSION = "0.21.0";
|
||||
export const APP_VERSION = "0.21.1";
|
||||
|
||||
Reference in New Issue
Block a user