-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [feat] add navigation to profile page in profile popover * [feat] add nickname change page * [chore] add workspace query to show workspace * [chore] delete duplicated route * [fix] delete eslint-disabled * [fix] delete unused textfieldElement value * [fix] change profile routes * [fix] add error message condition * [fix] profile route * [chore] fix typo * [feat] create setting route and related component * [chore] rename CommonHeader to DrawerAppBar * [refactor] separate layout constants * [refactor] refactor the function named with reversed naming convention
- Loading branch information
1 parent
33264ec
commit 94c0b9f
Showing
12 changed files
with
233 additions
and
33 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { styled } from "@mui/material"; | ||
import AppBar, { AppBarProps } from "@mui/material/AppBar"; | ||
import { DRAWER_WIDTH } from "../../constants/layout"; | ||
|
||
interface DrawerAppBarProps extends AppBarProps { | ||
open?: boolean; | ||
} | ||
|
||
export const DrawerAppBar = styled(AppBar, { | ||
shouldForwardProp: (prop) => prop !== "open", | ||
})<DrawerAppBarProps>(({ theme, open }) => ({ | ||
transition: theme.transitions.create(["margin", "width"], { | ||
easing: theme.transitions.easing.sharp, | ||
duration: theme.transitions.duration.leavingScreen, | ||
}), | ||
...(open && { | ||
width: `calc(100% - ${DRAWER_WIDTH}px)`, | ||
marginLeft: `${DRAWER_WIDTH}px`, | ||
transition: theme.transitions.create(["margin", "width"], { | ||
easing: theme.transitions.easing.easeOut, | ||
duration: theme.transitions.duration.enteringScreen, | ||
}), | ||
}), | ||
})); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { MouseEventHandler, useState } from "react"; | ||
import { Avatar, IconButton, Stack, Toolbar } from "@mui/material"; | ||
import { useSelector } from "react-redux"; | ||
import { selectUser } from "../../store/userSlice"; | ||
import ProfilePopover from "../popovers/ProfilePopover"; | ||
import CodePairIcon from "../icons/CodePairIcon"; | ||
import { useNavigate } from "react-router-dom"; | ||
import { DrawerAppBar } from "./DrawerAppBar"; | ||
|
||
function SettingHeader() { | ||
const navigate = useNavigate(); | ||
const userStore = useSelector(selectUser); | ||
const [profileAnchorEl, setProfileAnchorEl] = useState<(EventTarget & Element) | null>(null); | ||
|
||
const handleOpenProfilePopover: MouseEventHandler = (event) => { | ||
setProfileAnchorEl(event.currentTarget); | ||
}; | ||
|
||
const handleCloseProfilePopover = () => { | ||
setProfileAnchorEl(null); | ||
}; | ||
|
||
const handleToWorkspace = () => { | ||
navigate(`/${userStore.data?.lastWorkspaceSlug}`); | ||
}; | ||
|
||
return ( | ||
<DrawerAppBar position="fixed"> | ||
<Toolbar> | ||
<Stack | ||
width="100%" | ||
direction="row-reverse" | ||
justifyContent="space-between" | ||
alignItems="center" | ||
> | ||
<IconButton onClick={handleOpenProfilePopover}> | ||
<Avatar>{userStore.data?.nickname?.charAt(0)}</Avatar> | ||
</IconButton> | ||
<IconButton onClick={handleToWorkspace}> | ||
<CodePairIcon /> | ||
</IconButton> | ||
</Stack> | ||
</Toolbar> | ||
<ProfilePopover | ||
open={Boolean(profileAnchorEl)} | ||
anchorEl={profileAnchorEl} | ||
onClose={handleCloseProfilePopover} | ||
/> | ||
</DrawerAppBar> | ||
); | ||
} | ||
|
||
export default SettingHeader; |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import Box from "@mui/material/Box"; | ||
import { Outlet } from "react-router-dom"; | ||
import SettingHeader from "../headers/SettingHeader"; | ||
|
||
function SettingLayout() { | ||
return ( | ||
<Box sx={{ display: "flex" }}> | ||
<SettingHeader /> | ||
<Outlet /> | ||
</Box> | ||
); | ||
} | ||
|
||
export default SettingLayout; |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const DRAWER_WIDTH = 282; |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { Container, Stack, Avatar, Typography, Button, FormControl } from "@mui/material"; | ||
import { TextFieldElement, FormContainer } from "react-hook-form-mui"; | ||
import { useSelector } from "react-redux"; | ||
import { selectUser } from "../../../store/userSlice"; | ||
import { useEffect, useMemo, useState } from "react"; | ||
import { useDebounce } from "react-use"; | ||
import { useUpdateUserNicknameMutation } from "../../../hooks/api/user"; | ||
import { useCheckNameConflictQuery } from "../../../hooks/api/check"; | ||
|
||
const avatarSize = 117; | ||
|
||
function ProfileIndex() { | ||
const userStore = useSelector(selectUser); | ||
const [nickname, setNickname] = useState(userStore.data?.nickname || ""); | ||
const [debouncedNickname, setDebouncedNickname] = useState(""); | ||
const { data: conflictResult } = useCheckNameConflictQuery(debouncedNickname); | ||
const { mutateAsync: updateUserNickname } = useUpdateUserNicknameMutation(); | ||
const errorMessage = useMemo(() => { | ||
if (debouncedNickname != userStore.data?.nickname && conflictResult?.conflict) { | ||
return "Already Exists"; | ||
} | ||
return null; | ||
}, [conflictResult?.conflict, debouncedNickname, userStore.data?.nickname]); | ||
|
||
const isSubmitDisabled = useMemo(() => { | ||
return ( | ||
Boolean(errorMessage) || nickname === userStore.data?.nickname || nickname.length === 0 | ||
); | ||
}, [errorMessage, nickname, userStore.data?.nickname]); | ||
|
||
useDebounce( | ||
() => { | ||
setDebouncedNickname(nickname); | ||
}, | ||
500, | ||
[nickname] | ||
); | ||
|
||
useEffect(() => { | ||
if (userStore.data?.nickname) { | ||
setNickname(userStore.data?.nickname || ""); | ||
} | ||
}, [userStore.data?.nickname]); | ||
|
||
const handleNicknameChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { | ||
setNickname(e.target.value); | ||
}; | ||
|
||
const handleUpdateUserNickname = async (data: { nickname: string }) => { | ||
await updateUserNickname(data); | ||
}; | ||
|
||
return ( | ||
<Container sx={{ height: "calc(100vh - 88px)", width: "100%" }}> | ||
<Stack alignItems="center" justifyContent="center" gap={6} sx={{ height: 1 }}> | ||
<Avatar | ||
sx={{ | ||
width: avatarSize, | ||
height: avatarSize, | ||
fontSize: avatarSize / 2, | ||
}} | ||
> | ||
{userStore.data?.nickname?.charAt(0).toUpperCase()} | ||
</Avatar> | ||
<Stack width={310}> | ||
<FormControl> | ||
<Typography variant="body1">User name</Typography> | ||
{userStore.data?.nickname && ( | ||
<FormContainer | ||
defaultValues={{ nickname: userStore.data?.nickname }} | ||
onSuccess={handleUpdateUserNickname} | ||
> | ||
<Stack gap={3}> | ||
<TextFieldElement | ||
variant="standard" | ||
name="nickname" | ||
required | ||
fullWidth | ||
inputProps={{ | ||
maxLength: 255, | ||
}} | ||
onChange={handleNicknameChange} | ||
error={Boolean(errorMessage)} | ||
helperText={errorMessage} | ||
/> | ||
|
||
<Button | ||
type="submit" | ||
variant="contained" | ||
size="large" | ||
disabled={isSubmitDisabled} | ||
> | ||
Save | ||
</Button> | ||
</Stack> | ||
</FormContainer> | ||
)} | ||
</FormControl> | ||
</Stack> | ||
</Stack> | ||
</Container> | ||
); | ||
} | ||
|
||
export default ProfileIndex; |
This file contains 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