"use client"; import { useEffect, useState } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Activity, Clock, DollarSign, FolderOpen, Settings, Loader2, Github, MessageSquare, CheckCircle2, AlertCircle, Link as LinkIcon } from "lucide-react"; import Link from "next/link"; import { useParams } from "next/navigation"; import { db, auth } from "@/lib/firebase/config"; import { doc, getDoc, collection, query, where, getDocs } from "firebase/firestore"; import { toast } from "sonner"; interface Project { id: string; name: string; productName: string; productVision?: string; workspacePath?: string; workspaceName?: string; githubRepo?: string; githubRepoUrl?: string; chatgptUrl?: string; projectType: 'scratch' | 'existing'; status: string; createdAt: any; } interface Stats { totalSessions: number; totalCost: number; totalTokens: number; totalDuration: number; } interface UnassociatedSession { id: string; workspacePath: string; workspaceName: string; count: number; } export default function ProjectOverviewPage() { const params = useParams(); const projectId = params.projectId as string; const workspace = params.workspace as string; const [project, setProject] = useState(null); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [unassociatedSessions, setUnassociatedSessions] = useState(0); const [linkingSessions, setLinkingSessions] = useState(false); useEffect(() => { const fetchProjectData = async () => { try { const user = auth.currentUser; if (!user) { setError('Not authenticated'); setLoading(false); return; } // Fetch project details const projectDoc = await getDoc(doc(db, 'projects', projectId)); if (!projectDoc.exists()) { setError('Project not found'); setLoading(false); return; } const projectData = projectDoc.data() as Project; setProject({ ...projectData, id: projectDoc.id }); // Fetch stats const statsResponse = await fetch(`/api/stats?projectId=${projectId}`); if (statsResponse.ok) { const statsData = await statsResponse.json(); setStats(statsData); } // If project has a workspace path, check for unassociated sessions if (projectData.workspacePath) { try { const sessionsRef = collection(db, 'sessions'); const unassociatedQuery = query( sessionsRef, where('userId', '==', user.uid), where('workspacePath', '==', projectData.workspacePath), where('needsProjectAssociation', '==', true) ); const unassociatedSnap = await getDocs(unassociatedQuery); setUnassociatedSessions(unassociatedSnap.size); } catch (err) { // Index might not be ready yet, silently fail console.log('Could not check for unassociated sessions:', err); } } } catch (err: any) { console.error('Error fetching project:', err); setError(err.message); } finally { setLoading(false); } }; const unsubscribe = auth.onAuthStateChanged((user) => { if (user) { fetchProjectData(); } else { setError('Not authenticated'); setLoading(false); } }); return () => unsubscribe(); }, [projectId]); const handleLinkSessions = async () => { if (!project?.workspacePath) return; setLinkingSessions(true); try { const user = auth.currentUser; if (!user) { toast.error('You must be signed in'); return; } const token = await user.getIdToken(); const response = await fetch('/api/sessions/associate-project', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ projectId, workspacePath: project.workspacePath, workspaceName: project.workspaceName, }), }); if (response.ok) { const data = await response.json(); toast.success(`✅ Linked ${unassociatedSessions} sessions to this project!`); setUnassociatedSessions(0); // Refresh stats const statsResponse = await fetch(`/api/stats?projectId=${projectId}`); if (statsResponse.ok) { const statsData = await statsResponse.json(); setStats(statsData); } } else { toast.error('Failed to link sessions'); } } catch (error) { console.error('Error linking sessions:', error); toast.error('An error occurred'); } finally { setLinkingSessions(false); } }; if (loading) { return (
); } if (error || !project) { return (

Error Loading Project

{error || 'Project not found'}

); } return (
{/* Header */}
📦

{project.productName}

{project.name}

{project.productVision && (

{project.productVision}

)} {project.workspacePath && (
{project.workspacePath}
)}
{/* Content */}
{/* 🔗 Link Unassociated Sessions - Show this FIRST if available */} {unassociatedSessions > 0 && (
Sessions Detected! We found {unassociatedSessions} coding session{unassociatedSessions > 1 ? 's' : ''} from this workspace that {unassociatedSessions > 1 ? 'aren\'t' : 'isn\'t'} linked to any project yet.

Workspace: {project.workspacePath}

Linking these sessions will add their costs, time, and activity to this project's stats.

)} {/* Stats Cards - Only show if there are sessions */} {stats && stats.totalSessions > 0 && (
Total Sessions
{stats.totalSessions}
Total Time
{stats.totalDuration}m
Total Cost
${stats.totalCost.toFixed(2)}
Tokens Used
{stats.totalTokens.toLocaleString()}
)} {/* Quick Actions */}
Sessions View all coding sessions Analytics Cost & usage analytics Connections Manage integrations
{/* Getting Started - Show if no sessions and no unassociated */} {stats && stats.totalSessions === 0 && unassociatedSessions === 0 && (
{/* Show different icons based on project type */}
{project.workspacePath && } {project.githubRepo && } {project.chatgptUrl && } {!project.workspacePath && !project.githubRepo && !project.chatgptUrl && ( )}
{/* Dynamic title based on project type */} {project.workspacePath && ( <>

Start Coding in This Workspace!

Open {project.workspacePath} in Cursor and start coding. Sessions from this workspace will automatically appear here.

)} {project.githubRepo && ( <>

Clone & Start Coding!

Clone your repository and open it in Cursor to start tracking your development.

)} {project.chatgptUrl && ( <>

Turn Your Idea Into Code!

Start building based on your ChatGPT conversation. Open your project in Cursor to begin tracking.

)} {!project.workspacePath && !project.githubRepo && !project.chatgptUrl && ( <>

Start Building!

Create your project directory and open it in Cursor to start tracking your development.

)}
{/* Setup status */}

Setup Checklist

Project created
Install Cursor Monitor extension
Start coding in your workspace
)}
); }