Last active
July 5, 2023 02:24
-
-
Save Ebrahim-Ramadan/330c767fc601b5b6ad80a249405bbf82 to your computer and use it in GitHub Desktop.
pfp crop&update - Reactjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 0; | |
padding: 0; | |
} | |
.crop-image { | |
position: absolute; | |
background-color: rgba(71, 71, 71, 0.901); | |
top: 0; | |
right: 0; | |
left: 0; | |
bottom: 0; | |
z-index: 999; | |
width: 100%; | |
width: 100%; | |
border-radius: 8px; | |
} | |
input#upload-image-btn{ | |
opacity: 0; | |
} | |
/* .crop-image div{ | |
position: absolute; | |
top: 50%; | |
left: 20%; | |
transform: translate(-50%, -50%); | |
} */ | |
.crop-container { | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 80px; | |
} | |
.cropped-image-container{ | |
z-index: 9999999; | |
} | |
.controls >*{ | |
margin: 10px; | |
} | |
.controls { | |
position: absolute; | |
bottom: 20px; | |
left: 50%; | |
width: 50%; | |
transform: translateX(-50%); | |
height: 40px; | |
display: flex; | |
justify-content: space-around; | |
align-items: center; | |
} | |
/* | |
*/ | |
.slider { | |
padding: 22px 0px; | |
} | |
.zoom-range { | |
-webkit-appearance: none; | |
-moz-appearance: none; | |
height: 2px; | |
border-top: 5px solid #fff; | |
border-bottom: 5px solid #fff; | |
background: #3f51b5; | |
width: 100%; | |
} | |
.zoom-range::-moz-range-thumb { | |
-webkit-appearance: none; | |
-moz-appearance: none; | |
border: 1px solid #3f51b5; | |
background: #3f51b5; | |
border-radius: 50%; | |
width: 12px; | |
height: 12px; | |
transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; | |
} | |
.zoom-range::-webkit-slider-thumb { | |
-webkit-appearance: none; | |
-moz-appearance: none; | |
border: 1px solid #3f51b5; | |
background: #3f51b5; | |
border-radius: 50%; | |
width: 12px; | |
height: 12px; | |
transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; | |
} | |
.controls:hover input[type='range']::-webkit-slider-thumb { | |
box-shadow: 0px 0px 0px 8px rgba(63, 81, 181, 0.16); | |
border-radius: 50%; | |
} | |
.controls:hover input[type='range']::-moz-range-thumb { | |
box-shadow: 0px 0px 0px 8px rgba(63, 81, 181, 0.16); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useCallback, useEffect } from 'react'; | |
import Cropper from 'react-easy-crop'; | |
import '../components/ImageUploadcrop.css'; | |
import { Button } from '@mui/material'; | |
export const ImageUploadcrop = ({ setCroppedImage }) => { | |
const [crop, setCrop] = useState({ x: 0, y: 0 }); | |
const [zoom, setZoom] = useState(1); | |
const [croppedAreaPixels, setCroppedAreaPixels] = useState(null); | |
// const [croppedImage, setCroppedImage] = useState(null); | |
const [selectedImage, setSelectedImage] = useState(null); | |
const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => { | |
setCroppedAreaPixels(croppedAreaPixels); | |
}, []); | |
const getCroppedImg = useCallback(async () => { | |
try { | |
const image = document.createElement('img'); | |
image.src = selectedImage; | |
const canvas = document.createElement('canvas'); | |
canvas.width = croppedAreaPixels.width; | |
canvas.height = croppedAreaPixels.height; | |
const ctx = canvas.getContext('2d'); | |
ctx.drawImage( | |
image, | |
croppedAreaPixels.x, | |
croppedAreaPixels.y, | |
croppedAreaPixels.width, | |
croppedAreaPixels.height, | |
0, | |
0, | |
croppedAreaPixels.width, | |
croppedAreaPixels.height | |
); | |
const dataURL = canvas.toDataURL('image/jpeg'); | |
return dataURL; | |
} catch (error) { | |
console.error('Error generating cropped image:', error); | |
return null; | |
} | |
}, [selectedImage, croppedAreaPixels]); | |
const handleSave = useCallback(async () => { | |
const croppedImageURL = await getCroppedImg(); | |
setCroppedImage(croppedImageURL); | |
}, [getCroppedImg, setCroppedImage]); | |
const handleImageSelect = (event) => { | |
const file = event.target.files[0]; | |
const reader = new FileReader(); | |
reader.onload = (e) => { | |
setSelectedImage(e.target.result); | |
}; | |
reader.readAsDataURL(file); | |
}; | |
useEffect(() => { | |
const handleKeyPress = (event) => { | |
if (event.key === 'Enter') { | |
handleSave(); | |
} | |
}; | |
document.addEventListener('keydown', handleKeyPress); | |
return () => { | |
document.removeEventListener('keydown', handleKeyPress); | |
}; | |
}, [handleSave]); | |
return ( | |
<div className="crop-image"> | |
<div className="crop-container"> | |
{selectedImage && ( | |
<Cropper | |
image={selectedImage} | |
crop={crop} | |
zoom={zoom} | |
aspect={4 / 4} | |
onCropChange={setCrop} | |
onCropComplete={onCropComplete} | |
onZoomChange={setZoom} | |
restrictPosition={false} | |
/> | |
)} | |
</div> | |
<div className="controls"> | |
<input type="file" accept="image/*" onChange={handleImageSelect} id="upload-image-btn" /> | |
<Button onClick={handleSave} variant="outlined"> | |
Save | |
</Button> | |
<label variant="outlined" htmlFor="upload-image-btn"> | |
Upload | |
</label> | |
<input | |
type="range" | |
value={zoom} | |
min={1} | |
max={5} | |
step={0.01} | |
aria-labelledby="Zoom" | |
onChange={(e) => { | |
setZoom(e.target.value); | |
}} | |
className="zoom-range" | |
/> | |
</div> | |
{/* {croppedImage && ( | |
<div className="cropped-image-container"> | |
<img alt="Cropped_Image" src={croppedImage} style={{ maxWidth: '100%' }} /> | |
<a href={croppedImage} download="croppedImage.jpeg"> | |
Download Cropped Image | |
</a> | |
</div> | |
)} */} | |
</div> | |
); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.classifyList-ul { | |
font-size: 20px; | |
font-weight: bolder; | |
padding: 1rem 1rem; | |
text-decoration: none; | |
border-radius: 5px; | |
} | |
.classifyList-ul.active { | |
background-color: #989590; | |
color: #f8f3ff; | |
} | |
.upperPart { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
padding-bottom: 30px; | |
} | |
.username-main{ | |
display: grid; | |
justify-content: center; | |
} | |
.username-main > * { | |
margin: 0 0 2px 0; | |
text-align: center; | |
} | |
.pfp-img img { | |
width: 180px; | |
border-radius: 12px; | |
border: #767676 solid 2px; | |
position: relative; | |
} | |
img{ | |
cursor: zoom-in; | |
} | |
.cover-img{ | |
height: 300px; | |
border-bottom: 1px solid gray; | |
} | |
.pfp-img{ | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
margin-top: -30px; | |
} | |
.dropmenu-profile { | |
position: fixed; | |
top: 50px; | |
right: 50px; | |
color: #ffffff; | |
padding: 10px; | |
z-index: 999; | |
border-radius: 8px; | |
background-color: #161B22; | |
} | |
h6 p span { | |
margin: 0; | |
opacity:0.8; | |
} | |
.dropdownItem.profile { | |
list-style: none; | |
padding: 10px; | |
margin: 2px; | |
font-size: 18px; | |
font-weight: bolder; | |
white-space: nowrap; | |
box-sizing: border-box; /* Include border within specified width and height */ | |
opacity: 0.8; | |
} | |
.dropdownItem p { | |
color:'gray'; | |
font-size:13px; | |
transform: translateX(30px); | |
} | |
.dropdownItem i { | |
margin-right: 8px; | |
font-size: large; | |
cursor: pointer; | |
} | |
.dropmenu-profile div { | |
margin-top: 20px; | |
} | |
.dropmenu-profile div .dropdownItem{ | |
cursor: pointer; | |
} | |
.dropmenu-profile div p{ | |
opacity: 0.8; | |
color: gray; | |
} | |
.dropdownItem:hover { | |
opacity: 1; | |
font-size: 22px; | |
} | |
.dropmenu-notification | |
{ | |
position: fixed; | |
top: 50px; | |
right: 180px; | |
color: #ffffff; | |
padding: 10px; | |
z-index: 999; | |
border-radius: 8px; | |
background-color: #161B22; | |
} | |
h8 a{ | |
/* text-decoration: none ; */ | |
color: rgb(177, 177, 177); | |
font-weight: 600; | |
} | |
#editcover{ | |
display: flex; | |
justify-content: center; | |
position: fixed; | |
top: 0; | |
/* align-items: center; */ | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(34, 27, 27, 0.712); /* Semi-transparent black */ | |
z-index: 9999; | |
padding: 50px; | |
} | |
#editcover p{ | |
display: flex; | |
justify-content: center; | |
} | |
span.following, span.followers{ | |
opacity: 0.8; | |
font-weight: 600; | |
transition: 0.2s; | |
} | |
span.following:hover, span.followers:hover{ | |
opacity: 1; | |
cursor: pointer; | |
color: #386BC0; | |
} | |
.dropmenu-followers { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(0, 0, 0, 0.403); | |
z-index: 9999; | |
} | |
.dropmenu-followers > div { | |
width: 30%; | |
height: 70%; | |
border-radius: 10px; | |
background-color: rgb(0, 0, 0); | |
padding: 20px; | |
display: flex; | |
justify-content: center; | |
} | |
.dropmenu-followers div div li{ | |
background-color: rgba(142, 142, 142, 0.27); | |
cursor: pointer; | |
} | |
.dropmenu-followers { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(0, 0, 0, 0.805); | |
z-index: 9999; | |
} | |
.dropmenu-followers { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(0, 0, 0, 0.767); | |
z-index: 9999; | |
transition: 0.2s; | |
} | |
.dropmenu-followers div div h4{ | |
display: flex; | |
justify-content: center; | |
} | |
.dropdownItem.follower-following { | |
display: flex; | |
align-items: center; | |
list-style: none; | |
padding: 10px; | |
font-size: 18px; | |
font-weight: bolder; | |
white-space: nowrap; | |
box-sizing: border-box; | |
opacity: 0.8; | |
border-radius: 10px; | |
width: 120%; | |
margin: 10px; | |
transition: 0.2s; | |
margin-left: -20px; | |
margin-right: 50px; | |
margin-bottom: 5px; | |
justify-content: space-around; | |
} | |
.dropdownItem.follower-following div{ | |
display: flex; | |
align-items: center; | |
} | |
.dropdownItem.follower-following:hover { | |
opacity: 1; | |
} | |
.dropdownItem.follower-following i { | |
margin-right: 12px; | |
font-size: larger; | |
cursor: pointer; | |
} | |
.dropdownItem.follower-following .follower-count { | |
margin-left: 10px; | |
font-size: 14px; | |
color: gray; | |
display: flex; | |
justify-content: flex-end; | |
} | |
.dropmenu-post{ | |
position: absolute; | |
box-shadow: 0px 0px 3px rgba(170, 170, 170, 0.921); | |
top: 180px; | |
right: 480px; | |
z-index: 999; | |
border-radius: 8px; | |
background-color: #343434; | |
} | |
.dropdownItem.post{ | |
list-style: none; | |
padding: 10px; | |
margin: 2px; | |
font-size: 14px; | |
font-weight: 400; | |
box-sizing: border-box; | |
cursor: pointer; | |
opacity: 0.8; | |
} | |
.dropdownItem.post:hover{ | |
opacity: 1; | |
} | |
.notifications .container .header .header-title { | |
color: white; | |
} | |
.notifications .icon{ | |
opacity: 0.8; | |
transition: 0.2s; | |
} | |
.notifications .icon:hover{ | |
opacity: 1; | |
} | |
.pfp_cropimage{ | |
position: absolute; | |
box-shadow: 0px 0px 3px rgba(170, 170, 170, 0.921); | |
top: 180px; | |
right: 480px; | |
z-index: 999; | |
border-radius: 8px; | |
background-color: #343434; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useCallback, useEffect, useRef } from 'react'; | |
import { Outlet, NavLink } from 'react-router-dom'; | |
import './Profile.css'; | |
import pfp from '../assets/human_head.jpeg'; | |
import header from '../assets//New-header.jpg'; | |
import Carousel, { Modal, ModalGateway } from 'react-images'; | |
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | |
import { faPenToSquare, faTimes } from '@fortawesome/free-solid-svg-icons'; | |
import { ImageUploadcrop } from './imageUpload-crop'; | |
import { HeaderUploadcrop } from './HeaderUpload_crop'; | |
import { toast } from 'react-toastify'; | |
import 'react-toastify/dist/ReactToastify.css'; | |
function DropdownItem(props) { | |
return ( | |
<li className="dropdownItem follower-following"> | |
<div> | |
<i className={props.i}></i> | |
<a href={props.href}>{props.text}</a> | |
</div> | |
<span className="follower-count">165 followers</span> | |
</li> | |
); | |
} | |
const toastify = (ImageSrc) => { | |
toast.success(`${ImageSrc} updated`, { | |
position: toast.POSITION.BOTTOM_CENTER, | |
autoClose: 1500, | |
theme: 'dark' | |
}); | |
}; | |
const male = 'he/him'; | |
const female = 'she/her'; | |
const sharmo_jj = 'sharmo_jj'; | |
const bio = 'https://www.instagram.com/iilujj/'; | |
export const Profile = () => { | |
const [viewerIsOpen, setViewerIsOpen] = useState(false); | |
const [selectedImage, setSelectedImage] = useState(null); | |
const [imgviewercaption, setImgViewerCaption] = useState(null); | |
const [croppedImage, setCroppedImage] = useState(null); | |
const openLightbox = useCallback((imgsource, caption) => { | |
setImgViewerCaption(caption); | |
setSelectedImage(imgsource); | |
setViewerIsOpen(true); | |
}, []); | |
const closeLightbox = () => { | |
setImgViewerCaption(null); | |
setSelectedImage(null); | |
setViewerIsOpen(false); | |
}; | |
// Editing pfp | |
const [src, stsrc] = useState(null); | |
const [src_header, stsrc_header] = useState(null); | |
const [preview, setPreview] = useState(null); | |
const onClose = () => { | |
setPreview(null); | |
}; | |
const onCrop = (view) => { | |
setPreview(view); | |
}; | |
// Show the pfp edit btn | |
const [editpfp_imgcrop, seteditpfp_imgcrop] = useState(false) | |
const editpfp_imgcrop_func = () => { | |
seteditpfp_imgcrop(true) | |
} | |
const [editheader_imgcrop, seteditheader_imgcrop] = useState(false) | |
const editheader_imgcrop_func = () => { | |
seteditheader_imgcrop(true) | |
} | |
// Show the edit btn | |
useEffect(() => { | |
const handleKeyPress = (event) => { | |
if (event.key === 'Escape') { | |
seteditheader_imgcrop(false); | |
seteditpfp_imgcrop(false) | |
} | |
}; | |
window.addEventListener('keydown', handleKeyPress); | |
return () => { | |
window.removeEventListener('keydown', handleKeyPress); | |
}; | |
}, []); | |
const dropdownRef = useRef(null); | |
const [showDropdown, setShowDropdown] = useState(false); | |
const triggerFollowersMenu = () => { | |
setShowDropdown(true); | |
// dropdownRef.current.style.display = 'flex'; | |
}; | |
const closeDropdown = () => { | |
setShowDropdown(false); | |
// dropdownRef.current.style.display = 'none'; | |
}; | |
useEffect(() => { | |
const handleKeyDown = (event) => { | |
if (event.key === 'Escape') { | |
closeDropdown(); | |
} | |
}; | |
document.addEventListener('keydown', handleKeyDown); | |
return () => { | |
document.removeEventListener('keydown', handleKeyDown); | |
}; | |
}, []); | |
const handleSave = (croppedImageURL) => { | |
stsrc(croppedImageURL); | |
seteditpfp_imgcrop(false); | |
toastify('pfp') | |
}; | |
const handleSave_header = (croppedImageURL) => { | |
stsrc_header(croppedImageURL); | |
seteditheader_imgcrop(false); | |
toastify('header') | |
}; | |
return ( | |
<div className="page-content"> | |
<div className="upperPart"> | |
<div className="headerpluspfp"> | |
<div className="cover-img"> | |
<img | |
alt="cover" | |
src={src_header || header} | |
style={{ width: '100%', height: '100%' }} | |
onClick={() => openLightbox(src_header, 'header')} | |
/> | |
<FontAwesomeIcon | |
icon={faPenToSquare} | |
style={{ | |
transform: 'translate(9px, -32px)', | |
fontSize: '20px', | |
cursor: 'pointer', | |
opacity: '0.9', | |
}} | |
onClick={editheader_imgcrop_func} | |
/> | |
{editheader_imgcrop && ( | |
<HeaderUploadcrop setCroppedImage={handleSave_header} /> | |
)} | |
{editpfp_imgcrop && ( | |
<ImageUploadcrop setCroppedImage={handleSave} /> | |
)} | |
</div> | |
<div className="pfp-img"> | |
<img | |
alt="PFP" | |
src={src||pfp} | |
style={{ height: '180px' }} | |
onClick={() => openLightbox(src, 'pfp<3')} | |
/> | |
<FontAwesomeIcon | |
icon={faPenToSquare} | |
style={{ | |
position: 'absolute', | |
fontSize: '20px', | |
cursor: 'pointer', | |
bottom: '135px', | |
right: '610px', | |
opacity: '0.9', | |
}} | |
onClick={editpfp_imgcrop_func} | |
/> | |
</div> | |
<div className="username-main"> | |
<h3>Mourii</h3> | |
<h6> | |
<p style={{ color: 'gray' }}> | |
@<span>{sharmo_jj}</span> | |
<span style={{ padding: '0px 4px' }}>·</span> | |
<span>{male}</span> | |
</p> | |
</h6> | |
<h6> | |
<a href={bio} target="_blank "> | |
{bio} | |
</a> | |
</h6> | |
<h6> | |
<span className="followers" onClick={triggerFollowersMenu}> | |
2 followers | |
</span> | |
<span style={{ padding: '0px 2px' }} />. | |
<span style={{ padding: '0px 2px' }} /> | |
<span className="following">28 following</span> | |
</h6> | |
</div> | |
</div> | |
</div> | |
{showDropdown && ( | |
<div className="dropmenu-followers" ref={dropdownRef}> | |
<div> | |
<div> | |
<h4>Followers</h4> | |
<DropdownItem i="bi bi-person-square" href="/person01" text="person01" /> | |
<DropdownItem i="bi bi-person-square" href="/person02" text="person02" /> | |
<DropdownItem i="bi bi-person-square" href="/person05" text="person05" /> | |
<DropdownItem i="bi bi-person-square" href="/person03" text="person03" /> | |
<DropdownItem i="bi bi-person-square" href="/person04" text="person04" /> | |
</div> | |
<FontAwesomeIcon | |
icon={faTimes} | |
className='close-icon' | |
onClick={closeDropdown} | |
style={{ cursor: 'pointer',fontSize:'20px', translate:'40px 0px'}} | |
/> | |
</div> | |
</div> | |
)} | |
<div className="classifyList"> | |
<NavLink className="classifyList-ul" to="/Profile/YourDesires" activeClassName="active"> | |
YourDesires | |
</NavLink> | |
<NavLink className="classifyList-ul" to="/Profile/YourFeed" activeClassName="active"> | |
YourFeed | |
</NavLink> | |
<NavLink | |
className="classifyList-ul" | |
to="/Profile/Recommendations" | |
activeClassName="active" | |
> | |
Recommendations | |
</NavLink> | |
<NavLink className="classifyList-ul" to="/Profile/Memories" activeClassName="active"> | |
Memories | |
</NavLink> | |
<NavLink className="classifyList-ul" to="/Profile/Terribles" activeClassName="active"> | |
Terribles | |
</NavLink> | |
</div> | |
<Outlet /> | |
<ModalGateway> | |
{viewerIsOpen && selectedImage && imgviewercaption && ( | |
<Modal onClose={closeLightbox}> | |
<Carousel views={[{ source: selectedImage, caption: imgviewercaption }]} /> | |
</Modal> | |
)} | |
</ModalGateway> | |
</div> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment