mirror of
https://github.com/marcogll/TaxHacker_s23.git
synced 2026-01-13 21:35:19 +00:00
164 lines
5.7 KiB
TypeScript
164 lines
5.7 KiB
TypeScript
"use client"
|
|
|
|
import { useNotification } from "@/app/(app)/context"
|
|
import { uploadFilesAction } from "@/app/(app)/files/actions"
|
|
import { uploadTransactionFilesAction } from "@/app/(app)/transactions/actions"
|
|
import { AlertCircle, CloudUpload, Loader2 } from "lucide-react"
|
|
import { useParams, useRouter } from "next/navigation"
|
|
import { useCallback, useEffect, useRef, useState } from "react"
|
|
|
|
export default function ScreenDropArea({ children }: { children: React.ReactNode }) {
|
|
const router = useRouter()
|
|
const { showNotification } = useNotification()
|
|
const [isDragging, setIsDragging] = useState(false)
|
|
const [isUploading, setIsUploading] = useState(false)
|
|
const [uploadError, setUploadError] = useState("")
|
|
const dragCounter = useRef(0)
|
|
const { transactionId } = useParams()
|
|
|
|
const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
|
|
// Check if the dragged items are files
|
|
const items = e.dataTransfer.items
|
|
if (!items) return
|
|
|
|
let hasFiles = false
|
|
for (const item of items) {
|
|
if (item.kind === "file") {
|
|
hasFiles = true
|
|
break
|
|
}
|
|
}
|
|
if (!hasFiles) return
|
|
|
|
dragCounter.current++
|
|
if (dragCounter.current === 1) {
|
|
setIsDragging(true)
|
|
}
|
|
}
|
|
|
|
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
}
|
|
|
|
const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
dragCounter.current--
|
|
|
|
if (dragCounter.current === 0) {
|
|
setIsDragging(false)
|
|
}
|
|
}
|
|
|
|
const handleDrop = useCallback(
|
|
async (e: React.DragEvent<HTMLDivElement>) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
|
|
// Reset counter and dragging state
|
|
dragCounter.current = 0
|
|
setIsDragging(false)
|
|
|
|
const files = e.dataTransfer.files
|
|
if (files && files.length > 0) {
|
|
setIsUploading(true)
|
|
setUploadError("")
|
|
|
|
try {
|
|
const formData = new FormData()
|
|
if (transactionId) {
|
|
formData.append("transactionId", transactionId as string)
|
|
}
|
|
for (let i = 0; i < files.length; i++) {
|
|
formData.append("files", files[i])
|
|
}
|
|
|
|
const result = transactionId
|
|
? await uploadTransactionFilesAction(formData)
|
|
: await uploadFilesAction(formData)
|
|
|
|
if (result.success) {
|
|
showNotification({ code: "sidebar.unsorted", message: "new" })
|
|
setTimeout(() => showNotification({ code: "sidebar.unsorted", message: "" }), 3000)
|
|
if (!transactionId) {
|
|
router.push("/unsorted")
|
|
}
|
|
} else {
|
|
setUploadError(result.error ? result.error : "Something went wrong...")
|
|
}
|
|
} catch (error) {
|
|
console.error("Upload error:", error)
|
|
setUploadError(error instanceof Error ? error.message : "Something went wrong...")
|
|
} finally {
|
|
setIsUploading(false)
|
|
}
|
|
}
|
|
},
|
|
[transactionId, router, showNotification]
|
|
)
|
|
|
|
// Add event listeners to document body
|
|
useEffect(() => {
|
|
document.body.addEventListener("dragenter", handleDragEnter as unknown as EventListener)
|
|
document.body.addEventListener("dragover", handleDragOver as unknown as EventListener)
|
|
document.body.addEventListener("dragleave", handleDragLeave as unknown as EventListener)
|
|
document.body.addEventListener("drop", handleDrop as unknown as EventListener)
|
|
|
|
return () => {
|
|
document.body.removeEventListener("dragenter", handleDragEnter as unknown as EventListener)
|
|
document.body.removeEventListener("dragover", handleDragOver as unknown as EventListener)
|
|
document.body.removeEventListener("dragleave", handleDragLeave as unknown as EventListener)
|
|
document.body.removeEventListener("drop", handleDrop as unknown as EventListener)
|
|
}
|
|
}, [isDragging, handleDrop])
|
|
|
|
return (
|
|
<div className="relative min-h-screen w-full">
|
|
{children}
|
|
|
|
{isDragging && (
|
|
<div
|
|
className="fixed inset-0 bg-opacity-20 backdrop-blur-sm z-50 flex items-center justify-center"
|
|
onDragEnter={handleDragEnter}
|
|
onDragOver={handleDragOver}
|
|
onDragLeave={handleDragLeave}
|
|
onDrop={handleDrop}
|
|
>
|
|
<div className="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-xl text-center">
|
|
<CloudUpload className="h-16 w-16 mx-auto mb-4 text-primary" />
|
|
<h3 className="text-xl font-semibold mb-2">
|
|
{transactionId ? "Drop Files to Add to Transaction" : "Drop Files to Upload"}
|
|
</h3>
|
|
<p className="text-gray-600 dark:text-gray-400">Drop anywhere on the screen</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{isUploading && (
|
|
<div className="fixed inset-0 bg-opacity-20 backdrop-blur-sm z-50 flex items-center justify-center">
|
|
<div className="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-xl text-center">
|
|
<Loader2 className="h-16 w-16 mx-auto mb-4 text-primary animate-spin" />
|
|
<h3 className="text-xl font-semibold mb-2">
|
|
{transactionId ? "Adding files to transaction..." : "Uploading..."}
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{uploadError && (
|
|
<div className="fixed inset-0 bg-opacity-20 backdrop-blur-sm z-50 flex items-center justify-center">
|
|
<div className="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-xl text-center">
|
|
<AlertCircle className="h-16 w-16 mx-auto mb-4 text-red-500" />
|
|
<h3 className="text-xl font-semibold mb-2">Upload Error</h3>
|
|
<p className="text-gray-600 dark:text-gray-400">{uploadError}</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|