"use client"; import { useState, useEffect } from "react"; import { useParams, useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; import { ArrowLeft, AlertCircle } from "lucide-react"; import { UnifiedCloudPicker, CloudFile } from "@/components/cloud-picker"; import { useTask } from "@/contexts/task-context"; import { Toast } from "@/components/ui/toast"; // CloudFile interface is now imported from the unified cloud picker interface CloudConnector { id: string; name: string; description: string; status: "not_connected" | "connecting" | "connected" | "error"; type: string; connectionId?: string; clientId: string; hasAccessToken: boolean; accessTokenError?: string; } export default function UploadProviderPage() { const params = useParams(); const router = useRouter(); const provider = params.provider as string; const { addTask, tasks } = useTask(); const [connector, setConnector] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [accessToken, setAccessToken] = useState(null); const [selectedFiles, setSelectedFiles] = useState([]); const [isIngesting, setIsIngesting] = useState(false); const [currentSyncTaskId, setCurrentSyncTaskId] = useState( null ); const [showSuccessToast, setShowSuccessToast] = useState(false); useEffect(() => { const fetchConnectorInfo = async () => { setIsLoading(true); setError(null); try { // Fetch available connectors to validate the provider const connectorsResponse = await fetch("/api/connectors"); if (!connectorsResponse.ok) { throw new Error("Failed to load connectors"); } const connectorsResult = await connectorsResponse.json(); const providerInfo = connectorsResult.connectors[provider]; if (!providerInfo || !providerInfo.available) { setError( `Cloud provider "${provider}" is not available or configured.` ); return; } // Check connector status const statusResponse = await fetch( `/api/connectors/${provider}/status` ); if (!statusResponse.ok) { throw new Error(`Failed to check ${provider} status`); } const statusData = await statusResponse.json(); const connections = statusData.connections || []; const activeConnection = connections.find( (conn: { is_active: boolean; connection_id: string }) => conn.is_active ); const isConnected = activeConnection !== undefined; let hasAccessToken = false; let accessTokenError: string | undefined = undefined; // Try to get access token for connected connectors if (isConnected && activeConnection) { try { const tokenResponse = await fetch( `/api/connectors/${provider}/token?connection_id=${activeConnection.connection_id}` ); if (tokenResponse.ok) { const tokenData = await tokenResponse.json(); if (tokenData.access_token) { hasAccessToken = true; setAccessToken(tokenData.access_token); } } else { const errorData = await tokenResponse .json() .catch(() => ({ error: "Token unavailable" })); accessTokenError = errorData.error || "Access token unavailable"; } } catch { accessTokenError = "Failed to fetch access token"; } } setConnector({ id: provider, name: providerInfo.name, description: providerInfo.description, status: isConnected ? "connected" : "not_connected", type: provider, connectionId: activeConnection?.connection_id, clientId: activeConnection?.client_id, hasAccessToken, accessTokenError, }); } catch (error) { console.error("Failed to load connector info:", error); setError( error instanceof Error ? error.message : "Failed to load connector information" ); } finally { setIsLoading(false); } }; if (provider) { fetchConnectorInfo(); } }, [provider]); // Watch for sync task completion and redirect useEffect(() => { if (!currentSyncTaskId) return; const currentTask = tasks.find(task => task.task_id === currentSyncTaskId); if (currentTask && currentTask.status === "completed") { // Task completed successfully, show toast and redirect setIsIngesting(false); setShowSuccessToast(true); setTimeout(() => { router.push("/knowledge"); }, 2000); // 2 second delay to let user see toast } else if (currentTask && currentTask.status === "failed") { // Task failed, clear the tracking but don't redirect setIsIngesting(false); setCurrentSyncTaskId(null); } }, [tasks, currentSyncTaskId, router]); const handleFileSelected = (files: CloudFile[]) => { setSelectedFiles(files); console.log(`Selected ${files.length} files from ${provider}:`, files); // You can add additional handling here like triggering sync, etc. }; const handleSync = async (connector: CloudConnector) => { if (!connector.connectionId || selectedFiles.length === 0) return; setIsIngesting(true); try { const syncBody: { connection_id: string; max_files?: number; selected_files?: string[]; } = { connection_id: connector.connectionId, selected_files: selectedFiles.map(file => file.id), }; const response = await fetch(`/api/connectors/${connector.type}/sync`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(syncBody), }); const result = await response.json(); if (response.status === 201) { const taskIds = result.task_ids; if (taskIds && taskIds.length > 0) { const taskId = taskIds[0]; // Use the first task ID addTask(taskId); setCurrentSyncTaskId(taskId); } } else { console.error("Sync failed:", result.error); } } catch (error) { console.error("Sync error:", error); setIsIngesting(false); } }; const getProviderDisplayName = () => { const nameMap: { [key: string]: string } = { google_drive: "Google Drive", onedrive: "OneDrive", sharepoint: "SharePoint", }; return nameMap[provider] || provider; }; if (isLoading) { return (

Loading {getProviderDisplayName()} connector...

); } if (error || !connector) { return (

Provider Not Available

{error}

); } if (connector.status !== "connected") { return (

{connector.name} Not Connected

You need to connect your {connector.name} account before you can select files.

); } if (!connector.hasAccessToken) { return (

Access Token Required

{connector.accessTokenError || `Unable to get access token for ${connector.name}. Try reconnecting your account.`}

); } return (

Add from {getProviderDisplayName()}

{/* Success toast notification */} setShowSuccessToast(false)} duration={20000} />
); }