Files
vibn-frontend/app/[workspace]/project/[projectId]/overview/page.tsx
Mark Henderson bada63452f feat(ui): apply Justine ink & parchment design system
- Map Justine tokens to shadcn CSS variables (--vibn-* aliases)
- Switch fonts to Inter + Lora via next/font (IBM Plex Mono for code)
- Base typography: body Inter, h1–h3 Lora; marketing hero + wordmark serif
- Project shell and global chrome use semantic colors
- Replace Outfit/Newsreader references across TSX inline styles

Made-with: Cursor
2026-04-01 21:03:40 -07:00

112 lines
3.3 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import { useSession } from "next-auth/react";
import { Loader2 } from "lucide-react";
import { FreshIdeaMain } from "@/components/project-main/FreshIdeaMain";
import { ChatImportMain } from "@/components/project-main/ChatImportMain";
import { CodeImportMain } from "@/components/project-main/CodeImportMain";
import { MigrateMain } from "@/components/project-main/MigrateMain";
interface Project {
id: string;
productName: string;
name?: string;
stage?: "discovery" | "architecture" | "building" | "active";
creationMode?: "fresh" | "chat-import" | "code-import" | "migration";
creationStage?: string;
sourceData?: {
chatText?: string;
repoUrl?: string;
liveUrl?: string;
hosting?: string;
description?: string;
};
analysisResult?: Record<string, unknown>;
migrationPlan?: string;
}
export default function ProjectOverviewPage() {
const params = useParams();
const projectId = params.projectId as string;
const { status: authStatus } = useSession();
const [project, setProject] = useState<Project | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (authStatus !== "authenticated") {
if (authStatus === "unauthenticated") setLoading(false);
return;
}
fetch(`/api/projects/${projectId}`)
.then(r => r.json())
.then(d => setProject(d.project))
.catch(() => {})
.finally(() => setLoading(false));
}, [authStatus, projectId]);
if (loading) {
return (
<div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%", fontFamily: "var(--font-inter), ui-sans-serif, sans-serif" }}>
<Loader2 style={{ width: 24, height: 24, color: "#a09a90" }} className="animate-spin" />
</div>
);
}
if (!project) {
return (
<div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%", fontFamily: "var(--font-inter), ui-sans-serif, sans-serif", color: "#a09a90", fontSize: "0.88rem" }}>
Project not found.
</div>
);
}
const projectName = project.productName || project.name || "Untitled";
const mode = project.creationMode ?? "fresh";
if (mode === "chat-import") {
return (
<ChatImportMain
projectId={projectId}
projectName={projectName}
sourceData={project.sourceData}
analysisResult={project.analysisResult as Parameters<typeof ChatImportMain>[0]["analysisResult"]}
/>
);
}
if (mode === "code-import") {
return (
<CodeImportMain
projectId={projectId}
projectName={projectName}
sourceData={project.sourceData}
analysisResult={project.analysisResult}
creationStage={project.creationStage}
/>
);
}
if (mode === "migration") {
return (
<MigrateMain
projectId={projectId}
projectName={projectName}
sourceData={project.sourceData}
analysisResult={project.analysisResult}
migrationPlan={project.migrationPlan}
creationStage={project.creationStage}
/>
);
}
// Default: "fresh" — wraps AtlasChat with decision banner
return (
<FreshIdeaMain
projectId={projectId}
projectName={projectName}
/>
);
}