diff --git a/src/components/images/DropZone.tsx b/src/components/images/DropZone.tsx new file mode 100644 index 0000000..ea1a5ea --- /dev/null +++ b/src/components/images/DropZone.tsx @@ -0,0 +1,73 @@ +'use client' +import { useCallback, useRef, useState } from 'react' + +interface DropZoneProps { + onFiles: (files: File[]) => void + disabled?: boolean +} + +const ACCEPTED_TYPES = ['.heic', '.heif', '.jpg', '.jpeg', '.png', '.zip'] +const ACCEPT_ATTR = ACCEPTED_TYPES.join(',') + +export function DropZone({ onFiles, disabled = false }: DropZoneProps) { + const [isDragging, setIsDragging] = useState(false) + const inputRef = useRef(null) + + const handleFiles = useCallback( + (fileList: FileList | null) => { + if (!fileList) return + const files = Array.from(fileList).filter((f) => { + const ext = '.' + f.name.split('.').pop()?.toLowerCase() + return ACCEPTED_TYPES.includes(ext) + }) + if (files.length > 0) onFiles(files) + }, + [onFiles], + ) + + const onDragOver = (e: React.DragEvent) => { + e.preventDefault() + if (!disabled) setIsDragging(true) + } + + const onDragLeave = () => setIsDragging(false) + + const onDrop = (e: React.DragEvent) => { + e.preventDefault() + setIsDragging(false) + if (!disabled) handleFiles(e.dataTransfer.files) + } + + return ( +
!disabled && inputRef.current?.click()} + className={`border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-colors ${ + isDragging + ? 'border-indigo-400 bg-indigo-950/30' + : disabled + ? 'border-slate-700 bg-slate-800/20 cursor-not-allowed' + : 'border-slate-600 bg-slate-800/10 hover:border-indigo-500 hover:bg-indigo-950/20' + }`} + > +
🖼️
+

+ Déposez vos images ici ou cliquez pour parcourir +

+

+ HEIC, JPG, PNG, ZIP — le nom du fichier = référence produit +

+ handleFiles(e.target.files)} + disabled={disabled} + /> +
+ ) +}