patient.html
| 1 | {{define "title"}}{{.P.Name}}{{end}} |
| 2 | {{define "content"}} |
| 3 | {{$p := .P}} |
| 4 | <nav aria-label="breadcrumb"><ul><li><a href="/patienten">Patienten</a></li><li>{{$p.Name}}</li></ul></nav> |
| 5 | <header class="patient-head"> |
| 6 | <h1>{{$p.Name}}{{if $p.Archived}} <small class="muted">(archiviert)</small>{{end}}</h1> |
| 7 | <p class="muted">{{with $p.Dob}}geb. {{.}}{{end}}{{with $p.Phone}} · {{.}}{{end}}{{with $p.Email}} · {{.}}{{if not $p.EmailConsent}} (keine E-Mail-Einwilligung){{end}}{{end}}</p> |
| 8 | </header> |
| 9 | |
| 10 | <article id="befunde"> |
| 11 | <h3>Befunde</h3> |
| 12 | {{if .Befunde}} |
| 13 | <div class="tablewrap"> |
| 14 | <table class="list"> |
| 15 | <thead><tr><th>Datum</th><th>Befund</th><th class="hide-sm">Diagnose</th><th></th></tr></thead> |
| 16 | <tbody> |
| 17 | {{range .Befunde}} |
| 18 | <tr><td>{{de .Date}}</td><td><a href="/befund/{{.ID}}"><strong>{{.Title}}</strong></a></td><td class="muted hide-sm">{{diag .Data}}</td> |
| 19 | <td class="nowrap"><a href="/befund/{{.ID}}/druck" target="_blank">Druck</a></td></tr> |
| 20 | {{end}} |
| 21 | </tbody> |
| 22 | </table> |
| 23 | </div> |
| 24 | {{else}}<p class="muted">Noch kein Befund.</p>{{end}} |
| 25 | <div class="actions"> |
| 26 | <form method="post" action="/patient/{{$p.ID}}/befund" class="inline"><button type="submit">+ Erstbefund (leer)</button></form> |
| 27 | {{with .Befunde}}{{$last := index . 0}} |
| 28 | <form method="post" action="/patient/{{$p.ID}}/befund" class="inline"> |
| 29 | <input type="hidden" name="kopie" value="{{$last.ID}}"> |
| 30 | <button type="submit" class="secondary" title="Übernimmt alle Angaben aus dem letzten Befund – nur Veränderungen neu erfassen">+ Wiederbefund (Kopie vom {{de $last.Date}})</button> |
| 31 | </form> |
| 32 | {{if gt (len .) 1}}<a role="button" class="outline" href="/patient/{{$p.ID}}/vergleich">Befunde vergleichen</a>{{end}} |
| 33 | {{end}} |
| 34 | </div> |
| 35 | </article> |
| 36 | |
| 37 | {{if gt (len .Trend) 1}} |
| 38 | <article id="trend"> |
| 39 | <h3>Verlauf der Kernwerte</h3> |
| 40 | <div class="tablewrap"> |
| 41 | <table class="list"> |
| 42 | <thead><tr><th>Datum</th><th class="hide-sm">Befund</th><th>NRS jetzt</th><th>NRS max</th><th>PSFS Ø</th></tr></thead> |
| 43 | <tbody>{{range .Trend}}<tr><td>{{de .Date}}</td><td class="hide-sm"><a href="/befund/{{.ID}}">{{.Title}}</a></td><td>{{.Now}}</td><td>{{.Worst}}</td><td>{{.PSFS}}</td></tr>{{end}}</tbody> |
| 44 | </table> |
| 45 | </div> |
| 46 | <small class="muted">Orientierung: Änderungen um etwa 2 Punkte auf NRS bzw. PSFS gelten in Studien häufig als klinisch relevant. Details im Vergleich.</small> |
| 47 | </article> |
| 48 | {{end}} |
| 49 | |
| 50 | {{with .Error}}<p class="error" role="alert">{{.}}</p>{{end}} |
| 51 | <article id="termine"> |
| 52 | <h3>Termine</h3> |
| 53 | {{with .Appt.Upcoming}} |
| 54 | <div class="appts"> |
| 55 | {{range .}} |
| 56 | <div class="appt{{if .Cancelled}} cancelled{{end}}"> |
| 57 | <span class="appt-time">{{day .Start}} · {{hm .Start}}–{{hm .End}}</span> |
| 58 | <span>{{.Title}}{{with .TherapistName}} · {{.}}{{end}}{{if .Cancelled}} · <strong>abgesagt</strong>{{end}}</span> |
| 59 | <span class="appt-actions"> |
| 60 | <a href="/termin/{{.ID}}" class="small-link">Bearbeiten</a> |
| 61 | <form method="post" action="/termin/{{.ID}}/absagen" class="inline"><button type="submit" class="link small-link">{{if .Cancelled}}Wieder zusagen{{else}}Absagen{{end}}</button></form> |
| 62 | </span> |
| 63 | </div> |
| 64 | {{end}} |
| 65 | </div> |
| 66 | {{else}}<p class="muted">Keine anstehenden Termine.</p>{{end}} |
| 67 | {{with .Appt.Past}}<details><summary>Vergangene Termine ({{len .}})</summary> |
| 68 | <ul class="past-appts">{{range .}}<li>{{day .Start}} {{hm .Start}} · {{.Title}}{{with .TherapistName}} · {{.}}{{end}}{{if .Cancelled}} · abgesagt{{end}}</li>{{end}}</ul> |
| 69 | </details>{{end}} |
| 70 | |
| 71 | <details> |
| 72 | <summary>+ Termin / Terminserie anlegen</summary> |
| 73 | <form method="post" action="/termine"> |
| 74 | <input type="hidden" name="patient" value="{{$p.ID}}"><input type="hidden" name="back" value="patient"> |
| 75 | <div class="appt-fields"> |
| 76 | <label>Datum <input type="date" name="date" value="{{.Today}}" required></label> |
| 77 | <label>Uhrzeit <input type="time" name="time" value="08:00" step="300" required></label> |
| 78 | <label>Dauer (Min.) <input type="number" name="duration" value="30" min="5" max="480" step="5"></label> |
| 79 | <label>Behandler |
| 80 | <select name="therapist"><option value="0">—</option>{{range .Appt.Therapists}}<option value="{{.ID}}">{{.Name}}</option>{{end}}</select> |
| 81 | </label> |
| 82 | <label>Art <input name="title" value="Physiotherapie"></label> |
| 83 | <label>Ort <input name="location" placeholder="{{if .Appt.Address}}{{.Appt.Address}}{{else}}Praxis / Hausbesuch{{end}}"></label> |
| 84 | <label class="wide">Hinweis für den Patienten <input name="note" placeholder="z. B. Handtuch mitbringen"></label> |
| 85 | <label>Wiederholen <input type="number" name="repeat" value="1" min="1" max="40"></label> |
| 86 | <label>alle … Tage <input type="number" name="every" value="7" min="1" max="60"></label> |
| 87 | </div> |
| 88 | <button type="submit">Anlegen</button> |
| 89 | {{if not .Appt.Therapists}}<small class="muted">Behandler werden unter <a href="/termine#behandler">Termine</a> eingetragen.</small>{{end}} |
| 90 | </form> |
| 91 | </details> |
| 92 | |
| 93 | <div class="cal-share"> |
| 94 | <img src="/patient/{{$p.ID}}/kalender-qr.svg" alt="QR-Code für das Kalender-Abo" class="qr"> |
| 95 | <div> |
| 96 | <strong>Termine im Kalender des Patienten</strong> |
| 97 | <p class="muted">QR-Code scannen lassen oder den Link senden. Neue Termine, Änderungen und Absagen kommen automatisch an. Der Kalender enthält nur Zeiten, Behandler, Ort und Hinweis – keine Diagnosen.</p> |
| 98 | {{if not .Appt.CalPublic}}<p class="error">PHYSIOBASE_PUBLIC_URL ist nicht gesetzt: Der Link funktioniert nur im Praxisnetz.</p>{{end}} |
| 99 | <p><a href="{{.Appt.Webcal}}">Kalender abonnieren (webcal)</a> · <a href="{{.Appt.CalURL}}">.ics-Datei</a></p> |
| 100 | <input readonly value="{{.Appt.CalURL}}" aria-label="Kalender-Link" class="mono"> |
| 101 | <div class="actions"> |
| 102 | <a role="button" class="secondary" href="/patient/{{$p.ID}}/termine/druck" target="_blank">Terminliste drucken</a> |
| 103 | <form method="post" action="/patient/{{$p.ID}}/kalender-link" class="inline"><button type="submit" class="outline secondary" title="Der alte Link funktioniert danach nicht mehr">Link erneuern</button></form> |
| 104 | </div> |
| 105 | </div> |
| 106 | </div> |
| 107 | </article> |
| 108 | |
| 109 | <article id="verlauf"> |
| 110 | <h3>Behandlungsverlauf</h3> |
| 111 | <form method="post" action="/patient/{{$p.ID}}/verlauf" class="session-form"> |
| 112 | <input type="date" name="date" value="{{.Today}}" aria-label="Datum"> |
| 113 | <input name="goal" placeholder="Ziel + Maßnahme(n)" aria-label="Ziel und Maßnahmen"> |
| 114 | <textarea name="note" rows="2" placeholder="Reaktion, Re-Test, Bemerkung" aria-label="Bemerkung"></textarea> |
| 115 | <button type="submit">+ Eintrag</button> |
| 116 | </form> |
| 117 | {{range .Sessions}} |
| 118 | <div class="session"> |
| 119 | <div class="session-head"><strong>{{de .Date}}</strong> {{.Goal}} |
| 120 | <span class="session-actions"> |
| 121 | <form method="post" action="/verlauf/{{.ID}}/zusammenfassung" class="inline"><button type="submit" class="link small-link" title="Zusammenfassung dieser Behandlung für den Patienten">📝 Für Patient</button></form> |
| 122 | <form method="post" action="/verlauf/{{.ID}}/loeschen" class="inline"><button type="submit" class="link" title="Löschen">✕</button></form> |
| 123 | </span> |
| 124 | </div> |
| 125 | {{with .Note}}<div class="session-note">{{.}}</div>{{end}} |
| 126 | </div> |
| 127 | {{else}}<p class="muted">Noch keine Behandlungen dokumentiert.</p>{{end}} |
| 128 | </article> |
| 129 | |
| 130 | <article id="zusammenfassungen"> |
| 131 | <h3>Zusammenfassungen für den Patienten</h3> |
| 132 | {{if .Summaries}} |
| 133 | <ul class="summaries">{{range .Summaries}} |
| 134 | <li><a href="/zusammenfassung/{{.ID}}"><strong>{{.Title}}</strong></a> |
| 135 | <small class="muted">{{de .Date}} · {{if eq .Kind "gesamt"}}Gesamt{{else}}Behandlung{{end}}</small> |
| 136 | <a href="/zusammenfassung/{{.ID}}/druck" target="_blank" class="small-link">Druck</a></li> |
| 137 | {{end}}</ul> |
| 138 | {{else}}<p class="muted">Zum Mitgeben: eine Gesamtzusammenfassung (Beschwerden, Ziele, Plan, Übungen, Fortschritt) oder nach jeder Behandlung über „📝 Für Patient“ im Behandlungsverlauf.</p>{{end}} |
| 139 | <form method="post" action="/patient/{{$p.ID}}/zusammenfassung" class="inline"><button type="submit" class="secondary">+ Gesamtzusammenfassung</button></form> |
| 140 | </article> |
| 141 | |
| 142 | <article id="dokumente"> |
| 143 | <h3>Dokumente</h3> |
| 144 | {{if .Docs}} |
| 145 | <div class="docs"> |
| 146 | {{range .Docs}} |
| 147 | <figure class="doc"> |
| 148 | <a href="/dokumente/{{.Filename}}" target="_blank" class="doc-preview"> |
| 149 | {{if isImage .Filename}}<img src="/dokumente/{{.Filename}}" alt="{{.Title}}" loading="lazy"> |
| 150 | {{else if isPDF .Filename}}<span class="doc-icon">PDF</span> |
| 151 | {{else}}<span class="doc-icon">{{.Original}}</span>{{end}} |
| 152 | </a> |
| 153 | <figcaption> |
| 154 | <a href="/dokumente/{{.Filename}}" target="_blank"><strong>{{.Title}}</strong></a> |
| 155 | <small class="muted">{{de .Date}}{{with .Category}} · {{.}}{{end}} · {{size .Size}}</small> |
| 156 | <form method="post" action="/dokument/{{.ID}}/loeschen" class="inline"><button type="submit" class="link" title="Dokument löschen">✕</button></form> |
| 157 | </figcaption> |
| 158 | </figure> |
| 159 | {{end}} |
| 160 | </div> |
| 161 | {{else}}<p class="muted">Noch keine Dokumente. Verordnungen, Arztbriefe, Bildgebung oder Fotos hier ablegen.</p>{{end}} |
| 162 | <form method="post" action="/patient/{{$p.ID}}/dokumente" enctype="multipart/form-data" class="doc-form"> |
| 163 | <input type="file" name="files" accept="application/pdf,image/*,.heic,.heif,.tif,.tiff" multiple required aria-label="Dateien (PDF oder Foto)"> |
| 164 | <input name="title" placeholder="Titel (optional, sonst Dateiname)" aria-label="Titel"> |
| 165 | <input name="category" list="dl-doccat" placeholder="Kategorie" aria-label="Kategorie"> |
| 166 | <datalist id="dl-doccat">{{range .DocCategories}}<option value="{{.}}">{{end}}</datalist> |
| 167 | <input type="date" name="date" value="{{.Today}}" aria-label="Datum des Dokuments"> |
| 168 | <button type="submit">Hochladen</button> |
| 169 | </form> |
| 170 | <small class="muted">Mehrere Dateien auf einmal möglich. Auf Handy/Tablet kann direkt fotografiert werden.</small> |
| 171 | </article> |
| 172 | |
| 173 | <div class="grid"> |
| 174 | <article id="wissen"> |
| 175 | <h3>Wissen zum Fall</h3> |
| 176 | {{if .Linked}}<ul class="links">{{range .Linked}} |
| 177 | <li><span class="kind kind-{{.Kind}}">{{kindLabel .Kind}}</span> <a href="/eintrag/{{.ID}}">{{.Title}}</a> |
| 178 | <form method="post" action="/patient/{{$p.ID}}/wissen/{{.ID}}/loeschen" class="inline"><button type="submit" class="link" title="Entfernen">✕</button></form></li> |
| 179 | {{end}}</ul>{{else}}<p class="muted">Krankheitsbild oder Protokoll verknüpfen – dann sind Tests, Übungen und Quellen einen Klick entfernt.</p>{{end}} |
| 180 | {{if .Linkable}} |
| 181 | <form method="post" action="/patient/{{$p.ID}}/wissen" class="row"> |
| 182 | <select name="entry" aria-label="Eintrag" required><option value="">Eintrag wählen …</option> |
| 183 | {{range .Linkable}}<option value="{{.ID}}">{{kindLabel .Kind}}: {{.Title}}</option>{{end}} |
| 184 | </select> |
| 185 | <button type="submit" class="secondary">Verknüpfen</button> |
| 186 | </form> |
| 187 | {{end}} |
| 188 | </article> |
| 189 | |
| 190 | <article id="handouts"> |
| 191 | <h3>Heimprogramme</h3> |
| 192 | {{if .Handouts}}<ul>{{range .Handouts}}<li><a href="/handout/{{.ID}}">{{.Title}}</a> <small class="muted">{{.Count}} Übung(en) · {{date .Updated}}</small></li>{{end}}</ul>{{end}} |
| 193 | <form method="post" action="/patient/{{$p.ID}}/handout" class="row"> |
| 194 | <input name="title" placeholder="Titel, z. B. Woche 1" aria-label="Titel"> |
| 195 | <button type="submit" class="secondary">+ Handout</button> |
| 196 | </form> |
| 197 | </article> |
| 198 | </div> |
| 199 | |
| 200 | <details> |
| 201 | <summary>Stammdaten bearbeiten</summary> |
| 202 | <form method="post" action="/patient/{{$p.ID}}"> |
| 203 | <div class="grid"> |
| 204 | <label>Name <input name="name" value="{{$p.Name}}" required></label> |
| 205 | <label>Geburtsdatum/Alter <input name="dob" value="{{$p.Dob}}"></label> |
| 206 | <label>Telefon <input name="phone" value="{{$p.Phone}}"></label> |
| 207 | </div> |
| 208 | <label>E-Mail <input type="email" name="email" value="{{$p.Email}}" autocomplete="off"></label> |
| 209 | <label class="consent"><input type="checkbox" name="email_consent" value="1"{{if $p.EmailConsent}} checked{{end}}> |
| 210 | Patient ist einverstanden, Zusammenfassungen mit Gesundheitsinformationen per E-Mail zu erhalten |
| 211 | (Einwilligung nach Art. 9 DSGVO, schriftlich dokumentieren – z. B. unter „Dokumente“).</label> |
| 212 | <label>Notizen <textarea name="notes" rows="3">{{$p.Notes}}</textarea></label> |
| 213 | <button type="submit">Speichern</button> |
| 214 | </form> |
| 215 | <div class="actions"> |
| 216 | <form method="post" action="/patient/{{$p.ID}}/archiv" class="inline"> |
| 217 | <input type="hidden" name="archiv" value="{{if $p.Archived}}0{{else}}1{{end}}"> |
| 218 | <button type="submit" class="secondary outline">{{if $p.Archived}}Aus Archiv holen{{else}}Archivieren (Behandlung abgeschlossen){{end}}</button> |
| 219 | </form> |
| 220 | <details class="danger"> |
| 221 | <summary>Patient löschen …</summary> |
| 222 | <form method="post" action="/patient/{{$p.ID}}/loeschen"> |
| 223 | <p>Alle Befunde, Behandlungen und Verknüpfungen von „{{$p.Name}}“ werden endgültig gelöscht.</p> |
| 224 | <button type="submit" class="danger">Endgültig löschen</button> |
| 225 | </form> |
| 226 | </details> |
| 227 | </div> |
| 228 | </details> |
| 229 | {{end}} |
| 230 |