Преглед на файлове

add confirmation before deleting stock from portfolio

Daniel Bohry преди 9 месеца
родител
ревизия
3d9966596f
променени са 1 файла, в които са добавени 108 реда и са изтрити 2 реда
  1. 108 2
      src/routes/portfolio/+page.svelte

+ 108 - 2
src/routes/portfolio/+page.svelte

@@ -1,6 +1,6 @@
 <script>
 	import { authentication } from '../store.js';
-	import { onMount } from 'svelte';
+	import { onDestroy, onMount } from 'svelte';
 	import { fade } from 'svelte/transition';
 	import AddStock from '../../components/AddStock.svelte';
 	import { getRequest } from '../../utils/api.js';
@@ -17,8 +17,22 @@
 	let orderBy = 'total';
 	let currency = 'USD';
 	let hasChanges = false;
+	let showDeleteConfirm = false;
+	let stockToDelete = null;
+
+	function handleKeyDown(event) {
+		if (event.key === 'Escape' && showDeleteConfirm) {
+			cancelDelete();
+		}
+
+		if (event.key === 'Escape' && showModal) {
+			closeModal();
+		}
+	}
 
 	onMount(() => {
+		window.addEventListener('keydown', handleKeyDown);
+
 		return authentication.subscribe(async (auth) => {
 			if (!auth || !auth.token) {
 				await goto('/login');
@@ -29,6 +43,10 @@
 		});
 	});
 
+	onDestroy(() => {
+		window.removeEventListener('keydown', handleKeyDown);
+	});
+
 	async function fetchPortfolio() {
 		try {
 			const response = await getRequest(`${import.meta.env.VITE_STOCKS_HOST}/api/portfolios?currency=${currency}`, {}, authToken);
@@ -214,6 +232,24 @@
 			: input;
 	}
 
+	function confirmDelete(code) {
+		stockToDelete = code;
+		showDeleteConfirm = true;
+	}
+
+	function cancelDelete() {
+		stockToDelete = null;
+		showDeleteConfirm = false;
+	}
+
+	function confirmDeleteAction() {
+		if (stockToDelete) {
+			remove(stockToDelete);
+			stockToDelete = null;
+		}
+		showDeleteConfirm = false;
+	}
+
 	function handleInputChange(event) {
 		const form = new FormData(event.target.closest('form'));
 		const code = form.get('code');
@@ -280,6 +316,15 @@
 		searchResults={searchStockResult}
 	/>
 
+	{#if showDeleteConfirm}
+		<div class="modal-confirm">
+			<div class="modal-actions">
+				<button class="btn btn-danger" on:click={confirmDeleteAction}>Confirm deletion</button>
+				<button class="btn btn-cancel" on:click={cancelDelete}>Cancel</button>
+			</div>
+		</div>
+	{/if}
+
 	<div in:fade class="table-container">
 		<table class="stock-table">
 			<thead>
@@ -333,7 +378,7 @@
 					<td class="total">{formatCurrency(stock.total)}</td>
 					<td class="percent">{calculatePercentage(stock.total, totalValue)}%</td>
 					<td>
-						<button class="remove-btn" aria-label="Delete" on:click={() => remove(stock.code)} title="remove">
+						<button class="remove-btn" aria-label="Delete" on:click={() => confirmDelete(stock.code)} title="remove">
 							<svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round"
 									 stroke-linejoin="round">
 								<polyline points="3 6 5 6 21 6"></polyline>
@@ -498,6 +543,67 @@
         box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.4);
     }
 
+    .btn-cancel {
+        background-color: #bdc3c7;
+        color: #2c3e50;
+        border: none;
+        border-radius: 8px;
+        padding: 0.6rem 1.2rem;
+        font-size: 1rem;
+        cursor: pointer;
+        transition: background-color 0.3s ease;
+    }
+
+    .btn-cancel:hover {
+        background-color: #aeb6bf;
+    }
+
+    .btn-cancel:focus {
+        outline: none;
+        box-shadow: 0 0 0 3px rgba(189, 195, 199, 0.5);
+    }
+
+    .modal-confirm {
+        position: fixed;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+        background: white;
+        padding: 2rem;
+        border-radius: 12px;
+        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
+        z-index: 1000;
+        text-align: center;
+        max-width: 90%;
+        width: 400px;
+        animation: fadeIn 0.2s ease;
+    }
+
+    .modal-confirm h2 {
+        margin-bottom: 0.5rem;
+        font-size: 1.25rem;
+    }
+
+    .modal-confirm p {
+        margin-bottom: 1.5rem;
+        color: #555;
+    }
+
+    .modal-actions {
+        display: flex;
+        justify-content: center;
+        gap: 1rem;
+    }
+
+    .btn-danger {
+        background-color: #e74c3c;
+        color: white;
+    }
+
+    .btn-danger:hover {
+        background-color: #c0392b;
+    }
+
     .price {
         color: #27ae60;
         font-weight: bold;