- Fuenf Kennzahlen ueber dem Board: Projektzahl mit Durchschnittsfortschritt, Ideen, aktive Entwicklungen, fertige Projekte, verknuepfte Repos - Volltextsuche ueber Name, Beschreibung, Tags und Repo-Pfad - Statusfilter als Chips mit Trefferzaehler, mehrfach kombinierbar - Sortierung nach Aenderung, Anlage, Name, Fortschritt oder Prioritaet; Favoriten stehen immer oben - Zwei Ansichten: freies Raster oder nach Status gruppiert - Archiv standardmaessig ausgeblendet, per Schalter sichtbar Die Projektkarte zeigt Fortschritt, Provider, Default-Branch, letzten Tag, Alter des letzten Commits, Notizzahl und Sync-Fehler. Status und Favorit sind direkt auf der Karte aenderbar - beides optimistisch, mit Rollback wenn der Server ablehnt. Die Karte ist ein "stretched link", damit die Schaltflaechen darin nicht in einem Anker verschachtelt sind. Der Anlege-Dialog verlangt nur einen Namen; neue Projekte starten als Idee. Ist eine Git-Verbindung gewaehlt, laesst sich das Repository aus einer durchsuchbaren Liste uebernehmen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
95 lines
3.2 KiB
TypeScript
95 lines
3.2 KiB
TypeScript
import { CircleDot, GitBranch, Lightbulb, Rocket, Trophy } from "lucide-react";
|
||
import { ProjectBoard } from "@/components/ProjectBoard";
|
||
import { StatCard } from "@/components/StatCard";
|
||
import { prisma } from "@/lib/db";
|
||
import { connectionSafeSelect, projectListInclude } from "@/lib/projects";
|
||
import { STATUS_META } from "@/lib/status";
|
||
import type { ConnectionSafe, ProjectListItem } from "@/types";
|
||
|
||
export const dynamic = "force-dynamic";
|
||
|
||
export default async function DashboardPage() {
|
||
const [projects, connections] = await Promise.all([
|
||
prisma.project.findMany({
|
||
include: projectListInclude,
|
||
orderBy: [{ favorite: "desc" }, { updatedAt: "desc" }],
|
||
}),
|
||
prisma.gitConnection.findMany({
|
||
select: connectionSafeSelect,
|
||
orderBy: { name: "asc" },
|
||
}),
|
||
]);
|
||
|
||
const active = projects.filter((project) => project.status !== "ARCHIVED");
|
||
const ideas = active.filter((project) => project.status === "IDEA").length;
|
||
const inDev = active.filter((project) => project.status === "IN_DEVELOPMENT").length;
|
||
const done = active.filter((project) => project.status === "DONE").length;
|
||
const linked = active.filter((project) => Boolean(project.repoOwner && project.repoName)).length;
|
||
|
||
const averageProgress =
|
||
active.length > 0
|
||
? Math.round(active.reduce((sum, project) => sum + project.progress, 0) / active.length)
|
||
: 0;
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<header className="fade-up pt-4">
|
||
<p className="text-[11px] font-semibold uppercase tracking-[0.3em] text-violet-300/70">
|
||
Vibe Coding Kontrollzentrum
|
||
</p>
|
||
<h1 className="mt-2 text-3xl font-semibold tracking-tight text-white sm:text-4xl">
|
||
Deine Projekte auf{" "}
|
||
<span className="text-gradient">einen Blick</span>
|
||
</h1>
|
||
<p className="mt-2 max-w-2xl text-sm text-slate-400">
|
||
Ideen festhalten, Status pflegen, Notizen sammeln – und live sehen, was in den
|
||
verknuepften Repositories bei GitHub, GitLab und Gitea passiert.
|
||
</p>
|
||
</header>
|
||
|
||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-5">
|
||
<StatCard
|
||
label="Projekte"
|
||
value={active.length}
|
||
hint={`Ø Fortschritt ${averageProgress}%`}
|
||
icon={CircleDot}
|
||
color="#a78bfa"
|
||
/>
|
||
<StatCard
|
||
label="Ideen"
|
||
value={ideas}
|
||
hint={STATUS_META.IDEA.description}
|
||
icon={Lightbulb}
|
||
color={STATUS_META.IDEA.color}
|
||
/>
|
||
<StatCard
|
||
label="In Entwicklung"
|
||
value={inDev}
|
||
hint="Aktiv in Arbeit"
|
||
icon={Rocket}
|
||
color={STATUS_META.IN_DEVELOPMENT.color}
|
||
/>
|
||
<StatCard
|
||
label="Fertig"
|
||
value={done}
|
||
hint="Ausgeliefert"
|
||
icon={Trophy}
|
||
color={STATUS_META.DONE.color}
|
||
/>
|
||
<StatCard
|
||
label="Repos verknuepft"
|
||
value={linked}
|
||
hint={`${connections.length} Git-Verbindung${connections.length === 1 ? "" : "en"}`}
|
||
icon={GitBranch}
|
||
color="#38bdf8"
|
||
/>
|
||
</div>
|
||
|
||
<ProjectBoard
|
||
projects={projects as unknown as ProjectListItem[]}
|
||
connections={connections as unknown as ConnectionSafe[]}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|