patient.html
⎇
Raw
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