Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/components/Sidebar/SidebarIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ import type { ReactNode } from 'react';

interface SidebarIconProps {
icon: ReactNode;
isActive: boolean;
onClick?: () => void;
}

const SidebarIcon = ({ icon, onClick }: SidebarIconProps) => {
const SidebarIcon = ({ icon, isActive, onClick }: SidebarIconProps) => {
const handleClick = () => {
if (onClick) onClick();
};
return (
<button
onClick={handleClick}
className="flex h-[4.4rem] w-[4.4rem] items-center rounded-[0.8rem] px-[1.2rem] hover:bg-black-10"
className={`flex h-[4.4rem] w-[4.4rem] items-center rounded-[0.8rem] px-[1.2rem] ${
isActive
? 'bg-blue-5 text-blue-100'
: 'bg-black-5 text-black-50 hover:bg-black-10'
}`}
>
{icon}
</button>
Expand Down
23 changes: 19 additions & 4 deletions src/components/Sidebar/SidebarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ interface SubItem {
interface SidebarItemProps {
icon: ReactNode;
label: string;
isActive: boolean;
onClick?: () => void;
subItems?: SubItem[];
}

const SidebarItem = ({ icon, label, onClick, subItems }: SidebarItemProps) => {
const SidebarItem = ({
icon,
label,
isActive,
onClick,
subItems,
}: SidebarItemProps) => {
const [isOpen, setIsOpen] = useState(false);

const hasSubItems = subItems && subItems.length > 0;
Expand Down Expand Up @@ -69,10 +76,18 @@ const SidebarItem = ({ icon, label, onClick, subItems }: SidebarItemProps) => {
return (
<>
<button onClick={handleClick}>
<div className="flex h-[4.4rem] items-center rounded-[0.8rem] bg-black-5 px-[1.2rem] hover:bg-black-10">
<div className="flex w-[21.8rem] gap-[0.8rem]">
<div
className={`flex h-[4.4rem] items-center rounded-[0.8rem] px-[1.2rem] ${
isActive ? 'bg-blue-5' : 'bg-black-5 hover:bg-black-10'
}`}
>
<div
className={`flex w-[21.8rem] gap-[0.8rem] ${isActive ? 'text-blue-100' : 'text-black-50'}`}
>
{icon}
<span className="text-[1.6rem] font-bold text-black-40">
<span
className={`text-[1.6rem] font-bold ${isActive ? 'text-blue-100' : 'text-black-60'}`}
>
{label}
</span>
</div>
Expand Down
40 changes: 32 additions & 8 deletions src/components/Sidebar/SidebarMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useNavigate } from 'react-router';
import { useLocation, useNavigate } from 'react-router';
import SidebarIcon from './SidebarIcon';
import SidebarItem from './SidebarItem';

Expand All @@ -24,25 +24,25 @@ const SIDEBAR_MENUS: SidebarMenu[] = [
{
key: 'team',
label: '내팀',
icon: <FaceSmileIcon className="text-black-40" />,
icon: <FaceSmileIcon />,
getPath: ({ teamId }) => `/team/${teamId}`,
},
{
key: 'notification',
label: '알림',
icon: <BellIcon className="text-black-40" />,
icon: <BellIcon />,
getPath: () => '/notification',
},
{
key: 'message',
label: '메시지',
icon: <MessageIcon className="text-black-40" />,
icon: <MessageIcon />,
getPath: () => '/message',
},
{
key: 'mypage',
key: 'profile',
label: '마이페이지',
icon: <PersonIcon className="text-black-40" />,
icon: <PersonIcon />,
getPath: ({ userId }) => `/profile/${userId}`,
},
];
Expand All @@ -53,34 +53,58 @@ const SIDEBAR_MENUS: SidebarMenu[] = [
// ];

const SidebarMenu = ({
isLoggedIn,
setIsLoginModalOpen,
isFolded,
teamId,
userId,
}: {
isLoggedIn: boolean;
setIsLoginModalOpen: () => void;
isFolded: boolean;
teamId?: number;
userId?: string;
}) => {
const { pathname } = useLocation();
const navigate = useNavigate();

const visibleMenus = isLoggedIn
? SIDEBAR_MENUS
: SIDEBAR_MENUS.filter((menu) => menu.key === 'team');

return (
<div
className={`flex flex-col gap-[0.4rem] ${isFolded ? 'w-[4.8rem]' : 'w-[25.8rem]'}`}
>
{SIDEBAR_MENUS.map(({ key, icon, label, getPath }) => {
{visibleMenus.map(({ key, icon, label, getPath }) => {
const path = getPath({ teamId, userId });

const isActive =
pathname.includes(key) &&
!(key === 'team' && pathname === '/team/new');

const handleClick = () => {
if (!isLoggedIn && key === 'team') {
setIsLoginModalOpen();
return;
}
if (!path) return;
navigate(path);
};

return isFolded ? (
<SidebarIcon key={key} icon={icon} onClick={handleClick} />
<SidebarIcon
key={key}
icon={icon}
isActive={isActive}
onClick={handleClick}
/>
) : (
<SidebarItem
key={key}
icon={icon}
label={label}
isActive={isActive}
onClick={handleClick}
/>
);
Expand Down
45 changes: 21 additions & 24 deletions src/components/Sidebar/SidebarProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { UserMeResponse } from '../../types/api/user';
// Icons
import BaicProfileIcon from '../../assets/icons/ic_profile_basic.svg?react';
import LogoutIcon from '../../assets/icons/normal/ic_logout.svg?react';
import CharacterGrayIcon from '../../assets/icons/ic_character_gray.svg?react';

const SidebarProfile = ({
data,
Expand All @@ -21,29 +20,27 @@ const SidebarProfile = ({
if (isFolded) return <BaicProfileIcon />;

return (
<div
className={`flex w-[25.8rem] items-center justify-center gap-[1rem] ${!isLoggedIn && 'pt-[0.2rem]'}`}
>
{isLoggedIn ? (
<>
<BaicProfileIcon />
<div className="flex w-[14.8rem] flex-col justify-center">
<span className="text-[1.6rem] font-semibold text-black-100">
{data?.username || '닉네임'}
</span>
<span className="h-[2rem] text-[1.3rem] font-medium text-black-60">
{POSITION_CONVERTER[data?.position] || '포지션'}
</span>
</div>
<button
onClick={() => logout()}
className="h-[3.2rem] w-[3.2rem] rounded-full px-[0.8rem] py-[0.8rem] hover:bg-black-10"
>
<LogoutIcon className="h-[1.6rem] w-[1.6rem] text-black-40" />
</button>
</>
) : (
<CharacterGrayIcon />
<div className="flex w-[25.8rem] items-center gap-[1rem] pr-[1rem]">
<BaicProfileIcon />
<div className="flex w-[15.2rem] flex-col justify-center">
<span className="text-[1.6rem] font-semibold text-black-100">
{isLoggedIn ? data?.username || '게스트' : '게스트'}
</span>
<span
className={`h-[2rem] text-[1.3rem] font-medium ${isLoggedIn ? 'text-black-60' : 'text-blue-60'}`}
>
{isLoggedIn && data?.position
? POSITION_CONVERTER[data?.position] || '로그인해주세요'
: '로그인해주세요'}
</span>
</div>
{isLoggedIn && (
<button
onClick={() => logout()}
className="h-[3.2rem] w-[3.2rem] rounded-full px-[0.8rem] py-[0.8rem] hover:bg-black-10"
>
<LogoutIcon className="h-[1.6rem] w-[1.6rem] text-black-40" />
</button>
)}
</div>
);
Expand Down
18 changes: 8 additions & 10 deletions src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const Sidebar = () => {
const { data: myteamData } = useGetUserMeTeam();

const [isFolded, setIsFolded] = useState(false);
const [isLogInModalOpen, setIsLogInModalOpen] = useState(false);
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);

const accessToken = useAuthStore((state) => state.accessToken);
const isLoggedIn = !!accessToken;
Expand All @@ -50,11 +50,7 @@ const Sidebar = () => {
{/* middle content */}
<div className="flex flex-1 flex-col gap-[1.2rem] px-[2rem]">
{/* 프로필 및 모집글 작성 버튼 */}
<div
className={`flex flex-col ${
isLoggedIn ? 'gap-[1.8rem] py-[2rem]' : 'gap-[1rem] py-[2rem]'
} `}
>
<div className="flex flex-col gap-[1.8rem] py-[2rem]">
<SidebarProfile
data={myData}
isFolded={isFolded}
Expand All @@ -64,7 +60,7 @@ const Sidebar = () => {
{isFolded ? (
<IconWrapper
onClick={() => {
if (!isLoggedIn) setIsLogInModalOpen(true);
if (!isLoggedIn) setIsLoginModalOpen(true);
}}
>
{isLoggedIn ? <PencilIcon /> : <LogInIcon />}
Expand All @@ -80,13 +76,15 @@ const Sidebar = () => {
</BaseButton>
)
) : (
<BaseButton onClick={() => setIsLogInModalOpen(true)}>
<BaseButton onClick={() => setIsLoginModalOpen(true)}>
로그인
</BaseButton>
)}
</div>

<SidebarMenu
isLoggedIn={isProfileComplete}
setIsLoginModalOpen={() => setIsLoginModalOpen(true)}
isFolded={isFolded}
teamId={myteamData?.[0]?.teamId}
userId={myData?.userId}
Expand Down Expand Up @@ -114,8 +112,8 @@ const Sidebar = () => {
)}
</aside>
<LoginModal
isOpen={isLogInModalOpen}
onClose={() => setIsLogInModalOpen(false)}
isOpen={isLoginModalOpen}
onClose={() => setIsLoginModalOpen(false)}
/>
</>
);
Expand Down
Loading