Skip to content

Instantly share code, notes, and snippets.

@Ebrahim-Ramadan
Last active July 5, 2023 02:24
Show Gist options
  • Save Ebrahim-Ramadan/330c767fc601b5b6ad80a249405bbf82 to your computer and use it in GitHub Desktop.
Save Ebrahim-Ramadan/330c767fc601b5b6ad80a249405bbf82 to your computer and use it in GitHub Desktop.
pfp crop&update - Reactjs
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);
}
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>
);
};
.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;
}
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