← back to AbramsOS

views/recalls.ejs

141 lines

<%- include('partials/header', { title: 'Recalls' }) %>

<section class="page-head">
  <h1>Recall matches</h1>
  <p class="subtle" style="margin:0;color:var(--text-dim);font-size:13px">CPSC recalls auto-matched to your purchases. Confidence ≥ 0.60 lands here for review.</p>
</section>

<% const ndcF = (typeof ndcFlags !== 'undefined') ? ndcFlags : []; %>
<% if (ndcF.length) { %>
<section class="page-head" style="margin-top:18px">
  <div>
    <h1 style="font-size:16px">Your dispensed products vs FDA recalls <span class="subtle" style="font-weight:400">(NDC + lot/date checked)</span></h1>
    <p class="subtle" style="margin:0;color:var(--text-dim);font-size:13px">
      The exact product you were dispensed (matched by <strong>NDC</strong>) appears in an FDA recall — then checked against the
      recall's <strong>lot expiration + distribution dates</strong>. <span style="color:#7fd0a0">Green = your fills predate/postdate the recalled lot (clear)</span>;
      amber = worth confirming your lot #.
    </p>
  </div>
</section>
<section class="glass" style="padding:8px 6px;overflow:auto;border:1px solid rgba(248,113,113,.35)">
  <table class="mr-table">
    <thead><tr><th>Your fills</th><th>Severity</th><th>Medication</th><th>Person</th><th>NDC</th><th>Recall #</th><th class="num">Fills</th><th>Fill dates</th><th>Assessment</th><th>Read about it</th></tr></thead>
    <tbody>
      <% ndcF.forEach(function(x){
           var badge = x.ndc_recall_class==='Class I' ? '#f87171' : x.ndc_recall_class==='Class II' ? '#fbbf24' : '#9aa0aa';
           var poss = x.status==='possible', conf = x.status==='confirm';
           var sBg = poss ? '#f87171' : conf ? '#fbbf24' : '#7fd0a0';
           var sTxt = poss ? '⚠ Possible match' : conf ? '⚠ Check lot' : '✓ Clear'; %>
        <tr>
          <td><span class="sev" style="background:<%= sBg %>22;color:<%= sBg %>;border:1px solid <%= sBg %>66"><%= sTxt %></span></td>
          <td><span class="sev" style="background:<%= badge %>22;color:<%= badge %>;border:1px solid <%= badge %>55"><%= x.ndc_recall_class || '—' %></span></td>
          <td><%= x.drug_name %></td>
          <td><%= x.person %></td>
          <td class="mono"><%= x.ndc %></td>
          <td class="mono"><a href="https://www.accessdata.fda.gov/scripts/ires/index.cfm?Product=<%= encodeURIComponent(x.ndc_recall_number||'') %>" target="_blank" rel="noopener noreferrer"><%= x.ndc_recall_number || '' %></a></td>
          <td class="num"><% if (x.relevant_fills > 0) { %><strong style="color:#f87171"><%= x.relevant_fills %></strong> of <% } %><%= x.fills %></td>
          <td class="mono"><%= x.first_fill ? String(x.first_fill).slice(0,10) : '' %> → <%= x.last_fill ? String(x.last_fill).slice(0,10) : '' %></td>
          <td class="reason"><%= x.assessment || ((x.ndc_recall_reason||'').slice(0,110)) %></td>
          <td class="links"><% (x.links || []).forEach(function(l){ %><a href="<%= l.url %>" target="_blank" rel="noopener noreferrer"><%= l.label %></a><% }) %></td>
        </tr>
      <% }) %>
    </tbody>
  </table>
</section>
<% } %>

<% const medR = (typeof medRecalls !== 'undefined') ? medRecalls : []; %>
<% if (medR.length) { %>
<section class="page-head" style="margin-top:18px">
  <div>
    <h1 style="font-size:16px">💊 Medication recalls <span class="subtle" style="font-weight:400">(FDA openFDA)</span></h1>
    <p class="subtle" style="margin:0;color:var(--text-dim);font-size:13px">
      Your <strong><%= medR.length %></strong> medications cross-referenced against the FDA drug-enforcement database
      (<strong><%= medRecallTotal %></strong> recall records). Matched by <em>drug name</em>, so these are
      <strong>advisory</strong> — “this drug has had recalls,” not necessarily your specific lot.
    </p>
  </div>
</section>
<section class="glass" style="padding:8px 6px;overflow:auto">
  <table class="mr-table">
    <thead><tr><th>Severity</th><th>Medication</th><th>Person</th><th class="num">Recalls</th><th>Latest</th><th>Most-recent reason</th></tr></thead>
    <tbody>
      <% medR.forEach(function(x){
           var badge = x.worst==='Class I' ? '#f87171' : x.worst==='Class II' ? '#fbbf24' : '#9aa0aa'; %>
        <tr>
          <td><span class="sev" style="background:<%= badge %>22;color:<%= badge %>;border:1px solid <%= badge %>55"><%= x.worst || '—' %></span></td>
          <td><%= x.name %><% if (x.generic_name && x.generic_name.toUpperCase() !== (x.name||'').toUpperCase()) { %> <span class="subtle">· <%= x.generic_name %></span><% } %></td>
          <td><%= x.person %></td>
          <td class="num"><a href="<%= x.sample_url || 'https://www.fda.gov/drugs/drug-recalls' %>" target="_blank" rel="noopener noreferrer"><%= x.n %></a></td>
          <td class="mono"><%= x.latest ? String(x.latest).slice(0,10) : '' %></td>
          <td class="reason subtle"><%= (x.sample_reason || '').slice(0,90) %></td>
        </tr>
      <% }) %>
    </tbody>
  </table>
</section>
<style>
  .mr-table{width:100%;border-collapse:collapse;font-size:12.5px}
  .mr-table th,.mr-table td{text-align:left;padding:6px 10px;border-bottom:1px solid rgba(255,255,255,.06);vertical-align:top}
  .mr-table th{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-dim)}
  .mr-table td.num,.mr-table th.num{text-align:right}
  .mr-table td.mono{font-variant-numeric:tabular-nums;white-space:nowrap}
  .mr-table td.reason{max-width:340px}
  .sev{display:inline-block;padding:1px 8px;border-radius:999px;font-size:11px;font-weight:600;white-space:nowrap}
  .mr-table td.links{max-width:220px}
  .mr-table td.links a{display:block;font-size:11.5px;color:var(--accent,#7dd3fc);white-space:normal;margin:1px 0}
</style>
<% } %>

<section class="page-head" style="margin-top:22px"><h1 style="font-size:16px">🛒 Product recalls <span class="subtle" style="font-weight:400">(CPSC · purchases)</span></h1></section>
<section class="glass" style="padding:14px 18px">
  <div style="display:flex;flex-wrap:wrap;gap:8px;align-items:center;font-size:12px">
    <span style="color:var(--text-dim);margin-right:6px">Filter:</span>
    <a href="/recalls" style="padding:3px 10px;border-radius:999px;background:<%= !activeStatus ? 'rgba(125,211,252,0.15)' : 'var(--surface-strong)' %>;color:<%= !activeStatus ? 'var(--accent)' : 'var(--text-dim)' %>;text-decoration:none">all</a>
    <% counts.forEach(c => { %>
      <a href="/recalls?status=<%= encodeURIComponent(c.status) %>" style="padding:3px 10px;border-radius:999px;background:<%= activeStatus === c.status ? 'rgba(125,211,252,0.15)' : 'var(--surface-strong)' %>;color:<%= activeStatus === c.status ? 'var(--accent)' : 'var(--text-dim)' %>;text-decoration:none">
        <%= c.status %> · <%= c.n %>
      </a>
    <% }) %>
  </div>
</section>

<% if (!matches.length) { %>
  <section class="empty glass">
    <p>No recall matches in this view. The CPSC sync runs daily at 03:17; matches will appear here as soon as one of your purchases overlaps.</p>
  </section>
<% } else { %>
  <section class="connector-grid">
    <% matches.forEach(m => { %>
      <article class="connector-card glass" style="display:flex;flex-direction:column;gap:10px">
        <header>
          <span class="name">
            <span class="icon" style="background:<%= m.confidence >= 0.85 ? 'rgba(248,113,113,0.20)' : 'rgba(251,191,36,0.20)' %>;color:<%= m.confidence >= 0.85 ? 'var(--danger)' : 'var(--warn)' %>">!</span>
            <%= m.title || (m.authority + ' ' + m.external_id) %>
          </span>
          <span class="status <%= m.status === 'confirmed' ? 'connected' : m.status === 'dismissed' ? 'not_connected' : 'syncing' %>"><%= m.status %></span>
        </header>
        <% if (m.merchant_name) { %>
          <p class="desc">
            Matched purchase: <strong><%= m.merchant_name %></strong>
            <% if (m.purchase_date) { %> · <%= new Date(m.purchase_date).toLocaleDateString() %><% } %>
            <% if (m.total_amount) { %> · <%= m.currency || 'USD' %> <%= Number(m.total_amount).toFixed(2) %><% } %>
          </p>
        <% } %>
        <% if (m.hazard) { %>
          <p class="desc"><strong>Hazard:</strong> <%= m.hazard %></p>
        <% } %>
        <% if (m.remedy) { %>
          <p class="desc"><strong>Remedy:</strong> <%= m.remedy %></p>
        <% } %>
        <p class="subtle" style="font-size:11px">
          Confidence: <%= Math.round(m.confidence * 100) %>% · matched <%= new Date(m.matched_at).toLocaleString() %>
          <% if (m.url) { %> · <a href="<%= m.url %>" target="_blank" rel="noopener noreferrer" style="margin-left:6px">CPSC notice ↗</a><% } %>
        </p>
      </article>
    <% }) %>
  </section>
<% } %>

<%- include('partials/footer') %>