diff --git a/app/components/assets/bulk-actions-dropdown.tsx b/app/components/assets/bulk-actions-dropdown.tsx index 40a24a233..ec9c8ca78 100644 --- a/app/components/assets/bulk-actions-dropdown.tsx +++ b/app/components/assets/bulk-actions-dropdown.tsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import { useNavigation } from "@remix-run/react"; import { useAtomValue } from "jotai"; import { useHydrated } from "remix-utils/use-hydrated"; @@ -33,6 +34,7 @@ import { import When from "../when/when"; import BookSelectedAssetsDropdown from "./assets-index/book-selected-assets-dropdown"; import BulkDownloadQrDialog from "./bulk-download-qr-dialog"; +import Icon from "../icons/icon"; export default function BulkActionsDropdown() { const isHydrated = useHydrated(); @@ -58,6 +60,7 @@ export default function BulkActionsDropdown() { function ConditionalDropdown() { const navigation = useNavigation(); const isLoading = isFormProcessing(navigation.state); + const [isBulkDownloadQrOpen, setIsBulkDownloadQrOpen] = useState(false); const { ref: dropdownRef, @@ -130,6 +133,13 @@ function ConditionalDropdown() { + { + setIsBulkDownloadQrOpen(false); + }} + /> + - - + { + closeMenu(); + setIsBulkDownloadQrOpen(true); + }} + className="py-1 lg:p-0" + > + void; +}; + +type DownloadState = + | { status: "idle" } + | { status: "loading" } + | { status: "success" } + | { status: "error"; error: string }; + +export default function BulkDownloadQrDialog({ + className, + isDialogOpen, + onClose, +}: BulkDownloadQrDialogProps) { + const [downloadState, setDownloadState] = useState({ + status: "idle", + }); const [searchParams] = useSearchParams(); const selectedAssets = useAtomValue(selectedBulkItemsAtom); + const allAssetsSelected = isSelectingAllItems(selectedAssets); + + const disabled = + selectedAssets.length === 0 || downloadState.status === "loading"; + + function handleClose() { + setDownloadState({ status: "idle" }); + onClose(); + } async function handleBulkDownloadQr() { const query = new URLSearchParams(); @@ -24,7 +55,7 @@ export default function BulkDownloadQrDialog() { query.append("assetIds", asset.id); }); - setIsGeneratingQrCodes(true); + setDownloadState({ status: "loading" }); try { /* Getting all validated assets with qr object */ @@ -47,7 +78,7 @@ export default function BulkDownloadQrDialog() { /* Converting our React compoentn to html so that we can later convert it into an image */ const qrCodeContent = renderToStaticMarkup( -
+
); @@ -65,6 +96,7 @@ export default function BulkDownloadQrDialog() { display: "flex", alignItems: "center", justifyContent: "center", + textAlign: "center", transform: "scale(2)", transformOrigin: "center", }, @@ -91,26 +123,67 @@ export default function BulkDownloadQrDialog() { setTimeout(() => { URL.revokeObjectURL(downloadLink.href); }, 4e4); + + setDownloadState({ status: "success" }); } catch (error) { - setError( - error instanceof Error ? error.message : "Something went wrong." - ); - } finally { - setIsGeneratingQrCodes(false); + setDownloadState({ + status: "error", + error: error instanceof Error ? error.message : "Something went wrong.", + }); } } return ( - + + + +
+ } + > +
+

+ Download qr codes for{" "} + {allAssetsSelected ? "all" : selectedAssets.length} asset(s). +

+

+ {allAssetsSelected ? "All" : selectedAssets.length} qr code(s) will + be downloaded in a zip file. +

+ +

+ Successfully downloaded qr codes. +

+
+ + {downloadState.status === "error" ? ( +

{downloadState.error}

+ ) : null} + +
+ + + +
+
+ + ); }