import { FormEvent, useCallback, useEffect, useState } from "react"; import Cropper from "react-easy-crop"; import { Area, getCroppedImg } from "@lib/cropImage"; import { useFileReader } from "@lib/hooks/useFileReader"; import { useLocale } from "@lib/hooks/useLocale"; import { DialogClose, DialogTrigger, Dialog, DialogContent } from "@components/Dialog"; import Slider from "@components/Slider"; import Button from "@components/ui/Button"; type ImageUploaderProps = { id: string; buttonMsg: string; handleAvatarChange: (imageSrc: string) => void; imageSrc?: string; target: string; }; interface FileEvent extends FormEvent { target: EventTarget & T; } // This is separate to prevent loading the component until file upload function CropContainer({ onCropComplete, imageSrc, }: { imageSrc: string; onCropComplete: (croppedAreaPixels: Area) => void; }) { const { t } = useLocale(); const [crop, setCrop] = useState({ x: 0, y: 0 }); const [zoom, setZoom] = useState(1); const handleZoomSliderChange = (value: number) => { value < 1 ? setZoom(1) : setZoom(value); }; return (
onCropComplete(croppedAreaPixels)} onZoomChange={setZoom} />
); } export default function ImageUploader({ target, id, buttonMsg, handleAvatarChange, ...props }: ImageUploaderProps) { const { t } = useLocale(); const [imageSrc, setImageSrc] = useState(); const [croppedAreaPixels, setCroppedAreaPixels] = useState(); const [{ result }, setFile] = useFileReader({ method: "readAsDataURL", }); useEffect(() => { setImageSrc(props.imageSrc); }, [props.imageSrc]); const onInputFile = (e: FileEvent) => { if (!e.target.files?.length) { return; } setFile(e.target.files[0]); }; const showCroppedImage = useCallback( async (croppedAreaPixels) => { try { const croppedImage = await getCroppedImg( result as string /* result is always string when using readAsDataUrl */, croppedAreaPixels ); setImageSrc(croppedImage); handleAvatarChange(croppedImage); } catch (e) { console.error(e); } }, [result, handleAvatarChange] ); return ( !opened && setFile(null) // unset file on close }>
{!result && (
{!imageSrc && (

{t("no_target", { target })}

)} {imageSrc && {target}}
)} {result && }
); }