'use client'; import { useEffect, useState } from 'react'; import { db, auth } from '@/lib/firebase/config'; import { collection, query, where, limit, getDocs, orderBy } from 'firebase/firestore'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { FolderOpen, Plus, Link as LinkIcon } from 'lucide-react'; import { toast } from 'sonner'; import { ProjectCreationModal } from './project-creation-modal'; interface UnassociatedWorkspace { workspacePath: string; workspaceName: string; sessionCount: number; } interface Project { id: string; name: string; productName: string; slug: string; } export function ProjectAssociationPrompt({ workspace }: { workspace: string }) { // Temporarily disabled - will be re-enabled with better UX return null; const [unassociatedWorkspace, setUnassociatedWorkspace] = useState(null); const [projects, setProjects] = useState([]); const [showDialog, setShowDialog] = useState(false); const [showCreationModal, setShowCreationModal] = useState(false); const [loading, setLoading] = useState(false); const [dismissedWorkspaces, setDismissedWorkspaces] = useState>(new Set()); const [hasCheckedThisSession, setHasCheckedThisSession] = useState(false); // Load dismissed workspaces from localStorage on mount useEffect(() => { const stored = localStorage.getItem('dismissedWorkspaces'); if (stored) { try { setDismissedWorkspaces(new Set(JSON.parse(stored))); } catch (e) { console.error('Error loading dismissed workspaces:', e); } } }, []); useEffect(() => { let unsubscribe: () => void; const checkForUnassociatedSessions = async (user: any) => { // Check if we've already shown the prompt in this browser session const lastPromptTime = sessionStorage.getItem('vibn_last_workspace_prompt'); const now = Date.now(); const fiveMinutes = 5 * 60 * 1000; if (lastPromptTime && (now - parseInt(lastPromptTime)) < fiveMinutes) { console.log('⏭️ Already checked recently, skipping'); return; } try { // Mark that we've checked sessionStorage.setItem('vibn_last_workspace_prompt', now.toString()); // Check for sessions that need project association const sessionsRef = collection(db, 'sessions'); const q = query( sessionsRef, where('userId', '==', user.uid), where('needsProjectAssociation', '==', true), orderBy('createdAt', 'desc'), limit(1) ); const snapshot = await getDocs(q); if (!snapshot.empty) { const session = snapshot.docs[0].data(); // Check if this workspace was dismissed if (dismissedWorkspaces.has(session.workspacePath)) { console.log('⏭️ Workspace was dismissed, skipping prompt'); return; } // Count sessions from this workspace const countQuery = query( sessionsRef, where('userId', '==', user.uid), where('workspacePath', '==', session.workspacePath), where('needsProjectAssociation', '==', true) ); const countSnapshot = await getDocs(countQuery); setUnassociatedWorkspace({ workspacePath: session.workspacePath, workspaceName: session.workspaceName || 'Unknown', sessionCount: countSnapshot.size, }); // Fetch user's projects for linking const projectsRef = collection(db, 'projects'); const projectsQuery = query( projectsRef, where('userId', '==', user.uid), orderBy('createdAt', 'desc') ); const projectsSnapshot = await getDocs(projectsQuery); const userProjects = projectsSnapshot.docs.map(doc => ({ id: doc.id, name: doc.data().name, productName: doc.data().productName, slug: doc.data().slug, })); setProjects(userProjects); setShowDialog(true); } } catch (error: any) { // Silently handle index building errors - the feature will work once indexes are ready if (error?.message?.includes('index')) { console.log('⏳ Firestore indexes are still building. Project detection will be available shortly.'); } else { console.error('Error checking for unassociated sessions:', error); } } }; unsubscribe = auth.onAuthStateChanged((user) => { if (user) { checkForUnassociatedSessions(user); } }); return () => { if (unsubscribe) unsubscribe(); }; }, []); // Empty dependency array - only run once on mount const handleCreateNewProject = () => { setShowDialog(false); setShowCreationModal(true); }; const handleRemindLater = () => { if (!unassociatedWorkspace) return; // Add to dismissed list const newDismissed = new Set(dismissedWorkspaces); newDismissed.add(unassociatedWorkspace.workspacePath); setDismissedWorkspaces(newDismissed); // Save to localStorage localStorage.setItem('dismissedWorkspaces', JSON.stringify(Array.from(newDismissed))); // Close dialog setShowDialog(false); setUnassociatedWorkspace(null); toast.info('💡 We\'ll remind you next time you visit'); }; const handleLinkToProject = async (projectId: string) => { if (!unassociatedWorkspace || !auth.currentUser) return; setLoading(true); try { const response = await fetch('/api/sessions/associate-project', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ workspacePath: unassociatedWorkspace.workspacePath, projectId, userId: auth.currentUser.uid, }), }); if (response.ok) { const data = await response.json(); toast.success(`✅ Linked ${data.sessionsUpdated} sessions to project!`); setShowDialog(false); setUnassociatedWorkspace(null); } else { toast.error('Failed to link sessions to project'); } } catch (error) { console.error('Error linking project:', error); toast.error('An error occurred while linking'); } finally { setLoading(false); } }; if (!unassociatedWorkspace) return null; return ( <> New Workspace Detected We detected coding activity in a new workspace {unassociatedWorkspace && (
📂

{unassociatedWorkspace?.workspaceName}

{unassociatedWorkspace?.workspacePath}

{unassociatedWorkspace?.sessionCount} coding session{(unassociatedWorkspace?.sessionCount || 0) > 1 ? 's' : ''} tracked

)}

What would you like to do?

{projects.length > 0 && ( <>
Or link to existing project
{projects.map((project) => ( ))}
)}
{/* Project Creation Modal */} { setShowCreationModal(open); if (!open) { // Refresh to check for newly created project setUnassociatedWorkspace(null); } }} initialWorkspacePath={unassociatedWorkspace?.workspacePath} workspace={workspace} /> ); }