## 1. Produktidee Ein **einfaches Kalender- und Reservierungstool**, bei dem ein Admin Kalender anlegt und Personen gezielt Zugang zu einem bestimmten Kalender gibt. Der wichtigste Grundsatz sollte sein: > **Ein User gehört genau einem Kalender an und sieht ausschließlich diesen Kalender.** Ein Admin kann dagegen mehrere Kalender besitzen und verwalten. ### Beispiel Ein Admin betreibt drei Kalender: - „Fußballplatz“ - „Besprechungsraum“ - „Tennisplatz“ Er erstellt für „Fußballplatz“ einen Invite-Link und verschickt ihn an die entsprechenden Personen. Ein eingeladener User sieht nach der Anmeldung ausschließlich: **Fußballplatz** und kann dort freie Zeiten ansehen und Reservierungen erstellen. --- # 2. Rollen und Rechte ## Admin Der Admin kann: - sich registrieren/anmelden - Kalender erstellen - Kalender bearbeiten - Kalender löschen/deaktivieren - Kalender-Titel festlegen - Beschreibung festlegen - Zeitzone festlegen - Invite-Links erzeugen - Benutzer einem Kalender zuordnen - alle Reservierungen seines Kalenders sehen - Reservierungen verwalten/löschen - optional Reservierungen für andere Benutzer erstellen Ein Admin sollte mehrere Kalender besitzen können. --- ## User Ein User kann: - sich per E-Mail und Passwort anmelden - seinen zugewiesenen Kalender öffnen - freie Zeiten sehen - bestehende Reservierungen sehen - eigene Reservierungen erstellen - Dauer einer Reservierung festlegen - eigene Reservierungen ändern - eigene Reservierungen stornieren Wichtig: **Ein User darf niemals Daten eines anderen Kalenders über die URL oder API abrufen können.** Also nicht nur im Frontend verstecken, sondern auch serverseitig erzwingen. --- # 3. Invite-System Das würde ich etwas stärker ausbauen als in deinem ursprünglichen Konzept. Ein Admin klickt auf: **„Benutzer einladen“** und bekommt einen Link wie: ``` https://deine-app.de/invite/a8f73kd92... ``` Der Link enthält einen zufälligen, nicht erratbaren Token. Der Empfänger öffnet den Link und sieht: > Du wurdest zum Kalender „Besprechungsraum“ eingeladen. Danach: **E-Mail + Passwort erstellen** und der Benutzer wird automatisch diesem Kalender zugeordnet. ### Wichtig Ein Invite sollte: - einen zufälligen Token besitzen - optional ein Ablaufdatum haben - optional nur einmal verwendbar sein - deaktivierbar sein Noch besser: Der Admin kann später sehen: ``` Einladungen ──────────────────────────── Aktiv 3 Abgelaufen 1 Verwendet 5 ``` --- # 4. Kalender Jeder Kalender sollte mehr Informationen als nur einen Titel besitzen. Zum Beispiel: ``` Calendar ------------------------- Titel Beschreibung Zeitzone Erstellt am Besitzer Status ``` Beispiel: ``` Besprechungsraum 1 Raum für interne Meetings Europe/Berlin Aktiv ``` ### Sinnvolle spätere Einstellungen - Öffnungszeiten - erlaubte Reservierungsdauer - maximale Reservierungsdauer - minimale Vorlaufzeit - maximale Vorausbuchung - Puffer zwischen Reservierungen - Wochenenden erlauben/deaktivieren Das würde ich aber teilweise erst nach dem MVP bauen. --- # 5. Reservierungen Eine Reservierung sollte mindestens folgende Daten haben: ``` Reservierung ------------------------- Kalender Benutzer Startzeit Endzeit Dauer Titel / Betreff Notiz Status Erstellt am Geändert am ``` Beispiel: ``` Besprechungsraum 10:00 ───────────────── Max Mustermann 60 Minuten Projektmeeting 11:00 ───────────────── ``` ### Dauer Der Benutzer soll nicht nur eine Startzeit wählen, sondern auch eine Dauer: ``` Start: 14:00 Dauer: 90 Minuten ``` Das System berechnet: ``` Ende: 15:30 ``` Intern würde ich **Startzeit + Endzeit** speichern und die Dauer daraus berechnen. --- # 6. Ganz wichtig: Doppelbuchungen verhindern Das ist eine der wichtigsten Funktionen der gesamten Anwendung. Wenn bereits existiert: ``` 14:00 - 15:00 ``` darf niemand buchen: ``` 14:30 - 15:30 ``` Ebenso nicht: ``` 14:00 - 14:30 ``` oder: ``` 13:00 - 14:01 ``` Das muss **serverseitig und in der Datenbanklogik** geprüft werden. Nicht nur: > „Button deaktivieren, wenn es im Frontend belegt aussieht.“ Denn zwei Benutzer könnten gleichzeitig buchen. Der Server muss die Reservierung atomar validieren. --- # 7. Kalenderansicht Für das MVP würde ich drei Ansichten anbieten: ### Monat Gut für den Überblick. ### Woche Wahrscheinlich die wichtigste Ansicht für Reservierungen. ### Tag Sehr praktisch, wenn viele Buchungen vorhanden sind. Optisch beispielsweise: ``` Montag 18. September 08:00 09:00 10:00 █████████████ 11:00 █████████████ 12:00 13:00 ███████ 14:00 ███████ 15:00 ``` Reservierungen sollten anklickbar sein. --- # 8. Sichtbarkeit Hier würde ich dein ursprüngliches Konzept etwas anders definieren. Ich würde **nicht** sagen: > „Öffentlicher Kalender = jeder im Internet kann ihn sehen.“ Das kann später Datenschutzprobleme verursachen. Besser: ### Standard: Invite-only Ein Kalender ist nur für Benutzer sichtbar, die ihm zugeordnet sind. Der Invite-Link dient als Zugang. Später kannst du einen zweiten Modus einbauen: ### Öffentlich Der Kalender kann ohne Anmeldung angesehen werden. Zum Beispiel: ``` https://deine-app.de/c/public/abc123 ``` Aber: **Reservierungen erfordern weiterhin Anmeldung.** Damit hast du beide Möglichkeiten. --- # 9. Datenbank Für das Projekt würde ich PostgreSQL verwenden. Eine mögliche Struktur: ``` users ---------------- id email password_hash role created_at updated_at ``` ``` calendars ---------------- id owner_id title description timezone is_active created_at updated_at ``` ``` calendar_members ---------------- id calendar_id user_id created_at ``` Damit kannst du sauber abbilden: ``` Admin │ ├── Kalender A │ ├── User 1 │ ├── User 2 │ └── User 3 │ └── Kalender B ├── User 4 └── User 5 ``` Reservierungen: ``` reservations ---------------- id calendar_id user_id title start_at end_at status notes created_at updated_at ``` Invites: ``` invites ---------------- id calendar_id token_hash expires_at used_at created_at ``` Ich würde den Invite-Token **nicht im Klartext** speichern, sondern nur seinen Hash. --- # 10. Rollen würde ich technisch einfach halten Zum Start: ``` ADMIN USER ``` Nicht sofort ein kompliziertes Berechtigungssystem bauen. Später könntest du erweitern: ``` SUPER_ADMIN ADMIN USER VIEWER ``` Aber für Version 1 reichen zwei Rollen völlig. --- # 11. Authentifizierung Login: ``` E-Mail Passwort [Anmelden] ``` Registrierung: ``` E-Mail Passwort Passwort wiederholen ``` Zusätzlich: - Passwort-Hashing - Passwort vergessen - Session-Management - E-Mail-Verifizierung - Rate-Limiting beim Login - sichere Cookies - CSRF-Schutz, falls dein Auth-Setup das erfordert Passwörter niemals selbst verschlüsseln oder im Klartext speichern. --- # 12. Mein technischer Stack Für dein Projekt würde ich etwas Modernes und relativ simples nehmen: ### Frontend + Backend **Next.js + TypeScript** **Docker Cotainer** Damit kannst du Frontend und Backend in einem Projekt haben. ### Datenbank **PostgreSQL** ### ORM **Prisma** ### UI **Tailwind CSS** **ShadCN* plus eine Kalender-Komponente wie z. B. FullCalendar. ### Auth Eine etablierte Auth-Lösung statt eigener Session-Implementierung. ### Deployment Zum Beispiel: ``` Frontend/API → Next.js Hosting Datenbank → PostgreSQL Domain → deine-domain.de Dockercontainer -> als stack ``` Damit bleibt die Architektur relativ klein: ``` Browser │ ▼ Next.js │ ├── Auth ├── API ├── UI │ ▼ PostgreSQL ``` --- # 13. Seiten der Anwendung Ich würde ungefähr diese Struktur bauen. ``` / ├── login ├── register ├── forgot-password │ ├── dashboard │ ├── calendar/[id] │ ├── reservation/new ├── reservation/[id] │ ├── invite/[token] │ └── admin ├── calendars ├── calendars/new ├── calendars/[id] ├── users └── invites ``` --- # 14. Dashboard ### User Der User bekommt praktisch nur: ``` Mein Kalender ┌──────────────────────────────┐ │ Besprechungsraum │ │ │ │ [ Kalender öffnen ] │ └──────────────────────────────┘ ``` Da ein User nur einen Kalender haben darf, brauchst du keine komplizierte Kalenderauswahl. ### Admin Beim Admin: ``` Dashboard Meine Kalender [ Besprechungsraum ] [ Fußballplatz ] [ Tennisplatz ] + Kalender erstellen ``` --- # 15. Reservierung erstellen Ich würde den Ablauf sehr einfach halten: ``` Neue Reservierung Datum [ 18.09.2026 ] Startzeit [ 14:00 ] Dauer [ 60 Minuten ] Titel [ Besprechung ] Notiz [ ............. ] [ Reservieren ] ``` Nach dem Abschicken prüft der Server: ``` Ist der Kalender gültig? Ist der Benutzer berechtigt? Ist die Zeit verfügbar? Liegt die Zeit innerhalb der erlaubten Buchungszeiten? Ist die Dauer erlaubt? ``` Dann wird gebucht. --- # 16. Zusätzliche Funktion, die ich unbedingt ergänzen würde ## Verfügbarkeitsregeln Sonst kann jemand beispielsweise um 03:00 Uhr nachts einen Raum reservieren. Der Admin sollte deshalb irgendwann einstellen können: ``` Buchungszeiten Montag 08:00 - 18:00 Dienstag 08:00 - 18:00 Mittwoch 08:00 - 18:00 Donnerstag 08:00 - 18:00 Freitag 08:00 - 16:00 Samstag geschlossen Sonntag geschlossen ``` Und: ``` Mindestdauer: 30 Minuten Maximaldauer: 4 Stunden Buchbar bis: 30 Tage im Voraus Vorlaufzeit: 1 Stunde ``` Das macht aus einem simplen Kalender tatsächlich ein brauchbares Reservierungssystem. --- # 17. Weitere sinnvolle Funktionen Für **Version 1.0** würde ich nur das Nötigste bauen. Danach könnten kommen: **E-Mail-Benachrichtigungen** Bei: - neuer Reservierung - Änderung - Stornierung - Einladung **Wiederkehrende Reservierungen** Zum Beispiel: ``` Jeden Montag 18:00 - 19:00 ``` **ICS / Kalender-Export** Damit Benutzer Reservierungen in Outlook, Apple Calendar oder Google Calendar übernehmen können. **Admin-Statistiken** Zum Beispiel: ``` Reservierungen diesen Monat: 143 Auslastung: 67 % ``` **Audit-Log** Damit der Admin nachvollziehen kann: ``` 10:31 Max erstellt Reservierung 10:42 Max geändert Reservierung 11:03 Admin gelöscht Reservierung ``` --- # 18. Was ich ausdrücklich nicht in Version 1 bauen würde Sonst wird das Projekt unnötig groß. Zunächst würde ich weglassen: - Chat - Push-Benachrichtigungen - Mobile Apps - komplizierte Rollen - mehrere Kalender pro User - Zahlungen - Abonnements - externe Kalender-Synchronisierung - komplexe Ressourcenverwaltung Erst einmal: **Login → Kalender → Einladung → Reservierung → Konfliktprüfung** Das ist dein Kernprodukt. --- # 19. MVP-Definition Ich würde dein erstes Release auf diese Funktionen begrenzen: ### Auth - Registrierung - Login - Logout - Passwort vergessen ### Admin - Kalender erstellen - Kalender bearbeiten - Kalender deaktivieren - Invite-Link erstellen - Benutzer sehen - Reservierungen sehen/löschen ### User - genau einem Kalender zugeordnet - Kalender ansehen - Reservierung erstellen - Startzeit wählen - Dauer wählen - eigene Reservierung bearbeiten - eigene Reservierung löschen ### System - Berechtigungsprüfung - Doppelbuchungen verhindern - Zeitzonen sauber behandeln - responsive Oberfläche - sichere Sessions - saubere Fehlerbehandlung --- # 20. Projektstruktur Ich würde ungefähr so starten: ``` calendar-app/ │ ├── app/ │ ├── login/ │ ├── register/ │ ├── dashboard/ │ ├── calendar/ │ ├── invite/ │ └── admin/ │ ├── components/ │ ├── calendar/ │ ├── reservation/ │ ├── forms/ │ └── ui/ │ ├── lib/ │ ├── auth/ │ ├── db/ │ ├── permissions/ │ ├── reservations/ │ └── invites/ │ ├── prisma/ │ └── schema.prisma │ ├── api/ │ └── tests/ ``` Besonders wichtig ist eine zentrale Berechtigungsschicht. Zum Beispiel konzeptionell: ``` canViewCalendar(user, calendar) canCreateReservation(user, calendar) canDeleteReservation(user, reservation) canManageCalendar(user, calendar) ``` Dann verteilst du Berechtigungslogik nicht überall im Code. --- # 21. Eine wichtige Entscheidung für dein Konzept Ich würde den Satz > „Jeder kann nur seinen einen Kalender sehen“ technisch als feste Regel definieren: ``` USER → genau 1 Kalender ADMIN → 0..n Kalender ``` Damit ist das Datenmodell eindeutig. Und bei einem Invite gilt: ``` Invite ↓ User registriert sich ↓ User wird Kalender zugeordnet ↓ User sieht ausschließlich diesen Kalender ``` Ein User kann anschließend **nicht selbstständig einen zweiten Kalender hinzufügen**. Das verhindert sehr viel Komplexität.