From 1a3ff0ff665107b3bcc682b65327bdde4331af77 Mon Sep 17 00:00:00 2001
From: Che <30403707+Che-Zhu@users.noreply.github.com>
Date: Tue, 16 Dec 2025 22:18:08 +0800
Subject: [PATCH] feat: add GitHub integration page and sidebar item - Add
GitHub integration page at app/projects/[id]/github/page.tsx for repository
management - Add "GitHub Integration" item to project sidebar navigation -
Update homepage "Fullstack Agent" link to point to the GitHub repository
---
app/projects/[id]/github/page.tsx | 184 ++++++++++++++++++++
components/home-page.tsx | 2 +-
components/sidebars/project-sidebar-new.tsx | 7 +
3 files changed, 192 insertions(+), 1 deletion(-)
create mode 100644 app/projects/[id]/github/page.tsx
diff --git a/app/projects/[id]/github/page.tsx b/app/projects/[id]/github/page.tsx
new file mode 100644
index 0000000..d3fb898
--- /dev/null
+++ b/app/projects/[id]/github/page.tsx
@@ -0,0 +1,184 @@
+'use client';
+
+import { useState } from 'react';
+import { ExternalLink, Github, Loader2, RefreshCw } from 'lucide-react';
+import { useParams, useRouter } from 'next/navigation';
+import { toast } from 'sonner';
+
+import { ConfigLayout } from '@/components/config/config-layout';
+import SettingsDialog from '@/components/dialog/settings-dialog';
+import { Button } from '@/components/ui/button';
+import { useProject } from '@/hooks/use-project';
+import { commitChanges, initializeRepo } from '@/lib/services/repoService';
+
+export default function GithubPage() {
+ const params = useParams();
+ const projectId = params.id as string;
+ const router = useRouter();
+
+ const { data: project, isLoading: projectLoading } = useProject(projectId);
+
+ const [isInitializing, setIsInitializing] = useState(false);
+ const [isCommitting, setIsCommitting] = useState(false);
+ const [showSettings, setShowSettings] = useState(false);
+
+ // Create a new repository on GitHub
+ const handleInitialize = async () => {
+ if (project?.githubRepo || isInitializing) return;
+
+ setIsInitializing(true);
+ try {
+ const result = await initializeRepo(projectId);
+ if (result.success) {
+ toast.success(result.message);
+ router.refresh();
+ } else {
+ if (result.code === 'GITHUB_NOT_BOUND') {
+ toast.error('Please connect your GitHub account first');
+ setShowSettings(true);
+ } else {
+ toast.error(result.message);
+ }
+ }
+ } catch (_error) {
+ toast.error('An unexpected error occurred');
+ } finally {
+ setIsInitializing(false);
+ }
+ };
+
+ // Commit changes to the repository and push to GitHub
+ const handleCommit = async () => {
+ if (isCommitting) return;
+
+ setIsCommitting(true);
+ try {
+ const result = await commitChanges(projectId);
+ if (result.success) {
+ toast.success(result.message);
+ } else {
+ if (result.code === 'GITHUB_NOT_BOUND') {
+ toast.error('Please connect your GitHub account first');
+ setShowSettings(true);
+ } else {
+ toast.error(result.message);
+ }
+ }
+ } catch (_error) {
+ toast.error('Failed to commit changes');
+ } finally {
+ setIsCommitting(false);
+ }
+ };
+
+ return (
+
+
+ {/* Connection Status Section */}
+
+ {/* Visual Header */}
+
+
+
+
+
+
+ {project?.githubRepo ? 'Connected to GitHub' : 'GitHub Repository'}
+
+
+ {project?.githubRepo
+ ? 'Your project is currently active and synced with a remote GitHub repository. You can push your latest changes below.'
+ : 'Initialize a new repository to start tracking changes. This will create a private repository in your GitHub account and push the initial code.'}
+