| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- import React, { useCallback, useState } from 'react';
- import { Upload as UploadIcon, FileText, Image as ImageIcon, Folder, FileUp, ShieldCheck } from 'lucide-react';
- import { useLanguage } from '../contexts/LanguageContext';
- import { GROUP_ALLOWED_EXTENSIONS, IMAGE_MIME_TYPES } from '../constants/fileSupport';
- import { motion, AnimatePresence } from 'framer-motion';
- interface NotebookDragDropUploadProps {
- onFilesSelected: (files: FileList) => void;
- isAdmin: boolean;
- globalMode?: boolean;
- children?: React.ReactNode;
- }
- export const NotebookDragDropUpload: React.FC<NotebookDragDropUploadProps> = ({ onFilesSelected, isAdmin, globalMode = false, children }) => {
- const { t } = useLanguage();
- const [isDragging, setIsDragging] = useState(false);
- const handleDragEnter = useCallback((e: React.DragEvent) => {
- e.preventDefault();
- e.stopPropagation();
- if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
- setIsDragging(true);
- }
- }, []);
- const handleDragLeave = useCallback((e: React.DragEvent) => {
- e.preventDefault();
- e.stopPropagation();
- setIsDragging(false);
- }, []);
- const handleDragOver = useCallback((e: React.DragEvent) => {
- e.preventDefault();
- e.stopPropagation();
- e.dataTransfer.dropEffect = 'copy';
- }, []);
- const handleDrop = useCallback((e: React.DragEvent) => {
- e.preventDefault();
- e.stopPropagation();
- setIsDragging(false);
- if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
- onFilesSelected(e.dataTransfer.files);
- e.dataTransfer.clearData();
- }
- }, [onFilesSelected]);
- const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
- if (e.target.files && e.target.files.length > 0) {
- onFilesSelected(e.target.files);
- e.target.value = '';
- }
- };
- if (!isAdmin) return <>{children}</>;
- return (
- <div className="relative h-full flex flex-col">
- <AnimatePresence>
- {isDragging && (
- <motion.div
- initial={{ opacity: 0 }}
- animate={{ opacity: 1 }}
- exit={{ opacity: 0 }}
- className="absolute inset-0 z-[100] bg-blue-600/10 backdrop-blur-sm flex items-center justify-center p-8 pointer-events-none"
- >
- <motion.div
- initial={{ scale: 0.9 }}
- animate={{ scale: 1 }}
- className="bg-white rounded-[2rem] p-10 text-center shadow-2xl border border-blue-100 flex flex-col items-center gap-6"
- >
- <div className="w-16 h-16 bg-blue-600 text-white rounded-2xl flex items-center justify-center animate-bounce">
- <FileUp size={32} />
- </div>
- <div className="space-y-1">
- <h3 className="text-xl font-bold text-slate-900">Ingest into Group</h3>
- <p className="text-slate-500 font-medium text-sm">Release to start processing</p>
- </div>
- </motion.div>
- </motion.div>
- )}
- </AnimatePresence>
- <div
- className="flex-1 flex flex-col"
- onDragEnter={handleDragEnter}
- onDragOver={handleDragOver}
- onDragLeave={handleDragLeave}
- onDrop={handleDrop}
- >
- {children}
- </div>
- <input
- type="file"
- multiple
- onChange={handleFileInput}
- className="hidden"
- id="notebook-file-upload-input"
- accept={GROUP_ALLOWED_EXTENSIONS.map(ext => `.${ext}`).join(',') + ',' + IMAGE_MIME_TYPES.join(',')}
- />
- </div>
- );
- };
|