refactor(ui): separate diff dots with distinct colors, align modal badges
Replace 2 combined dots with 4 individual dots per diff type: - CUI/TVA (red), Denumire (orange), Adresa (blue), Pret (green) - Remove redundant price column from dashboard table - Add --compare design token (orange) for denomination mismatches - Align modal badge colors with table dot colors (4 separate CSS classes) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,10 @@ Every admin tool is blue. This one uses amber — reads as "operational" and "at
|
||||
|
||||
--cancelled: #78716C;
|
||||
--cancelled-light: #F5F5F4;
|
||||
|
||||
--compare: #EA580C;
|
||||
--compare-light: #FFF7ED;
|
||||
--compare-text: #9A3412;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -140,6 +144,10 @@ Strategy: invert surfaces, reduce accent saturation ~15%, keep semantic colors r
|
||||
|
||||
--cancelled: #78716C;
|
||||
--cancelled-light: rgba(120,113,108,0.15);
|
||||
|
||||
--compare: #EA580C;
|
||||
--compare-light: rgba(234,88,12,0.15);
|
||||
--compare-text: #FB923C;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
--cancelled: #78716C;
|
||||
--cancelled-light: #F5F5F4;
|
||||
|
||||
--compare: #EA580C;
|
||||
--compare-light: #FFF7ED;
|
||||
--compare-text: #9A3412;
|
||||
|
||||
/* Border radius */
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 8px;
|
||||
@@ -93,6 +97,10 @@
|
||||
|
||||
--cancelled: #78716C;
|
||||
--cancelled-light: rgba(120,113,108,0.15);
|
||||
|
||||
--compare: #EA580C;
|
||||
--compare-light: rgba(234,88,12,0.15);
|
||||
--compare-text: #FB923C;
|
||||
}
|
||||
|
||||
/* Dark mode overrides for elements with hardcoded colors */
|
||||
@@ -1179,7 +1187,9 @@ tr.mapping-deleted td {
|
||||
/* Diff-type badges (reuses .anaf-badge sizing per DESIGN.md type scale minimum) */
|
||||
.diff-badge { display:inline-block; font-family:var(--font-body); font-size:12px; font-weight:500; padding:2px 8px; border-radius:9999px; margin-left:4px; vertical-align:middle; }
|
||||
.diff-badge-anaf { background:var(--error-light); color:var(--error-text); }
|
||||
.diff-badge-info { background:var(--warning-light); color:var(--warning-text); }
|
||||
.diff-badge-denumire { background:var(--compare-light); color:var(--compare-text); }
|
||||
.diff-badge-addr { background:var(--info-light); color:var(--info-text); }
|
||||
.diff-badge-price { background:var(--success-light); color:var(--success-text); }
|
||||
|
||||
/* ── Compact order detail layout ──────────────── */
|
||||
.detail-col-label {
|
||||
|
||||
@@ -358,7 +358,7 @@ async function loadDashOrders() {
|
||||
const orders = data.orders || [];
|
||||
|
||||
if (orders.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="text-center text-muted py-3">Nicio comanda</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="9" class="text-center text-muted py-3">Nicio comanda</td></tr>';
|
||||
} else {
|
||||
tbody.innerHTML = orders.map(o => {
|
||||
const dateStr = fmtDate(o.order_date);
|
||||
@@ -368,13 +368,12 @@ async function loadDashOrders() {
|
||||
<td>${statusDot(o.status)}</td>
|
||||
<td class="text-nowrap">${dateStr}</td>
|
||||
${renderClientCell(o)}
|
||||
<td><code>${esc(o.order_number)}</code>${(o.anaf_cod_fiscal_adjusted===1||o.anaf_denumire_mismatch===1||(o.cod_fiscal_gomag&&o.anaf_platitor_tva!==null&&o.anaf_cod_fiscal_adjusted!==1&&(/^RO/i.test(o.cod_fiscal_gomag)!==(o.anaf_platitor_tva===1))))?'<span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--error);margin-left:4px;vertical-align:middle" title="Diferente ANAF"></span>':''}${(o.address_mismatch===1||o.price_match===false)?'<span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--warning);margin-left:2px;vertical-align:middle" title="Diferente adresa/pret"></span>':''}</td>
|
||||
<td><code>${esc(o.order_number)}</code>${diffDots(o)}</td>
|
||||
<td>${o.items_count || 0}</td>
|
||||
<td class="text-end text-muted">${fmtCost(o.delivery_cost)}</td>
|
||||
<td class="text-end text-muted">${fmtCost(o.discount_total)}</td>
|
||||
<td class="text-end fw-bold">${orderTotal}</td>
|
||||
<td class="text-center">${invoiceDot(o)}</td>
|
||||
<td class="text-center">${priceDot(o)}</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
}
|
||||
@@ -394,14 +393,11 @@ async function loadDashOrders() {
|
||||
}
|
||||
const name = o.customer_name || o.shipping_name || o.billing_name || '\u2014';
|
||||
const totalStr = o.order_total ? Number(o.order_total).toFixed(2) : '';
|
||||
const anafDiffDot = (o.anaf_cod_fiscal_adjusted===1||o.anaf_denumire_mismatch===1||(o.cod_fiscal_gomag&&o.anaf_platitor_tva!==null&&o.anaf_cod_fiscal_adjusted!==1&&(/^RO/i.test(o.cod_fiscal_gomag)!==(o.anaf_platitor_tva===1)))) ? '<span style="display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--error);margin-right:2px;vertical-align:middle" title="ANAF"></span>' : '';
|
||||
const addrDiffDot = o.address_mismatch===1 ? '<span style="display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--warning);margin-right:2px;vertical-align:middle" title="Adresa"></span>' : '';
|
||||
const priceMismatch = o.price_match === false ? '<span class="dot dot-red" style="width:6px;height:6px" title="Pret!="></span> ' : '';
|
||||
return `<div class="flat-row" onclick="openDashOrderDetail('${esc(o.order_number)}')" style="font-size:0.875rem">
|
||||
${statusDot(o.status)}
|
||||
<span style="color:var(--text-muted)" class="text-nowrap">${dateFmt}</span>
|
||||
<span class="grow truncate fw-bold">${esc(name)}</span>
|
||||
<span class="text-nowrap">x${o.items_count || 0}${totalStr ? ' · ' + anafDiffDot + addrDiffDot + priceMismatch + '<strong>' + totalStr + '</strong>' : ''}</span>
|
||||
<span class="text-nowrap">x${o.items_count || 0}${totalStr ? ' · ' + diffDots(o, true) + '<strong>' + totalStr + '</strong>' : ''}</span>
|
||||
</div>`;
|
||||
}).join('');
|
||||
}
|
||||
@@ -500,10 +496,22 @@ function statusLabelText(status) {
|
||||
}
|
||||
}
|
||||
|
||||
function priceDot(order) {
|
||||
if (order.price_match === true) return '<span class="dot dot-green" title="Preturi OK"></span>';
|
||||
if (order.price_match === false) return '<span class="dot dot-red" title="Diferenta de pret"></span>';
|
||||
return '<span class="dot dot-gray" title="Neverificat"></span>';
|
||||
function diffDots(o, mobile) {
|
||||
const sz = mobile ? 6 : 7;
|
||||
const ml = mobile ? 'margin-right:2px' : 'margin-left:3px';
|
||||
let d = '';
|
||||
const s = `display:inline-block;width:${sz}px;height:${sz}px;border-radius:50%;${ml};vertical-align:middle`;
|
||||
if (o.anaf_cod_fiscal_adjusted===1 ||
|
||||
(o.cod_fiscal_gomag && o.anaf_platitor_tva!==null && o.anaf_cod_fiscal_adjusted!==1 &&
|
||||
(/^RO/i.test(o.cod_fiscal_gomag)!==(o.anaf_platitor_tva===1))))
|
||||
d += `<span style="${s};background:var(--error)" title="CUI/TVA ANAF"></span>`;
|
||||
if (o.anaf_denumire_mismatch===1)
|
||||
d += `<span style="${s};background:var(--compare)" title="Denumire ANAF"></span>`;
|
||||
if (o.address_mismatch===1)
|
||||
d += `<span style="${s};background:var(--info)" title="Adresa diferita"></span>`;
|
||||
if (o.price_match===false)
|
||||
d += `<span style="${s};background:var(--success)" title="Pret diferit"></span>`;
|
||||
return d;
|
||||
}
|
||||
|
||||
function invoiceDot(order) {
|
||||
|
||||
@@ -1019,15 +1019,15 @@ function _renderHeaderInfo(order) {
|
||||
orderNumEl.parentNode.querySelectorAll('.diff-badge').forEach(b => b.remove());
|
||||
const badges = [];
|
||||
if (isPJ && pi.anaf_cod_fiscal_adjusted) badges.push({label:'CUI', cls:'diff-badge-anaf', aria:'CUI ajustat conform ANAF'});
|
||||
if (isPJ && pi.anaf_denumire_mismatch) badges.push({label:'Denumire', cls:'diff-badge-anaf', aria:'Denumire diferita fata de ANAF'});
|
||||
if (isPJ && pi.anaf_denumire_mismatch) badges.push({label:'Denumire', cls:'diff-badge-denumire', aria:'Denumire diferita fata de ANAF'});
|
||||
if (isPJ && !pi.anaf_cod_fiscal_adjusted && pi.anaf_platitor_tva !== null && pi.anaf_platitor_tva !== undefined) {
|
||||
const gomagImpliesPlatitor = pi.cod_fiscal_gomag && /^RO/i.test(pi.cod_fiscal_gomag);
|
||||
const anafPlatitor = pi.anaf_platitor_tva === 1;
|
||||
if (gomagImpliesPlatitor !== anafPlatitor) badges.push({label:'TVA', cls:'diff-badge-anaf', aria: anafPlatitor ? 'Platitor TVA conform ANAF (GoMag fara RO)' : 'Neplatitor TVA conform ANAF (GoMag cu RO)'});
|
||||
}
|
||||
if (addr && addr.livrare_roa && !addrMatch(addr.livrare_gomag, addr.livrare_roa)) badges.push({label:'Adr. livr.', cls:'diff-badge-info', aria:'Adresa livrare diferita'});
|
||||
if (addr && addr.facturare_roa && !addrMatch(addr.facturare_gomag, addr.facturare_roa)) badges.push({label:'Adr. fact.', cls:'diff-badge-info', aria:'Adresa facturare diferita'});
|
||||
if (order.price_check && order.price_check.mismatches > 0) badges.push({label:'Preturi (' + order.price_check.mismatches + ')', cls:'diff-badge-info', aria:'Preturi diferite: ' + order.price_check.mismatches});
|
||||
if (addr && addr.livrare_roa && !addrMatch(addr.livrare_gomag, addr.livrare_roa)) badges.push({label:'Adr. livr.', cls:'diff-badge-addr', aria:'Adresa livrare diferita'});
|
||||
if (addr && addr.facturare_roa && !addrMatch(addr.facturare_gomag, addr.facturare_roa)) badges.push({label:'Adr. fact.', cls:'diff-badge-addr', aria:'Adresa facturare diferita'});
|
||||
if (order.price_check && order.price_check.mismatches > 0) badges.push({label:'Preturi (' + order.price_check.mismatches + ')', cls:'diff-badge-price', aria:'Preturi diferite: ' + order.price_check.mismatches});
|
||||
let insertAfter = orderNumEl;
|
||||
badges.forEach(b => {
|
||||
const el = document.createElement('span');
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.css" rel="stylesheet">
|
||||
{% set rp = request.scope.get('root_path', '') %}
|
||||
<link href="{{ rp }}/static/css/style.css?v=35" rel="stylesheet">
|
||||
<link href="{{ rp }}/static/css/style.css?v=38" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Navbar (hidden on mobile via CSS) -->
|
||||
@@ -161,7 +161,7 @@
|
||||
|
||||
<script>window.ROOT_PATH = "{{ rp }}";</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="{{ rp }}/static/js/shared.js?v=28"></script>
|
||||
<script src="{{ rp }}/static/js/shared.js?v=29"></script>
|
||||
<script>
|
||||
// Dark mode toggle
|
||||
function toggleDarkMode() {
|
||||
|
||||
@@ -100,11 +100,10 @@
|
||||
<th class="text-end">Discount</th>
|
||||
<th class="text-end">Total</th>
|
||||
<th style="width:28px" title="Facturat">F</th>
|
||||
<th class="text-center" style="width:30px" title="Preturi ROA">₽</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dashOrdersBody">
|
||||
<tr><td colspan="10" class="text-center text-muted py-3">Se incarca...</td></tr>
|
||||
<tr><td colspan="9" class="text-center text-muted py-3">Se incarca...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -115,5 +114,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.scope.get('root_path', '') }}/static/js/dashboard.js?v=39"></script>
|
||||
<script src="{{ request.scope.get('root_path', '') }}/static/js/dashboard.js?v=40"></script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user