Skip to content

Commit feea4d0

Browse files
committed
feat: 사이드바 UI 작업
1 parent a8cfb41 commit feea4d0

File tree

11 files changed

+454
-278
lines changed

11 files changed

+454
-278
lines changed

src/assets/svgs/PencilIcon.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const PencilIcon = () => {
2+
return (
3+
<svg width="18" height="18" viewBox="0 0 18 18" fill="black" xmlns="http://www.w3.org/2000/svg">
4+
<g clipPath="url(#clip0_1487_633)">
5+
<path
6+
d="M12.6463 3.365L13.9119 2.09938C14.4611 1.55021 15.3514 1.55021 15.9006 2.09938C16.4498 2.64856 16.4498 3.53894 15.9006 4.08812L5.12414 14.8646C4.72763 15.2611 4.23858 15.5526 3.70117 15.7127L1.6875 16.3125L2.28734 14.2988C2.44742 13.7614 2.73888 13.2724 3.13539 12.8759L12.6463 3.365ZM12.6463 3.365L14.625 5.34374"
7+
stroke="#E2E6DA"
8+
strokeWidth="1.5"
9+
strokeLinecap="round"
10+
strokeLinejoin="round"
11+
/>
12+
</g>
13+
<defs>
14+
<clipPath id="clip0_1487_633">
15+
<rect width="18" height="18" fill="white" />
16+
</clipPath>
17+
</defs>
18+
</svg>
19+
);
20+
};
21+
22+
export default PencilIcon;

src/assets/svgs/ProfileIcon.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const ProfileIcon = ({ imageUrl }: { imageUrl: string | null }) => {
2+
return imageUrl === null ? (
3+
<svg width="49" height="49" viewBox="0 0 49 49" fill="none" xmlns="http://www.w3.org/2000/svg">
4+
<path
5+
fillRule="evenodd"
6+
clipRule="evenodd"
7+
d="M40.9349 41.947C45.5732 37.5762 48.4688 31.3762 48.4688 24.5C48.4688 11.2624 37.7376 0.53125 24.5 0.53125C11.2624 0.53125 0.53125 11.2624 0.53125 24.5C0.53125 31.3762 3.42681 37.5762 8.06512 41.947C12.3561 45.9906 18.1387 48.4688 24.5 48.4688C30.8613 48.4688 36.6439 45.9906 40.9349 41.947ZM10.1068 38.7886C13.4857 34.5738 18.6777 31.875 24.5 31.875C30.3223 31.875 35.5143 34.5738 38.8932 38.7886C35.219 42.4896 30.1271 44.7812 24.5 44.7812C18.8729 44.7812 13.781 42.4896 10.1068 38.7886ZM33.7188 17.125C33.7188 22.2164 29.5914 26.3438 24.5 26.3438C19.4086 26.3438 15.2812 22.2164 15.2812 17.125C15.2812 12.0336 19.4086 7.90625 24.5 7.90625C29.5914 7.90625 33.7188 12.0336 33.7188 17.125Z"
8+
fill="white"
9+
/>
10+
</svg>
11+
) : (
12+
<div className="avatar">
13+
<div className="w-24 rounded">
14+
<img src={imageUrl} />
15+
</div>
16+
</div>
17+
);
18+
};
19+
20+
export default ProfileIcon;

src/assets/svgs/SettingIcon.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const SettingIcon = () => {
2+
return (
3+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
4+
<path
5+
fillRule="evenodd"
6+
clipRule="evenodd"
7+
d="M9.82802 0.25C8.91145 0.25 8.12922 0.912649 7.97854 1.81675L7.88699 2.36602C7.84017 2.64695 7.63707 2.87407 7.37035 2.97395C7.20811 3.0347 7.04853 3.1009 6.89184 3.17235C6.63259 3.29056 6.32822 3.27363 6.09636 3.10801L5.64299 2.78418C4.89714 2.25143 3.87546 2.33599 3.22734 2.9841L2.98413 3.22732C2.33601 3.87544 2.25145 4.89712 2.7842 5.64297L3.10803 6.09633C3.27364 6.32819 3.29057 6.63256 3.17236 6.89182C3.10091 7.04851 3.0347 7.20809 2.97395 7.37034C2.87408 7.63706 2.64695 7.84016 2.36602 7.88698L1.81675 7.97852C0.91265 8.12921 0.25 8.91144 0.25 9.82801V10.172C0.25 11.0885 0.912648 11.8708 1.81675 12.0215L2.36602 12.113C2.64695 12.1598 2.87407 12.3629 2.97395 12.6297C3.03469 12.7919 3.1009 12.9515 3.17234 13.1082C3.29056 13.3674 3.27362 13.6718 3.10801 13.9036L2.78416 14.357C2.25141 15.1029 2.33597 16.1246 2.98408 16.7727L3.2273 17.0159C3.87541 17.664 4.8971 17.7486 5.64295 17.2158L6.09633 16.892C6.32819 16.7264 6.63256 16.7094 6.89182 16.8276C7.04851 16.8991 7.20809 16.9653 7.37034 17.026C7.63706 17.1259 7.84016 17.353 7.88698 17.634L7.97852 18.1832C8.12921 19.0873 8.91144 19.75 9.82801 19.75H10.172C11.0885 19.75 11.8708 19.0874 12.0215 18.1832L12.113 17.634C12.1598 17.3531 12.3629 17.1259 12.6297 17.0261C12.7919 16.9653 12.9515 16.8991 13.1082 16.8277C13.3674 16.7094 13.6718 16.7264 13.9036 16.892L14.357 17.2158C15.1029 17.7486 16.1245 17.664 16.7727 17.0159L17.0159 16.7727C17.664 16.1246 17.7485 15.1029 17.2158 14.357L16.892 13.9037C16.7264 13.6718 16.7094 13.3674 16.8276 13.1082C16.8991 12.9515 16.9653 12.7919 17.026 12.6297C17.1259 12.3629 17.353 12.1598 17.634 12.113L18.1832 12.0215C19.0873 11.8708 19.75 11.0886 19.75 10.172V9.82802C19.75 8.91145 19.0874 8.12922 18.1832 7.97854L17.634 7.88699C17.3531 7.84017 17.1259 7.63707 17.0261 7.37035C16.9653 7.20811 16.8991 7.04854 16.8277 6.89185C16.7094 6.63259 16.7264 6.32822 16.892 6.09636L17.2158 5.64297C17.7486 4.89712 17.664 3.87544 17.0159 3.22732L16.7727 2.9841C16.1246 2.33599 15.1029 2.25143 14.3571 2.78418L13.9037 3.10802C13.6718 3.27364 13.3674 3.29057 13.1082 3.17236C12.9515 3.10091 12.7919 3.0347 12.6297 2.97395C12.3629 2.87408 12.1598 2.64695 12.113 2.36602L12.0215 1.81675C11.8708 0.91265 11.0886 0.25 10.172 0.25H9.82802ZM10 13.75C12.0711 13.75 13.75 12.0711 13.75 10C13.75 7.92893 12.0711 6.25 10 6.25C7.92893 6.25 6.25 7.92893 6.25 10C6.25 12.0711 7.92893 13.75 10 13.75Z"
8+
fill="#F9FDF0"
9+
/>
10+
</svg>
11+
);
12+
};
13+
14+
export default SettingIcon;

src/components/common/AppBar.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
1-
import { FC } from 'react';
1+
import { FC, ReactNode } from 'react';
22
import HistoryBackButton from './HistoryBackButton';
33

44
interface AppBarProps {
5-
title?: string;
5+
title?: string | null;
66
backButton?: boolean;
7+
IconButton?: ReactNode | null;
8+
calendarName?: string | null;
79
}
810

9-
const AppBar: FC<AppBarProps> = ({ title = '', backButton = true }) => {
11+
const AppBar: FC<AppBarProps> = ({ title = null, backButton = true, IconButton = null, calendarName = null }) => {
1012
return (
11-
<nav className="grid grid-cols-5 py-5">
12-
<div className="col-span-1">{backButton ? <HistoryBackButton /> : <span />}</div>
13-
<h1 className="col-span-3 text-center">{title}</h1>
14-
<span className="col-span-1" />
13+
<nav className="grid grid-cols-5 px-5 py-5">
14+
<div className="col-span-1">{backButton ? <HistoryBackButton /> : IconButton ?? <span />}</div>
15+
{title === null ? (
16+
<div className="col-span-2"></div>
17+
) : (
18+
<h1 className="col-span-3 my-auto text-center">{title}</h1>
19+
)}
20+
{calendarName === null ? (
21+
<span />
22+
) : (
23+
<div
24+
style={{
25+
backgroundColor: 'rgba(226, 230, 218, 0.5)',
26+
}}
27+
className="col-span-2 h-full rounded-lg py-1.5 text-center text-sm font-bold"
28+
>
29+
{calendarName}
30+
</div>
31+
)}
1532
</nav>
1633
);
1734
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { useGetProfile } from '@/react-queries/userGetProfile';
2+
import SideBarGroupList from './SideBarGroupList';
3+
import SideBarProfile from './SideBarProfile';
4+
import { useNavigate } from 'react-router-dom';
5+
import { useEffect } from 'react';
6+
7+
const HamburgerButton = () => {
8+
const { data: user, isLoading, isError } = useGetProfile();
9+
10+
const navigate = useNavigate();
11+
12+
useEffect(() => {
13+
if (isError) {
14+
navigate('/login');
15+
}
16+
}, [isError, navigate]);
17+
18+
return isLoading ? (
19+
<div className="loading"></div>
20+
) : (
21+
<header className="relative z-10">
22+
<div className="drawer">
23+
<input id="my-drawer-3" type="checkbox" className="drawer-toggle" />
24+
<label htmlFor="my-drawer-3" aria-label="open sidebar" className="btn-ghost lg:hidden">
25+
<svg
26+
xmlns="http://www.w3.org/2000/svg"
27+
fill="none"
28+
viewBox="0 0 24 24"
29+
className="inline-block h-6 w-6 stroke-current"
30+
>
31+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16"></path>
32+
</svg>
33+
</label>
34+
<div className="drawer-side lg:w-80">
35+
<label htmlFor="my-drawer-3" aria-label="close sidebar" className="drawer-overlay"></label>
36+
<ul className="menu min-h-full w-80 bg-base-200 p-4">
37+
<SideBarProfile imageUrl={user?.image_url ?? null} userName={user?.user_name ?? ''} />
38+
<SideBarGroupList userId={user?.id ?? ''} />
39+
</ul>
40+
</div>
41+
</div>
42+
</header>
43+
);
44+
};
45+
46+
export default HamburgerButton;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import PencilIcon from '@/assets/svgs/PencilIcon';
2+
import { useGetAllGroupByUserId } from '@/react-queries/useGetAllGroupByUserId';
3+
import { FC } from 'react';
4+
import { Link } from 'react-router-dom';
5+
6+
interface Props {
7+
userId: string;
8+
}
9+
10+
const SideBarGroupList: FC<Props> = ({ userId }) => {
11+
const { data, error, isError, isLoading } = useGetAllGroupByUserId(userId);
12+
13+
if (isError) {
14+
// TODO: 추후 에러 처리
15+
console.error(error);
16+
}
17+
return (
18+
<ul>
19+
{isLoading && <span className="loading" />}
20+
<div className="flex flex-row items-center justify-between border-b border-white py-3">
21+
<h2>모임 리스트</h2>
22+
<Link to="/add-group" className="text-2xl">
23+
+
24+
</Link>
25+
</div>
26+
{data?.map((group) => (
27+
<li
28+
className="flex flex-row items-center justify-between border-b border-white py-2"
29+
key={group.id + 'sidebar-group-list'}
30+
>
31+
<Link to={`/group/${group.id}`}>{group.name}</Link>
32+
<Link to={`/group/${group.id}/edit/${group.id}`}>
33+
<PencilIcon />
34+
</Link>
35+
</li>
36+
))}
37+
</ul>
38+
);
39+
};
40+
41+
export default SideBarGroupList;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import ProfileIcon from '@/assets/svgs/ProfileIcon';
2+
import SettingIcon from '@/assets/svgs/SettingIcon';
3+
import { FC } from 'react';
4+
import { Link } from 'react-router-dom';
5+
6+
interface Props {
7+
userName: string;
8+
imageUrl: string | null;
9+
}
10+
11+
const SideBarProfile: FC<Props> = ({ userName, imageUrl }) => {
12+
/**
13+
* TODO: 프로필 이미지 값이 있는지 없는지에 따라 아이콘 또는 이미지 보여주기
14+
*/
15+
16+
return (
17+
<div className="flex w-full flex-row justify-between border-b-2 border-white pb-4">
18+
<div className="flex flex-row items-center gap-1 text-lg">
19+
<ProfileIcon imageUrl={imageUrl} />
20+
<span className="ml-2">{userName}</span>
21+
</div>
22+
<div className="flex flex-row items-center gap-2">
23+
<Link to="/" className="cursor-pointer rounded-lg bg-base-100 px-3 py-1 font-black hover:opacity-50">
24+
내 캘린더 보기
25+
</Link>
26+
{/**
27+
* // TODO: 버튼 링크 수정 해야함.
28+
* */}
29+
<Link to="/setting" className="cursor-pointer hover:opacity-50">
30+
<SettingIcon />
31+
</Link>
32+
</div>
33+
</div>
34+
);
35+
};
36+
37+
export default SideBarProfile;

src/pages/EditGroupSchedulePage.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ const EditGroupSchedulePage = () => {
4141
mutate(updatePayload);
4242
};
4343

44-
if (updateIsPending) {
45-
// TODO: 로딩 스피너 표시
46-
}
47-
4844
return (
4945
<>
5046
{isLoading ? (

src/pages/GroupSchedulePage.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import AppBar from '@/components/common/AppBar';
2+
import HamburgerButton from '@/components/common/SideBar/HamburgerButton';
3+
import Calendar from '@/components/common/Calendar';
4+
import CreateEventButton from '@/components/MyCalendar/CreateEventButton';
5+
import { useParams } from 'react-router-dom';
6+
import { useGetOneGroupSchedule } from '@/react-queries/useGetOneGroupSchedule';
7+
import { Loading } from '.';
8+
9+
const GroupSchedulePage = () => {
10+
// TODO: 캘린더 수정해서 이벤트 리스트를 외부에서 받을 수 있도록 해야함.
11+
const params = useParams<{ groupId: string }>();
12+
const groupId = params.groupId!;
13+
14+
const { data, isLoading, isError } = useGetOneGroupSchedule(groupId);
15+
16+
if (isError) {
17+
return <div>에러가 발생했습니다.</div>;
18+
}
19+
20+
console.log(data);
21+
22+
return (
23+
<div className="lg:ml-80">
24+
{isLoading && <Loading size="lg" display="spinner" color="primary" />}
25+
<AppBar backButton={false} IconButton={<HamburgerButton />} calendarName={data?.title ?? ''} />
26+
<main className="z-1 relative flex-grow">
27+
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
28+
<div className="rounded bg-white p-6 px-4 sm:px-0">
29+
<Calendar />
30+
</div>
31+
</div>
32+
</main>
33+
<CreateEventButton />
34+
</div>
35+
);
36+
};
37+
38+
export default GroupSchedulePage;

src/pages/MyCalendarPage.tsx

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,12 @@
1+
import AppBar from '@/components/common/AppBar.tsx';
12
import Calendar from '../components/common/Calendar.tsx';
23
import CreateEventButton from '@/components/MyCalendar/CreateEventButton.tsx';
4+
import HamburgerButton from '@/components/common/SideBar/HamburgerButton.tsx';
35

46
const MyCalendarPage: React.FC = () => {
57
return (
6-
<div>
7-
<header className="relative z-10">
8-
<div className="drawer">
9-
<input id="my-drawer-3" type="checkbox" className="drawer-toggle" />
10-
<div className="drawer-content flex flex-col">
11-
{/* Navbar */}
12-
<div className="navbar w-full">
13-
<div className="flex-none lg:hidden">
14-
<label htmlFor="my-drawer-3" aria-label="open sidebar" className="btn btn-square btn-ghost">
15-
<svg
16-
xmlns="http://www.w3.org/2000/svg"
17-
fill="none"
18-
viewBox="0 0 24 24"
19-
className="inline-block h-6 w-6 stroke-current"
20-
>
21-
<path
22-
strokeLinecap="round"
23-
strokeLinejoin="round"
24-
strokeWidth="2"
25-
d="M4 6h16M4 12h16M4 18h16"
26-
></path>
27-
</svg>
28-
</label>
29-
</div>
30-
<div className="flex-1">
31-
<h1 className="base-200 min-w-40 p-2 text-center">개인 일정 캘린더</h1>
32-
</div>
33-
</div>
34-
</div>
35-
<div className="drawer-side">
36-
<label htmlFor="my-drawer-3" aria-label="close sidebar" className="drawer-overlay"></label>
37-
<ul className="menu min-h-full w-80 bg-base-200 p-4">
38-
{/* Sidebar content here */}
39-
<li>
40-
<a>그룹 일정 캘린더 1</a>
41-
</li>
42-
<li>
43-
<a>그룹 일정 캘린더 2</a>
44-
</li>
45-
</ul>
46-
</div>
47-
</div>
48-
</header>
8+
<div className="lg:ml-80">
9+
<AppBar backButton={false} IconButton={<HamburgerButton />} calendarName="내 캘린더" />
4910
<main className="z-1 relative flex-grow">
5011
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
5112
<div className="rounded bg-white p-6 px-4 sm:px-0">

0 commit comments

Comments
 (0)