"use client" import { useState, useEffect } from "react" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { FileText, Folder, Plus, Trash2 } from "lucide-react" import { Card, CardContent } from "@/components/ui/card" interface GoogleDrivePickerProps { onFileSelected: (files: GoogleDriveFile[]) => void selectedFiles?: GoogleDriveFile[] isAuthenticated: boolean accessToken?: string onPickerStateChange?: (isOpen: boolean) => void } interface GoogleDriveFile { id: string name: string mimeType: string webViewLink?: string iconLink?: string size?: number modifiedTime?: string isFolder?: boolean } interface GoogleAPI { load: (api: string, options: { callback: () => void; onerror?: () => void }) => void } interface GooglePickerData { action: string docs: GooglePickerDocument[] } interface GooglePickerDocument { [key: string]: string } declare global { interface Window { gapi: GoogleAPI google: { picker: { api: { load: (callback: () => void) => void } PickerBuilder: new () => GooglePickerBuilder ViewId: { DOCS: string FOLDERS: string DOCS_IMAGES_AND_VIDEOS: string DOCUMENTS: string PRESENTATIONS: string SPREADSHEETS: string } Feature: { MULTISELECT_ENABLED: string NAV_HIDDEN: string SIMPLE_UPLOAD_ENABLED: string } Action: { PICKED: string CANCEL: string } Document: { ID: string NAME: string MIME_TYPE: string URL: string ICON_URL: string } } } } } interface GooglePickerBuilder { addView: (view: string) => GooglePickerBuilder setOAuthToken: (token: string) => GooglePickerBuilder setCallback: (callback: (data: GooglePickerData) => void) => GooglePickerBuilder enableFeature: (feature: string) => GooglePickerBuilder setTitle: (title: string) => GooglePickerBuilder build: () => GooglePicker } interface GooglePicker { setVisible: (visible: boolean) => void } export function GoogleDrivePicker({ onFileSelected, selectedFiles = [], isAuthenticated, accessToken, onPickerStateChange }: GoogleDrivePickerProps) { const [isPickerLoaded, setIsPickerLoaded] = useState(false) const [isPickerOpen, setIsPickerOpen] = useState(false) useEffect(() => { const loadPickerApi = () => { if (typeof window !== 'undefined' && window.gapi) { window.gapi.load('picker', { callback: () => { setIsPickerLoaded(true) }, onerror: () => { console.error('Failed to load Google Picker API') } }) } } // Load Google API script if not already loaded if (typeof window !== 'undefined') { if (!window.gapi) { const script = document.createElement('script') script.src = 'https://apis.google.com/js/api.js' script.async = true script.defer = true script.onload = loadPickerApi script.onerror = () => { console.error('Failed to load Google API script') } document.head.appendChild(script) return () => { if (document.head.contains(script)) { document.head.removeChild(script) } } } else { loadPickerApi() } } }, []) const openPicker = () => { if (!isPickerLoaded || !accessToken || !window.google?.picker) { return } try { setIsPickerOpen(true) onPickerStateChange?.(true) // Create picker with higher z-index and focus handling const picker = new window.google.picker.PickerBuilder() .addView(window.google.picker.ViewId.DOCS) .addView(window.google.picker.ViewId.FOLDERS) .setOAuthToken(accessToken) .enableFeature(window.google.picker.Feature.MULTISELECT_ENABLED) .setTitle('Select files from Google Drive') .setCallback(pickerCallback) .build() picker.setVisible(true) // Apply z-index fix after a short delay to ensure picker is rendered setTimeout(() => { const pickerElements = document.querySelectorAll('.picker-dialog, .goog-modalpopup') pickerElements.forEach(el => { (el as HTMLElement).style.zIndex = '10000' }) const bgElements = document.querySelectorAll('.picker-dialog-bg, .goog-modalpopup-bg') bgElements.forEach(el => { (el as HTMLElement).style.zIndex = '9999' }) }, 100) } catch (error) { console.error('Error creating picker:', error) setIsPickerOpen(false) onPickerStateChange?.(false) } } const pickerCallback = async (data: GooglePickerData) => { if (data.action === window.google.picker.Action.PICKED) { const files: GoogleDriveFile[] = data.docs.map((doc: GooglePickerDocument) => ({ id: doc[window.google.picker.Document.ID], name: doc[window.google.picker.Document.NAME], mimeType: doc[window.google.picker.Document.MIME_TYPE], webViewLink: doc[window.google.picker.Document.URL], iconLink: doc[window.google.picker.Document.ICON_URL], size: doc['sizeBytes'] ? parseInt(doc['sizeBytes']) : undefined, modifiedTime: doc['lastEditedUtc'], isFolder: doc[window.google.picker.Document.MIME_TYPE] === 'application/vnd.google-apps.folder' })) // If size is still missing, try to fetch it via Google Drive API if (accessToken && files.some(f => !f.size && !f.isFolder)) { try { const enrichedFiles = await Promise.all(files.map(async (file) => { if (!file.size && !file.isFolder) { try { const response = await fetch(`https://www.googleapis.com/drive/v3/files/${file.id}?fields=size,modifiedTime`, { headers: { 'Authorization': `Bearer ${accessToken}` } }) if (response.ok) { const fileDetails = await response.json() return { ...file, size: fileDetails.size ? parseInt(fileDetails.size) : undefined, modifiedTime: fileDetails.modifiedTime || file.modifiedTime } } } catch (error) { console.warn('Failed to fetch file details:', error) } } return file })) onFileSelected(enrichedFiles) } catch (error) { console.warn('Failed to enrich file data:', error) onFileSelected(files) } } else { onFileSelected(files) } } setIsPickerOpen(false) onPickerStateChange?.(false) } const removeFile = (fileId: string) => { const updatedFiles = selectedFiles.filter(file => file.id !== fileId) onFileSelected(updatedFiles) } const getFileIcon = (mimeType: string) => { if (mimeType.includes('folder')) { return } return } const getMimeTypeLabel = (mimeType: string) => { const typeMap: { [key: string]: string } = { 'application/vnd.google-apps.document': 'Google Doc', 'application/vnd.google-apps.spreadsheet': 'Google Sheet', 'application/vnd.google-apps.presentation': 'Google Slides', 'application/vnd.google-apps.folder': 'Folder', 'application/pdf': 'PDF', 'text/plain': 'Text', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word Doc', 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'PowerPoint' } return typeMap[mimeType] || 'Document' } const formatFileSize = (bytes?: number) => { if (!bytes) return '' const sizes = ['B', 'KB', 'MB', 'GB', 'TB'] if (bytes === 0) return '0 B' const i = Math.floor(Math.log(bytes) / Math.log(1024)) return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}` } if (!isAuthenticated) { return (
Please connect to Google Drive first to select specific files.
) } return (

Select files from Google Drive to ingest.

{selectedFiles.length > 0 && (

Added files

{selectedFiles.map((file) => (
{getFileIcon(file.mimeType)} {file.name} {getMimeTypeLabel(file.mimeType)}
{formatFileSize(file.size)}
))}
)}
) }