Fix dragCounterRef going negative in audit list dropzone
Clamp the counter with Math.max(0, ...) and use <= 0 check to prevent the drag overlay from getting stuck when dragLeave fires more than dragEnter. Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -20,8 +20,10 @@ import {
|
|||||||
Thead,
|
Thead,
|
||||||
Tr,
|
Tr,
|
||||||
useDialogRef,
|
useDialogRef,
|
||||||
|
useToast,
|
||||||
} from "@probo/ui";
|
} from "@probo/ui";
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import {
|
import {
|
||||||
graphql,
|
graphql,
|
||||||
@@ -91,6 +93,7 @@ type Props = {
|
|||||||
|
|
||||||
export default function AuditsPage(props: Props) {
|
export default function AuditsPage(props: Props) {
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
|
const { toast } = useToast();
|
||||||
const organizationId = useOrganizationId();
|
const organizationId = useOrganizationId();
|
||||||
|
|
||||||
const data = usePreloadedQuery(auditsQuery, props.queryRef);
|
const data = usePreloadedQuery(auditsQuery, props.queryRef);
|
||||||
@@ -115,14 +118,22 @@ export default function AuditsPage(props: Props) {
|
|||||||
const dragCounterRef = useRef(0);
|
const dragCounterRef = useRef(0);
|
||||||
|
|
||||||
const onDrop = useCallback(
|
const onDrop = useCallback(
|
||||||
(acceptedFiles: File[]) => {
|
(acceptedFiles: File[], fileRejections: { file: File }[]) => {
|
||||||
setIsDragging(false);
|
setIsDragging(false);
|
||||||
dragCounterRef.current = 0;
|
dragCounterRef.current = 0;
|
||||||
|
if (fileRejections.length > 0) {
|
||||||
|
toast({
|
||||||
|
title: __("Unsupported file type"),
|
||||||
|
description: __("Only PDF files are supported."),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!canCreateAudit || acceptedFiles.length === 0) return;
|
if (!canCreateAudit || acceptedFiles.length === 0) return;
|
||||||
setDroppedFile(acceptedFiles[0]);
|
setDroppedFile(acceptedFiles[0]);
|
||||||
dropDialogRef.current?.open();
|
dropDialogRef.current?.open();
|
||||||
},
|
},
|
||||||
[canCreateAudit, dropDialogRef],
|
[canCreateAudit, dropDialogRef, toast, __],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -138,8 +149,8 @@ export default function AuditsPage(props: Props) {
|
|||||||
|
|
||||||
const handleDragLeave = (e: DragEvent) => {
|
const handleDragLeave = (e: DragEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
dragCounterRef.current--;
|
dragCounterRef.current = Math.max(0, dragCounterRef.current - 1);
|
||||||
if (dragCounterRef.current === 0) {
|
if (dragCounterRef.current <= 0) {
|
||||||
setIsDragging(false);
|
setIsDragging(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -179,19 +190,28 @@ export default function AuditsPage(props: Props) {
|
|||||||
setDroppedFile(null);
|
setDroppedFile(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mainRef = useRef<HTMLElement | null>(null);
|
||||||
|
useEffect(() => {
|
||||||
|
mainRef.current = document.querySelector("main");
|
||||||
|
if (mainRef.current) {
|
||||||
|
mainRef.current.style.position = "relative";
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{isDragging && canCreateAudit && (
|
{isDragging && canCreateAudit && mainRef.current && createPortal(
|
||||||
<div
|
<div
|
||||||
{...getRootProps()}
|
{...getRootProps()}
|
||||||
className="border-primary bg-primary/5 pointer-events-auto fixed inset-0 top-12 z-40 flex flex-col items-center justify-center border-2 border-dashed"
|
className="border-primary bg-primary/5 pointer-events-auto absolute inset-0 z-40 flex flex-col items-center justify-center border-2 border-dashed"
|
||||||
>
|
>
|
||||||
<input {...getInputProps()} />
|
<input {...getInputProps()} />
|
||||||
<IconUpload className="text-primary mb-2 size-8" />
|
<IconUpload className="text-primary mb-2 size-8" />
|
||||||
<p className="text-primary text-sm font-medium">
|
<p className="text-primary text-sm font-medium">
|
||||||
{__("Drop a PDF to create an audit with a report")}
|
{__("Drop a PDF to create an audit with a report")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>,
|
||||||
|
mainRef.current,
|
||||||
)}
|
)}
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={__("Audits")}
|
title={__("Audits")}
|
||||||
|
|||||||
Reference in New Issue
Block a user