select profile picture dialog

This commit is contained in:
luisa.bellitto 2025-06-20 14:15:55 +02:00 committed by Kai Ritthaler
parent b7d65b08cb
commit 788be272a7
7 changed files with 112 additions and 48 deletions

View file

@ -10,7 +10,7 @@
"dependencies": { "dependencies": {
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0", "@emotion/styled": "^11.14.0",
"@mui/icons-material": "^7.1.1", "@mui/icons-material": "^7.1.2",
"@mui/material": "^7.1.1", "@mui/material": "^7.1.1",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3", "@testing-library/jest-dom": "^6.6.3",
@ -3115,9 +3115,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@mui/core-downloads-tracker": { "node_modules/@mui/core-downloads-tracker": {
"version": "7.1.1", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz", "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.2.tgz",
"integrity": "sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ==", "integrity": "sha512-0gLO1PvbJwSYe5ji021tGj6HFqrtEPMGKK4L1zWwRbhzrWWUumUJvMvJUsIgWQIYQsgOnhq9k2Fc1BxLGHDsAg==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -3125,9 +3125,9 @@
} }
}, },
"node_modules/@mui/icons-material": { "node_modules/@mui/icons-material": {
"version": "7.1.1", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.1.tgz", "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.2.tgz",
"integrity": "sha512-X37+Yc8QpEnl0sYmz+WcLFy2dWgNRzbswDzLPXG7QU1XDVlP5TPp1HXjdmCupOWLL/I9m1fyhcyZl8/HPpp/Cg==", "integrity": "sha512-slqJByDub7Y1UcokrM17BoMBMvn8n7daXFXVoTv0MEH5k3sHjmsH8ql/Mt3s9vQ20cORDr83UZ448TEGcbrXtw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.27.1" "@babel/runtime": "^7.27.1"
@ -3140,7 +3140,7 @@
"url": "https://opencollective.com/mui-org" "url": "https://opencollective.com/mui-org"
}, },
"peerDependencies": { "peerDependencies": {
"@mui/material": "^7.1.1", "@mui/material": "^7.1.2",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0" "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
}, },
@ -3151,13 +3151,13 @@
} }
}, },
"node_modules/@mui/material": { "node_modules/@mui/material": {
"version": "7.1.1", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.1.tgz", "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.2.tgz",
"integrity": "sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A==", "integrity": "sha512-Z5PYKkA6Kd8vS04zKxJNpwuvt6IoMwqpbidV7RCrRQQKwczIwcNcS8L6GnN4pzFYfEs+N9v6co27DmG07rcnoA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.27.1", "@babel/runtime": "^7.27.1",
"@mui/core-downloads-tracker": "^7.1.1", "@mui/core-downloads-tracker": "^7.1.2",
"@mui/system": "^7.1.1", "@mui/system": "^7.1.1",
"@mui/types": "^7.4.3", "@mui/types": "^7.4.3",
"@mui/utils": "^7.1.1", "@mui/utils": "^7.1.1",

View file

@ -5,7 +5,7 @@
"dependencies": { "dependencies": {
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0", "@emotion/styled": "^11.14.0",
"@mui/icons-material": "^7.1.1", "@mui/icons-material": "^7.1.2",
"@mui/material": "^7.1.1", "@mui/material": "^7.1.1",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3", "@testing-library/jest-dom": "^6.6.3",

View file

@ -9,6 +9,8 @@ import IconButton from "@mui/material/IconButton";
import CloseIcon from "@mui/icons-material/Close"; import CloseIcon from "@mui/icons-material/Close";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import Avatar from "@mui/material/Avatar"; import Avatar from "@mui/material/Avatar";
import EditSquareIcon from "@mui/icons-material/EditSquare";
import { useRef, useState } from "react";
const BootstrapDialog = styled(Dialog)(({ theme }) => ({ const BootstrapDialog = styled(Dialog)(({ theme }) => ({
"& .MuiDialogContent-root": { "& .MuiDialogContent-root": {
@ -29,6 +31,17 @@ export default function CustomizedDialogs() {
setOpen(false); setOpen(false);
}; };
const inputFile = useRef<HTMLInputElement | null>(null);
const openFileExplorer = () => {
// `current` points to the mounted file input element
if (inputFile.current) {
inputFile.current.click();
}
};
const [selectedImage, setSelectedImage] = useState<File | null>(null);
return ( return (
<React.Fragment> <React.Fragment>
<Button onClick={handleClickOpen}> <Button onClick={handleClickOpen}>
@ -46,7 +59,7 @@ export default function CustomizedDialogs() {
open={open} open={open}
> >
<DialogTitle sx={{ m: 0, p: 2 }} id="customized-dialog-title"> <DialogTitle sx={{ m: 0, p: 2 }} id="customized-dialog-title">
Modal title Change Profile Picture
</DialogTitle> </DialogTitle>
<IconButton <IconButton
aria-label="close" aria-label="close"
@ -61,21 +74,22 @@ export default function CustomizedDialogs() {
<CloseIcon /> <CloseIcon />
</IconButton> </IconButton>
<DialogContent dividers> <DialogContent dividers>
<Typography gutterBottom> {selectedImage && <img className="profile-image-large" src={URL.createObjectURL(selectedImage)} alt="Profile Picture" />}
Cras mattis consectetur purus sit amet fermentum. Cras justo odio, <IconButton aria-label="upload picture" onClick={openFileExplorer}>
dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta <EditSquareIcon />
ac consectetur ac, vestibulum at eros. <input
</Typography> type="file"
<Typography gutterBottom> id="file"
Praesent commodo cursus magna, vel scelerisque nisl consectetur et. ref={inputFile}
Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor style={{ display: "none" }}
auctor. onChange={(event) => {
</Typography> console.log(event.target.files?[0]:undefined); // Log the selected file
<Typography gutterBottom> if (event.target.files && event.target.files[0]) {
Aenean lacinia bibendum nulla sed consectetur. Praesent commodo setSelectedImage(event.target.files[0]); // Update the state with the selected file
cursus magna, vel scelerisque nisl consectetur et. Donec sed odio }
dui. Donec ullamcorper nulla non metus auctor fringilla. }}
</Typography> />
</IconButton>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button autoFocus onClick={handleClose}> <Button autoFocus onClick={handleClose}>

View file

@ -0,0 +1,14 @@
.dialog-content {
display: flex;
flex-direction: column;
}
.profile-image-large {
width: 5rem;
height: 5rem;
}
#file {
max-width: 50rem;
max-height: 50rem;
}

View file

@ -4,7 +4,7 @@ import "./loginAndSignUpPage.css";
import "../styles/sizes.css"; import "../styles/sizes.css";
import "../styles/colors.css"; import "../styles/colors.css";
import "../styles/fonts.css"; import "../styles/fonts.css";
import { useState } from "react"; import { useRef, useState } from "react";
import Avatar from "@mui/material/Avatar"; import Avatar from "@mui/material/Avatar";
import QuiltedImageList from "../components/QuiltedImageList"; import QuiltedImageList from "../components/QuiltedImageList";
import TextField from "@mui/material/TextField"; import TextField from "@mui/material/TextField";
@ -17,6 +17,8 @@ import {
Divider, Divider,
Button, Button,
Tooltip, Tooltip,
Popover,
Typography,
} from "@mui/material"; } from "@mui/material";
import ProfilePictureDialog from "../components/ChagneAvatarDialog"; import ProfilePictureDialog from "../components/ChagneAvatarDialog";
@ -39,6 +41,21 @@ function Profile() {
}); });
const matchDownMd = useMediaQuery(theme.breakpoints.down("sm")); const matchDownMd = useMediaQuery(theme.breakpoints.down("sm"));
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
const username = "Username12345678"; /* Get username from database */
return ( return (
<StyledEngineProvider injectFirst> <StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
@ -46,11 +63,26 @@ function Profile() {
<div className="user-info"> <div className="user-info">
<div className="user"> <div className="user">
<ProfilePictureDialog /> <ProfilePictureDialog />
<Tooltip title="Username12345678" placement="top" arrow> <Popover
<button className="profile-username body-l"> className="profile-popover"
Username12345678 onClose={handleClose}
</button> id={id}
</Tooltip> open={open}
anchorEl={anchorEl}
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
transformOrigin={{
vertical: "bottom",
horizontal: "left",
}}
>
<Typography sx={{p: 1}}>{username}</Typography>
</Popover>
<span className="profile-username body-l" onClick={handleClick}>
{username}
</span>
</div> </div>
<div> <div>
<Box <Box

View file

@ -64,6 +64,10 @@
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.profile-popover {
padding: 1rem;
}
.button { .button {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }

View file

@ -1646,25 +1646,25 @@
resolved "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz" resolved "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz"
integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==
"@mui/core-downloads-tracker@^7.1.1": "@mui/core-downloads-tracker@^7.1.2":
version "7.1.1" version "7.1.2"
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz" resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.2.tgz"
integrity sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ== integrity sha512-0gLO1PvbJwSYe5ji021tGj6HFqrtEPMGKK4L1zWwRbhzrWWUumUJvMvJUsIgWQIYQsgOnhq9k2Fc1BxLGHDsAg==
"@mui/icons-material@^7.1.1": "@mui/icons-material@^7.1.2":
version "7.1.1" version "7.1.2"
resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.1.tgz" resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.2.tgz"
integrity sha512-X37+Yc8QpEnl0sYmz+WcLFy2dWgNRzbswDzLPXG7QU1XDVlP5TPp1HXjdmCupOWLL/I9m1fyhcyZl8/HPpp/Cg== integrity sha512-slqJByDub7Y1UcokrM17BoMBMvn8n7daXFXVoTv0MEH5k3sHjmsH8ql/Mt3s9vQ20cORDr83UZ448TEGcbrXtw==
dependencies: dependencies:
"@babel/runtime" "^7.27.1" "@babel/runtime" "^7.27.1"
"@mui/material@^7.1.1": "@mui/material@^7.1.1", "@mui/material@^7.1.2":
version "7.1.1" version "7.1.2"
resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.1.tgz" resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.2.tgz"
integrity sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A== integrity sha512-Z5PYKkA6Kd8vS04zKxJNpwuvt6IoMwqpbidV7RCrRQQKwczIwcNcS8L6GnN4pzFYfEs+N9v6co27DmG07rcnoA==
dependencies: dependencies:
"@babel/runtime" "^7.27.1" "@babel/runtime" "^7.27.1"
"@mui/core-downloads-tracker" "^7.1.1" "@mui/core-downloads-tracker" "^7.1.2"
"@mui/system" "^7.1.1" "@mui/system" "^7.1.1"
"@mui/types" "^7.4.3" "@mui/types" "^7.4.3"
"@mui/utils" "^7.1.1" "@mui/utils" "^7.1.1"