Without this the bot PAT 403s on POST /orgs/{org}/repos, which is
the single most important operation — creating new project repos
inside the workspace's Gitea org.
Made-with: Cursor
124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { useParams } from "next/navigation";
|
|
import { useSession } from "next-auth/react";
|
|
import { isClientDevProjectBypass } from "@/lib/dev-bypass";
|
|
import { Loader2 } from "lucide-react";
|
|
import { JM } from "@/components/project-creation/modal-theme";
|
|
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(() => {
|
|
const bypass = isClientDevProjectBypass();
|
|
if (!bypass && authStatus !== "authenticated") {
|
|
if (authStatus === "unauthenticated") setLoading(false);
|
|
return;
|
|
}
|
|
if (!bypass && authStatus === "loading") 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: JM.fontSans,
|
|
background: "linear-gradient(180deg, #FAFAFA 0%, #F5F3FF 100%)",
|
|
}}>
|
|
<Loader2 style={{ width: 24, height: 24, color: JM.indigo }} className="animate-spin" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!project) {
|
|
return (
|
|
<div style={{
|
|
display: "flex", alignItems: "center", justifyContent: "center",
|
|
height: "100%", fontFamily: JM.fontSans, color: JM.muted, fontSize: 14,
|
|
background: "linear-gradient(180deg, #FAFAFA 0%, #F5F3FF 100%)",
|
|
}}>
|
|
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}
|
|
/>
|
|
);
|
|
}
|