Skip to content

Commit

Permalink
feat: Nav區有導覽列的UI
Browse files Browse the repository at this point in the history
  • Loading branch information
whalekiller03 committed Jul 25, 2024
1 parent 28321c6 commit 11122b3
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 145 deletions.
2 changes: 1 addition & 1 deletion pages/profile/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const HomePageWrapper = styled.div`
`;

const StyledTab = styled(Tab)(({ isActive, mobileScreen }) => ({
width: `${mobileScreen ? '50%' : '100%'}`,
width: `${mobileScreen ? '33%' : '100%'}`,
color: '#536166',
borderRadius: '8px',
'&.Mui-selected': {
Expand Down
41 changes: 13 additions & 28 deletions shared/components/Navigation_v2/MainNav/Hamberger/MenuItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,47 +37,32 @@ const MenuItemWrapper = styled.li`
`;

const ItemWrapper = styled.div`
font-size: 30px;
padding: 1rem 0;
margin: 0 5%;
font-size: 18px;
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
color: #fafafa;
transition: color 0.2s ease-in-out;
animation: 0.5s ${slideInFrames} forwards;
color: #536166;
${(props) => css`
animation-delay: ${props.delay};
`}
&:hover {
color: 'gray';
background-color: #def5f5;
font-weight: bold;
}
`;

const LineStyle = styled.div`
width: '90%';
height: '1px';
background: '#fafafa';
margin: '0 auto';
animation: 0.5s ${shrinkFrames} forwards;
${(props) => css`
animation-delay: ${props.delay};
`}
`;

const MenuItem = ({ delay, text, link, onClick }) => {
if (link) {
return (
<MenuItemWrapper delay={delay} onClick={onClick}>
<Link href={link} passHref>
<ItemWrapper delay={delay}>{text}</ItemWrapper>
</Link>
<LineStyle delay={delay} />
</MenuItemWrapper>
);
}
return (
<MenuItemWrapper delay={delay} onClick={onClick}>
<ItemWrapper delay={delay}>{text}</ItemWrapper>
<LineStyle delay={delay} />
{link ? (
<Link href={link} passHref color="gray">
<ItemWrapper delay={delay}>{text}</ItemWrapper>
</Link>
) : (
<ItemWrapper delay={delay}>{text}</ItemWrapper>
)}
</MenuItemWrapper>
);
};
Expand Down
44 changes: 30 additions & 14 deletions shared/components/Navigation_v2/MainNav/Hamberger/MenuList.jsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,55 @@
// import { keyframes, css } from '@emotion/react';
import styled from '@emotion/styled';
import { Box } from '@mui/material';
import { useRouter } from 'next/router';
import MenuItem from './MenuItem';
import UserAvatar from '../SubList/UserAvatar';
import { useSelector } from 'react-redux';
import { Button } from '@mui/material';

const MenuWrapper = styled.div`
position: fixed;
top: 0;
top: ${(props) => props.shiftTop};
left: 0;
height: ${(props) => (props.open ? '100%' : 0)};
height: ${(props) => (props.open ? '100dvh' : 0)};
width: 100vw;
display: flex;
flex-direction: column;
background: #16b9b3;
opacity: 0.95;
color: #fafafa;
background: white;
transition: height 0.3s ease;
z-index: 100;
overflow: auto;
`;

const MenuListWrapper = styled.div`
padding: 3rem;
margin-top: 30px;
padding: 1rem;
position: relative;
z-index: 100;
height: inherit;
`;

const Menu = ({ open, list, onCloseMenu }) => {
const router = useRouter();
const MenuDivider = styled.div`
height: 1px;
width: 100%;
background-color: #def5f5;
margin: 1rem 0;
`;

const LoginButton = styled(Button)`
width: 100%;
height: 40px;
padding: 5px 20px;
color: #536166;
font-size: 16px;
line-height: 1.4;
border-radius: 20px;
border: 1px solid #16b9b3;
`;

const Menu = ({ open, list, onCloseMenu, shiftTop = '80px' }) => {
const user = useSelector((state) => state.user);
console.log("MenuList", user);
return (
<MenuWrapper open={open}>
<MenuWrapper open={open} shiftTop={shiftTop}>
{open && (
<MenuListWrapper>
<UserAvatar user={user} />
{list.map((value, index) => {
return (
<MenuItem
Expand All @@ -51,6 +61,12 @@ const Menu = ({ open, list, onCloseMenu }) => {
/>
);
})}
<MenuDivider />
{user._id ? (
<UserAvatar user={user} onCloseMenu={onCloseMenu} />
) : (
<LoginButton href="/login">登入</LoginButton>
)}
</MenuListWrapper>
)}
</MenuWrapper>
Expand Down
8 changes: 6 additions & 2 deletions shared/components/Navigation_v2/MainNav/Hamberger/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ const MobileLinkListWrapper = styled.ul`
li {
flex: none;
width: 100%;
border-bottom: solid 1px white;
}
li a {
color: #536166;
}
svg[type='menu']:checked + ul {
Expand All @@ -39,13 +42,14 @@ const MobileLinkListWrapper = styled.ul`
}
`;

const MainNav = () => {
const MainNav = ({ shiftTop = 0 }) => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const avatar = '';
const isUserLogin = true;
return (
<MobileLinkListWrapper>
<MenuList
shiftTop={shiftTop}
isUserLogin={isUserLogin}
avatar={avatar}
open={isMenuOpen}
Expand Down
159 changes: 99 additions & 60 deletions shared/components/Navigation_v2/MainNav/SubList/UserAvatar/index.jsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,114 @@
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import { Avatar, Box, IconButton, Menu, MenuItem } from '@mui/material';
import { Group } from '@mui/icons-material';
import { keyframes, css } from '@emotion/react';
import styled from '@emotion/styled';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import { userLogout } from '@/redux/actions/user';
import useMediaQuery from '@mui/material/useMediaQuery';

import { Avatar, Box, MenuItem, Typography } from '@mui/material';
import { useRouter } from 'next/router';

const UserAvatar = () => {
const slideInFrames = keyframes`
0% {
transform: translateX(-2%);
}
100% {
transform: translateX(0);
}
`;

const StyledMenuItem = styled(MenuItem)`
animation: 0.5s ${slideInFrames} forwards;
transition: color 0.2s ease-in-out;
color: #536166;
border-radius: 4px;
${(props) => css`
animation-delay: ${props.delay};
padding: ${props.isPadScreen} ? 12px : 12px 52px;
font-size: ${props.isPadScreen} ? 18px : 16px;
magrin: ${props.isPadScreen} ? 8px 0; : '0';
&:hover {
background-color: #DEF5F5;
}
`}
`;

const UserAvatar = ({ onCloseMenu = () => {}, user }) => {
const isPadScreen = useMediaQuery('(max-width: 767px)');

const { push } = useRouter();
const user = useSelector((state) => state.user);

const [isOpenMenu, setIsOpenMenu] = useState(null);

const handleSignOut = () => {
console.log('handleSignOut');
const logout = () => {
dispatch(userLogout());
setIsOpenMenu(false);
onCloseMenu();
push('/');
};

if (!user._id) {
return (
<IconButton
sx={{ margin: '0 10px', fontSize: '16px', color: 'white' }}
onClick={() => {
push('/login');
}}
>
<Group sx={{ fontSize: '30px' }} />
</IconButton>
);
}
return (
<IconButton sx={{ margin: '0 10px' }}>
<Avatar
alt={user?.displayName ?? ''}
src={user?.photoURL ?? ''}
// onClick={(event) => setIsOpenMenu(event.currentTarget)}
onClick={() => {
setIsOpenMenu(false);
push('/profile');
<Box sx={{ margin: '8px 32px', cursor: 'pointer', position: 'relative' }}>
<Box
sx={{ display: 'flex', alignItems: 'center' }}
onClick={() => setIsOpenMenu(!isOpenMenu)}
>
{user.name && (
<Avatar alt={user?.displayName ?? ''} src={user?.photoURL ?? ''} />
)}
{isPadScreen && (
<>
<Typography
sx={{
flexGrow: 1,
marginLeft: '12px',
fontWeight: 'bold',
fontSize: '18px',
color: '#536166',
}}
>
{user.name}
</Typography>
{isOpenMenu ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</>
)}
</Box>
<Box
sx={{
display: isOpenMenu ? 'block' : 'none',
position: isPadScreen ? 'relative' : 'absolute',
top: isPadScreen ? 0 : '60px',
borderRadius: '8px',
backgroundColor: 'white',
right: '0',
zIndex: 1,
}}
/>
<Menu
id="user-menu"
anchorEl={isOpenMenu}
open={Boolean(isOpenMenu)}
onClose={() => setIsOpenMenu(false)}
>
<MenuItem
onClick={() => {
setIsOpenMenu(false);
push('/profile');
}}
>
個人頁面
</MenuItem>
<MenuItem
onClick={() => {
setIsOpenMenu(false);
push('/profile');
}}
>
帳號設定
</MenuItem>
<MenuItem
onClick={() => {
handleSignOut();
push('/');
setIsOpenMenu(false);
}}
>
登出
</MenuItem>
</Menu>
</IconButton>
<Box sx={{ padding: !isPadScreen && '12px' }}>
{[
{ name: '個人資料', id: 'person-setting' },
{ name: '我的揪團', id: 'my-group' },
{ name: '帳號設定', id: 'account-setting' },
].map((v, i) => (
<StyledMenuItem
key={v.id}
delay={`${i * 0.1}s`}
isPadScreen={isPadScreen}
onClick={() => {
setIsOpenMenu(false);
onCloseMenu();
push('/profile?id=' + v.id);
}}
>
{v.name}
</StyledMenuItem>
))}

<StyledMenuItem onClick={logout}>登出</StyledMenuItem>
</Box>
</Box>
</Box>
);
};

Expand Down
Loading

0 comments on commit 11122b3

Please sign in to comment.