147 lines
4.7 KiB
TypeScript
147 lines
4.7 KiB
TypeScript
/**
|
|
* Dashboard (plan.md Abschnitt 14).
|
|
*
|
|
* User: sieht genau seinen einen Kalender als Karte (oeffnet die
|
|
* Kalenderuebersicht im Modal). Reservieren ja, verwalten nein.
|
|
* Admin: sieht alle Kalender als Karten; Klick oeffnet die
|
|
* Kalenderuebersicht, der Stift die Verwaltung (Einstellungen,
|
|
* Mitglieder, Regeln). Nur Admins erstellen/bearbeiten Kalender.
|
|
*/
|
|
import { redirect } from 'next/navigation';
|
|
import { prisma } from '@/lib/db/client';
|
|
import { requireDbUser } from '@/lib/api/context';
|
|
import { Card } from '@/components/ui/ui';
|
|
import { AppShell } from '@/components/layout/AppShell';
|
|
import { DashboardCalendarGrid } from '@/components/dashboard/DashboardCalendarGrid';
|
|
import type { ManagedCalendar } from '@/components/admin/CalendarManager';
|
|
|
|
export default async function DashboardPage() {
|
|
const user = await requireDbUser().catch(() => null);
|
|
if (!user) {
|
|
redirect('/login');
|
|
}
|
|
|
|
const membership = await prisma.calendarMember.findUnique({
|
|
where: { userId: user.id },
|
|
select: {
|
|
calendar: {
|
|
select: {
|
|
id: true,
|
|
title: true,
|
|
description: true,
|
|
timezone: true,
|
|
isActive: true,
|
|
maxReservationMinutes: true,
|
|
showTitleToMembers: true,
|
|
showNotesToMembers: true,
|
|
owner: { select: { email: true, username: true } },
|
|
_count: { select: { members: true, reservations: true } },
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const ownedCalendars =
|
|
user.role === 'ADMIN'
|
|
? await prisma.calendar.findMany({
|
|
orderBy: { createdAt: 'desc' },
|
|
select: {
|
|
id: true,
|
|
title: true,
|
|
description: true,
|
|
timezone: true,
|
|
isActive: true,
|
|
maxReservationMinutes: true,
|
|
showTitleToMembers: true,
|
|
showNotesToMembers: true,
|
|
owner: { select: { email: true, username: true } },
|
|
_count: { select: { members: true, reservations: true } },
|
|
},
|
|
})
|
|
: [];
|
|
|
|
/** Vereinheitlicht DB-Zeilen auf das Karten-Datenformat. */
|
|
function toManagedCalendar(row: {
|
|
id: string;
|
|
title: string;
|
|
description: string | null;
|
|
timezone: string;
|
|
isActive: boolean;
|
|
maxReservationMinutes: number;
|
|
showTitleToMembers: boolean;
|
|
showNotesToMembers: boolean;
|
|
owner: { email: string; username: string | null };
|
|
_count: { members: number; reservations: number };
|
|
}): ManagedCalendar {
|
|
return {
|
|
id: row.id,
|
|
title: row.title,
|
|
description: row.description,
|
|
timezone: row.timezone,
|
|
isActive: row.isActive,
|
|
ownerEmail: row.owner.username ?? row.owner.email,
|
|
isOwn: true,
|
|
memberCount: row._count.members,
|
|
reservationCount: row._count.reservations,
|
|
maxReservationMinutes: row.maxReservationMinutes,
|
|
showTitleToMembers: row.showTitleToMembers,
|
|
showNotesToMembers: row.showNotesToMembers,
|
|
};
|
|
}
|
|
|
|
const adminCalendars = ownedCalendars.map(toManagedCalendar);
|
|
const userCalendar = membership?.calendar
|
|
? [toManagedCalendar(membership.calendar)]
|
|
: [];
|
|
|
|
return (
|
|
<AppShell role={user.role} userEmail={user.email} username={user.username}>
|
|
<header className="mb-8">
|
|
<h1 className="text-2xl font-bold">Dashboard</h1>
|
|
</header>
|
|
|
|
{/* User-Ansicht: genau ein Kalender (als Karte) */}
|
|
{user.role === 'USER' && (
|
|
<section>
|
|
<h2 className="mb-4 text-lg font-semibold">Mein Kalender</h2>
|
|
{userCalendar.length === 0 ? (
|
|
<Card>
|
|
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
Du bist noch keinem Kalender zugeordnet. Bitte wende dich an den
|
|
Administrator, damit er dich einem Kalender zuordnet.
|
|
</p>
|
|
</Card>
|
|
) : (
|
|
<DashboardCalendarGrid
|
|
calendars={userCalendar}
|
|
currentUserId={user.id}
|
|
isAdmin={false}
|
|
/>
|
|
)}
|
|
</section>
|
|
)}
|
|
|
|
{/* Admin-Ansicht: alle Kalender als Karten (Verwaltung) */}
|
|
{user.role === 'ADMIN' && (
|
|
<section>
|
|
<h2 className="mb-4 text-lg font-semibold">Kalender</h2>
|
|
{adminCalendars.length === 0 ? (
|
|
<Card>
|
|
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
Noch keine Kalender vorhanden. Erstelle deinen ersten Kalender
|
|
unter "Kalender verwalten".
|
|
</p>
|
|
</Card>
|
|
) : (
|
|
<DashboardCalendarGrid
|
|
calendars={adminCalendars}
|
|
currentUserId={user.id}
|
|
isAdmin={true}
|
|
/>
|
|
)}
|
|
</section>
|
|
)}
|
|
</AppShell>
|
|
);
|
|
}
|