"use client" import * as React from "react" import Link from "next/link" import { usePathname } from "next/navigation" import { Command, Frame, HelpCircle, Settings2, Terminal, Target, Plus } from "lucide-react" import { NavUser } from "@/components/nav-user" import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, } from "@/components/ui/sidebar" import { useQuery, useMutation } from "convex/react" import { api } from "@/convex/_generated/api" import { Checkbox } from "@/components/ui/checkbox" import { Label } from "@/components/ui/label" import { useProject } from "@/components/project-context" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" export function AppSidebar({ ...props }: React.ComponentProps) { const pathname = usePathname() const projects = useQuery(api.projects.getProjects); const { selectedProjectId, setSelectedProjectId } = useProject(); const addDataSource = useMutation(api.dataSources.addDataSource); const updateDataSourceStatus = useMutation(api.dataSources.updateDataSourceStatus); const createAnalysis = useMutation(api.analyses.createAnalysis); const [isAdding, setIsAdding] = React.useState(false); const [sourceUrl, setSourceUrl] = React.useState(""); const [sourceName, setSourceName] = React.useState(""); const [sourceError, setSourceError] = React.useState(null); const [isSubmittingSource, setIsSubmittingSource] = React.useState(false); // Set default selected project React.useEffect(() => { if (projects && projects.length > 0 && !selectedProjectId) { // Prefer default project, otherwise first const defaultProj = projects.find(p => p.isDefault); setSelectedProjectId(defaultProj ? defaultProj._id : projects[0]._id); } }, [projects, selectedProjectId]); // Data Sources Query const dataSources = useQuery( api.dataSources.getProjectDataSources, selectedProjectId ? { projectId: selectedProjectId as any } : "skip" ); const toggleConfig = useMutation(api.projects.toggleDataSourceConfig); const selectedProject = projects?.find(p => p._id === selectedProjectId); const selectedSourceIds = selectedProject?.dorkingConfig?.selectedSourceIds || []; const handleToggle = async (sourceId: string, checked: boolean) => { if (!selectedProjectId) return; await toggleConfig({ projectId: selectedProjectId as any, sourceId: sourceId as any, selected: checked }); }; const handleAddSource = async () => { if (!sourceUrl) { setSourceError("Please enter a URL."); return; } setSourceError(null); setIsSubmittingSource(true); try { const { sourceId, projectId } = await addDataSource({ projectId: selectedProjectId as any, url: sourceUrl, name: sourceName || sourceUrl, type: "website", }); await updateDataSourceStatus({ dataSourceId: sourceId, analysisStatus: "pending", lastError: undefined, lastAnalyzedAt: undefined, }); const response = await fetch("/api/analyze", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ url: sourceUrl }), }); const data = await response.json(); if (!response.ok) { await updateDataSourceStatus({ dataSourceId: sourceId, analysisStatus: "failed", lastError: data.error || "Analysis failed", lastAnalyzedAt: Date.now(), }); throw new Error(data.error || "Analysis failed"); } await createAnalysis({ projectId, dataSourceId: sourceId, analysis: data.data, }); await updateDataSourceStatus({ dataSourceId: sourceId, analysisStatus: "completed", lastError: undefined, lastAnalyzedAt: Date.now(), }); setSourceUrl(""); setSourceName(""); setIsAdding(false); } catch (err: any) { setSourceError(err?.message || "Failed to add source."); } finally { setIsSubmittingSource(false); } }; return (
Sanati Pro
{/* Platform Nav */} Platform Dashboard Opportunities Settings Help {/* Projects (Simple List for now, can be switcher) */} Projects {projects?.map((project) => ( setSelectedProjectId(project._id)} isActive={selectedProjectId === project._id} > {project.name} ))} Create Project {/* Data Sources Config */} {selectedProjectId && ( Active Data Sources ({selectedProject?.name})
{(!dataSources || dataSources.length === 0) && (
No data sources yet.
)} {dataSources?.map((source) => (
handleToggle(source._id, checked === true)} />
))}
)}
Add Data Source Add a website to analyze for this project.
setSourceUrl(event.target.value)} disabled={isSubmittingSource} />
setSourceName(event.target.value)} disabled={isSubmittingSource} />
{sourceError && (
{sourceError}
)}
) }