degmods.com/src/components/Inputs/ImageUpload.tsx
2025-01-07 16:39:23 +01:00

117 lines
3.4 KiB
TypeScript

import { useDropzone } from 'react-dropzone'
import React, { useCallback, useMemo, useState } from 'react'
import {
MediaOption,
MEDIA_OPTIONS,
ImageController,
MEDIA_DROPZONE_OPTIONS
} from '../../controllers'
import { errorFeedback } from '../../types'
import { MediaInputPopover } from './MediaInputPopover'
export interface ImageUploadProps {
multiple?: boolean | undefined
onChange: (values: string[]) => void
}
export const ImageUpload = React.memo(
({ multiple = false, onChange }: ImageUploadProps) => {
const [mediaOption, setMediaOption] = useState<MediaOption>(
MEDIA_OPTIONS[0]
)
const handleOptionChange = useCallback(
(mo: MediaOption) => () => {
setMediaOption(mo)
},
[]
)
const handleUpload = useCallback(
async (acceptedFiles: File[]) => {
if (acceptedFiles.length) {
try {
const imageController = new ImageController(mediaOption)
const urls: string[] = []
for (let i = 0; i < acceptedFiles.length; i++) {
const file = acceptedFiles[i]
urls.push(await imageController.post(file))
}
onChange(urls)
} catch (error) {
errorFeedback(error)
}
}
},
[mediaOption, onChange]
)
const {
getRootProps,
getInputProps,
isDragActive,
acceptedFiles,
isFileDialogActive,
isDragAccept,
isDragReject,
fileRejections
} = useDropzone({
...MEDIA_DROPZONE_OPTIONS,
onDrop: handleUpload,
multiple: multiple
})
const dropzoneLabel = useMemo(
() =>
isFileDialogActive
? 'Select files in dialog'
: isDragActive
? isDragAccept
? 'Drop the files here...'
: isDragReject
? 'Drop the files here (one more more unsupported types)...'
: 'Drop the files here...'
: 'Click or drag files here',
[isDragAccept, isDragActive, isDragReject, isFileDialogActive]
)
return (
<div aria-label='upload featuredImageUrl' className='uploadBoxMain'>
<MediaInputPopover
acceptedFiles={acceptedFiles}
fileRejections={fileRejections}
/>
<div className='uploadBoxMainInside' {...getRootProps()} tabIndex={-1}>
<input id='featuredImageUrl-upload' {...getInputProps()} />
<span>{dropzoneLabel}</span>
<div
className='FiltersMainElement'
onClick={(e) => e.stopPropagation()}
>
<div className='dropdown dropdownMain'>
<button
className='btn dropdown-toggle btnMain btnMainDropdown'
aria-expanded='false'
data-bs-toggle='dropdown'
type='button'
>
Image Host: {mediaOption.name}
</button>
<div className='dropdown-menu dropdownMainMenu'>
{MEDIA_OPTIONS.map((mo) => {
return (
<div
key={mo.host}
onClick={handleOptionChange(mo)}
className='dropdown-item dropdownMainMenuItem'
>
{mo.name}
</div>
)
})}
</div>
</div>
</div>
</div>
</div>
)
}
)