[object Object]

← back to Lifestyle Asset Intel

yolo tick #19: condition_facets chips on asset detail comps

9cba52d26ecc50bfd6ddf1e7b6c774821c36060f · 2026-05-13 13:46:14 -0700 · Steve Abrams

Files touched

Diff

commit 9cba52d26ecc50bfd6ddf1e7b6c774821c36060f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed May 13 13:46:14 2026 -0700

    yolo tick #19: condition_facets chips on asset detail comps
---
 public/css/app.css | 20 ++++++++++++++++++++
 views/asset.ejs    | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/public/css/app.css b/public/css/app.css
index 7a14d54..d02a5ca 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -193,6 +193,26 @@ tfoot tr.totals th, tfoot tr.totals td {
 .exotic-badge { background: color-mix(in srgb, var(--accent) 22%, var(--card)); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 50%, var(--line)); }
 .edition-badge { background: color-mix(in srgb, var(--warn) 22%, var(--card)); color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 50%, var(--line)); }
 
+/* condition facet chips on asset detail comp rows (v0.2) */
+.facets-row {
+  display: flex; flex-wrap: wrap; gap: 0.3rem;
+  margin-top: 0.3rem; max-width: 36rem;
+}
+.facet-chip {
+  display: inline-flex; align-items: center; gap: 0.3rem;
+  font-size: 0.72em; line-height: 1;
+  padding: 0.2rem 0.45rem; border-radius: 999px;
+  background: var(--card); color: var(--muted);
+  border: 1px solid var(--line);
+  font-family: var(--mono);
+}
+.facet-chip .facet-k { color: var(--muted); }
+.facet-chip .facet-v { color: var(--fg); font-weight: 600; }
+.facet-chip.facet-true  { background: color-mix(in srgb, var(--good) 14%, var(--card)); border-color: color-mix(in srgb, var(--good) 35%, var(--line)); }
+.facet-chip.facet-true  .facet-v { color: var(--good); }
+.facet-chip.facet-false { background: color-mix(in srgb, var(--bad)  10%, var(--card)); border-color: color-mix(in srgb, var(--bad)  30%, var(--line)); }
+.facet-chip.facet-false .facet-v { color: var(--bad); }
+
 /* MSRP / premium-to-retail block (v0.2) */
 .msrp-block .premium-cell { background: color-mix(in srgb, var(--accent) 14%, var(--card)); border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
 .msrp-block .premium-val { color: var(--accent); font-size: 1.05em; }
diff --git a/views/asset.ejs b/views/asset.ejs
index 5e5bfb6..ccd2832 100644
--- a/views/asset.ejs
+++ b/views/asset.ejs
@@ -103,7 +103,10 @@
               <td><%= fmtDate(c.transacted_at) %></td>
               <td><%= c.source %></td>
               <td>T<%= c.source_tier %></td>
-              <td><%= grade(c.condition_grade) %></td>
+              <td>
+                <%= grade(c.condition_grade) %>
+                <%- facetChips(c.condition_facets) %>
+              </td>
               <td class="num">$<%= money(c.gross) %></td>
               <td class="num">$<%= money(c.net) %></td>
             </tr>
@@ -141,5 +144,32 @@ function pct(v){ if(v==null||v==='') return '—'; var n=parseFloat(v); return i
 function numFmt(v){ if(v==null) return '—'; var n=parseFloat(v); return isFinite(n)?n.toFixed(2):String(v); }
 function fmtDate(v){ if(!v) return '—'; try { return new Date(v).toISOString().slice(0,10); } catch(e){ return String(v); } }
 function grade(g){ const labels=['As Is','Fair','Good','Very Good','Excellent','Pristine','Giftable']; return (g==null) ? '—' : (labels[g] || g); }
+function htmlEscape(s){ return String(s).replace(/[&<>"']/g, function(ch){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[ch]; }); }
+function facetLabel(k){ return k.replace(/_/g,' '); }
+function facetValue(v){
+  if (v === true) return '✓';
+  if (v === false) return '✗';
+  if (v == null) return '—';
+  return String(v);
+}
+function facetChips(f){
+  if (!f || typeof f !== 'object') return '';
+  var keys = Object.keys(f);
+  if (!keys.length) return '';
+  var html = '<div class="facets-row">';
+  for (var i=0;i<keys.length;i++){
+    var k = keys[i], v = f[k];
+    var cls = 'facet-chip';
+    if (v === true) cls += ' facet-true';
+    else if (v === false) cls += ' facet-false';
+    html += '<span class="' + cls + '" title="' + htmlEscape(k) + ': ' + htmlEscape(facetValue(v)) + '">';
+    html += '<span class="facet-k">' + htmlEscape(facetLabel(k)) + '</span>';
+    if (typeof v !== 'boolean') html += '<span class="facet-v">' + htmlEscape(facetValue(v)) + '</span>';
+    else html += '<span class="facet-v">' + htmlEscape(facetValue(v)) + '</span>';
+    html += '</span>';
+  }
+  html += '</div>';
+  return html;
+}
 %>
 <%- include('partials/foot') %>

← ced9794 yolo tick #18: /admin/audit HTML view over recent valuation_  ·  back to Lifestyle Asset Intel  ·  yolo tick #20: sparkline Y-axis min/max labels + descriptive 39ba614 →