import React, { useState, useRef, useCallback, useEffect } from 'react'; import { Upload, LogIn, LogOut, FileText, Clock, ChevronLeft, ChevronRight, Settings, History, MousePointerClick, FileUp, ClipboardPaste, Loader2 } from 'lucide-react'; import { useAuth } from '../contexts/AuthContext'; import { FileRecord } from '../types'; import AuthModal from './AuthModal'; interface LeftSidebarProps { files: FileRecord[]; selectedFileId: string | null; onFileSelect: (fileId: string) => void; onUploadClick: () => void; isCollapsed: boolean; onToggleCollapse: () => void; onUploadFiles: (files: File[]) => void; hasMore: boolean; loadingMore: boolean; onLoadMore: () => void; } export default function LeftSidebar({ files, selectedFileId, onFileSelect, onUploadClick, isCollapsed, onToggleCollapse, onUploadFiles, hasMore, loadingMore, onLoadMore, }: LeftSidebarProps) { const { user, signOut } = useAuth(); const [showAuthModal, setShowAuthModal] = useState(false); const [isDragging, setIsDragging] = useState(false); const fileInputRef = useRef(null); const listRef = useRef(null); // Handle scroll to load more const handleScroll = useCallback(() => { if (!listRef.current || loadingMore || !hasMore) return; const { scrollTop, scrollHeight, clientHeight } = listRef.current; // Trigger load more when scrolled to bottom (with 50px threshold) if (scrollHeight - scrollTop - clientHeight < 50) { onLoadMore(); } }, [loadingMore, hasMore, onLoadMore]); // Auto-load more if content doesn't fill the container useEffect(() => { if (!hasMore || loadingMore || !user || files.length === 0) return; // Use requestAnimationFrame to ensure DOM has been updated const checkAndLoadMore = () => { requestAnimationFrame(() => { if (!listRef.current) return; const { scrollHeight, clientHeight } = listRef.current; // If content doesn't fill container and there's more data, load more if (scrollHeight <= clientHeight && hasMore && !loadingMore) { onLoadMore(); } }); }; // Small delay to ensure DOM is fully rendered const timer = setTimeout(checkAndLoadMore, 100); return () => clearTimeout(timer); }, [files.length, hasMore, loadingMore, onLoadMore, user]); const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }; const handleDragLeave = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); const droppedFiles = Array.from(e.dataTransfer.files); const validFiles = droppedFiles.filter(file => file.type.startsWith('image/') || file.type === 'application/pdf' ); if (validFiles.length > 0) { onUploadFiles(validFiles); } }; const handleFileChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { onUploadFiles(Array.from(e.target.files)); } // Reset input if (fileInputRef.current) { fileInputRef.current.value = ''; } }; if (isCollapsed) { return (
); } return ( <>
{/* Top Area: Title & Upload */}

Formula Recognize

Support handwriting and printed formulas

fileInputRef.current?.click()} className={` border-2 border-dashed rounded-xl p-6 text-center cursor-pointer transition-all duration-200 group ${isDragging ? 'border-blue-500 bg-blue-50' : 'border-gray-200 hover:border-blue-400 hover:bg-gray-50' } `} >
Click
Drop
Paste
{/* Middle Area: History */}
History
{!user ? (
Please login to view history
) : files.length === 0 ? (
No history records
) : ( <> {files.map((file) => ( ))} {/* Loading more indicator */} {loadingMore && (
Loading...
)} {/* End of list indicator */} {!hasMore && files.length > 0 && (
No more records
)} )}
{/* Bottom Area: User/Login */}
{user ? (

{user.email}

) : ( )}
{showAuthModal && ( setShowAuthModal(false)} /> )} ); }