// src/server.js import 'dotenv/config'; import express from 'express'; import cors from 'cors'; import { connectToDb, getDb } from './db/db.js'; import { ObjectId } from 'mongodb'; // Wichtig für die Arbeit mit MongoDB IDs // Initialisiert Express const app = express(); const PORT = process.env.PORT || 3001; // Middleware konfigurieren - CORS muss vor allen Routen kommen app.use((req, res, next) => { console.log(`📥 ${req.method} ${req.path} from ${req.get('origin') || 'unknown origin'}`); res.header('Access-Control-Allow-Origin', 'http://localhost:5173'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); res.header('Access-Control-Allow-Credentials', 'true'); // Handle preflight requests if (req.method === 'OPTIONS') { console.log('✅ Preflight request handled'); return res.sendStatus(200); } next(); }); app.use(express.json()); // ----------------------------------------------------- // API ROUTEN // ----------------------------------------------------- // 1. READ: Alle Termine abrufen (GET /api/appointments) app.get('/api/appointments', async (req, res) => { try { const db = getDb(); // Finde alle Dokumente in der Collection 'appointments' const appointments = await db.collection('appointments') .find({}) // Optional: Nach Termindatum sortieren (aufsteigend) .sort({ termin: 1 }) .toArray(); // Sende die Daten zurück an das Frontend res.json(appointments); } catch (error) { console.error("Fehler beim Abrufen der Termine:", error); res.status(500).json({ message: "Interner Serverfehler beim Abrufen der Daten." }); } }); // 2. CREATE: Neuen Termin erstellen (POST /api/appointments) app.post('/api/appointments', async (req, res) => { try { const db = getDb(); const appointmentData = req.body; // Die Daten kommen vom React-Formular // Validiere, dass der Termin ein gültiges Datum hat (Optional, aber gut) if (!appointmentData.arztName || !appointmentData.termin) { return res.status(400).json({ message: "Arztname und Termin sind erforderlich." }); } // Mongo generiert die _id automatisch. const result = await db.collection('appointments').insertOne(appointmentData); // Der eingefügte Termin, inklusive der von Mongo erstellten _id const newAppointment = { _id: result.insertedId, ...appointmentData }; // Sende den neu erstellten Termin zurück an das Frontend (Status 201 Created) res.status(201).json(newAppointment); } catch (error) { console.error("Fehler beim Erstellen des Termins:", error); res.status(500).json({ message: "Interner Serverfehler beim Speichern der Daten." }); } }); // 3. UPDATE: Termin aktualisieren (PUT /api/appointments/:id) app.put('/api/appointments/:id', async (req, res) => { try { const db = getDb(); const { id } = req.params; const updatedFields = req.body; // Enthält alle Felder (oder nur die geänderten) // Die _id des Dokuments muss ein gültiges ObjectId-Objekt sein const filter = { _id: new ObjectId(id) }; // Entferne das _id Feld aus den aktualisierten Daten, um Fehler zu vermeiden delete updatedFields._id; // Führe die Aktualisierung durch const result = await db.collection('appointments').updateOne( filter, { $set: updatedFields } ); if (result.matchedCount === 0) { return res.status(404).json({ message: "Termin nicht gefunden." }); } // Hole das aktualisierte Dokument, um es zurückzusenden (optional, aber nützlich) const updatedAppointment = await db.collection('appointments').findOne(filter); res.json(updatedAppointment); } catch (error) { console.error(`Fehler beim Aktualisieren des Termins ${req.params.id}:`, error); // Gib einen 400 Bad Request zurück, falls die ID ungültig ist (z.B. falsches Format) res.status(400).json({ message: "Ungültige ID oder Serverfehler." }); } }); // 4. DELETE: Termin löschen (DELETE /api/appointments/:id) app.delete('/api/appointments/:id', async (req, res) => { try { const db = getDb(); const { id } = req.params; const filter = { _id: new ObjectId(id) }; const result = await db.collection('appointments').deleteOne(filter); if (result.deletedCount === 0) { return res.status(404).json({ message: "Termin nicht gefunden." }); } // Sende Status 204 (No Content), um den erfolgreichen Löschvorgang zu signalisieren res.status(204).send(); } catch (error) { console.error(`Fehler beim Löschen des Termins ${req.params.id}:`, error); res.status(400).json({ message: "Ungültige ID oder Serverfehler." }); } }); // ----------------------------------------------------- // Server Start Logik // ----------------------------------------------------- async function startServer() { try { await connectToDb(); app.listen(PORT, () => { console.log(`🚀 Server läuft auf Port ${PORT}`); }); } catch (error) { console.error("Fehler beim Starten des Servers:", error); } } startServer();