import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { FileText } from "lucide-react"; import { ActivityFeed } from "@/components/ActivityFeed"; import { GitPanel } from "@/components/GitPanel"; import { Markdown } from "@/components/Markdown"; import { NotesPanel } from "@/components/NotesPanel"; import { ReadmePanel } from "@/components/ReadmePanel"; import { ProjectHeader } from "@/components/ProjectHeader"; import { TaskBoard } from "@/components/tasks/TaskBoard"; import { requireUserPage } from "@/lib/auth/guard"; import { getSessionUser } from "@/lib/auth/session"; import { prisma } from "@/lib/db"; import { connectionSafeSelect, projectDetailInclude, webhookRepositoryIds } from "@/lib/projects"; import type { ConnectionSafe, ProjectDetail } from "@/types"; export const dynamic = "force-dynamic"; type PageProps = { params: Promise<{ id: string }> }; export async function generateMetadata({ params }: PageProps): Promise { const user = await getSessionUser(); if (!user) return { title: "Projekt" }; const { id } = await params; const project = await prisma.project.findFirst({ where: { id, ownerId: user.id }, select: { name: true, summary: true }, }); return { title: project?.name ?? "Projekt", description: project?.summary ?? undefined, }; } export default async function ProjectPage({ params }: PageProps) { const user = await requireUserPage(); const { id } = await params; const [project, connections] = await Promise.all([ // findFirst mit Besitzerbedingung: ein fremdes Projekt fuehrt zu 404, // nicht zu einer Fehlermeldung, die seine Existenz bestaetigt. prisma.project.findFirst({ where: { id, ownerId: user.id }, include: projectDetailInclude, }), prisma.gitConnection.findMany({ where: { ownerId: user.id }, select: connectionSafeSelect, orderBy: { name: "asc" }, }), ]); if (!project) notFound(); const detail = project as unknown as ProjectDetail; // Nur die Angabe "hier haengt ein Webhook", nicht das Geheimnis selbst. const webhookIds = await webhookRepositoryIds(detail.id); const fuehrend = detail.repositories[0]?.snapshot; const readme = fuehrend?.readme ? { content: fuehrend.readme, path: fuehrend.readmePath, baseUrl: fuehrend.readmeBaseUrl, // Die Basis endet auf dem Verzeichnis; angehaengt ergibt das die Datei. fileUrl: fuehrend.readmeBaseUrl && fuehrend.readmePath ? `${fuehrend.readmeBaseUrl}${fuehrend.readmePath.split("/").pop()}` : (fuehrend.htmlUrl ?? null), } : null; return (
{/* min-w-0 an beiden Spalten ist hier nicht Kosmetik, sondern der Kern: ein Rasterkind hat "min-width: auto" und weigert sich damit, unter die Inhaltsbreite seines breitesten Kindes zu schrumpfen. Die Heatmap ist ueber 700px breit – auf dem Telefon zog sie damit die ganze Spalte und mit ihr die Seite auseinander. Erst mit min-w-0 greift das overflow-x-auto darin ueberhaupt. */}

Beschreibung

{detail.description ? ( {detail.description} ) : (

Keine Beschreibung hinterlegt. Ueber „Bearbeiten“ kannst du die Idee ausformulieren.

)}
{/* Das README des fuehrenden Repositories – bei mehreren waere eine zweite Vorschau untereinander mehr Laenge als Nutzen. */} {readme ? ( ) : null}
); }