VIBN Frontend for Coolify deployment

This commit is contained in:
2026-02-15 19:25:52 -08:00
commit 40bf8428cd
398 changed files with 76513 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
"use client";
import { WorkspaceLeftRail } from "@/components/layout/workspace-left-rail";
import { RightPanel } from "@/components/layout/right-panel";
import { ReactNode, useState } from "react";
import { Toaster } from "sonner";
export default function ConnectionsLayout({
children,
}: {
children: ReactNode;
}) {
const [activeSection, setActiveSection] = useState<string>("connections");
return (
<>
<div className="flex h-screen w-full overflow-hidden bg-background">
{/* Left Rail - Workspace Navigation */}
<WorkspaceLeftRail activeSection={activeSection} onSectionChange={setActiveSection} />
{/* Main Content Area */}
<main className="flex-1 flex flex-col overflow-hidden">
{children}
</main>
{/* Right Panel - AI Chat */}
<RightPanel />
</div>
<Toaster position="top-center" />
</>
);
}

View File

@@ -0,0 +1,360 @@
"use client";
import { useState, useEffect } from "react";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Github, CheckCircle2, Download, Copy, Check, Eye, EyeOff } from "lucide-react";
import { CursorIcon } from "@/components/icons/custom-icons";
import { toast } from "sonner";
import { auth } from "@/lib/firebase/config";
import type { User } from "firebase/auth";
import { MCPConnectionCard } from "@/components/mcp-connection-card";
import { ChatGPTImportCard } from "@/components/chatgpt-import-card";
export default function ConnectionsPage() {
const [githubConnected, setGithubConnected] = useState(false);
const [extensionInstalled] = useState(false); // Future use: track extension installation
const [copiedApiKey, setCopiedApiKey] = useState(false);
const [showApiKey, setShowApiKey] = useState(false);
const [apiKey, setApiKey] = useState<string | null>(null);
const [loadingApiKey, setLoadingApiKey] = useState(true);
const [apiUrl, setApiUrl] = useState('https://vibnai.com');
// Set API URL on client side to avoid hydration mismatch
useEffect(() => {
if (typeof window !== 'undefined') {
setApiUrl(window.location.origin);
}
}, []);
// Fetch API key on mount
useEffect(() => {
async function fetchApiKey(user: User) {
try {
console.log('[Client] Getting ID token for user:', user.uid);
const token = await user.getIdToken();
console.log('[Client] Token received, length:', token.length);
const response = await fetch('/api/user/api-key', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
console.log('[Client] Response status:', response.status);
if (response.ok) {
const data = await response.json();
console.log('[Client] API key received');
setApiKey(data.apiKey);
} else {
const errorData = await response.json();
console.error('[Client] Failed to fetch API key:', response.status, errorData);
}
} catch (error) {
console.error('[Client] Error fetching API key:', error);
} finally {
setLoadingApiKey(false);
}
}
// Listen for auth state changes
const unsubscribe = auth.onAuthStateChanged((user) => {
if (user) {
fetchApiKey(user);
} else {
setLoadingApiKey(false);
}
});
return () => unsubscribe();
}, []);
const handleConnectGitHub = async () => {
// TODO: Implement GitHub OAuth flow
toast.success("GitHub connected successfully!");
setGithubConnected(true);
};
const handleInstallExtension = () => {
// Link to Cursor Monitor extension (update with actual marketplace URL when published)
window.open("https://marketplace.visualstudio.com/items?itemName=cursor-monitor", "_blank");
};
const handleCopyApiKey = () => {
if (apiKey) {
navigator.clipboard.writeText(apiKey);
setCopiedApiKey(true);
toast.success("API key copied to clipboard!");
setTimeout(() => setCopiedApiKey(false), 2000);
}
};
return (
<div className="flex h-full flex-col overflow-auto">
<div className="flex-1 p-8 space-y-8 max-w-4xl">
{/* Header */}
<div>
<h1 className="text-4xl font-bold mb-2">Connect Your Tools</h1>
<p className="text-muted-foreground text-lg">
Set up your development tools to unlock the full power of Vib&apos;n
</p>
</div>
{/* Connection Cards */}
<div className="space-y-6">
{/* Cursor Extension */}
<Card className={extensionInstalled ? "border-green-500/50 bg-green-500/5" : ""}>
<CardHeader>
<div className="flex items-start justify-between">
<div className="flex items-center gap-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-blue-500/10">
<CursorIcon className="h-6 w-6 text-blue-600" />
</div>
<div>
<div className="flex items-center gap-2">
<CardTitle>Cursor Monitor Extension</CardTitle>
{extensionInstalled && (
<CheckCircle2 className="h-4 w-4 text-green-600" />
)}
</div>
<CardDescription>
Automatically track your coding sessions, AI usage, and costs
</CardDescription>
</div>
</div>
{!extensionInstalled ? (
<Button onClick={handleInstallExtension}>
<Download className="h-4 w-4 mr-2" />
Get Extension
</Button>
) : (
<Button variant="outline" disabled>
<CheckCircle2 className="h-4 w-4 mr-2" />
Installed
</Button>
)}
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="space-y-2 text-sm text-muted-foreground">
<p className="font-medium text-foreground">What it does:</p>
<ul className="list-disc list-inside space-y-1 ml-2">
<li>Tracks your coding sessions in real-time</li>
<li>Monitors AI model usage and token consumption</li>
<li>Logs file changes and conversation history</li>
<li>Calculates costs automatically</li>
</ul>
</div>
{!extensionInstalled && (
<>
<div className="rounded-lg bg-muted p-4 space-y-2">
<p className="text-sm font-medium">Installation Steps:</p>
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground ml-2">
<li>Install the Cursor Monitor extension from the marketplace</li>
<li>Restart Cursor to activate the extension</li>
<li>Configure your API key (see instructions below)</li>
<li>Start coding - sessions will be tracked automatically!</li>
</ol>
</div>
<div className="rounded-lg bg-primary/10 border border-primary/20 p-4 space-y-3">
<div className="flex items-center justify-between">
<p className="text-sm font-medium">Your API Key</p>
{!loadingApiKey && apiKey && (
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="sm"
onClick={() => setShowApiKey(!showApiKey)}
>
{showApiKey ? (
<EyeOff className="h-4 w-4" />
) : (
<Eye className="h-4 w-4" />
)}
</Button>
<Button
variant="ghost"
size="sm"
onClick={handleCopyApiKey}
>
{copiedApiKey ? (
<Check className="h-4 w-4" />
) : (
<Copy className="h-4 w-4" />
)}
</Button>
</div>
)}
</div>
{loadingApiKey ? (
<div className="text-sm text-muted-foreground">Loading...</div>
) : apiKey ? (
<>
<Input
type={showApiKey ? "text" : "password"}
value={apiKey}
readOnly
className="font-mono text-xs"
/>
<p className="text-xs text-muted-foreground">
Add this key to your extension settings to connect it to your Vibn account.
</p>
</>
) : (
<p className="text-sm text-muted-foreground">
Sign in to generate your API key
</p>
)}
</div>
<div className="rounded-lg bg-muted p-4 space-y-2">
<p className="text-sm font-medium">Configure Cursor Monitor Extension:</p>
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground ml-2">
<li>Open Cursor Settings (Cmd/Ctrl + ,)</li>
<li>Search for &quot;Cursor Monitor&quot;</li>
<li>Find &quot;Cursor Monitor: Vibn Api Key&quot;</li>
<li>Paste your API key (from above)</li>
<li>Verify &quot;Cursor Monitor: Vibn Api Url&quot; is set to: <code className="text-xs bg-background px-1 py-0.5 rounded">{apiUrl}/api</code></li>
<li>Make sure &quot;Cursor Monitor: Vibn Enabled&quot; is checked</li>
<li>Reload Cursor to start tracking</li>
</ol>
</div>
</>
)}
{extensionInstalled && (
<div className="rounded-lg bg-green-500/10 border border-green-500/20 p-4">
<p className="text-sm text-green-700 dark:text-green-400">
Extension is installed and tracking your sessions
</p>
</div>
)}
</div>
</CardContent>
</Card>
{/* GitHub Connection */}
<Card className={githubConnected ? "border-green-500/50 bg-green-500/5" : ""}>
<CardHeader>
<div className="flex items-start justify-between">
<div className="flex items-center gap-3">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<Github className="h-6 w-6 text-primary" />
</div>
<div>
<div className="flex items-center gap-2">
<CardTitle>GitHub</CardTitle>
{githubConnected && (
<CheckCircle2 className="h-4 w-4 text-green-600" />
)}
</div>
<CardDescription>
Connect your repositories for automatic analysis
</CardDescription>
</div>
</div>
{!githubConnected ? (
<Button onClick={handleConnectGitHub}>
<Github className="h-4 w-4 mr-2" />
Connect GitHub
</Button>
) : (
<Button variant="outline" disabled>
<CheckCircle2 className="h-4 w-4 mr-2" />
Connected
</Button>
)}
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="space-y-2 text-sm text-muted-foreground">
<p className="font-medium text-foreground">What we&apos;ll access:</p>
<ul className="list-disc list-inside space-y-1 ml-2">
<li>Read your repository code and structure</li>
<li>Access repository metadata and commit history</li>
<li>Analyze tech stack and dependencies</li>
<li>Identify project architecture patterns</li>
</ul>
</div>
{!githubConnected && (
<div className="rounded-lg bg-muted p-4 space-y-2">
<p className="text-sm font-medium">Why connect GitHub?</p>
<p className="text-sm text-muted-foreground">
Our AI will analyze your codebase to understand your tech stack,
architecture, and features. This helps generate better documentation
and provides smarter insights.
</p>
</div>
)}
{githubConnected && (
<div className="rounded-lg bg-green-500/10 border border-green-500/20 p-4">
<p className="text-sm text-green-700 dark:text-green-400">
GitHub connected - Your repositories are ready for analysis
</p>
</div>
)}
</div>
</CardContent>
</Card>
{/* ChatGPT (MCP) Connection */}
<MCPConnectionCard />
{/* ChatGPT Import */}
<ChatGPTImportCard />
</div>
{/* Status Summary */}
{(githubConnected || extensionInstalled) && (
<Card className="bg-primary/5 border-primary/20">
<CardHeader>
<CardTitle className="text-lg">Connection Status</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span className="flex items-center gap-2">
<CursorIcon className="h-4 w-4" />
Cursor Extension
</span>
{extensionInstalled ? (
<span className="text-green-600 flex items-center gap-1">
<CheckCircle2 className="h-4 w-4" />
Installed
</span>
) : (
<span className="text-muted-foreground">Not installed</span>
)}
</div>
<div className="flex items-center justify-between text-sm">
<span className="flex items-center gap-2">
<Github className="h-4 w-4" />
GitHub
</span>
{githubConnected ? (
<span className="text-green-600 flex items-center gap-1">
<CheckCircle2 className="h-4 w-4" />
Connected
</span>
) : (
<span className="text-muted-foreground">Not connected</span>
)}
</div>
</div>
</CardContent>
</Card>
)}
</div>
</div>
);
}