From 1aef5a5749b8c6801ede097a967a63e1b1d54855 Mon Sep 17 00:00:00 2001 From: Cay Date: Sat, 17 Jan 2026 16:45:38 +0000 Subject: [PATCH] =?UTF-8?q?Dr.=20Titel=20hinzugef=C3=BCgt=20und=20auch=20i?= =?UTF-8?q?n=20den=20NOtizen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/admin.controller.js | 55 ++++- controllers/patient.controller.js | 46 ++-- public/css/style.css | 70 ++++--- routes/admin.routes.js | 2 + services/admin.service.js | 36 +++- views/admin_create_user.ejs | 160 +++++++------- views/admin_users.ejs | 336 ++++++++++++++++-------------- views/dashboard.ejs | 4 - views/partials/flash.ejs | 11 +- views/patient_overview.ejs | 18 +- views/waiting_room.ejs | 67 ------ 11 files changed, 454 insertions(+), 351 deletions(-) delete mode 100644 views/waiting_room.ejs diff --git a/controllers/admin.controller.js b/controllers/admin.controller.js index ad2d5f8..87a6c7e 100644 --- a/controllers/admin.controller.js +++ b/controllers/admin.controller.js @@ -1,6 +1,10 @@ const db = require("../db"); -const { createUser, getAllUsers } = require("../services/admin.service"); const bcrypt = require("bcrypt"); +const { + createUser, + getAllUsers, + updateUserById, +} = require("../services/admin.service"); async function listUsers(req, res) { const { q } = req.query; @@ -34,6 +38,7 @@ function showCreateUser(req, res) { async function postCreateUser(req, res) { let { + title, first_name, last_name, username, @@ -43,6 +48,7 @@ async function postCreateUser(req, res) { arztnummer, } = req.body; + title = title?.trim(); first_name = first_name?.trim(); last_name = last_name?.trim(); username = username?.trim(); @@ -69,11 +75,13 @@ async function postCreateUser(req, res) { // Sicherheit: Mitarbeiter dürfen keine Arzt-Daten haben fachrichtung = null; arztnummer = null; + title = null; } try { await createUser( db, + title, first_name, last_name, username, @@ -265,6 +273,50 @@ async function showInvoiceOverview(req, res) { } } +async function updateUser(req, res) { + const userId = req.params.id; + + let { title, first_name, last_name, username, role } = req.body; + + title = title?.trim() || null; + first_name = first_name?.trim(); + last_name = last_name?.trim(); + username = username?.trim(); + role = role?.trim(); + + try { + // ✅ Fehlende Felder aus DB holen (weil disabled inputs nicht gesendet werden) + const [rows] = await db + .promise() + .query("SELECT * FROM users WHERE id = ?", [userId]); + + if (!rows.length) { + req.session.flash = { type: "danger", message: "User nicht gefunden" }; + return res.redirect("/admin/users"); + } + + const current = rows[0]; + + // ✅ Fallback: wenn Felder nicht gesendet wurden -> alte Werte behalten + const updatedData = { + title: title ?? current.title, + first_name: first_name ?? current.first_name, + last_name: last_name ?? current.last_name, + username: username ?? current.username, + role: role ?? current.role, + }; + + await updateUserById(db, userId, updatedData); + + req.session.flash = { type: "success", message: "User aktualisiert ✅" }; + return res.redirect("/admin/users"); + } catch (err) { + console.error(err); + req.session.flash = { type: "danger", message: "Fehler beim Speichern" }; + return res.redirect("/admin/users"); + } +} + module.exports = { listUsers, showCreateUser, @@ -274,4 +326,5 @@ module.exports = { activateUser, deactivateUser, showInvoiceOverview, + updateUser, }; diff --git a/controllers/patient.controller.js b/controllers/patient.controller.js index 089a21a..ffdfc2b 100644 --- a/controllers/patient.controller.js +++ b/controllers/patient.controller.js @@ -210,13 +210,14 @@ function moveToWaitingRoom(req, res) { ` UPDATE patients SET waiting_room = 1, - discharged = 0 + discharged = 0, + active = 1 WHERE id = ? `, [id], (err) => { if (err) return res.send("Fehler beim Verschieben ins Wartezimmer"); - res.redirect("/patients"); + return res.redirect("/dashboard"); // optional: direkt Dashboard } ); } @@ -245,11 +246,16 @@ function showPatientOverview(req, res) { `; const notesSql = ` - SELECT * - FROM patient_notes - WHERE patient_id = ? - ORDER BY created_at DESC - `; + SELECT + pn.*, + u.title, + u.first_name, + u.last_name + FROM patient_notes pn + LEFT JOIN users u ON pn.created_by = u.id + WHERE pn.patient_id = ? + ORDER BY pn.created_at DESC +`; const medicationVariantsSql = ` SELECT @@ -381,8 +387,9 @@ function addPatientNote(req, res) { } db.query( - "INSERT INTO patient_notes (patient_id, note) VALUES (?, ?)", - [patientId, note], + "INSERT INTO patient_notes (patient_id, created_by, note) VALUES (?, ?, ?)", + [patientId, req.session.user.id, note], + (err) => { if (err) return res.send("Fehler beim Speichern der Notiz"); res.redirect(`/patients/${patientId}/overview`); @@ -407,11 +414,21 @@ function dischargePatient(req, res) { const patientId = req.params.id; db.query( - "UPDATE patients SET discharged = 1 WHERE id = ?", + ` + UPDATE patients + SET discharged = 1, + waiting_room = 0, + active = 0 + WHERE id = ? + `, [patientId], (err) => { - if (err) return res.send("Fehler beim Entlassen des Patienten"); - res.redirect("/waiting-room"); + if (err) { + console.error(err); + return res.send("Fehler beim Entlassen des Patienten"); + } + + return res.redirect("/dashboard"); } ); } @@ -462,7 +479,8 @@ function movePatientToWaitingRoom(req, res) { UPDATE patients SET waiting_room = 1, discharged = 0, - status = 'waiting' + status = 'waiting', + active = 1 WHERE id = ? `, [patientId], @@ -481,7 +499,7 @@ function movePatientToWaitingRoom(req, res) { message: "Patient wurde ins Wartezimmer gesetzt", }; - res.redirect("/waiting-room"); + return res.redirect("/dashboard"); } ); } diff --git a/public/css/style.css b/public/css/style.css index 618583e..5d3a129 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -3,51 +3,51 @@ ========================= */ .waiting-monitor { - border: 3px solid #343a40; - border-radius: 10px; - padding: 15px; - min-height: 45vh; /* untere Hälfte */ - background-color: #f8f9fa; + border: 3px solid #343a40; + border-radius: 10px; + padding: 15px; + min-height: 45vh; /* untere Hälfte */ + background-color: #f8f9fa; } .waiting-grid { - display: grid; - grid-template-columns: repeat(7, 1fr); - grid-template-rows: repeat(3, 1fr); - gap: 10px; - height: 100%; + display: grid; + grid-template-columns: repeat(7, 1fr); + grid-template-rows: repeat(3, 1fr); + gap: 10px; + height: 100%; } .waiting-slot { - border: 2px dashed #adb5bd; - border-radius: 6px; - padding: 10px; - background-color: #ffffff; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; + border: 2px dashed #adb5bd; + border-radius: 6px; + padding: 10px; + background-color: #ffffff; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; } .waiting-slot.occupied { - border-style: solid; - border-color: #198754; - background-color: #e9f7ef; + border-style: solid; + border-color: #198754; + background-color: #e9f7ef; } .waiting-slot .name { - font-weight: bold; + font-weight: bold; } .waiting-slot .birthdate { - font-size: 0.8rem; - color: #6c757d; + font-size: 0.8rem; + color: #6c757d; } .waiting-slot .placeholder { - color: #adb5bd; - font-style: italic; + color: #adb5bd; + font-style: italic; } .waiting-slot.empty { @@ -62,3 +62,19 @@ opacity: 0.4; } +.auto-hide-flash { + animation: flashFadeOut 3s forwards; +} + +@keyframes flashFadeOut { + 0% { + opacity: 1; + } + 70% { + opacity: 1; + } + 100% { + opacity: 0; + visibility: hidden; + } +} diff --git a/routes/admin.routes.js b/routes/admin.routes.js index e868f73..ed2e1e2 100644 --- a/routes/admin.routes.js +++ b/routes/admin.routes.js @@ -10,6 +10,7 @@ const { activateUser, deactivateUser, showInvoiceOverview, + updateUser, } = require("../controllers/admin.controller"); const { requireAdmin } = require("../middleware/auth.middleware"); @@ -23,5 +24,6 @@ router.post("/users/reset-password/:id", requireAdmin, resetUserPassword); router.post("/users/activate/:id", requireAdmin, activateUser); router.post("/users/deactivate/:id", requireAdmin, deactivateUser); router.get("/invoices", requireAdmin, showInvoiceOverview); +router.post("/users/update/:id", requireAdmin, updateUser); module.exports = router; diff --git a/services/admin.service.js b/services/admin.service.js index 5846c1b..77c47da 100644 --- a/services/admin.service.js +++ b/services/admin.service.js @@ -2,6 +2,7 @@ const bcrypt = require("bcrypt"); async function createUser( db, + title, first_name, last_name, username, @@ -15,9 +16,18 @@ async function createUser( return new Promise((resolve, reject) => { db.query( `INSERT INTO users - (first_name, last_name, username, password, role, fachrichtung, arztnummer, active) - VALUES (?, ?, ?, ?, ?, ?, ?, 1)`, - [first_name, last_name, username, hash, role, fachrichtung, arztnummer], + (title, first_name, last_name, username, password, role, fachrichtung, arztnummer, active) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1)`, + [ + title, + first_name, + last_name, + username, + hash, + role, + fachrichtung, + arztnummer, + ], (err) => { if (err) { if (err.code === "ER_DUP_ENTRY") { @@ -57,7 +67,27 @@ async function getAllUsers(db, search = null) { return rows; } +async function updateUserById(db, userId, data) { + const { title, first_name, last_name, username, role } = data; + + const [result] = await db.promise().query( + ` + UPDATE users + SET title = ?, + first_name = ?, + last_name = ?, + username = ?, + role = ? + WHERE id = ? + `, + [title, first_name, last_name, username, role, userId] + ); + + return result; +} + module.exports = { createUser, getAllUsers, + updateUserById, }; diff --git a/views/admin_create_user.ejs b/views/admin_create_user.ejs index 5a3c341..d24a06b 100644 --- a/views/admin_create_user.ejs +++ b/views/admin_create_user.ejs @@ -1,90 +1,108 @@ - - + + Benutzer anlegen - - - + + + +
+ <%- include("partials/flash") %> -
- <%- include("partials/flash") %> - -
+
-

Benutzer anlegen

+

Benutzer anlegen

- <% if (error) { %> -
<%= error %>
- <% } %> + <% if (error) { %> +
<%= error %>
+ <% } %> -
+ + + - - + + - - + + - - + + - - + + - - + + - -
+
-
- - - - + + + diff --git a/views/admin_users.ejs b/views/admin_users.ejs index 44f7e03..68d50b2 100644 --- a/views/admin_users.ejs +++ b/views/admin_users.ejs @@ -1,181 +1,213 @@ - - User Verwaltung - - - - + + User Verwaltung + + + + + + + + + + + + - - -
- <%- include("partials/flash") %> -
-
+ <%- include("partials/flash") %> -

Benutzerübersicht

+
+
-
- -
-
-
- +

Benutzerübersicht

- + + - <% if (query?.q) { %> - - Reset - - <% } %> -
-
-
+ +
+ + + <% if (query?.q) { %> + Reset + <% } %> +
- - - - - - - - - - - +
+
IDNameRolleStatusAktionen
- <% users.forEach(u => { %> - - - - - + + + + + + + + + + + + - + <% users.forEach(u => { %> - - <% if (u.active === 1) { %> - - - - <% } else { %> - - - - <% } %> + - - - - - + + - - - - - + - <% } else { %> - - Du selbst - - <% } %> - - - <% }) %> + - -
<%= u.id %> - <%= u.first_name %> <%= u.last_name %>
- @<%= u.username %> -
- <% if (u.role === "arzt") { %> - Arzt - <% } else { %> - Mitarbeiter - <% } %> - - <% if (u.active === 0) { %> - Inaktiv - <% } else if (u.lock_until && new Date(u.lock_until) > new Date()) { %> - Gesperrt - <% } else { %> - Aktiv - <% } %> -
IDTitelVornameNachnameUsernameRolleStatusAktionen
- <% if (u.id !== currentUser.id) { %> +
<%= u.id %>
+ +
-
+ + + + + + + + + + + + + + + + + + <% if (u.active === 0) { %> + Inaktiv + <% } else if (u.lock_until && new Date(u.lock_until) > new Date()) { %> + Gesperrt + <% } else { %> + Aktiv + <% } %> + + + + + + + + + + + + <% if (u.id !== currentUser.id) { %> +
/<%= u.id %>"> + +
+ <% } else { %> + + Du selbst + + <% } %> + + + + + <% }) %> + + + +
-
- +
diff --git a/views/dashboard.ejs b/views/dashboard.ejs index 6c4a80c..b85e78e 100644 --- a/views/dashboard.ejs +++ b/views/dashboard.ejs @@ -166,10 +166,6 @@ Patienten - - Wartezimmer - - Medikamente diff --git a/views/partials/flash.ejs b/views/partials/flash.ejs index 01e3c42..f4538f4 100644 --- a/views/partials/flash.ejs +++ b/views/partials/flash.ejs @@ -1,6 +1,9 @@ <% if (flash) { %> - + <% } %> diff --git a/views/patient_overview.ejs b/views/patient_overview.ejs index 052c869..1d2c891 100644 --- a/views/patient_overview.ejs +++ b/views/patient_overview.ejs @@ -84,13 +84,13 @@ ✏️ Patient bearbeiten -
- + +
@@ -142,7 +142,9 @@ <% } else { %> <% notes.forEach(n => { %>
- <%= new Date(n.created_at).toLocaleString("de-DE") %> + <%= new Date(n.created_at).toLocaleString("de-DE") %> <% if + (n.first_name && n.last_name) { %> – <%= (n.title ? n.title + + " " : "") %><%= n.first_name %> <%= n.last_name %> <% } %>
<%= n.note %>
diff --git a/views/waiting_room.ejs b/views/waiting_room.ejs deleted file mode 100644 index 1cfcc68..0000000 --- a/views/waiting_room.ejs +++ /dev/null @@ -1,67 +0,0 @@ - - - - - Wartezimmer - - - - - - -
- - <%- include("partials/flash") %> <% if (patients.length === 0) { %> -
Keine Patienten im Wartezimmer
- <% } else { %> - - - - - - - - - - - <% patients.forEach(p => { %> - - - - - - <% }) %> - -
NameGeburtstagAktion
<%= p.firstname %> <%= p.lastname %><%= new Date(p.birthdate).toLocaleDateString("de-DE") %> - <% if (user.role === 'arzt') { %> -
- -
- <% } else { %> - 🔒 Nur Arzt - <% } %> -
- - <% } %> -
- -