"use client"; import { useCallback, Suspense } from "react"; import { useSearchParams, useRouter } from "next/navigation"; import { useProjects } from "@/hooks/use-projects"; import { useGitStatus, useGitLog, useGitBranches, useGitDiff, useGitOperations, } from "@/hooks/use-git"; import { BranchType } from "@/types/git"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { OfflineState } from "@/components/ui/offline-state"; import { GitStatusPanel } from "./git-status-panel"; import { GitBranchPanel } from "./git-branch-panel"; import { GitLogPanel } from "./git-log-panel"; import { GitDiffViewer } from "./git-diff-viewer"; import { GitActionsPanel } from "./git-actions-panel"; import { GitBranch, RefreshCw, FolderGit2 } from "lucide-react"; import { toast } from "sonner"; import { getErrorMessage } from "@/lib/api/client"; function GitBrowserContent() { const router = useRouter(); const searchParams = useSearchParams(); // Read state from URL const projectSlug = searchParams.get("project") || ""; const taskId = searchParams.get("task") || ""; // Fetch projects const { data: projects, isLoading: loadingProjects, error: projectsError, refetch: refetchProjects, } = useProjects(); // Git hooks - only enabled when project is selected const { data: status, isLoading: loadingStatus, refetch: refetchStatus, } = useGitStatus(projectSlug, taskId, !!projectSlug); const { data: log, isLoading: loadingLog, refetch: refetchLog, } = useGitLog(projectSlug, 20, undefined, !!projectSlug); const { data: branches, isLoading: loadingBranches, refetch: refetchBranches, } = useGitBranches(projectSlug, true, !!projectSlug); const { data: stagedDiff, isLoading: loadingStagedDiff } = useGitDiff( projectSlug, true, undefined, !!projectSlug, ); const { data: unstagedDiff, isLoading: loadingUnstagedDiff } = useGitDiff( projectSlug, false, undefined, !!projectSlug, ); // Git operations const { commit, push, createBranch, checkout, createPR, mergePR, pull, fetch, rebase, } = useGitOperations(); // Update URL params const updateParams = useCallback( (updates: Record) => { const params = new URLSearchParams(searchParams.toString()); Object.entries(updates).forEach(([key, value]) => { if (value) { params.set(key, value); } else { params.delete(key); } }); const query = params.toString(); router.push(query ? `/git?${query}` : "/git"); }, [router, searchParams], ); const handleProjectChange = useCallback( (slug: string) => { updateParams({ project: slug || null, task: null }); }, [updateParams], ); const handleRefresh = () => { refetchStatus(); refetchLog(); refetchBranches(); }; // Operation handlers // Note: agent_id is "ceo" because this panel is used by the CEO const handleCheckout = async (branch: string) => { try { await checkout.mutateAsync({ project_slug: projectSlug, branch, agent_id: "ceo", }); toast.success(`Checked out ${branch}`); } catch { toast.error("Failed to checkout branch"); } }; const handleCreateBranch = async ( branchType: BranchType, branchTaskId: string, ) => { try { const result = await createBranch.mutateAsync({ project_slug: projectSlug, task_id: branchTaskId, branch_type: branchType, agent_id: "ceo", }); toast.success(`Created branch ${result.branch_name}`); } catch { toast.error("Failed to create branch"); } }; const handleCommit = async (message: string) => { try { const result = await commit.mutateAsync({ project_slug: projectSlug, message, task_id: taskId || undefined, agent_id: "ceo", }); toast.success(`Committed: ${result.commit_hash.slice(0, 7)}`); } catch { toast.error("Failed to commit"); } }; const handlePush = async (force?: boolean) => { try { const result = await push.mutateAsync({ project_slug: projectSlug, task_id: taskId || undefined, agent_id: "ceo", force, }); toast.success( `Pushed ${result.commits_pushed} commits to ${result.branch}`, ); } catch { toast.error("Failed to push"); } }; const handleCreatePR = async (title: string, body: string) => { try { const result = await createPR.mutateAsync({ project_slug: projectSlug, task_id: taskId || undefined, title, body, agent_id: "ceo", }); toast.success( Created PR #{result.pr_number}:{" "} View , ); } catch { toast.error("Failed to create PR"); } }; const handleMergePR = async (prNumber: number) => { try { const result = await mergePR.mutateAsync({ project_slug: projectSlug, pr_number: prNumber, task_id: taskId || undefined, agent_id: "ceo", }); toast.success(`Merged PR #${result.pr_number} → ${result.target_branch}`); } catch { toast.error("Failed to merge PR"); } }; const handlePull = async () => { try { const result = await pull.mutateAsync({ project_slug: projectSlug, task_id: taskId || undefined, }); toast.success(`Pulled: now on ${result.current_branch}`); } catch { toast.error("Failed to pull from remote"); } }; const handleFetch = async () => { try { const result = await fetch.mutateAsync({ project_slug: projectSlug, task_id: taskId || undefined, }); toast.success(`Fetched: now on ${result.current_branch}`); } catch { toast.error("Failed to fetch from remote"); } }; const handleRebase = async (targetBranch: string) => { try { const result = await rebase.mutateAsync({ project_slug: projectSlug, target_branch: targetBranch, task_id: taskId || undefined, agent_id: "ceo", }); if (result.conflict) { toast.warning( `Rebase conflicts in: ${result.conflicted_files.join(", ") || "unknown files"}`, ); } else { toast.success("Rebase completed successfully"); } } catch (error) { toast.error(getErrorMessage(error)); } }; // Check offline const isOffline = projectsError && (projectsError.message?.includes("Network Error") || (projectsError as { code?: string })?.code === "ERR_NETWORK"); if (isOffline) { return ( refetchProjects()} /> ); } return (
{/* Header */}

Git Operations

Manage repositories, branches, and commits

{/* Project Selector */} {projectSlug && ( )}
{/* No Project Selected */} {!projectSlug && (

Select a Project

Choose a project from the dropdown to view git status and perform operations

)} {/* Git Dashboard */} {projectSlug && (
{/* Left Column - Status & Actions */}
{/* Middle Column - Branches & Log */}
{/* Right Column - Diff Viewer */}
)}
); } // Loading skeleton function GitBrowserSkeleton() { return (
); } // Wrap in Suspense for useSearchParams export function GitBrowser() { return ( }> ); }