V 1.0.0 (front/backend) Erste lauffähige Version
This commit is contained in:
18
backend/docker-compose.yml
Normal file
18
backend/docker-compose.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
services:
|
||||
mongodb:
|
||||
image: mongo:latest
|
||||
container_name: mongodb
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "27017:27017"
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER}
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWD}
|
||||
volumes:
|
||||
- mongodb_data:/data/db
|
||||
- mongodb_config:/data/configdb
|
||||
|
||||
volumes:
|
||||
mongodb_data:
|
||||
mongodb_config:
|
||||
24
backend/package.json
Normal file
24
backend/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "backend",
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"vdate": "2025-11-23 11:00 UTC",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node src/server.js",
|
||||
"dev": "nodemon src/server.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.3",
|
||||
"express": "^5.1.0",
|
||||
"mongodb": "^7.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.11"
|
||||
}
|
||||
}
|
||||
40
backend/src/db/db.js
Normal file
40
backend/src/db/db.js
Normal file
@@ -0,0 +1,40 @@
|
||||
// src/db/db.js
|
||||
import 'dotenv/config'; // Importiert und lädt Umgebungsvariablen
|
||||
import { MongoClient } from 'mongodb';
|
||||
|
||||
// MongoDB Verbindungs-URI aus der .env-Datei
|
||||
const uri = process.env.MONGO_URI;
|
||||
|
||||
let db;
|
||||
|
||||
/**
|
||||
* Stellt die Verbindung zur MongoDB her.
|
||||
* @returns {db} Die verbundene Datenbankinstanz.
|
||||
*/
|
||||
export async function connectToDb() {
|
||||
try {
|
||||
const client = new MongoClient(uri, {
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
// Die Datenbankinstanz speichern
|
||||
db = client.db();
|
||||
|
||||
console.log(`✅ Erfolgreich mit MongoDB verbunden.`);
|
||||
|
||||
return db;
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Fehler bei der Verbindung zur MongoDB:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die gespeicherte Datenbankinstanz zurück.
|
||||
* @returns {db} Die Datenbankinstanz.
|
||||
*/
|
||||
export function getDb() {
|
||||
return db;
|
||||
}
|
||||
154
backend/src/server.js
Normal file
154
backend/src/server.js
Normal file
@@ -0,0 +1,154 @@
|
||||
// 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();
|
||||
Reference in New Issue
Block a user