Skip to content

Commit

Permalink
Merge pull request #172 from daithihearn/settings-menue
Browse files Browse the repository at this point in the history
Adding settings menu
  • Loading branch information
daithihearn authored Jul 5, 2023
2 parents 2ebb92f + 748696b commit aa33fb5
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 155 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "frontend",
"version": "7.1.0",
"version": "7.2.0",
"description": "React frontend for the Cards 110",
"author": "Daithi Hearn",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"short_name": "Cards 110",
"name": "Cards 110",
"version": "7.1.0",
"version": "7.2.0",
"icons": [
{
"src": "./assets/favicon.png",
Expand Down
142 changes: 0 additions & 142 deletions src/components/Avatar/ProfilePictureEditor.tsx

This file was deleted.

19 changes: 8 additions & 11 deletions src/components/Header/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useAuth0 } from "@auth0/auth0-react"

import { useAppDispatch, useAppSelector } from "caches/hooks"

import ProfilePictureEditor from "components/Avatar/ProfilePictureEditor"
import {
AppBar,
Box,
Expand All @@ -30,6 +29,7 @@ import HomeButton from "@mui/icons-material/Home"
import GameService from "services/GameService"
import { useSnackbar } from "notistack"
import parseError from "utils/ErrorUtils"
import Settings from "components/Settings/Settings"

const NavBar = () => {
const { logout } = useAuth0()
Expand All @@ -42,7 +42,7 @@ const NavBar = () => {
const isGameActive = useAppSelector(getIsGameActive)
const gameId = useAppSelector(state => state.game.id)
const iamAdmin = useAppSelector(getIamAdmin)
const [showEditAvatar, setShowEditAvatar] = useState(false)
const [showSettings, setShowSettings] = useState(false)
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
const [modalLeaderboard, updateModalLeaderboard] = useState(false)

Expand Down Expand Up @@ -86,10 +86,10 @@ const NavBar = () => {
handleClose()
}, [modalLeaderboard])

const toggleEditAvatar = useCallback(() => {
setShowEditAvatar(!showEditAvatar)
const toggleSettings = useCallback(() => {
setShowSettings(!showSettings)
handleClose()
}, [showEditAvatar])
}, [showSettings])

const navigateHome = () => navigate("/")

Expand Down Expand Up @@ -121,8 +121,8 @@ const NavBar = () => {
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}>
<MenuItem onClick={toggleEditAvatar}>
Change Avatar
<MenuItem onClick={toggleSettings}>
Settings
</MenuItem>
{isGameActive && (
<MenuItem
Expand All @@ -146,10 +146,7 @@ const NavBar = () => {
</AppBar>
<Toolbar />

<ProfilePictureEditor
show={showEditAvatar}
callback={toggleEditAvatar}
/>
<Settings show={showSettings} callback={toggleSettings} />

<Dialog
fullScreen={false}
Expand Down
162 changes: 162 additions & 0 deletions src/components/Settings/Avatar/ProfilePictureEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import React, { useCallback, useRef, useState } from "react"

import heic2any from "heic2any"
import { useSnackbar } from "notistack"
import {
Button,
FormControl,
FormHelperText,
Input,
Slider,
Grid,
ButtonGroup,
Box,
} from "@mui/material"
import { useAppDispatch, useAppSelector } from "caches/hooks"
import { getMyProfile } from "caches/MyProfileSlice"
import ProfileService from "services/ProfileService"
import AvatarEditor from "react-avatar-editor"
import parseError from "utils/ErrorUtils"

const ProfilePictureEditor: React.FC = () => {
const dispatch = useAppDispatch()
const { enqueueSnackbar } = useSnackbar()

const [selectedImage, updateSelectedImage] = useState<File>()
const [scale, updateScale] = useState(1.2)
const editorRef = useRef<AvatarEditor>()
const setEditorRef = useCallback(
(b: any) => (editorRef.current = b),
[editorRef],
)
const fileInputRef = useRef<HTMLInputElement>()
const setFileInputRef = useCallback(
(b: any) => (fileInputRef.current = b),
[fileInputRef],
)

const myProfile = useAppSelector(getMyProfile)

const reset = useCallback(() => {
updateSelectedImage(undefined)
updateScale(1.2)
if (fileInputRef.current) {
fileInputRef.current.value = ""
fileInputRef.current.files = null
}
}, [fileInputRef])

const handleSave = useCallback(
(event: React.SyntheticEvent<HTMLButtonElement>) => {
event.preventDefault()
if (!editorRef.current) return
const canvasScaled = editorRef.current.getImageScaledToCanvas()
const croppedImg = canvasScaled.toDataURL()

dispatch(
ProfileService.updateProfile({
name: myProfile.name,
picture: croppedImg,
forceUpdate: true,
}),
)
.catch((e: Error) =>
enqueueSnackbar(parseError(e), { variant: "error" }),
)
.finally(() => {
reset()
})
},
[myProfile, editorRef, fileInputRef],
)

const handleNewAvatarSelection = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
event.preventDefault()
if (!event.target.files || event.target.files.length < 1) return
const file = event.target.files[0]

if (file.type.includes("heic")) {
heic2any({ blob: file, toType: "image/jpg", quality: 1 }).then(
jpgFile => {
updateSelectedImage(jpgFile as File)
},
)
} else updateSelectedImage(file)
}

return (
<>
<FormControl fullWidth>
<Box
display="flex"
justifyContent="center"
alignItems="center"
height={200}>
{selectedImage && (
<AvatarEditor
ref={setEditorRef}
image={selectedImage}
width={150}
height={150}
border={25}
color={[255, 255, 255, 0.6]} // RGBA
scale={scale}
rotate={0}
/>
)}
</Box>
</FormControl>
<FormControl fullWidth>
<Input
ref={setFileInputRef}
type="file"
// accept="image/*,.heic"
name="newAvatar"
id="newAvatar"
onChange={handleNewAvatarSelection}
// multiple={false}
/>
<FormHelperText>Please choose your new avatar</FormHelperText>
</FormControl>
<FormControl fullWidth>
<Grid container spacing={2}>
<Grid item xs>
<Slider
name="scale"
onChange={(_, value) =>
updateScale(value as number)
}
min={1}
max={2}
step={0.01}
defaultValue={1.2}
color="secondary"
/>
</Grid>
</Grid>
</FormControl>
<FormControl fullWidth>
<ButtonGroup fullWidth>
<Button
type="button"
onClick={reset}
color="secondary"
variant="outlined">
Reset
</Button>
<Button
type="button"
onClick={handleSave}
color="secondary"
variant="outlined">
Save
</Button>
</ButtonGroup>
</FormControl>
</>
)
}

export default ProfilePictureEditor
Loading

0 comments on commit aa33fb5

Please sign in to comment.