{% extends "layout.html.tera" %}
{% block title %}Notes — {{ record.label }} — {{ app_display }}{% endblock title %}
{% block content %}
<nav class="breadcrumb-nav" aria-label="Breadcrumb">
<ol class="breadcrumb-list" aria-label="Breadcrumb trail">
<li class="breadcrumb-list-item"><a href="/">Home</a></li>
<li class="breadcrumb-list-item"><a href="/{{ entity_plural }}">{{ entity_plural | capitalize }}</a></li>
<li class="breadcrumb-list-item"><a href="/{{ entity_plural }}/{{ record.id }}">{{ record.label }}</a></li>
<li class="breadcrumb-list-item" aria-current="page">Notes</li>
</ol>
</nav>
<section aria-label="Notes thread"
x-data='{
filter: "all",
visible(item) {
return this.filter === "all" || item.role === this.filter;
},
draft: "",
draftRole: "clinical",
submitting: false,
submit($el) {
if (!this.draft.trim()) return;
// In production this would HTMX-post and the server would
// return the new <li class="chat-list-item"> for hx-swap.
this.submitting = true;
setTimeout(function () {
$el.dispatchEvent(new Event("noteAdded", { bubbles: true }));
}, 200);
}
}'
@note-added.stop="submitting = false; draft = ''; lily.toast('Note added', 'success')">
<h2>Notes — {{ record.label }}</h2>
<div class="information-callout" aria-label="Notes explainer">
<p>
Free-text annotations attached to this {{ entity_singular }}. Notes are
role-tagged (clinical / admin / system) so a clinician's note about a
penicillin allergy is visually distinct from an admin note about a
billing fix. Every note is in the audit log; deletion is soft.
</p>
</div>
<div class="action-bar" role="toolbar" aria-label="Notes filter">
<span class="action-bar-count">{{ notes | length }} note{% if notes | length != 1 %}s{% endif %}</span>
<button class="button"
type="button"
aria-label="Show all notes"
x-bind:aria-pressed="filter === 'all' ? 'true' : 'false'"
@click="filter = 'all'">All</button>
<button class="button"
type="button"
aria-label="Show clinical notes only"
x-bind:aria-pressed="filter === 'clinical' ? 'true' : 'false'"
@click="filter = 'clinical'">Clinical</button>
<button class="button"
type="button"
aria-label="Show admin notes only"
x-bind:aria-pressed="filter === 'admin' ? 'true' : 'false'"
@click="filter = 'admin'">Admin</button>
<button class="button"
type="button"
aria-label="Show system notes only"
x-bind:aria-pressed="filter === 'system' ? 'true' : 'false'"
@click="filter = 'system'">System</button>
</div>
<nav class="chat-nav" aria-label="Notes thread, newest first">
<ol class="chat-list" aria-label="Notes">
{% for note in notes %}
<li class="chat-list-item"
x-bind:aria-label="'Note from ' + '{{ note.author_name }}' + ', role {{ note.role }}'"
x-show='visible({ role: "{{ note.role }}" })'>
<div class="avatar"
aria-label="{{ note.author_name }}'s avatar"
style="background-color: {{ note.avatar_bg }};">
<div class="avatar-text" aria-hidden="true">{{ note.initials }}</div>
</div>
<article class="chat-message"
data-author-role="{{ note.role }}"
aria-label="Note by {{ note.author_name }} at {{ note.at }}">
<header>
<strong>{{ note.author_name }}</strong>
{% if note.role == "clinical" %}
<span class="badge" data-type="success" aria-label="Clinical role">Clinical</span>
{% elif note.role == "admin" %}
<span class="badge" data-type="warning" aria-label="Admin role">Admin</span>
{% elif note.role == "system" %}
<span class="badge" data-type="info" aria-label="System role">System</span>
{% endif %}
·
<time datetime="{{ note.at }}">{{ note.at }}</time>
{% if note.edited %}
· <span class="hint" aria-label="Edited">edited</span>
{% endif %}
</header>
<p>{{ note.body | safe }}</p>
{% if note.tags and note.tags | length > 0 %}
<div class="tag-group" aria-label="Note tags">
{% for t in note.tags %}
<span class="tag" aria-label="Tag: {{ t }}">{{ t }}</span>
{% endfor %}
</div>
{% endif %}
</article>
</li>
{% endfor %}
<li x-show="filter !== 'all'">
<span class="hint" aria-label="Filter active">
Filtered to <strong x-text="filter"></strong> only. Click "All" to see every note.
</span>
</li>
</ol>
</nav>
<h3>Add a note</h3>
<form class="form"
aria-label="Add note form"
hx-post="/api/{{ entity_plural }}/{{ record.id }}/notes"
hx-target=".chat-list"
hx-swap="beforeend"
@submit.prevent="submit($el); $el.dispatchEvent(new Event('note-added', { bubbles: true }))">
<div class="field" aria-label="Role field">
<label class="label" for="note-role">Role</label>
<select class="select"
id="note-role"
name="role"
aria-label="Note role"
x-model="draftRole">
<option class="option" value="clinical">Clinical</option>
<option class="option" value="admin">Admin</option>
</select>
</div>
<div class="field" aria-label="Body field" data-required>
<label class="label" for="note-body">Body</label>
<span class="hint" id="note-body-hint">Plain text. Notes are non-editable after 24 hours.</span>
<textarea class="text-area-input"
id="note-body"
name="body"
rows="3"
aria-label="Note body"
aria-describedby="note-body-hint"
x-model="draft"
required></textarea>
</div>
<div class="action-bar" role="toolbar" aria-label="Add-note actions">
<button class="button"
type="submit"
aria-label="Post note"
x-bind:disabled="submitting || !draft.trim()">
<span x-show="!submitting">Post note</span>
<span x-show="submitting">Posting…</span>
</button>
<button class="button"
type="button"
aria-label="Clear draft"
@click="draft = ''">Clear</button>
</div>
</form>
</section>
{% endblock content %}