Skip to content

Commit d4058fe

Browse files
authored
Merge pull request #163 from imaginer-dev/17-sidebar
17 ์‚ฌ์ด๋“œ๋ฐ” UI ์ˆ˜์ • ๋ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
2 parents 1cf09dd + 9db1db8 commit d4058fe

19 files changed

+329
-61
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import supabase from '@/supabase';
2+
3+
export const getAllGroupByUserIdFetch = async (userId: string) => {
4+
const { data, error } = await supabase.from('group_user_ralations').select('*').eq('user_id', userId);
5+
if (error) {
6+
throw error;
7+
}
8+
const { data: groupData, error: groupError } = await supabase
9+
.from('groups')
10+
.select('*')
11+
.in(
12+
'id',
13+
data.map((d) => d.group_id),
14+
);
15+
16+
if (groupError) {
17+
throw groupError;
18+
}
19+
20+
return groupData;
21+
};

โ€Žsrc/apis/getUserApi.tsโ€Ž

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import supabase from '@/supabase';
2+
3+
export const getUserFetch = async () => {
4+
const { data: session, error: sessionError } = await supabase.auth.getUser();
5+
6+
if (!session || sessionError) {
7+
throw sessionError;
8+
}
9+
10+
const { data, error } = await supabase.from('profiles').select('*').eq('id', session.user.id).single();
11+
12+
if (error) {
13+
throw error;
14+
}
15+
16+
return data;
17+
};

โ€Žsrc/apis/groupScheduleApis.tsโ€Ž

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ interface addGroupShedule {
1010
}
1111

1212
export const addGroupScheduleFetch = async ({ startDate, endDate, newMemberList, ...props }: addGroupShedule) => {
13+
// ํ˜„์žฌ ๋กœ๊ทธ์ธ๋œ ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
14+
const { data: user, error: userError } = await supabase.auth.getUser();
15+
16+
if (userError) {
17+
throw userError;
18+
}
19+
1320
// ๊ทธ๋ฃน์„ ์ƒ์„ฑํ•œ๋‹ค.
1421
const { data: groupInfo, error: groupInfoError } = await supabase
1522
.from('groups')
@@ -27,12 +34,15 @@ export const addGroupScheduleFetch = async ({ startDate, endDate, newMemberList,
2734
}
2835

2936
// ๊ทธ๋ฃน์— ๋ฉค๋ฒ„๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
30-
const { error: groupMemberError } = await supabase.from('group_user_ralations').insert(
31-
newMemberList.map((member) => ({
32-
group_id: groupInfo.id,
33-
user_id: member.id,
34-
})),
35-
);
37+
const newRelationSchema = newMemberList.map((member) => ({
38+
group_id: groupInfo.id,
39+
user_id: member.id,
40+
}));
41+
newRelationSchema.push({
42+
group_id: groupInfo.id,
43+
user_id: user.user.id,
44+
});
45+
const { error: groupMemberError } = await supabase.from('group_user_ralations').insert(newRelationSchema);
3646
if (groupMemberError) {
3747
throw groupMemberError;
3848
}
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;
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;
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
};

โ€Žsrc/components/common/Calendar.tsxโ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default function Calendar() {
3636
const calendarRef = useRef<FullCalendar | null>(null);
3737
const [selectedEvents, setSelectedEvents] = useState<Events[]>([]);
3838
const [selectedDate, setSelectedDate] = useState<string | null>(null);
39+
// ! : ์™ธ๋ถ€์—์„œ ์ด๋ฒคํŠธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ›์•„์˜ค๊ฒŒ ๋œ๋‹ค๋ฉด zustand ์Šคํ† ์–ด๋„ ํ•„์š” ์—†์„๊ฑฐ ๊ฐ™์Šต๋‹ˆ๋‹ค!
3940
const { events, addEvents } = useEventState();
4041

4142
/*
@@ -155,6 +156,7 @@ export default function Calendar() {
155156

156157
const [isLoaded, setIsLoaded] = useState(false); // ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์ƒํƒœ
157158

159+
// !: ์ด๋ฒ ํŠธ๋ฅผ ๋ฐ›์•„์˜จ๋‹ค๋ฉด ํ•„์š”์—†๋Š” ์ฝ”๋“œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์„๊ฑฐ ๊ฐ™์•„์š”.
158160
useEffect(() => {
159161
if (!isLoaded) {
160162
getPersonalSchedule().then((schedule) => {
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;

0 commit comments

Comments
ย (0)