From d32618068b5398a3711f871ffa1c6f2bf270e4dc Mon Sep 17 00:00:00 2001 From: rohitPandey469 Date: Thu, 15 Feb 2024 01:20:26 +0530 Subject: [PATCH] Added Image Upload Feature --- src/components/Forms/UserForm/index.jsx | 218 +++++++++++++++++++++++- 1 file changed, 216 insertions(+), 2 deletions(-) diff --git a/src/components/Forms/UserForm/index.jsx b/src/components/Forms/UserForm/index.jsx index 17d2088e..b79e428e 100644 --- a/src/components/Forms/UserForm/index.jsx +++ b/src/components/Forms/UserForm/index.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import Box from "@mui/material/Box"; import { alpha, @@ -22,7 +22,8 @@ import { useDispatch, useSelector } from "react-redux"; import { clearUserProfile, getUserProfileData, - updateUserProfile + updateUserProfile, + uploadProfileImage } from "../../../store/actions"; import countryList from "../../../helpers/countryList"; import { @@ -35,6 +36,13 @@ import FacebookIcon from "@mui/icons-material/Facebook"; import TwitterIcon from "@mui/icons-material/Twitter"; import LinkedInIcon from "@mui/icons-material/LinkedIn"; import GitHubIcon from "@mui/icons-material/GitHub"; +import { BasicImage, NoImage } from "../../../helpers/images"; +import LinearProgress from "@mui/material/LinearProgress"; +import CloudUploadIcon from "@mui/icons-material/CloudUpload"; +import { Grid, Dialog, DialogTitle, DialogContent } from "@mui/material"; +import Divider from "@mui/material/Divider" +import ReactCrop from "react-image-crop"; +import "react-image-crop/dist/ReactCrop.css"; const Input = styled(InputBase)(({ theme }) => ({ "label + &": { @@ -190,6 +198,85 @@ const UserForm = () => { }; }, [firebase, firestore, dispatch, handle]); + const [upImg, setUpImg] = useState(); + const imgRef = useRef(null); + const previewCanvasRef = useRef(null); + const [crop, setCrop] = useState({ unit: "%", width: 30, aspect: 16 / 16 }); + const [completedCrop, setCompletedCrop] = useState(null); + const [showImageDialog, setShowImageDialog] = useState(false); + const [imageUploading, setImageUploading] = useState(false); + const onSelectFile = e => { + if (e.target.files && e.target.files.length > 0) { + const reader = new FileReader(); + console.log("File loaded successfully:", reader.result); + reader.addEventListener("load", () => { + console.log("File loaded successfully:", reader.result); + setUpImg(reader.result); + }); + reader.readAsDataURL(e.target.files[0]); + } + }; + + const onLoad = useCallback(img => { + imgRef.current = img; + }, []); + + const base64StringToFile = (base64String, filename) => { + let arr = base64String.split(","), + mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), + n = bstr.length, + u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], filename, { type: mime }); + }; + + const saveImage = (canvas, crop) => { + if (!crop || !canvas) { + return; + } + setShowImageDialog(false); + uploadImage(base64StringToFile(canvas.toDataURL(), "newfile")); + }; + const uploadImage = file => { + setImageUploading(true); + uploadProfileImage(file, profileData.handle)(firebase, dispatch).then( + () => { + setImageUploading(false); + } + ); + return false; + }; + + useEffect(() => { + if (!completedCrop || !previewCanvasRef.current || !imgRef.current) { + return; + } + const image = imgRef.current; + const canvas = previewCanvasRef.current; + const crop = completedCrop; + const scaleX = image.naturalWidth / image.width; + const scaleY = image.naturalHeight / image.height; + const ctx = canvas.getContext("2d"); + const pixelRatio = window.devicePixelRatio; + canvas.width = crop.width * pixelRatio; + canvas.height = crop.height * pixelRatio; + ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); + ctx.imageSmoothingQuality = "high"; + ctx.drawImage( + image, + crop.x * scaleX, + crop.y * scaleY, + crop.width * scaleX, + crop.height * scaleY, + 0, + 0, + crop.width, + crop.height + ); + }, [completedCrop]); return ( { }} > + + + {profileData.photoURL && profileData.photoURL.length > 0 + ? BasicImage(profileData.photoURL, profileData.displayName) + : BasicImage(NoImage, "Not Available")} + + {imageUploading ? ( + + ) : ( + +
+ +
+
+ )} + + + + + {"Change Profile Picture"} + + + +
+
+ + + + + + +
+ setCrop(c)} + onComplete={c => setCompletedCrop(c)} + /> +
+ + + + + + + + + + + + + + + +
+
+
+
+
+