From 09ab1c3e295481c07a0da3530413cb5a5cb576d3 Mon Sep 17 00:00:00 2001 From: bl3kunja-FW Date: Sun, 31 May 2026 11:23:31 +0200 Subject: [PATCH] Store UI cleanup and rework --- __pycache__/data_manager.cpython-312.pyc | Bin 19689 -> 19687 bytes app.py | 4 +- data/store.json | 187 ++++++++++++++++++++++- data_manager.py | 4 +- static/css/style.css | 169 +++++++++++++------- static/js/app.js | 81 +++++----- templates/index.html | 35 ++--- 7 files changed, 356 insertions(+), 124 deletions(-) diff --git a/__pycache__/data_manager.cpython-312.pyc b/__pycache__/data_manager.cpython-312.pyc index 3366c88a77527dcc7a9ee020a83d69671f581662..94714213e1612025c4beee405412be0686bb0b19 100644 GIT binary patch delta 73 zcmaDklkxdXM&8rByj%=GaQKsS*5i%5EzFGGlP58&GP`?*Y~IUUZq3S8oSKuf*~0!D dGn16UW)5c+POhxn4-CSrk{8OWC!6_f1^{%&7qI{U delta 75 zcmaDplkw$DM&8rByj%=GVB#vB^ bool: + def log_payment(self, items: list, total: float, balance_before: float, balance_after: float, seller: str = '') -> bool: try: store = self.load_store() payments = store.get('payments', []) @@ -317,7 +317,7 @@ class DataManager: payments.append({ 'id': new_id, 'timestamp': datetime.now().isoformat(), - 'buyer': buyer, + 'seller': seller, 'items': items, 'total': round(total, 2), 'balance_before': round(balance_before, 2), diff --git a/static/css/style.css b/static/css/style.css index 24d7c1a..80fd3a8 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -56,6 +56,8 @@ body { overflow-y: auto; box-shadow: var(--shadow-sm); flex-shrink: 0; + display: flex; + flex-direction: column; } .logo-section { @@ -280,7 +282,8 @@ body { /* Admin Section */ .admin-section { - margin-bottom: 0; + margin-top: auto; + padding-top: 24px; } .admin-btn { @@ -394,6 +397,36 @@ body { overflow: hidden; } +.toolbar-stacked { + height: auto; + flex-direction: column; + align-items: stretch; + gap: 0; + padding: 8px 14px; + overflow: visible; +} + +.toolbar-row { + display: flex; + align-items: center; + gap: 6px; + min-height: 36px; +} + +.toolbar-row + .toolbar-row { + border-top: 1px solid var(--border-color); + padding-top: 6px; + margin-top: 2px; +} + +.toolbar-stacked .toolbar-actions { + margin-left: auto; +} + +.toolbar-stacked .tf-quick { + margin-left: 0; +} + .toolbar-title { font-size: 12px; font-weight: 700; @@ -1284,8 +1317,8 @@ table tbody tr.duplicate-warning:hover { .inventory-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 10px; + grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); + gap: 12px; align-content: start; padding-bottom: 4px; } @@ -1293,29 +1326,28 @@ table tbody tr.duplicate-warning:hover { .inventory-card { background: #fff; border: 1px solid var(--border-color); - border-radius: 10px; + border-radius: 12px; overflow: hidden; display: flex; flex-direction: column; - transition: box-shadow 0.15s, border-color 0.15s; + transition: border-color 0.15s; cursor: default; } .inventory-card:hover { - box-shadow: 0 4px 16px rgba(0,0,0,0.10); - border-color: #ccc; + border-color: var(--accent-blue); } .inventory-card.out-of-stock { - opacity: 0.5; + opacity: 0.45; } -/* Image area — fills full width, fixed height */ +/* Image area */ .inventory-card-img-wrap { position: relative; width: 100%; - height: 150px; - background: var(--bg-tertiary); + height: 120px; + background: #fff; overflow: hidden; flex-shrink: 0; } @@ -1337,11 +1369,12 @@ table tbody tr.duplicate-warning:hover { } .inventory-card-body { - padding: 10px 12px 8px; + padding: 10px 12px 6px; display: flex; flex-direction: column; - gap: 3px; + gap: 6px; flex: 1; + background: var(--bg-tertiary); border-top: 1px solid var(--border-color); } @@ -1353,8 +1386,15 @@ table tbody tr.duplicate-warning:hover { line-height: 1.3; } +.inventory-card-meta { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 6px; +} + .inventory-card-price { - font-size: 16px; + font-size: 15px; font-weight: 700; color: var(--text-primary); } @@ -1362,27 +1402,32 @@ table tbody tr.duplicate-warning:hover { .inventory-card-stock { font-size: 11px; color: var(--text-secondary); - letter-spacing: 0.2px; + background: var(--bg-tertiary); + border-radius: 4px; + padding: 1px 6px; + white-space: nowrap; } .inventory-card-stock.stock-empty { color: var(--accent-red); + background: rgba(239,68,68,0.08); font-weight: 600; } .inventory-card-actions { display: flex; - flex-wrap: wrap; + flex-direction: column; gap: 5px; - padding: 6px 12px 10px; + padding: 6px 12px 12px; + background: var(--bg-tertiary); } .inventory-add-btn { width: 100%; margin: 0; - padding: 7px; + padding: 8px; font-size: 12px; - border-radius: 6px; + border-radius: 7px; } .inventory-add-btn:disabled { @@ -1390,10 +1435,15 @@ table tbody tr.duplicate-warning:hover { cursor: not-allowed; } -.inventory-card-actions .action-btn { +.inventory-card-admin-actions { + display: flex; + gap: 5px; +} + +.inventory-card-admin-actions .action-btn { flex: 1; margin: 0; - padding: 6px 8px; + padding: 5px 6px; font-size: 11px; text-align: center; } @@ -1693,6 +1743,11 @@ table tbody tr.duplicate-warning:hover { /* Print Styles */ @media print { + @page { + size: A4 portrait; + margin: 18mm 22mm; + } + body { background: #fff !important; color: #000 !important; @@ -1759,10 +1814,9 @@ table tbody tr.duplicate-warning:hover { } body.printing-receipt #receiptPrintArea { - position: fixed; + position: absolute; top: 0; left: 0; width: 100%; - height: 100%; background: #fff; z-index: 9999; padding: 0; @@ -1771,59 +1825,62 @@ table tbody tr.duplicate-warning:hover { /* ---- Shared print page wrapper ---- */ .rp-page { - max-width: 580px; + max-width: 155mm; margin: 0 auto; - padding: 32px 40px; + padding: 6mm 0 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - font-size: 13px; + font-size: 14px; color: #000; } - .rp-monthly { max-width: 720px; } + .rp-monthly { + max-width: 100%; + padding: 0; + } - .rp-logo-block { text-align: center; margin-bottom: 16px; } - .rp-logo { height: 72px; object-fit: contain; } + .rp-logo-block { text-align: center; margin-bottom: 20px; } + .rp-logo { height: 80px; object-fit: contain; } - .rp-divider { border: none; border-top: 2px solid #111; margin: 10px 0; } - .rp-divider-dashed { border: none; border-top: 2px dashed #999; margin: 10px 0; } + .rp-divider { border: none; border-top: 2px solid #111; margin: 12px 0; } + .rp-divider-dashed { border: none; border-top: 2px dashed #999; margin: 12px 0; } .rp-title { text-align: center; - font-size: 17px; + font-size: 20px; font-weight: 700; - letter-spacing: 1.5px; + letter-spacing: 2px; text-transform: uppercase; - margin: 10px 0 6px; + margin: 12px 0 8px; } .rp-meta { display: flex; justify-content: space-between; - font-size: 11px; + font-size: 12px; color: #555; - margin-bottom: 6px; + margin-bottom: 8px; } .rp-table { width: 100%; border-collapse: collapse; - margin: 10px 0; - font-size: 12px; + margin: 12px 0; + font-size: 13px; } .rp-table th { - font-size: 10px; + font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; - border-bottom: 1px solid #333; - padding: 5px 4px; + border-bottom: 1.5px solid #333; + padding: 7px 5px; background: #f5f5f5; } .rp-table td { - padding: 5px 4px; - border-bottom: 1px solid #eee; + padding: 7px 5px; + border-bottom: 1px solid #e8e8e8; vertical-align: top; } @@ -1835,56 +1892,56 @@ table tbody tr.duplicate-warning:hover { .rp-total { display: flex; justify-content: space-between; - font-size: 16px; + font-size: 18px; font-weight: 700; - padding: 8px 0; + padding: 10px 0; } .rp-footer { text-align: center; - font-size: 11px; + font-size: 12px; letter-spacing: 0.5px; color: #555; - padding-top: 8px; + padding-top: 12px; } /* Monthly-specific */ .rp-monthly-kpi { display: flex; - gap: 24px; - margin: 12px 0; + gap: 20px; + margin: 14px 0; } .rp-kpi-box { flex: 1; border: 1px solid #ddd; border-radius: 6px; - padding: 10px 14px; + padding: 12px 16px; text-align: center; } .rp-kpi-label { - font-size: 10px; + font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; color: #666; - margin-bottom: 4px; + margin-bottom: 5px; } .rp-kpi-value { - font-size: 20px; + font-size: 22px; font-weight: 700; } .rp-section-title { - font-size: 10px; + font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: #555; border-bottom: 1px solid #ccc; - padding-bottom: 4px; - margin: 14px 0 6px; + padding-bottom: 5px; + margin: 16px 0 8px; } } diff --git a/static/js/app.js b/static/js/app.js index 2468a5d..086bef4 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -36,6 +36,7 @@ async function checkAdminStatus() { function updateAdminUI() { const adminBtn = document.getElementById('adminToggleBtn'); const addBtn = document.querySelector('[onclick="openAddParticipantModal()"]'); + const participantsToolbar = document.getElementById('participantsToolbar'); const addUnregisteredBtn = document.getElementById('addUnregisteredBtn'); const addItemBtn = document.getElementById('addItemBtn'); const editBalanceBtn = document.getElementById('editBalanceBtn'); @@ -47,6 +48,7 @@ function updateAdminUI() { adminBtn.onclick = adminLogout; adminBtn.classList.add('active'); if (addBtn) addBtn.style.display = 'block'; + if (participantsToolbar) participantsToolbar.style.display = ''; if (addItemBtn) addItemBtn.style.display = 'inline-flex'; if (editBalanceBtn) editBalanceBtn.style.display = 'inline-flex'; } else { @@ -54,6 +56,7 @@ function updateAdminUI() { adminBtn.onclick = openLoginModal; adminBtn.classList.remove('active'); if (addBtn) addBtn.style.display = 'none'; + if (participantsToolbar) participantsToolbar.style.display = 'none'; if (addItemBtn) addItemBtn.style.display = 'none'; if (editBalanceBtn) editBalanceBtn.style.display = 'none'; } @@ -532,7 +535,10 @@ function resetFilters() { } function getDateString(date) { - return date.toISOString().split('T')[0]; + const y = date.getFullYear(); + const m = String(date.getMonth() + 1).padStart(2, '0'); + const d = String(date.getDate()).padStart(2, '0'); + return `${y}-${m}-${d}`; } function filterByToday() { @@ -732,6 +738,7 @@ function switchTab(tabName, event) { event.target.classList.add('active'); // Load tab-specific data + if (tabName === 'logs') filterByToday(); if (tabName === 'documents') loadDocuments(); if (tabName === 'store') { // Always return to shop view when switching to store tab @@ -903,7 +910,7 @@ async function loadBalance() { const response = await fetch('/api/store/balance'); const data = await response.json(); currentBalance = data.balance; - document.getElementById('storeBalanceDisplay').textContent = '€' + currentBalance.toFixed(2); + document.getElementById('storeBalanceDisplay').textContent = '€ ' + currentBalance.toFixed(2); updateCartTotals(); } catch (error) { console.error('Error loading balance:', error); @@ -933,13 +940,17 @@ function renderInventory() { ${imgHtml}
${item.name}
-
€${item.price.toFixed(2)}
-
Zaloga: ${item.stock}
+
+
€ ${item.price.toFixed(2)}
+
${item.stock === 0 ? 'Ni zaloge' : item.stock + ' kos'}
+
- ${isAdmin ? ` - ` : ''} + ${isAdmin ? `
+ + +
` : ''}
`; grid.appendChild(card); @@ -1003,7 +1014,7 @@ function renderCart() { ${item.qty} -
€${(item.price * item.qty).toFixed(2)}
+
€ ${(item.price * item.qty).toFixed(2)}
`; container.appendChild(row); }); @@ -1018,9 +1029,9 @@ function updateCartTotals() { const totalEl = document.getElementById('cartTotal'); const balanceAfterEl = document.getElementById('cartBalanceAfter'); - if (totalEl) totalEl.textContent = '€' + total.toFixed(2); + if (totalEl) totalEl.textContent = '€ ' + total.toFixed(2); if (balanceAfterEl) { - balanceAfterEl.textContent = '€' + balanceAfter.toFixed(2); + balanceAfterEl.textContent = '€ ' + balanceAfter.toFixed(2); balanceAfterEl.className = 'cart-balance-after'; } } @@ -1033,12 +1044,11 @@ function processPayment() { const total = cart.reduce((sum, i) => sum + i.price * i.qty, 0); const balanceAfter = currentBalance + total; - document.getElementById('checkoutFirstName').value = ''; - document.getElementById('checkoutLastName').value = ''; - document.getElementById('checkoutTotal').textContent = '€' + total.toFixed(2); - document.getElementById('checkoutBalanceAfter').textContent = '€' + balanceAfter.toFixed(2); + document.getElementById('checkoutBuyer').value = ''; + document.getElementById('checkoutTotal').textContent = '€ ' + total.toFixed(2); + document.getElementById('checkoutBalanceAfter').textContent = '€ ' + balanceAfter.toFixed(2); document.getElementById('checkoutModal').classList.add('show'); - document.getElementById('checkoutFirstName').focus(); + document.getElementById('checkoutBuyer').focus(); } function closeCheckoutModal() { @@ -1046,15 +1056,12 @@ function closeCheckoutModal() { } async function confirmCheckout() { - const firstName = document.getElementById('checkoutFirstName').value.trim(); - const lastName = document.getElementById('checkoutLastName').value.trim(); + const seller = document.getElementById('checkoutBuyer').value.trim(); - if (!firstName || !lastName) { - alert('Prosimo, vnesite ime in priimek kupca'); + if (!seller) { + alert('Prosimo, vnesite ime in priimek prodajalca'); return; } - - const buyer = firstName + ' ' + lastName; const total = cart.reduce((sum, i) => sum + i.price * i.qty, 0); const balanceAfter = currentBalance + total; @@ -1077,7 +1084,7 @@ async function confirmCheckout() { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ - buyer, + seller, items: cart.map(i => ({ name: i.name, qty: i.qty, price: i.price })), cart_items: cartItems, total, @@ -1090,7 +1097,7 @@ async function confirmCheckout() { if (!data.success) { alert('Napaka: ' + data.message); return; } const payment = { - buyer, + seller, items: cart.map(i => ({ name: i.name, qty: i.qty, price: i.price })), total, balance_before: currentBalance, @@ -1299,13 +1306,13 @@ async function loadPaymentHistory() { const row = document.createElement('tr'); row.innerHTML = ` ${p.id} - ${p.buyer || '-'} + ${p.seller || '-'} ${date} ${time} ${itemsSummary} - €${p.total.toFixed(2)} - €${p.balance_before.toFixed(2)} - €${p.balance_after.toFixed(2)} + € ${p.total.toFixed(2)} + € ${p.balance_before.toFixed(2)} + € ${p.balance_after.toFixed(2)} `; tbody.appendChild(row); @@ -1323,7 +1330,7 @@ function printReceipt(payment) { const date = fmtDate(ts.split('T')[0]); const time = ts.split('T')[1] ? ts.split('T')[1].substring(0, 5) : ''; const rows = payment.items.map(i => - `${i.name}${i.qty}×€${i.price.toFixed(2)}€${(i.price * i.qty).toFixed(2)}` + `${i.name}${i.qty}×€ ${i.price.toFixed(2)}€ ${(i.price * i.qty).toFixed(2)}` ).join(''); const html = ` @@ -1335,17 +1342,17 @@ function printReceipt(payment) {
POTRDILO O PLAČILU
${date} ${time} - Prodajalec: ${payment.buyer || '-'} + Prodajalec: ${payment.seller || '-'}
- + ${rows}
ArtikelKol.CenaZnesek
ArtikelKoličinaCenaZnesek
SKUPAJ - €${payment.total.toFixed(2)} + € ${payment.total.toFixed(2)}
@@ -1404,17 +1411,17 @@ async function renderMonthlyOverview() { })); const itemRows = Object.entries(itemTotals).map(([name, v]) => - `${name}${v.qty}€${v.revenue.toFixed(2)}` + `${name}${v.qty}€ ${v.revenue.toFixed(2)}` ).join(''); const txRows = [...filtered].reverse().map(p => { const date = fmtDate(p.timestamp.split('T')[0]); const time = p.timestamp.split('T')[1].substring(0, 5); - return `${date}${time}${p.buyer || '-'}${p.items.map(i => `${i.name} ×${i.qty}`).join(', ')}€${p.total.toFixed(2)}`; + return `${date}${time}${p.seller || '-'}${p.items.map(i => `${i.name} ×${i.qty}`).join(', ')}€ ${p.total.toFixed(2)}`; }).join(''); content.innerHTML = ` -
Skupaj prihodek: €${grandTotal.toFixed(2)} (${filtered.length} transakcij)
+
Skupaj prihodek: € ${grandTotal.toFixed(2)} (${filtered.length} transakcij)

Po artiklih

@@ -1445,14 +1452,14 @@ function printMonthlyOverview() { })); const itemRows = Object.entries(itemTotals).map(([name, v]) => - `` + `` ).join(''); const txRows = [...filtered].reverse().map(p => { const date = fmtDate(p.timestamp.split('T')[0]); const time = p.timestamp.split('T')[1].substring(0, 5); - const items = p.items.map(i => `${i.name} ×${i.qty} (€${(i.price*i.qty).toFixed(2)})`).join(', '); - return ``; + const items = p.items.map(i => `${i.name} ×${i.qty} (€ ${(i.price*i.qty).toFixed(2)})`).join(', '); + return ``; }).join(''); const [year, month] = picker.split('-'); @@ -1469,7 +1476,7 @@ function printMonthlyOverview() {
${monthName}Natisnjeno: ${printDate}
-
Skupaj prihodek
€${grandTotal.toFixed(2)}
+
Skupaj prihodek
€ ${grandTotal.toFixed(2)}
Št. transakcij
${filtered.length}
Po artiklih
diff --git a/templates/index.html b/templates/index.html index daf6f4b..cef9bb2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -60,8 +60,7 @@
-
- Člani +
@@ -88,8 +87,8 @@
-
-
+
+
+
+
@@ -119,10 +120,10 @@
-
-
- - +
+ + +
@@ -148,9 +149,6 @@
-
- Dokumenti -

Nalaganje dokumentov...

@@ -162,11 +160,10 @@
- Trgovina
Stanje - €0.00 + € 0.00
@@ -193,11 +190,11 @@
Skupaj: - €0.00 + € 0.00
Stanje po plačilu: - €0.00 + € 0.00
@@ -362,12 +359,8 @@ ×

Podatki prodajalca

- - -
-
- - + +
ArtikelKoličinaPrihodek
${name}${v.qty}€${v.revenue.toFixed(2)}
${name}${v.qty}€ ${v.revenue.toFixed(2)}
${date}${time}${p.buyer || '-'}${items}€${p.total.toFixed(2)}
${date}${time}${p.seller || '-'}${items}€ ${p.total.toFixed(2)}