From e223128565e7df875030dde4ddf3264d77f3f83d Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Thu, 9 Apr 2026 15:10:40 +0000 Subject: [PATCH] fix(dashboard): replace hover row-actions with kebab menu, fix modal button reset and delete color - Bug 1: hover actions covered total column; replaced with kebab dropdown in dedicated 44px column - Bug 2: resync/delete buttons kept stale state across modal opens; reset in modal init block - Bug 3: delete success button was green (btn-success); changed to red (btn-danger) - Dropdown styled per DESIGN.md: warm shadow, 8px radius, dark mode tokens Co-Authored-By: Claude Opus 4.5 --- api/app/static/css/style.css | 32 ++++++++++++++++++++------------ api/app/static/js/dashboard.js | 9 +++++---- api/app/static/js/shared.js | 6 +++++- api/app/templates/base.html | 4 ++-- api/app/templates/dashboard.html | 5 +++-- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/api/app/static/css/style.css b/api/app/static/css/style.css index 6e3a819..5ec4b56 100644 --- a/api/app/static/css/style.css +++ b/api/app/static/css/style.css @@ -393,19 +393,27 @@ input[type="checkbox"] { padding: 4px 8px; } -/* Dashboard row hover actions */ -#dashOrdersBody tr { position: relative; } -#dashOrdersBody tr .row-actions { - display: none; - position: absolute; - right: 8px; - top: 50%; - transform: translateY(-50%); - gap: 4px; - z-index: 1; +/* Dashboard kebab dropdown */ +.kebab-dropdown .btn { color: var(--text-muted); } +.kebab-dropdown .btn:hover { color: var(--text-secondary); } +.kebab-dropdown .dropdown-menu { + box-shadow: var(--card-shadow); + border-radius: 8px; + border: 1px solid var(--border); + background: var(--surface); + font-family: var(--font-body); + font-size: 13px; + min-width: 160px; } -#dashOrdersBody tr:hover .row-actions { - display: inline-flex; +.kebab-dropdown .dropdown-item { font-size: 13px; padding: 6px 12px; } +.kebab-dropdown .dropdown-item:hover { background: var(--surface-raised); } +[data-theme="dark"] .kebab-dropdown .dropdown-menu { + background: var(--surface); + border-color: var(--border); + color: var(--text-primary); +} +[data-theme="dark"] .kebab-dropdown .dropdown-item:hover { + background: var(--surface-raised); } /* ── Forms ───────────────────────────────────────── */ diff --git a/api/app/static/js/dashboard.js b/api/app/static/js/dashboard.js index f11616c..0c9846c 100644 --- a/api/app/static/js/dashboard.js +++ b/api/app/static/js/dashboard.js @@ -360,7 +360,7 @@ async function loadDashOrders() { const orders = data.orders || []; if (orders.length === 0) { - tbody.innerHTML = 'Nicio comanda'; + tbody.innerHTML = 'Nicio comanda'; } else { tbody.innerHTML = orders.map(o => { const dateStr = fmtDate(o.order_date); @@ -375,7 +375,8 @@ async function loadDashOrders() { ${o.items_count || 0} ${fmtCost(o.delivery_cost)} ${fmtCost(o.discount_total)} - ${orderTotal}${(o.status === 'IMPORTED' || o.status === 'ALREADY_IMPORTED') && !(o.invoice && o.invoice.facturat) ? '' : ''} + ${orderTotal} + ${(o.status === 'IMPORTED' || o.status === 'ALREADY_IMPORTED') && !(o.invoice && o.invoice.facturat) ? '' : ''} `; }).join(''); } @@ -442,7 +443,7 @@ async function loadDashOrders() { }); } catch (err) { document.getElementById('dashOrdersBody').innerHTML = - `${esc(err.message)}`; + `${esc(err.message)}`; } } @@ -636,7 +637,7 @@ function dashDeleteOrder(orderNumber, btn) { const data = await res.json(); if (data.success) { b.innerHTML = ''; - b.className = 'btn btn-xs btn-success'; + b.className = 'btn btn-xs btn-danger'; setTimeout(() => loadDashOrders(), 1500); } else { b.innerHTML = ''; diff --git a/api/app/static/js/shared.js b/api/app/static/js/shared.js index 149ee60..c92151b 100644 --- a/api/app/static/js/shared.js +++ b/api/app/static/js/shared.js @@ -507,6 +507,10 @@ async function renderOrderDetailModal(orderNumber, opts) { document.getElementById('detailError').style.display = 'none'; const retryBtn = document.getElementById('detailRetryBtn'); if (retryBtn) { retryBtn.style.display = 'none'; retryBtn.disabled = false; retryBtn.innerHTML = ' Reimporta'; retryBtn.className = 'btn btn-sm btn-outline-primary'; } + const resyncBtn = document.getElementById('detailResyncBtn'); + if (resyncBtn) { resyncBtn.style.display = 'none'; resyncBtn.disabled = false; resyncBtn.innerHTML = ' Resync'; resyncBtn.className = 'btn btn-sm btn-outline-warning'; } + const deleteBtn = document.getElementById('detailDeleteBtn'); + if (deleteBtn) { deleteBtn.style.display = 'none'; deleteBtn.disabled = false; deleteBtn.innerHTML = ' Sterge din ROA'; deleteBtn.className = 'btn btn-sm btn-outline-danger'; } const receiptEl = document.getElementById('detailReceipt'); if (receiptEl) receiptEl.innerHTML = ''; const receiptMEl = document.getElementById('detailReceiptMobile'); @@ -840,7 +844,7 @@ async function renderOrderDetailModal(orderNumber, opts) { const data = await res.json(); if (data.success) { btn.innerHTML = ' Sters'; - btn.className = 'btn btn-sm btn-success'; + btn.className = 'btn btn-sm btn-danger'; setTimeout(() => renderOrderDetailModal(orderNumber, opts), 1500); } else { btn.innerHTML = ' ' + (data.message || 'Eroare'); diff --git a/api/app/templates/base.html b/api/app/templates/base.html index ba26405..9e9d060 100644 --- a/api/app/templates/base.html +++ b/api/app/templates/base.html @@ -19,7 +19,7 @@ {% set rp = request.scope.get('root_path', '') %} - + @@ -169,7 +169,7 @@ - + + {% endblock %}