/** * controllers/calendar.controller.js */ const db = require("../db"); const Holidays = require("date-holidays"); // ── Hilfsfunktionen ────────────────────────────────────────────────────────── function pad(n) { return String(n).padStart(2, "0"); } function toISO(d) { return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; } // ── Hauptseite (EJS rendern) ───────────────────────────────────────────────── exports.index = async (req, res) => { try { // Alle aktiven Ärzte (users mit role = 'arzt') const [doctors] = await db.promise().query(` SELECT id, username AS name, doctor_color AS color FROM users WHERE role = 'arzt' AND active = 1 ORDER BY username `); const today = toISO(new Date()); return res.render("calendar/index", { active: "calendar", doctors, today, user: req.session.user, }); } catch (err) { console.error("❌ calendar.index:", err.message); return res.status(500).send("Interner Serverfehler"); } }; // ── API: Termine eines Tages ───────────────────────────────────────────────── exports.getAppointments = async (req, res) => { try { const { date } = req.params; // YYYY-MM-DD const [rows] = await db.promise().query( `SELECT a.id, a.doctor_id, a.date, TIME_FORMAT(a.time, '%H:%i') AS time, a.duration, a.patient_name, a.notes, a.status, u.username AS doctor_name, u.doctor_color AS doctor_color FROM appointments a JOIN users u ON u.id = a.doctor_id WHERE a.date = ? ORDER BY a.time, u.username`, [date] ); return res.json(rows); } catch (err) { console.error("❌ getAppointments:", err.message); return res.status(500).json({ error: "Datenbankfehler" }); } }; // ── API: Termin erstellen ──────────────────────────────────────────────────── exports.createAppointment = async (req, res) => { try { const { doctor_id, date, time, duration = 15, patient_name, notes = "" } = req.body; if (!doctor_id || !date || !time || !patient_name?.trim()) { return res .status(400) .json({ error: "doctor_id, date, time und patient_name sind Pflicht" }); } // Kollisionsprüfung const [conflict] = await db.promise().query( `SELECT id FROM appointments WHERE doctor_id = ? AND date = ? AND time = ? AND status != 'cancelled'`, [doctor_id, date, time] ); if (conflict.length > 0) { return res.status(409).json({ error: "Dieser Zeitslot ist bereits belegt" }); } const [result] = await db.promise().query( `INSERT INTO appointments (doctor_id, date, time, duration, patient_name, notes) VALUES (?, ?, ?, ?, ?, ?)`, [doctor_id, date, time, duration, patient_name.trim(), notes] ); return res.status(201).json({ id: result.insertId }); } catch (err) { console.error("❌ createAppointment:", err.message); return res.status(500).json({ error: "Datenbankfehler" }); } }; // ── API: Termin aktualisieren ──────────────────────────────────────────────── exports.updateAppointment = async (req, res) => { try { const { id } = req.params; const { doctor_id, date, time, duration, patient_name, notes, status } = req.body; await db.promise().query( `UPDATE appointments SET doctor_id = ?, date = ?, time = ?, duration = ?, patient_name = ?, notes = ?, status = ? WHERE id = ?`, [doctor_id, date, time, duration, patient_name, notes, status, id] ); return res.json({ success: true }); } catch (err) { console.error("❌ updateAppointment:", err.message); return res.status(500).json({ error: "Datenbankfehler" }); } }; // ── API: Termin löschen ────────────────────────────────────────────────────── exports.deleteAppointment = async (req, res) => { try { await db.promise().query("DELETE FROM appointments WHERE id = ?", [ req.params.id, ]); return res.json({ success: true }); } catch (err) { console.error("❌ deleteAppointment:", err.message); return res.status(500).json({ error: "Datenbankfehler" }); } }; // ── API: Status ändern ─────────────────────────────────────────────────────── exports.patchStatus = async (req, res) => { try { const allowed = ["scheduled", "completed", "cancelled"]; const { status } = req.body; if (!allowed.includes(status)) { return res.status(400).json({ error: "Ungültiger Status" }); } await db .promise() .query("UPDATE appointments SET status = ? WHERE id = ?", [ status, req.params.id, ]); return res.json({ success: true }); } catch (err) { console.error("❌ patchStatus:", err.message); return res.status(500).json({ error: "Datenbankfehler" }); } }; // ── API: Feiertage eines Jahres ────────────────────────────────────────────── exports.getHolidays = (req, res) => { try { const year = parseInt(req.params.year); const country = (req.query.country || process.env.HOLIDAY_COUNTRY || "DE").toUpperCase(); const state = (req.query.state || process.env.HOLIDAY_STATE || "").toUpperCase(); if (isNaN(year) || year < 1900 || year > 2100) { return res.status(400).json({ error: "Ungültiges Jahr" }); } const hd = new Holidays(); const inited = state ? hd.init(country, state) : hd.init(country); if (!inited) { return res.status(400).json({ error: `Unbekanntes Land/Bundesland: ${country}/${state}` }); } const holidays = hd .getHolidays(year) .filter((h) => ["public", "bank"].includes(h.type)) .map((h) => ({ date: h.date.substring(0, 10), name: h.name, type: h.type, })); return res.json({ country, state, year, holidays }); } catch (err) { console.error("❌ getHolidays:", err.message); return res.status(500).json({ error: "Fehler beim Laden der Feiertage" }); } }; // ── API: Patienten-Suche (Autocomplete) ───────────────────────────────────── exports.searchPatients = async (req, res) => { try { const q = (req.query.q || "").trim(); if (q.length < 1) return res.json([]); const like = `%${q}%`; const [rows] = await db.promise().query( `SELECT id, firstname, lastname, birthdate, CONCAT(firstname, ' ', lastname) AS full_name FROM patients WHERE active = 1 AND ( firstname LIKE ? OR lastname LIKE ? OR CONCAT(firstname, ' ', lastname) LIKE ? ) ORDER BY lastname, firstname LIMIT 10`, [like, like, like] ); return res.json(rows); } catch (err) { console.error("❌ searchPatients:", err.message); return res.status(500).json({ error: "Datenbankfehler" }); } }; // ── API: Arzt-Farbe speichern ──────────────────────────────────────────────── exports.updateDoctorColor = async (req, res) => { try { const { color } = req.body; await db .promise() .query("UPDATE users SET doctor_color = ? WHERE id = ?", [ color, req.params.id, ]); return res.json({ success: true }); } catch (err) { console.error("❌ updateDoctorColor:", err.message); return res.status(500).json({ error: "Datenbankfehler" }); } };