Files
kalendartool/plan.md

860 lines
13 KiB
Markdown

## 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.