diff --git a/frontend/src/api.ts b/frontend/src/api.ts index 6e465a4..219aaa6 100644 --- a/frontend/src/api.ts +++ b/frontend/src/api.ts @@ -73,11 +73,14 @@ export async function addItemTag(itemId: string, tagId: string): Promise { return res.json(); } -export async function createItem(name: string, tags: string[]): Promise { +export async function createItem(name: string, tagIds: string[]): Promise { const res = await fetch(`${API_BASE}/items/`, { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ name, tags }), + body: JSON.stringify({ + name, + tag_ids: tagIds, + }), }); if (!res.ok) throw new Error("Failed to create item"); return res.json(); diff --git a/frontend/src/components/ItemList.tsx b/frontend/src/components/ItemList.tsx index acc2f27..22511f2 100644 --- a/frontend/src/components/ItemList.tsx +++ b/frontend/src/components/ItemList.tsx @@ -8,6 +8,7 @@ interface ItemListProps { onUpdateName: (id: string, name: string) => void; onDeleteTag: (itemId: string, tagId: string) => void; onAddTag: (itemId: string, tagId: string) => void; + onDeleteItem: (itemId: string) => void; } export default function ItemList({ @@ -16,6 +17,7 @@ export default function ItemList({ onUpdateName, onDeleteTag, onAddTag, + onDeleteItem, }: ItemListProps) { if (items.length === 0) { return

Keine Items gefunden.

; @@ -31,6 +33,7 @@ export default function ItemList({ onUpdateName={onUpdateName} onDeleteTag={onDeleteTag} onAddTag={onAddTag} + onDeleteItem={onDeleteItem} /> ))} diff --git a/frontend/src/components/ItemRow.tsx b/frontend/src/components/ItemRow.tsx index 6fce0dd..7e741be 100644 --- a/frontend/src/components/ItemRow.tsx +++ b/frontend/src/components/ItemRow.tsx @@ -7,6 +7,7 @@ interface ItemRowProps { onUpdateName: (id: string, name: string) => void; onDeleteTag: (itemId: string, tagId: string) => void; onAddTag: (itemId: string, tagId: string) => void; + onDeleteItem: (itemId: string) => void; // <--- NEU } export default function ItemRow({ @@ -15,6 +16,7 @@ export default function ItemRow({ onUpdateName, onDeleteTag, onAddTag, + onDeleteItem, // <--- NEU }: ItemRowProps) { const [isEditing, setIsEditing] = useState(false); const [editName, setEditName] = useState(item.name); @@ -37,7 +39,7 @@ export default function ItemRow({ return (
  • setHover(true)} onMouseLeave={() => { setHover(false); @@ -129,6 +131,19 @@ export default function ItemRow({ )} )} + + {/* Löschen-Button am Ende der Zeile */} + + {hover && ( + + )} +
  • ); } diff --git a/frontend/src/pages/ItemsPage.tsx b/frontend/src/pages/ItemsPage.tsx index eaacb9c..994509b 100644 --- a/frontend/src/pages/ItemsPage.tsx +++ b/frontend/src/pages/ItemsPage.tsx @@ -6,6 +6,7 @@ import { updateItemName, deleteItemTag, addItemTag, + deleteItem, Item, Tag, } from "../api"; @@ -26,6 +27,11 @@ export default function ItemsPage() { const [selectedTags, setSelectedTags] = useState([]); const [loading, setLoading] = useState(false); + // State für neue ItemRow + const [newItemName, setNewItemName] = useState(""); + const [newItemTags, setNewItemTags] = useState([]); + const [adding, setAdding] = useState(false); + async function loadData() { setLoading(true); try { @@ -47,9 +53,17 @@ export default function ItemsPage() { ); } - async function handleAddItem(name: string, tagNames: string[]) { - const newItem = await createItem(name, tagNames); - setItems((prev) => [...prev, newItem]); + async function handleAddItem() { + if (!newItemName.trim()) return; + setAdding(true); + try { + const newItem = await createItem(newItemName.trim(), newItemTags); + setItems((prev) => [...prev, newItem]); + setNewItemName(""); + setNewItemTags([]); + } finally { + setAdding(false); + } } async function handleRenameItem(itemId: string, name: string) { @@ -67,6 +81,11 @@ export default function ItemsPage() { setItems((prev) => prev.map((it) => (it.id === itemId ? updated : it))); } + async function handleDeleteItem(itemId: string) { + await deleteItem(itemId); + setItems((prev) => prev.filter((it) => it.id !== itemId)); + } + // Filtern const filteredItems = items.filter((item) => { const matchesText = @@ -85,7 +104,14 @@ export default function ItemsPage() { normalizeName(a.name).localeCompare(normalizeName(b.name)) ); - return ( + // Hilfsfunktion für Tag-Auswahl im Add-Row + function toggleNewItemTag(tagId: string) { + setNewItemTags((prev) => + prev.includes(tagId) ? prev.filter((id) => id !== tagId) : [...prev, tagId] + ); + } + + return (

    Items

    @@ -105,17 +131,52 @@ export default function ItemsPage() { onToggle={handleTagToggle} /> - {loading ? ( -

    Lade...

    - ) : ( + {/* Neue ItemRow als erste Zeile */} +
      +
    • + setNewItemName(e.target.value)} + placeholder="Neues Item..." + onKeyDown={e => { + if (e.key === "Enter") handleAddItem(); + }} + disabled={adding} + /> + {tags.map((tag) => ( + toggleNewItemTag(tag.id)} + > + #{tag.name} + + ))} + +
    • - )} +
    + {loading &&

    Lade...

    }
    ); }