Medikamente übersicht geändert.

This commit is contained in:
Cay 2026-01-11 18:54:58 +00:00
parent 8754c22dc4
commit 961c024252
7 changed files with 352 additions and 146 deletions

90
app.js
View File

@ -1,16 +1,13 @@
const express = require("express");
const session = require("express-session");
const bcrypt = require("bcrypt");
const db = require("./db");
const fs = require("fs");
const path = require("path");
const { requireLogin, requireAdmin} = require("./middleware/auth.middleware");
const adminRoutes = require("./routes/admin.routes");
const dashboardRoutes = require("./routes/dashboard.routes");
const helmet = require("helmet");
const sessionStore = require("./config/session");
require("dotenv").config();
const adminRoutes = require("./routes/admin.routes");
const dashboardRoutes = require("./routes/dashboard.routes");
const patientRoutes = require("./routes/patient.routes");
const medicationRoutes = require("./routes/medication.routes");
const medicationRoutes = require("./routes/medications.routes");
const patientMedicationRoutes = require("./routes/patientMedication.routes");
const waitingRoomRoutes = require("./routes/waitingRoom.routes");
const serviceRoutes = require("./routes/service.routes");
@ -18,10 +15,7 @@ const patientServiceRoutes = require("./routes/patientService.routes");
const invoiceRoutes = require("./routes/invoice.routes");
const patientFileRoutes = require("./routes/patientFile.routes");
const companySettingsRoutes = require("./routes/companySettings.routes");
require("dotenv").config();
const authRoutes = require("./routes/auth.routes");
const app = express();
@ -31,37 +25,31 @@ const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(helmet());
app.use(session({
app.use(
session({
name: "praxis.sid",
secret: process.env.SESSION_SECRET,
store: sessionStore,
resave: false,
saveUninitialized: false
}));
saveUninitialized: false,
})
);
const flashMiddleware = require("./middleware/flash.middleware");
app.use(flashMiddleware);
app.use(express.static("public"));
app.use("/uploads", express.static("uploads"));
app.set("view engine", "ejs");
app.use("/patients", require("./routes/patient.routes"));
app.use("/uploads", express.static("uploads"));
/* ===============================
COMPANYDATA
COMPANY SETTINGS
================================ */
app.use(companySettingsRoutes);
/* ===============================
LOGIN
AUTH / LOGIN
================================ */
const authRoutes = require("./routes/auth.routes");
app.use("/", authRoutes);
/* ===============================
@ -70,7 +58,7 @@ app.use("/", authRoutes);
app.use("/dashboard", dashboardRoutes);
/* ===============================
Mitarbeiter
ADMIN
================================ */
app.use("/admin", adminRoutes);
@ -78,29 +66,33 @@ app.use("/admin", adminRoutes);
PATIENTEN
================================ */
app.use("/patients", patientRoutes);
app.use("/patients", patientMedicationRoutes);
app.use("/patients", patientServiceRoutes);
/* ===============================
MEDIKAMENTE
================================ */
app.use("/medications", medicationRoutes);
console.log("🧪 /medications Router mounted");
/* ===============================
LEISTUNGEN
================================ */
app.use("/services", serviceRoutes);
/* ===============================
DATEIEN
================================ */
app.use("/", patientFileRoutes);
/* ===============================
MEDIKAMENTENÜBERSICHT
WARTEZIMMER
================================ */
app.use("/medications", medicationRoutes);
app.use("/patients", patientMedicationRoutes);
// ===============================
// PATIENT INS WARTEZIMMER
// ===============================
app.use("/", waitingRoomRoutes);
// ===============================
// Leistungen
// ===============================
app.use("/services", serviceRoutes);
app.use("/patients", patientServiceRoutes);
// ===============================
// RECHNUNGEN
// ===============================
/* ===============================
RECHNUNGEN
================================ */
app.use("/", invoiceRoutes);
/* ===============================
@ -110,9 +102,9 @@ app.get("/logout", (req, res) => {
req.session.destroy(() => res.redirect("/"));
});
// ===============================
// ERROR HANDLING (IMMER ZUM SCHLUSS)
// ===============================
/* ===============================
ERROR HANDLING
================================ */
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send("Interner Serverfehler");
@ -121,8 +113,8 @@ app.use((err, req, res, next) => {
/* ===============================
SERVER
================================ */
const PORT = 51777; // garantiert frei
const HOST = "127.0.0.1"; // kein HTTP.sys
const PORT = 51777;
const HOST = "127.0.0.1";
app.listen(PORT, HOST, () => {
console.log(`Server läuft auf http://${HOST}:${PORT}`);

View File

@ -2,25 +2,50 @@ const db = require("../db");
// 📋 LISTE
function listMedications(req, res, next) {
const sql = `
const { q, onlyActive } = req.query;
let sql = `
SELECT
v.id,
m.id AS medication_id,
m.name AS medication,
m.active,
f.name AS form,
v.dosage,
v.package
FROM medication_variants v
JOIN medications m ON v.medication_id = m.id
JOIN medication_forms f ON v.form_id = f.id
ORDER BY m.name, v.dosage
WHERE 1=1
`;
db.query(sql, (err, rows) => {
const params = [];
if (q) {
sql += `
AND (
m.name LIKE ?
OR f.name LIKE ?
OR v.dosage LIKE ?
OR v.package LIKE ?
)
`;
params.push(`%${q}%`, `%${q}%`, `%${q}%`, `%${q}%`);
}
if (onlyActive === "1") {
sql += " AND m.active = 1";
}
sql += " ORDER BY m.name, v.dosage";
db.query(sql, params, (err, rows) => {
if (err) return next(err);
res.render("medications", {
rows,
user: req.session.user
query: { q, onlyActive },
user: req.session.user,
});
});
}
@ -38,7 +63,7 @@ function updateMedication(req, res, next) {
WHERE id = ?
`;
db.query(sql, [dosage, pkg, id], err => {
db.query(sql, [dosage, pkg, id], (err) => {
if (err) return next(err);
req.session.flash = { type: "success", message: "Medikament gespeichert" };
@ -46,8 +71,67 @@ function updateMedication(req, res, next) {
});
}
function toggleMedication(req, res, next) {
const id = req.params.id;
db.query(
"UPDATE medications SET active = NOT active WHERE id = ?",
[id],
(err) => {
if (err) return next(err);
res.redirect("/medications");
}
);
}
function showCreateMedication(req, res) {
const sql = "SELECT id, name FROM medication_forms ORDER BY name";
db.query(sql, (err, forms) => {
if (err) return res.send("DB Fehler");
res.render("medication_create", {
forms,
user: req.session.user,
error: null,
});
});
}
function createMedication(req, res) {
const { name, form_id, dosage, package: pkg } = req.body;
if (!name || !form_id || !dosage) {
return res.send("Pflichtfelder fehlen");
}
db.query(
"INSERT INTO medications (name, active) VALUES (?, 1)",
[name],
(err, result) => {
if (err) return res.send("Fehler Medikament");
const medicationId = result.insertId;
db.query(
`INSERT INTO medication_variants
(medication_id, form_id, dosage, package)
VALUES (?, ?, ?, ?)`,
[medicationId, form_id, dosage, pkg || null],
(err) => {
if (err) return res.send("Fehler Variante");
res.redirect("/medications");
}
);
}
);
}
module.exports = {
listMedications,
updateMedication
updateMedication,
toggleMedication,
showCreateMedication,
createMedication,
};

Binary file not shown.

View File

@ -4,12 +4,26 @@ const router = express.Router();
const { requireLogin } = require("../middleware/auth.middleware");
const {
listMedications,
updateMedication
updateMedication,
toggleMedication,
showCreateMedication,
createMedication,
} = require("../controllers/medication.controller");
console.log("✅ medication.routes geladen");
router.get("/", requireLogin, listMedications);
// 🆕 Formular anzeigen
router.get("/create", requireLogin, showCreateMedication);
// 🆕 Speichern
router.post("/create", requireLogin, createMedication);
// 🆕 UPDATE pro Zeile
router.post("/update/:id", requireLogin, updateMedication);
// 🆕 Toggle
router.post("/toggle/:id", requireLogin, toggleMedication);
module.exports = router;

View File

@ -6,13 +6,16 @@ const {
addPatientService,
deletePatientService,
updatePatientServicePrice,
updatePatientServiceQuantity
updatePatientServiceQuantity,
} = require("../controllers/patientService.controller");
router.post("/:id/services", requireLogin, addPatientService);
router.post("/services/delete/:id", requireAdmin, deletePatientService);
router.post("/services/update-price/:id", requireAdmin, updatePatientServicePrice);
router.post("/patients/services/update-quantity/:id", updatePatientServiceQuantity);
router.post(
"/services/update-price/:id",
requireAdmin,
updatePatientServicePrice
);
router.post("/services/update-quantity/:id", updatePatientServiceQuantity);
module.exports = router;

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<title>Neues Medikament</title>
<link rel="stylesheet" href="/css/bootstrap.min.css" />
</head>
<body class="bg-light">
<div class="container mt-4">
<h4> Neues Medikament</h4>
<% if (error) { %>
<div class="alert alert-danger"><%= error %></div>
<% } %>
<form method="POST" action="/medications/create">
<div class="mb-3">
<label class="form-label">Medikament</label>
<input name="name" class="form-control" required />
</div>
<div class="mb-3">
<label class="form-label">Darreichungsform</label>
<select name="form_id" class="form-control" required>
<% forms.forEach(f => { %>
<option value="<%= f.id %>"><%= f.name %></option>
<% }) %>
</select>
</div>
<div class="mb-3">
<label class="form-label">Dosierung</label>
<input name="dosage" class="form-control" required />
</div>
<div class="mb-3">
<label class="form-label">Packung</label>
<input name="package" class="form-control" />
</div>
<button class="btn btn-success">Speichern</button>
<a href="/medications" class="btn btn-secondary">Abbrechen</a>
</form>
</div>
</body>
</html>

View File

@ -1,87 +1,156 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta charset="UTF-8" />
<title>Medikamentenübersicht</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/bootstrap.min.css" />
<script src="/js/services-lock.js"></script>
<style>
input.form-control { box-shadow: none !important; }
input.form-control:disabled {
background-color: #fff !important;
color: #212529 !important;
opacity: 1 !important;
border: none !important;
box-shadow: none !important;
outline: none !important;
}
input.form-control:disabled:focus {
box-shadow: none !important;
outline: none !important;
}
/* Inaktive Medikamente ROT */
tr.table-secondary > td {
background-color: #f8d7da !important;
}
</style>
</head>
<body class="bg-light">
<nav class="navbar navbar-dark bg-dark position-relative px-3">
<!-- 🟢 ZENTRIERTER TITEL -->
<div class="position-absolute top-50 start-50 translate-middle
d-flex align-items-center gap-2 text-white">
<span style="font-size:1.3rem;">💊</span>
<div class="position-absolute top-50 start-50 translate-middle d-flex align-items-center gap-2 text-white">
<span style="font-size:1.3rem">💊</span>
<span class="fw-semibold fs-5">Medikamentenübersicht</span>
</div>
<!-- 🔵 RECHTS: DASHBOARD -->
<div class="ms-auto">
<a href="/dashboard" class="btn btn-outline-light btn-sm">
⬅️ Dashboard
</a>
<a href="/dashboard" class="btn btn-outline-light btn-sm">⬅️ Dashboard</a>
</div>
</nav>
<div class="container mt-4">
<%- include("partials/flash") %>
<div class="card shadow">
<div class="card-body">
<!-- 🔍 Suche -->
<form method="GET" action="/medications" class="row g-2 mb-3">
<div class="col-md-6">
<input type="text"
name="q"
class="form-control"
placeholder="🔍 Suche nach Medikament, Form, Dosierung"
value="<%= query?.q || '' %>">
</div>
<div class="col-md-3 d-flex gap-2">
<button class="btn btn-primary w-100">Suchen</button>
<a href="/medications" class="btn btn-secondary w-100">Reset</a>
</div>
<div class="col-md-3 d-flex align-items-center">
<div class="form-check">
<input class="form-check-input"
type="checkbox"
name="onlyActive"
value="1"
<%= query?.onlyActive === "1" ? "checked" : "" %>>
<label class="form-check-label">
Nur aktive Medikamente
</label>
</div>
</div>
</form>
<!-- Neu -->
<a href="/medications/create" class="btn btn-success mb-3">
Neues Medikament
</a>
<div class="table-responsive">
<table class="table table-bordered table-hover table-sm align-middle">
<thead class="table-dark">
<tr>
<th>Medikament</th>
<th>Darreichungsform</th>
<th>Dosierung</th>
<th>Packung</th>
<th>Status</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<% rows.forEach(r => { %>
<tr>
<form method="POST"
action="/medications/update/<%= r.id %>">
<td>
<input type="text"
name="medication"
value="<%= r.medication %>"
class="form-control form-control-sm"
required>
</td>
<tr class="<%= r.active ? '' : 'table-secondary' %>">
<td>
<input type="text"
name="form"
value="<%= r.form %>"
class="form-control form-control-sm">
</td>
<!-- UPDATE-FORM -->
<form method="POST" action="/medications/update/<%= r.id %>">
<td><%= r.medication %></td>
<td><%= r.form %></td>
<td>
<input type="text"
name="dosage"
value="<%= r.dosage %>"
class="form-control form-control-sm">
class="form-control form-control-sm"
disabled>
</td>
<td class="d-flex gap-2">
<td>
<input type="text"
name="package"
value="<%= r.package %>"
class="form-control form-control-sm">
<button class="btn btn-sm btn-outline-success"
type="submit">
💾
</button>
class="form-control form-control-sm"
disabled>
</td>
<td class="text-center">
<%= r.active ? "Aktiv" : "Inaktiv" %>
</td>
<td class="d-flex gap-2">
<button class="btn btn-sm btn-outline-success save-btn" disabled>
💾
</button>
<button type="button"
class="btn btn-sm btn-outline-warning lock-btn">
🔓
</button>
</form>
<!-- TOGGLE-FORM (separat!) -->
<form method="POST" action="/medications/toggle/<%= r.medication_id %>">
<button class="btn btn-sm <%= r.active ? 'btn-outline-danger' : 'btn-outline-success' %>">
<%= r.active ? "⛔" : "✅" %>
</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
@ -90,7 +159,6 @@
</div>
</div>
</div>
</body>