← back to AbramsOS
views/biometrics.ejs
97 lines
<%- include('partials/header', { title: 'Biometrics' }) %>
<section class="page-head">
<div>
<h1>Biometrics & ID</h1>
<p class="subtle">Each family member's physical & 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', {}) %>