feat: add WannPassts booking app with Go backend and Vue frontend
Initial project setup for a privacy-focused, self-hosted scheduling app: - Go backend with JWT auth, SQLite storage, and chi router - Calendar integrations via Google OAuth (FreeBusy), CalDAV, and ICS links - Public booking pages with configurable slots and booking requests - AES-256-GCM encryption for stored provider tokens - Vue 3 + TypeScript frontend with Vite, Pinia, and Vue Router - Docs, .gitignore, and .env.example for local development
This commit is contained in:
commit
cb30223fd4
47 changed files with 6599 additions and 0 deletions
41
backend/internal/calendar/provider.go
Normal file
41
backend/internal/calendar/provider.go
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package calendar
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Interval ist ein "beschäftigt"-Zeitraum. Enthält bewusst KEINE Termindetails,
|
||||
// nur Start und Ende – mehr verlässt den Kalender des Nutzers nie.
|
||||
type Interval struct {
|
||||
Start time.Time
|
||||
End time.Time
|
||||
}
|
||||
|
||||
type Provider interface {
|
||||
// FetchBusy liefert alle busy-Zeiträume im Fenster [from, to).
|
||||
FetchBusy(ctx context.Context, from, to time.Time) ([]Interval, error)
|
||||
}
|
||||
|
||||
// clampIntervals schneidet Intervalle aufs Fenster zurecht, verwirft ungültige
|
||||
// und sortiert das Ergebnis.
|
||||
func clampIntervals(in []Interval, from, to time.Time) []Interval {
|
||||
out := make([]Interval, 0, len(in))
|
||||
for _, iv := range in {
|
||||
if !iv.End.After(iv.Start) {
|
||||
continue
|
||||
}
|
||||
if iv.Start.Before(from) {
|
||||
iv.Start = from
|
||||
}
|
||||
if iv.End.After(to) {
|
||||
iv.End = to
|
||||
}
|
||||
if iv.End.After(iv.Start) {
|
||||
out = append(out, iv)
|
||||
}
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool { return out[i].Start.Before(out[j].Start) })
|
||||
return out
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue