From 748696bb29b30a349fafea5e0a1a67283398ed1c Mon Sep 17 00:00:00 2001 From: Daithi Hearn Date: Wed, 5 Jul 2023 21:26:05 +0200 Subject: [PATCH] Adding settings menu --- package.json | 2 +- public/manifest.json | 2 +- .../Avatar/ProfilePictureEditor.tsx | 142 --------------- src/components/Header/NavBar.tsx | 19 +- .../Settings/Avatar/ProfilePictureEditor.tsx | 162 ++++++++++++++++++ src/components/Settings/GamePlaySettings.tsx | 51 ++++++ src/components/Settings/Settings.tsx | 37 ++++ 7 files changed, 260 insertions(+), 155 deletions(-) delete mode 100644 src/components/Avatar/ProfilePictureEditor.tsx create mode 100644 src/components/Settings/Avatar/ProfilePictureEditor.tsx create mode 100644 src/components/Settings/GamePlaySettings.tsx create mode 100644 src/components/Settings/Settings.tsx diff --git a/package.json b/package.json index d018bc2..9b1a2ce 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/public/manifest.json b/public/manifest.json index e591ebd..d92ae77 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,7 +1,7 @@ { "short_name": "Cards 110", "name": "Cards 110", - "version": "7.1.0", + "version": "7.2.0", "icons": [ { "src": "./assets/favicon.png", diff --git a/src/components/Avatar/ProfilePictureEditor.tsx b/src/components/Avatar/ProfilePictureEditor.tsx deleted file mode 100644 index b7d55b4..0000000 --- a/src/components/Avatar/ProfilePictureEditor.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import React, { useCallback, useRef, useState } from "react" - -import heic2any from "heic2any" -import { useSnackbar } from "notistack" -import { - Dialog, - DialogTitle, - DialogContent, - DialogActions, - Button, - FormControl, - FormHelperText, - Input, - Slider, - Grid, -} 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" - -interface InputsI { - show: boolean - callback: () => void -} -const ProfilePictureEditor: React.FC = ({ show, callback }) => { - const dispatch = useAppDispatch() - const { enqueueSnackbar } = useSnackbar() - - const [selectedImage, updateSelectedImage] = useState() - const [scale, updateScale] = useState(1.2) - const editorRef = useRef() - const setEditorRef = useCallback( - (b: any) => (editorRef.current = b), - [editorRef], - ) - - const myProfile = useAppSelector(getMyProfile) - - const handleSave = useCallback( - (event: React.SyntheticEvent) => { - event.preventDefault() - 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(callback) - }, - [myProfile, editorRef], - ) - - const handleNewAvatarSelection = ( - event: React.ChangeEvent, - ) => { - 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 ( - - Edit Profile Picture - - - {selectedImage && ( - - )} - - - - - Please choose your new avatar - - - - - - - updateScale(value as number) - } - min={1} - max={2} - step={0.01} - defaultValue={1.2} - /> - - - - - - - - - - ) -} - -export default ProfilePictureEditor diff --git a/src/components/Header/NavBar.tsx b/src/components/Header/NavBar.tsx index 295cce5..e3b7731 100644 --- a/src/components/Header/NavBar.tsx +++ b/src/components/Header/NavBar.tsx @@ -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, @@ -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() @@ -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) const [modalLeaderboard, updateModalLeaderboard] = useState(false) @@ -86,10 +86,10 @@ const NavBar = () => { handleClose() }, [modalLeaderboard]) - const toggleEditAvatar = useCallback(() => { - setShowEditAvatar(!showEditAvatar) + const toggleSettings = useCallback(() => { + setShowSettings(!showSettings) handleClose() - }, [showEditAvatar]) + }, [showSettings]) const navigateHome = () => navigate("/") @@ -121,8 +121,8 @@ const NavBar = () => { anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}> - - Change Avatar + + Settings {isGameActive && ( { - + { + const dispatch = useAppDispatch() + const { enqueueSnackbar } = useSnackbar() + + const [selectedImage, updateSelectedImage] = useState() + const [scale, updateScale] = useState(1.2) + const editorRef = useRef() + const setEditorRef = useCallback( + (b: any) => (editorRef.current = b), + [editorRef], + ) + const fileInputRef = useRef() + 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) => { + 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, + ) => { + 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 ( + <> + + + {selectedImage && ( + + )} + + + + + Please choose your new avatar + + + + + + updateScale(value as number) + } + min={1} + max={2} + step={0.01} + defaultValue={1.2} + color="secondary" + /> + + + + + + + + + + + ) +} + +export default ProfilePictureEditor diff --git a/src/components/Settings/GamePlaySettings.tsx b/src/components/Settings/GamePlaySettings.tsx new file mode 100644 index 0000000..4386ac2 --- /dev/null +++ b/src/components/Settings/GamePlaySettings.tsx @@ -0,0 +1,51 @@ +import { FormControl, FormLabel, Checkbox, Grid } from "@mui/material" +import { getSettings } from "caches/SettingsSlice" +import { useAppDispatch, useAppSelector } from "caches/hooks" +import { useSnackbar } from "notistack" +import React, { useCallback } from "react" +import SettingsService from "services/SettingsService" +import parseError from "utils/ErrorUtils" + +const GamePlaySettings: React.FC = () => { + const dispatch = useAppDispatch() + const { enqueueSnackbar } = useSnackbar() + const settings = useAppSelector(getSettings) + + const toggleAutoBuy = useCallback(async () => { + const updatedSettings = { + ...settings, + autoBuyCards: !settings.autoBuyCards, + } + await dispatch(SettingsService.updateSettings(updatedSettings)).catch( + (e: Error) => enqueueSnackbar(parseError(e), { variant: "error" }), + ) + }, [settings]) + + return ( + + + + + Auto Buy Cards + + + + + + + + ) +} + +export default GamePlaySettings diff --git a/src/components/Settings/Settings.tsx b/src/components/Settings/Settings.tsx new file mode 100644 index 0000000..5f00a42 --- /dev/null +++ b/src/components/Settings/Settings.tsx @@ -0,0 +1,37 @@ +import React from "react" + +import { + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Button, +} from "@mui/material" +import ProfilePictureEditor from "./Avatar/ProfilePictureEditor" +import GamePlaySettings from "./GamePlaySettings" + +interface InputsI { + show: boolean + callback: () => void +} +const Settings: React.FC = ({ show, callback }) => { + return ( + + Avatar + + + + Gameplay + + + + + + + + ) +} + +export default Settings