import { Box, ChakraProps, Flex, Icon, IconButtonProps, Image, } from '@chakra-ui/react'; import { useDraggable, useDroppable } from '@dnd-kit/core'; import { useCombinedRefs } from '@dnd-kit/utilities'; import IAIIconButton from 'common/components/IAIIconButton'; import { IAIImageFallback } from 'common/components/IAIImageFallback'; import ImageMetadataOverlay from 'common/components/ImageMetadataOverlay'; import { AnimatePresence } from 'framer-motion'; import { ReactElement, SyntheticEvent, useCallback } from 'react'; import { memo, useRef } from 'react'; import { FaImage, FaTimes, FaUndo, FaUpload } from 'react-icons/fa'; import { ImageDTO } from 'services/api'; import { v4 as uuidv4 } from 'uuid'; import IAIDropOverlay from './IAIDropOverlay'; import { PostUploadAction, imageUploaded } from 'services/thunks/image'; import { useDropzone } from 'react-dropzone'; import { useAppDispatch } from 'app/store/storeHooks'; type IAIDndImageProps = { image: ImageDTO | null | undefined; onDrop: (droppedImage: ImageDTO) => void; onReset?: () => void; onError?: (event: SyntheticEvent) => void; onLoad?: (event: SyntheticEvent) => void; resetIconSize?: IconButtonProps['size']; withResetIcon?: boolean; withMetadataOverlay?: boolean; isDragDisabled?: boolean; isDropDisabled?: boolean; isUploadDisabled?: boolean; fallback?: ReactElement; payloadImage?: ImageDTO | null | undefined; minSize?: number; postUploadAction?: PostUploadAction; imageSx?: ChakraProps['sx']; }; const IAIDndImage = (props: IAIDndImageProps) => { const { image, onDrop, onReset, onError, resetIconSize = 'md', withResetIcon = false, withMetadataOverlay = false, isDropDisabled = false, isDragDisabled = false, isUploadDisabled = false, fallback = , payloadImage, minSize = 24, postUploadAction, imageSx, } = props; const dispatch = useAppDispatch(); const dndId = useRef(uuidv4()); const { isOver, setNodeRef: setDroppableRef, active: isDropActive, } = useDroppable({ id: dndId.current, disabled: isDropDisabled, data: { handleDrop: onDrop, }, }); const { attributes, listeners, setNodeRef: setDraggableRef, isDragging, } = useDraggable({ id: dndId.current, data: { image: payloadImage ? payloadImage : image, }, disabled: isDragDisabled || !image, }); const handleOnDropAccepted = useCallback( (files: Array) => { const file = files[0]; if (!file) { return; } dispatch( imageUploaded({ formData: { file }, imageCategory: 'user', isIntermediate: false, postUploadAction, }) ); }, [dispatch, postUploadAction] ); const { getRootProps, getInputProps } = useDropzone({ accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] }, onDropAccepted: handleOnDropAccepted, noDrag: true, multiple: false, disabled: isUploadDisabled, }); const setNodeRef = useCombinedRefs(setDroppableRef, setDraggableRef); const uploadButtonStyles = isUploadDisabled ? {} : { cursor: 'pointer', bg: 'base.800', _hover: { bg: 'base.750', color: 'base.300', }, }; return ( {image && ( {withMetadataOverlay && } {onReset && withResetIcon && ( } onClick={onReset} /> )} {isDropActive && } )} {!image && ( <> {isDropActive && } )} ); }; export default memo(IAIDndImage);