Initial commit: Kalendartool (Next.js, Prisma, Docker)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
146
app/dashboard/page.tsx
Normal file
146
app/dashboard/page.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* 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 fuer einen Einladungslink.
|
||||
</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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user