worker-service 0.2.0

Worker Service - A worker administration microservice that interoperates with the worker-matcher crate
{% 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(&apos;Note added&apos;, &apos;success&apos;)">
  <h2>Notes &mdash; {{ 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 %}
              &middot;
              <time datetime="{{ note.at }}">{{ note.at }}</time>
              {% if note.edited %}
                &middot; <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&hellip;</span>
      </button>
      <button class="button"
              type="button"
              aria-label="Clear draft"
              @click="draft = ''">Clear</button>
    </div>
  </form>
</section>
{% endblock content %}