mirror of
https://github.com/harivansh-afk/Saas-Teamspace.git
synced 2026-04-15 06:04:43 +00:00
84 lines
2.5 KiB
TypeScript
84 lines
2.5 KiB
TypeScript
import * as React from "react"
|
|
import { useDropzone } from "react-dropzone"
|
|
import { Cloud, File, X } from "lucide-react"
|
|
import { Button } from "@/components/ui/button"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
interface FileUploadProps {
|
|
onUpload: (files: File[]) => void
|
|
value?: File[]
|
|
onChange?: (files: File[]) => void
|
|
className?: string
|
|
}
|
|
|
|
export function FileUpload({ onUpload, value = [], onChange, className }: FileUploadProps) {
|
|
const [files, setFiles] = React.useState<File[]>(value)
|
|
|
|
const onDrop = React.useCallback((acceptedFiles: File[]) => {
|
|
setFiles(prev => [...prev, ...acceptedFiles])
|
|
onChange?.(acceptedFiles)
|
|
onUpload(acceptedFiles)
|
|
}, [onChange, onUpload])
|
|
|
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
onDrop,
|
|
accept: {
|
|
'image/*': [],
|
|
'application/pdf': [],
|
|
'application/msword': [],
|
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': [],
|
|
}
|
|
})
|
|
|
|
const removeFile = (fileToRemove: File) => {
|
|
const newFiles = files.filter(file => file !== fileToRemove)
|
|
setFiles(newFiles)
|
|
onChange?.(newFiles)
|
|
}
|
|
|
|
return (
|
|
<div className={className}>
|
|
<div
|
|
{...getRootProps()}
|
|
className={cn(
|
|
"border-2 border-dashed rounded-lg p-8 text-center hover:border-primary/50 transition-colors",
|
|
isDragActive && "border-primary",
|
|
className
|
|
)}
|
|
>
|
|
<input {...getInputProps()} />
|
|
<div className="flex flex-col items-center gap-2">
|
|
<Cloud className="h-10 w-10 text-muted-foreground" />
|
|
<p className="text-sm text-muted-foreground">
|
|
Drag & drop files here, or click to select files
|
|
</p>
|
|
<Button variant="secondary" size="sm">
|
|
Select Files
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{files.length > 0 && (
|
|
<div className="mt-4 space-y-2">
|
|
{files.map((file, index) => (
|
|
<div
|
|
key={index}
|
|
className="flex items-center gap-2 rounded-md border p-2"
|
|
>
|
|
<File className="h-4 w-4 text-muted-foreground" />
|
|
<span className="text-sm flex-1 truncate">{file.name}</span>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-8 w-8"
|
|
onClick={() => removeFile(file)}
|
|
>
|
|
<X className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|