From 3ea54d5a210093ba64c6c1b0f7282084e3387e61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dorien=20Gr=C3=B6nwald?=
 <dorien.groenwald@visuellverstehen.de>
Date: Wed, 20 Dec 2023 11:24:40 +0100
Subject: [PATCH] fix(web-service): add functionality for deleting entries

---
 .../frontend/src/lib/forms/Checkbox.svelte    | 10 +++--
 .../shopping-list/ShoppingListEntry.svelte    | 42 ++++++++++++++-----
 .../routes/shopping-lists/[id]/+page.svelte   | 17 +++++---
 3 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/src/web-service/frontend/src/lib/forms/Checkbox.svelte b/src/web-service/frontend/src/lib/forms/Checkbox.svelte
index 3849455a..1ebbe3fb 100644
--- a/src/web-service/frontend/src/lib/forms/Checkbox.svelte
+++ b/src/web-service/frontend/src/lib/forms/Checkbox.svelte
@@ -2,14 +2,15 @@
     import Checkmark from "../../assets/svg/Checkmark.svelte";
     import {createEventDispatcher} from "svelte";
 
-    export let label: string;
     export let id: number;
+    export let label: string;
+    export let count: number;
     export let checked: boolean | undefined;
 
     const dispatch = createEventDispatcher();
 </script>
 
-<div class="flex items-center mr-4 relative">
+<div class="flex items-center relative">
     <input
         on:click={() => { checked = ! checked; dispatch('updateShoppingListEntry') } }
         type="checkbox"
@@ -23,7 +24,10 @@
 
     <label
         for="input-{id}"
-        class="text-sm font-medium cursor-pointer lg:text-base { checked ? 'line-through opacity-50' : '' }">
+        class="text-sm font-medium cursor-pointer flex justify-center items-center gap-x-2 lg:text-base { checked ? 'line-through opacity-50' : '' }">
         {label}
+        <span class="border-l-[1.5px] font-normal border-l-gray-dark/50 pl-2 leading-none text-gray-dark text-sm whitespace-nowrap lg:text-base { checked ? 'hidden' : '' }">
+            {count} Stk.
+        </span>
     </label>
 </div>
\ No newline at end of file
diff --git a/src/web-service/frontend/src/lib/shopping-list/ShoppingListEntry.svelte b/src/web-service/frontend/src/lib/shopping-list/ShoppingListEntry.svelte
index 75a4e464..22e9594d 100644
--- a/src/web-service/frontend/src/lib/shopping-list/ShoppingListEntry.svelte
+++ b/src/web-service/frontend/src/lib/shopping-list/ShoppingListEntry.svelte
@@ -2,6 +2,7 @@
     import {createEventDispatcher, onMount} from 'svelte';
     import Checkbox from "$lib/forms/Checkbox.svelte";
     import {handleErrors} from "../../assets/helper/handleErrors";
+    import Trash from "../../assets/svg/Trash.svelte";
 
     type ViewState = "detailed" | "compressed";
 
@@ -47,7 +48,7 @@
     });
 
     function updateShoppingListEntry(): void {
-        if (! listId || !productData.id) return;
+        if (! listId || ! productData.id ) return;
 
         const apiUrl: string = `/api/v1/shoppinglistentries/${listId}/${productData.id}`;
         const requestOptions = {
@@ -61,18 +62,39 @@
             .then(()=> dispatch('updateCheckedEntriesCount', { state: entry.checked }))
             .catch(error => console.error("Failed to fetch data:", error.message));
     }
+
+    function deleteShoppingListEntry(): void {
+        if (! listId || ! productData.id) return;
+
+        const apiUrl: string = `/api/v1/shoppinglistentries/${listId}/${productData.id}`;
+        const requestOptions = {
+            method: "DELETE",
+            headers: { 'Content-Type': 'application/json' },
+        };
+
+        fetch(apiUrl, requestOptions)
+            .then(handleErrors)
+            .then(()=> { location.reload(); dispatch('updateCheckedEntriesCount', { state: true }) })
+            .catch(error => console.error("Failed to fetch data:", error.message));
+    }
 </script>
 
 <li class="border-t-2 border-t-gray-light py-3 lg:py-6">
-    <div class="flex gap-x-4 items-start justify-between">
-        <Checkbox
-            label="{productData.description}"
-            id="{productData.id}"
-            bind:checked={entry.checked}
-            on:updateShoppingListEntry={updateShoppingListEntry} />
-        <span class="mt-0.5 block text-gray-dark text-sm whitespace-nowrap lg:text-base { entry.checked ? 'opacity-50' : '' }">
-            {entry.count} Stk.
-        </span>
+    <div class="flex gap-x-2 items-center justify-between">
+        <div class="flex gap-x-2 items-center">
+            <Checkbox
+                label={productData.description}
+                id={productData.id}
+                count={entry.count}
+                bind:checked={entry.checked}
+                on:updateShoppingListEntry={updateShoppingListEntry} />
+        </div>
+        <button
+            aria-label="Eintrag löschen"
+            on:click={deleteShoppingListEntry}
+            class="bg-gray-light rounded-full p-2 text-gray-dark transition-all ease-in-out duration-300 hover:bg-gray-dark/25">
+            <Trash classes="w-4 h-4 md:w-5 md:h-5" />
+        </button>
     </div>
     {#if view === 'detailed' && priceData}
         <p class="text-gray-dark mt-1 ml-[2.1rem] text-sm flex flex-wrap items-center gap-2 lg:text-sm { entry.checked ? 'opacity-50' : '' }">
diff --git a/src/web-service/frontend/src/routes/shopping-lists/[id]/+page.svelte b/src/web-service/frontend/src/routes/shopping-lists/[id]/+page.svelte
index b6981892..4780c357 100644
--- a/src/web-service/frontend/src/routes/shopping-lists/[id]/+page.svelte
+++ b/src/web-service/frontend/src/routes/shopping-lists/[id]/+page.svelte
@@ -23,6 +23,11 @@
                 checkedEntriesCount++;
             }
         })
+
+        if (data.entries.length > 0 && data.list.completed && checkedEntriesCount != data.entries.length) {
+            data.list.completed = false;
+            updateShoppingList();
+        }
     });
 
     function updateCheckedEntriesCount(event: any): void {
@@ -83,6 +88,10 @@
 
         <p class="text-gray-dark text-sm">Deine Einkaufsliste</p>
         <ul class="mt-4">
+            {#if data.entries.length === 0}
+                <p>Keine Einträge vorhanden.</p>
+            {/if}
+
             {#each data.entries as entry}
                 <ShoppingListEntry
                     listId={data.list.id}
@@ -92,10 +101,8 @@
             {/each}
         </ul>
 
-        {#if ! data.list.completed}
-            <AddEntryModal
-                listId="{data.list.id}"
-                currentEntries="{data.entries}"/>
-        {/if}
+        <AddEntryModal
+            listId="{data.list.id}"
+            currentEntries="{data.entries}"/>
     </div>
 </main>