fix(ui): center header title on tablet + add skeleton loader to spesa stat card
Header title centering:
- .header-content: remove max-width:600px, use position:relative + justify-content:center
- .header-title: position:absolute; left:50%; transform:translateX(-50%)
so the title is always at the exact center of the header regardless of
screen width or how many action buttons are on the right
- Added max-width:calc(100% - 200px) to prevent overlap with action buttons
on narrow screens
Spesa skeleton preloader:
- index.html: add stat-loading class to stat-spesa (was missing, other 3 had it)
- app.js showPage('dashboard'): add 'spesa' to the skeleton init array
- app.js loadShoppingCount(): remove stat-loading class after data loads
(like loadDashboard() does for the other 3 locations)
This commit is contained in:
+13
-3
@@ -105,21 +105,31 @@ body {
|
||||
}
|
||||
|
||||
.header-content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
pointer-events: auto;
|
||||
/* prevent title overlapping action buttons on small screens */
|
||||
max-width: calc(100% - 200px);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.header-version {
|
||||
|
||||
+8
-4
@@ -2231,7 +2231,7 @@ function showPage(pageId, param = null) {
|
||||
switch(pageId) {
|
||||
case 'dashboard':
|
||||
// Show skeleton on stat-cards while data loads
|
||||
['dispensa', 'frigo', 'freezer'].forEach(loc => {
|
||||
['dispensa', 'frigo', 'freezer', 'spesa'].forEach(loc => {
|
||||
const el = document.getElementById(`stat-${loc}`);
|
||||
if (el) { el.textContent = '…'; el.classList.add('stat-loading'); }
|
||||
});
|
||||
@@ -8314,13 +8314,17 @@ async function addSmartToBring() {
|
||||
async function loadShoppingCount() {
|
||||
try {
|
||||
const data = await api('bring_list');
|
||||
const el = document.getElementById('stat-spesa');
|
||||
if (data.success && data.purchase) {
|
||||
document.getElementById('stat-spesa').textContent = data.purchase.length;
|
||||
el.textContent = data.purchase.length;
|
||||
} else {
|
||||
document.getElementById('stat-spesa').textContent = '-';
|
||||
el.textContent = '-';
|
||||
}
|
||||
el.classList.remove('stat-loading');
|
||||
} catch {
|
||||
document.getElementById('stat-spesa').textContent = '-';
|
||||
const el = document.getElementById('stat-spesa');
|
||||
el.textContent = '-';
|
||||
el.classList.remove('stat-loading');
|
||||
}
|
||||
// Smart urgency badge: use cached data if fresh (< 2 min), else fetch
|
||||
if (smartShoppingItems.length > 0 && (Date.now() - _smartShoppingLastFetch) < 2 * 60 * 1000) {
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@
|
||||
</div>
|
||||
<div class="stat-card" onclick="showPage('shopping')">
|
||||
<span class="stat-icon">🛒</span>
|
||||
<span class="stat-value" id="stat-spesa">-</span>
|
||||
<span class="stat-value stat-loading" id="stat-spesa">…</span>
|
||||
<span class="stat-label" data-i18n="nav.shopping">Spesa</span>
|
||||
<span class="stat-urgent" id="stat-urgent" style="display:none"></span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user