import React, { MutableRefObject, ReactNode, useImperativeHandle, useRef } from 'react'; import { Badge, Box, Chip, Header, Icon, Icons, Spinner, Text, as, percent } from 'folds'; import classNames from 'classnames'; import { useAtomValue } from 'jotai'; import * as css from './UploadBoard.css'; import { TUploadFamilyObserverAtom, Upload, UploadStatus, UploadSuccess } from '../../state/upload'; type UploadBoardProps = { header: ReactNode; }; export const UploadBoard = as<'div', UploadBoardProps>(({ header, children, ...props }, ref) => ( {children} {header} )); export type UploadBoardImperativeHandlers = { handleSend: () => Promise }; type UploadBoardHeaderProps = { open: boolean; onToggle: () => void; uploadFamilyObserverAtom: TUploadFamilyObserverAtom; onCancel: (uploads: Upload[]) => void; onSend: (uploads: UploadSuccess[]) => Promise; imperativeHandlerRef: MutableRefObject; }; export function UploadBoardHeader({ open, onToggle, uploadFamilyObserverAtom, onCancel, onSend, imperativeHandlerRef, }: UploadBoardHeaderProps) { const sendingRef = useRef(false); const uploads = useAtomValue(uploadFamilyObserverAtom); const isSuccess = uploads.every((upload) => upload.status === UploadStatus.Success); const isError = uploads.some((upload) => upload.status === UploadStatus.Error); const progress = uploads.reduce( (acc, upload) => { acc.total += upload.file.size; if (upload.status === UploadStatus.Loading) { acc.loaded += upload.progress.loaded; } if (upload.status === UploadStatus.Success) { acc.loaded += upload.file.size; } return acc; }, { loaded: 0, total: 0 } ); const handleSend = async () => { if (sendingRef.current) return; sendingRef.current = true; await onSend( uploads.filter((upload) => upload.status === UploadStatus.Success) as UploadSuccess[] ); sendingRef.current = false; }; useImperativeHandle(imperativeHandlerRef, () => ({ handleSend, })); const handleCancel = () => onCancel(uploads); return (
Files {isSuccess && ( } > Send )} {isError && !open && ( Upload Failed )} {!isSuccess && !isError && !open && ( <> {Math.round(percent(0, progress.total, progress.loaded))}% )} {!isSuccess && open && ( } > {uploads.length === 1 ? 'Remove' : 'Remove All'} )}
); } export const UploadBoardContent = as<'div'>(({ className, children, ...props }, ref) => ( {children} ));