diff --git a/src/app/(app)/page.tsx b/src/app/(app)/page.tsx
index 164dcd7..bfb27b8 100644
--- a/src/app/(app)/page.tsx
+++ b/src/app/(app)/page.tsx
@@ -1,6 +1,7 @@
import Link from 'next/link'
import { AufgabenListe } from '@/components/aufgaben/aufgaben-liste'
import { Schnellerfassung } from '@/components/aufgaben/schnellerfassung'
+import { Fortschrittsbalken } from '@/components/fortschrittsbalken'
import {
Card,
CardBeschreibung,
@@ -16,6 +17,7 @@ import {
projekteZurAuswahlLaden,
zaehlstaende,
} from '@/server/abfragen/aufgaben'
+import { belegungHeute, hatKalenderkonto } from '@/server/abfragen/kalender'
import { verlangeAnmeldung } from '@/server/berechtigung'
import { db } from '@/server/db'
import { jetzt } from '@/server/zeitgeber'
@@ -24,16 +26,19 @@ export default async function StartSeite() {
const benutzer = await verlangeAnmeldung('/')
const heute = jetzt()
- const [alleOffenen, bereiche, projekte, zahlen, bereichsListe] = await Promise.all([
- aufgabenLaden({ nurOffen: true, ohneIdeen: true }, 200),
- bereicheLaden(),
- projekteZurAuswahlLaden(),
- zaehlstaende(),
- db.bereich.findMany({
- where: { aktiv: true },
- orderBy: [{ reihenfolge: 'asc' }, { name: 'asc' }],
- }),
- ])
+ const [alleOffenen, bereiche, projekte, zahlen, bereichsListe, belegung, mitKalender] =
+ await Promise.all([
+ aufgabenLaden({ nurOffen: true, ohneIdeen: true }, 200),
+ bereicheLaden(),
+ projekteZurAuswahlLaden(),
+ zaehlstaende(),
+ db.bereich.findMany({
+ where: { aktiv: true },
+ orderBy: [{ reihenfolge: 'asc' }, { name: 'asc' }],
+ }),
+ belegungHeute(benutzer.id, heute),
+ hatKalenderkonto(benutzer.id),
+ ])
// Was jetzt zählt: überfällig, heute oder morgen fällig.
const dran = alleOffenen.filter(
@@ -108,9 +113,10 @@ export default async function StartSeite() {
{bereichsListe.map((bereich) => {
const offeneHier = alleOffenen.filter((a) => a.bereich?.id === bereich.id)
+ const heuteHier = belegung.find((b) => b.id === bereich.id)?.belegung
return (
-
-
+
{bereich.name}
-
+
{offeneHier.length === 0
? 'Nichts offen'
: `${offeneHier.length} offen`}{' '}
· {alsDauer(wochenKapazitaet(bereich))} Kapazität je Woche
+
+ {/*
+ Ohne verbundenen Kalender wäre die Belegung immer null –
+ das sähe nach "alles frei" aus und wäre irreführend.
+ */}
+ {mitKalender && heuteHier && (
+ <>
+
+
+ {heuteHier.kapazitaet === 0
+ ? 'Heute nicht eingeplant'
+ : heuteHier.ueberbucht
+ ? `Heute überbucht: ${alsDauer(heuteHier.belegt)} Termine bei ${alsDauer(heuteHier.kapazitaet)} Kapazität`
+ : `Heute noch ${alsDauer(heuteHier.frei)} frei von ${alsDauer(heuteHier.kapazitaet)}`}
+
+ >
+ )}
diff --git a/src/server/abfragen/kalender.ts b/src/server/abfragen/kalender.ts
new file mode 100644
index 0000000..cce0d1d
--- /dev/null
+++ b/src/server/abfragen/kalender.ts
@@ -0,0 +1,75 @@
+import 'server-only'
+import {
+ tagesBelegung,
+ termineAmTag,
+ type BelegenderTermin,
+ type TagesBelegung,
+} from '@/lib/kalender/belegung'
+import { tagesBeginn, tagesEnde } from '@/lib/zeit'
+import { db } from '@/server/db'
+import { jetzt } from '@/server/zeitgeber'
+
+/**
+ * Abfragen rund um die gespiegelten Termine.
+ *
+ * Die Termine gehören dem Benutzer über sein Kalenderkonto; die Kennung geht
+ * deshalb immer in die where-Bedingung.
+ */
+
+export type BereichMitBelegung = {
+ id: string
+ name: string
+ farbe: string
+ belegung: TagesBelegung
+}
+
+/** Alle Termine des Benutzers, die diesen Kalendertag berühren. */
+export async function termineAmTagLaden(
+ benutzerId: string,
+ tag: Date,
+): Promise {
+ const zeilen = await db.termin.findMany({
+ where: {
+ kalenderkonto: { benutzerId, aktiv: true },
+ beginn: { lte: tagesEnde(tag) },
+ ende: { gt: tagesBeginn(tag) },
+ },
+ select: { beginn: true, ende: true, ganztaegig: true, zeigtAls: true },
+ orderBy: { beginn: 'asc' },
+ })
+ return zeilen
+}
+
+/**
+ * Wie voll heute in jedem Bereich schon ist.
+ *
+ * Alle Bereiche rechnen gegen dieselben Termine — der Planer weiß nicht,
+ * welcher Termin zu welchem Bereich gehört, und ein Termin blockiert die Zeit
+ * ohnehin für alles andere mit.
+ */
+export async function belegungHeute(
+ benutzerId: string,
+ zeitpunkt: Date = jetzt(),
+): Promise {
+ const [bereiche, termine] = await Promise.all([
+ db.bereich.findMany({
+ where: { aktiv: true },
+ orderBy: [{ reihenfolge: 'asc' }, { name: 'asc' }],
+ }),
+ termineAmTagLaden(benutzerId, zeitpunkt),
+ ])
+
+ const heute = termineAmTag(termine, zeitpunkt)
+
+ return bereiche.map((bereich) => ({
+ id: bereich.id,
+ name: bereich.name,
+ farbe: bereich.farbe,
+ belegung: tagesBelegung(bereich, heute, zeitpunkt),
+ }))
+}
+
+/** Hat der Benutzer überhaupt einen Kalender verbunden? */
+export async function hatKalenderkonto(benutzerId: string): Promise {
+ return (await db.kalenderkonto.count({ where: { benutzerId, aktiv: true } })) > 0
+}