← back to AbramsOS

views/biometrics.ejs

97 lines

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

<section class="page-head">
  <div>
    <h1>Biometrics &amp; ID</h1>
    <p class="subtle">Each family member's physical &amp; emergency profile — a child-ID / medical record for when it matters. Private to you.</p>
  </div>
</section>

<section class="purchase-grid" style="grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));">
  <% profiles.forEach(p => { const d = p.derived; %>
    <article class="purchase glass" data-person="<%= p.person_id %>">
      <header>
        <h3><%= p.full_name %></h3>
        <% if (d.isChild) { %><span class="chip" style="background:rgba(83,155,245,.2)">child<%= d.age!=null?(' · '+d.age):'' %></span>
        <% } else if (d.age!=null) { %><span class="chip" style="background:rgba(128,128,128,.15)"><%= d.age %> yrs</span><% } %>
      </header>

      <div class="amount" style="font-size:1.1rem">
        <% if (d.bmi) { %>BMI <%= d.bmi %><% if (d.bmiCategory) { %> <span class="subtle">(<%= d.bmiCategory %>)</span><% } else if (d.isChild) { %> <span class="subtle">— <a href="<%= d.cdcPercentileUrl %>" target="_blank" rel="noopener noreferrer">CDC percentile ↗</a></span><% } %>
        <% } else { %><span class="subtle">no height/weight yet</span><% } %>
      </div>

      <dl class="meta">
        <% if (p.height_in) { %><dt>Height</dt><dd><%= Math.floor(p.height_in/12) %>'<%= Math.round(p.height_in%12) %>" (<%= p.height_in %> in)</dd><% } %>
        <% if (p.weight_lb) { %><dt>Weight</dt><dd><%= p.weight_lb %> lb</dd><% } %>
        <% if (p.blood_type) { %><dt>Blood type</dt><dd><%= p.blood_type %></dd><% } %>
        <% if (p.eye_color || p.hair_color) { %><dt>Eyes / hair</dt><dd><%= p.eye_color||'—' %> / <%= p.hair_color||'—' %></dd><% } %>
        <% if (p.allergies) { %><dt>Allergies</dt><dd style="color:#e5534b"><%= p.allergies %></dd><% } %>
        <% if (p.conditions) { %><dt>Conditions</dt><dd><%= p.conditions %></dd><% } %>
        <% if (p.distinguishing_marks) { %><dt>Marks</dt><dd><%= p.distinguishing_marks %></dd><% } %>
        <% if (p.emergency_contact) { %><dt>Emergency</dt><dd><%= p.emergency_contact %></dd><% } %>
        <dt>Prints on file</dt><dd><%= p.prints_on_file ? ('Yes' + (p.prints_location?(' · '+p.prints_location):'')) : 'No' %></dd>
      </dl>

      <footer class="card-foot">
        <span class="subtle" style="font-size:.72rem">Sensitive — informational, not medical advice.</span>
        <button type="button" class="btn tiny" data-edit="<%= p.person_id %>">Edit</button>
      </footer>

      <form class="bioForm add-form" data-form="<%= p.person_id %>" hidden style="margin-top:.6rem">
        <div class="row">
          <label>Date of birth<input name="date_of_birth" type="date" value="<%= p.date_of_birth ? new Date(p.date_of_birth).toISOString().slice(0,10) : '' %>"></label>
          <label>Sex<select name="sex"><option value="">—</option><option value="m" <%= p.sex==='m'?'selected':'' %>>M</option><option value="f" <%= p.sex==='f'?'selected':'' %>>F</option><option value="x" <%= p.sex==='x'?'selected':'' %>>X</option></select></label>
        </div>
        <div class="row">
          <label>Height (in)<input name="height_in" type="number" step="0.1" value="<%= p.height_in||'' %>"></label>
          <label>Weight (lb)<input name="weight_lb" type="number" step="0.1" value="<%= p.weight_lb||'' %>"></label>
          <label>Blood type<input name="blood_type" value="<%= p.blood_type||'' %>" placeholder="O+"></label>
        </div>
        <div class="row">
          <label>Eye color<input name="eye_color" value="<%= p.eye_color||'' %>"></label>
          <label>Hair color<input name="hair_color" value="<%= p.hair_color||'' %>"></label>
        </div>
        <div class="row">
          <label class="grow">Allergies<input name="allergies" value="<%= p.allergies||'' %>"></label>
          <label class="grow">Conditions<input name="conditions" value="<%= p.conditions||'' %>"></label>
        </div>
        <div class="row">
          <label class="grow">Distinguishing marks<input name="distinguishing_marks" value="<%= p.distinguishing_marks||'' %>"></label>
        </div>
        <div class="row">
          <label class="grow">Emergency contact<input name="emergency_contact" value="<%= p.emergency_contact||'' %>"></label>
        </div>
        <div class="row">
          <label>Prints on file<input name="prints_on_file" type="checkbox" <%= p.prints_on_file?'checked':'' %>></label>
          <label class="grow">Prints location<input name="prints_location" value="<%= p.prints_location||'' %>" placeholder="home safe / pediatrician"></label>
          <button type="submit" class="btn primary">Save</button>
        </div>
      </form>
    </article>
  <% }) %>
</section>

<% if (!profiles.length) { %>
  <section class="empty glass"><p>Add family members in <a href="/household">Household</a> first, then fill in their biometric profiles here.</p></section>
<% } %>

<script>
  window.__csrf = '<%= csrfToken %>';
  document.querySelectorAll('[data-edit]').forEach(b => b.addEventListener('click', () => {
    const f = document.querySelector('[data-form="'+b.dataset.edit+'"]'); f.hidden = !f.hidden;
  }));
  document.querySelectorAll('.bioForm').forEach(form => form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const pid = form.dataset.form;
    const fd = {}; new FormData(form).forEach((v,k)=>fd[k]=v);
    fd.prints_on_file = form.querySelector('[name=prints_on_file]').checked;
    fd._csrf = window.__csrf;
    const r = await fetch('/api/biometrics/'+pid, {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(fd)});
    const j = await r.json();
    if (j.ok) location.reload(); else alert(j.error||'error');
  }));
</script>

<%- include('partials/footer', {}) %>