"use client"; import React, { useCallback, useState } from "react"; import useUpload from "@/lib/hooks/upload-file"; import { cn } from "@/lib/utils"; import { TRPCClientError } from "@trpc/client"; import DropZone from "react-dropzone"; import { useCreateBookmarkWithPostHook } from "@hoarder/shared-react/hooks/bookmarks"; import { BookmarkTypes } from "@hoarder/shared/types/bookmarks"; import LoadingSpinner from "../ui/spinner"; import { toast } from "../ui/use-toast"; import BookmarkAlreadyExistsToast from "../utils/BookmarkAlreadyExistsToast"; export function useUploadAsset() { const { mutateAsync: createBookmark } = useCreateBookmarkWithPostHook({ onSuccess: (resp) => { if (resp.alreadyExists) { toast({ description: , variant: "default", }); } else { toast({ description: "Bookmark uploaded" }); } }, onError: () => { toast({ description: "Something went wrong", variant: "destructive" }); }, }); const { mutateAsync: runUploadAsset } = useUpload({ onSuccess: async (resp) => { const assetType = resp.contentType === "application/pdf" ? "pdf" : "image"; await createBookmark({ ...resp, type: BookmarkTypes.ASSET, assetType }); }, onError: (err, req) => { toast({ description: `${req.name}: ${err.error}`, variant: "destructive", }); }, }); return useCallback( (file: File) => { return runUploadAsset(file); }, [runUploadAsset], ); } function useUploadAssets({ onFileUpload, onFileError, onAllUploaded, }: { onFileUpload: () => void; onFileError: (name: string, e: Error) => void; onAllUploaded: () => void; }) { const runUpload = useUploadAsset(); return async (files: File[]) => { if (files.length == 0) { return; } for (const file of files) { try { await runUpload(file); onFileUpload(); } catch (e) { if (e instanceof TRPCClientError || e instanceof Error) { onFileError(file.name, e); } } } onAllUploaded(); }; } export default function UploadDropzone({ children, }: { children: React.ReactNode; }) { const [numUploading, setNumUploading] = useState(0); const [numUploaded, setNumUploaded] = useState(0); const uploadAssets = useUploadAssets({ onFileUpload: () => { setNumUploaded((c) => c + 1); }, onFileError: () => { setNumUploaded((c) => c + 1); }, onAllUploaded: () => { setNumUploading(0); setNumUploaded(0); return; }, }); const [isDragging, setDragging] = useState(false); const onDrop = (acceptedFiles: File[]) => { uploadAssets(acceptedFiles); setNumUploading(acceptedFiles.length); setDragging(false); }; return ( setDragging(true)} onDragLeave={() => setDragging(false)} > {({ getRootProps, getInputProps }) => ( 0 ? undefined : "hidden", )} > {numUploading > 0 ? ( Uploading {numUploaded} / {numUploading} ) : ( Drop Your Image / Bookmark file )} {children} )} ); }
Uploading {numUploaded} / {numUploading}
Drop Your Image / Bookmark file