diff --git a/src/assets/svgs/hamburgerIcon.svg b/src/assets/svgs/hamburgerIcon.svg
new file mode 100644
index 00000000..1682b89f
--- /dev/null
+++ b/src/assets/svgs/hamburgerIcon.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/assets/svgs/index.tsx b/src/assets/svgs/index.tsx
index 48202095..022d9662 100644
--- a/src/assets/svgs/index.tsx
+++ b/src/assets/svgs/index.tsx
@@ -94,3 +94,6 @@ export { default as GroupCuriousIc } from './groupCuriousIcn.svg?react';
export { default as GroupViewIc } from './groupViewIcn.svg?react';
// export { default as LoadingIc } from './loadingSvg.svg?react';
+
+export { default as LinkIc } from './linkIcon.svg?react';
+export { default as HamburgerIc } from './hamburgerIcon.svg?react';
diff --git a/src/assets/svgs/linkIcon.svg b/src/assets/svgs/linkIcon.svg
new file mode 100644
index 00000000..53fb9343
--- /dev/null
+++ b/src/assets/svgs/linkIcon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/commons/Header.tsx b/src/components/commons/Header.tsx
index a23e87a8..91f8b464 100644
--- a/src/components/commons/Header.tsx
+++ b/src/components/commons/Header.tsx
@@ -2,9 +2,9 @@ import styled from '@emotion/styled';
import { useEffect, useState } from 'react';
import Button from './Button';
-import LogInOutBtn from './LogInOutBtn';
+import { LogInOutBtn } from './HeaderButton';
-import { HeaderLogoIc } from '../../assets/svgs';
+import { HamburgerIc, HeaderLogoIc, LinkIc } from '../../assets/svgs';
import {
default as useNavigateHome,
default as useNavigateToHome,
@@ -16,6 +16,14 @@ import MyGroupDropDown from '../../pages/groupFeed/components/MyGroupDropDown';
import { useFetchHeaderGroup } from '../../pages/groupFeed/hooks/queries';
import logout from '../../utils/logout';
+import { MOBILE_MEDIA_QUERY } from '../../styles/mediaQuery';
+import Responsive from './Responsive/Responsive';
+import { MobileUnAuthorizedSidebar, MobileAuthorizedSidebar } from './MyMobileSidebar';
+
+import { useParams } from 'react-router-dom';
+import { useFetchInvitationLink } from '../../pages/admin/hooks/queries';
+import { copyLink } from '../../utils/copyLink';
+
interface onClickEditProps {
onClickEditSave: () => void;
}
@@ -33,25 +41,54 @@ interface OnClickTempExistProps {
export const AuthorizationHeader = () => {
const [moims, setMoims] = useState([]);
const { navigateToHome } = useNavigateToHome();
- const { data } = useFetchHeaderGroup();
+ const { moimsData } = useFetchHeaderGroup();
const handleLogOut = () => {
logout();
navigateToHome();
};
useEffect(() => {
- if (data?.data?.moims) setMoims(data?.data.moims);
- }, [data?.data?.moims]);
+ if (moimsData) setMoims(moimsData);
+ }, [moimsData]);
+
+ const [isSidebarOpen, setIsSidebarOpen] = useState(false);
return (
-
-
-
-
-
-
- 로그아웃
-
-
-
+ <>
+
+
+
+
+
+
+
+
+
+ 로그아웃
+
+
+
+
+
+
+
+
+ {
+ setIsSidebarOpen(true);
+ }}
+ />
+
+
+ {isSidebarOpen && (
+ {
+ setIsSidebarOpen(false);
+ }}
+ groupCount={moimsData?.length ?? 0}
+ groupData={moims ?? []}
+ />
+ )}
+
+ >
);
};
@@ -60,11 +97,38 @@ export const UnAuthorizationHeader = () => {
const { navigateToHome } = useNavigateHome();
const { navigateToLogin } = useNavigateLoginWithPath();
+ const [isSidebarOpen, setIsSidebarOpen] = useState(false);
+
return (
-
-
- 로그인
-
+ <>
+
+
+
+
+ 로그인
+
+
+
+
+
+
+
+ {
+ setIsSidebarOpen(true);
+ }}
+ />
+
+
+ {isSidebarOpen && (
+ {
+ setIsSidebarOpen(false);
+ }}
+ />
+ )}
+
+ >
);
};
@@ -124,6 +188,61 @@ export const DefaultHeader = () => {
);
};
+// 관리자 헤더
+export const AdminHeader = () => {
+ const { navigateToHome } = useNavigateHome();
+ const [isSidebarOpen, setIsSidebarOpen] = useState(false);
+ const [moims, setMoims] = useState([]);
+ const { moimsData } = useFetchHeaderGroup();
+ const { groupId } = useParams();
+ const { invitationCode } = useFetchInvitationLink(groupId);
+
+ const handleCopyLink = (invitationCode: string) => {
+ copyLink(import.meta.env.VITE_INVITE_URL + `group/${invitationCode}/groupInvite`);
+ };
+
+ const handleInviteBtnClick = () => {
+ handleCopyLink(invitationCode?.invitationCode || '');
+ };
+
+ useEffect(() => {
+ if (moimsData) setMoims(moimsData);
+ }, [moimsData]);
+ return (
+ <>
+
+
+
+
+
+
+
+
+ {
+ setIsSidebarOpen(true);
+ }}
+ />
+
+
+ {isSidebarOpen && (
+ {
+ setIsSidebarOpen(false);
+ }}
+ groupCount={moimsData?.length ?? 0}
+ groupData={moims ?? []}
+ />
+ )}
+
+ >
+ );
+};
+
+const LogInWrapper = styled.div`
+ width: 8.1rem;
+`;
+
const HeaderWrapper = styled.div`
position: fixed;
top: 0;
@@ -138,6 +257,26 @@ const HeaderWrapper = styled.div`
background-color: ${({ theme }) => theme.colors.white};
border-bottom: 1px solid ${({ theme }) => theme.colors.gray30};
+
+ @media ${MOBILE_MEDIA_QUERY} {
+ width: 100%;
+ height: 5.6rem;
+ padding: 0 2rem;
+ }
+`;
+
+const LinkIcon = styled(LinkIc)`
+ cursor: pointer;
+`;
+const HamburgerIcon = styled(HamburgerIc)`
+ cursor: pointer;
+`;
+
+const MobileHeaderButtons = styled.div`
+ display: flex;
+ gap: 1.6rem;
+ align-items: center;
+ ${({ theme }) => theme.fonts.mSubtitle4};
`;
const HeaderLayout = styled.div`
@@ -158,4 +297,13 @@ const HeaderLogoIcon = styled(HeaderLogoIc)`
flex-shrink: 0;
cursor: pointer;
+
+ @media ${MOBILE_MEDIA_QUERY} {
+ width: 7rem;
+ height: 1.68rem;
+ }
+`;
+
+const CreateGroupWrapper = styled.div`
+ width: 13.6rem;
`;
diff --git a/src/components/commons/HeaderButton.tsx b/src/components/commons/HeaderButton.tsx
new file mode 100644
index 00000000..c2e88157
--- /dev/null
+++ b/src/components/commons/HeaderButton.tsx
@@ -0,0 +1,88 @@
+import styled from '@emotion/styled';
+import { css } from '@emotion/react';
+
+const basicCSS = css`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 4rem;
+ padding: 1rem 1.6rem;
+
+ white-space: nowrap;
+
+ cursor: pointer;
+ border-radius: 0.8rem;
+
+ transition:
+ transform 0.5s,
+ background-color 0.5s,
+ color 0.5s;
+`;
+
+// 글모임 만들기 버튼
+export const CreateGroupBtnWrapper = styled.div`
+ ${basicCSS};
+ gap: 0.6rem;
+ width: 100%;
+
+ color: ${({ theme }) => theme.colors.white};
+
+ background-color: ${({ theme }) => theme.colors.black};
+
+ ${({ theme }) => theme.fonts.button3};
+
+ :hover {
+ color: ${({ theme }) => theme.colors.mainViolet};
+
+ background-color: ${({ theme }) => theme.colors.white};
+ box-shadow: 0 4px 8px 0 rgb(0 0 0 / 16%);
+ transform: scale(0.95);
+ }
+
+ :active {
+ transform: scale(1.1);
+ }
+`;
+
+// 로그인/로그아웃 버튼
+export const LogInOutBtn = styled.button`
+ ${basicCSS};
+ width: 100%;
+
+ color: ${({ theme }) => theme.colors.gray70};
+
+ ${({ theme }) => theme.fonts.button3};
+
+ :hover {
+ color: ${({ theme }) => theme.colors.mainViolet};
+
+ background-color: ${({ theme }) => theme.colors.gray10};
+ transform: scale(0.95);
+ }
+
+ :active {
+ transform: scale(1.1);
+ }
+`;
+
+// 내 글 모임 버튼
+export const MyGroupBtn = styled.button`
+ ${basicCSS};
+ width: 9.5rem;
+
+ color: ${({ theme }) => theme.colors.gray70};
+
+ ${({ theme }) => theme.fonts.subtitle6};
+
+ :hover {
+ color: ${({ theme }) => theme.colors.mainViolet};
+
+ background-color: ${({ theme }) => theme.colors.gray10};
+ transform: scale(0.95);
+ border-radius: 0.8rem;
+ }
+
+ :active {
+ transform: scale(1.1);
+ }
+`;
diff --git a/src/components/commons/LogInOutBtn.tsx b/src/components/commons/LogInOutBtn.tsx
deleted file mode 100644
index d6ae5394..00000000
--- a/src/components/commons/LogInOutBtn.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import styled from '@emotion/styled';
-import { ReactNode } from 'react';
-
-type LogInOutPropTypes = {
- children: ReactNode;
- onClick?: () => void;
-};
-const LogInOutBtn = ({ children, onClick }: LogInOutPropTypes) => {
- return (
-
- {children}
-
- );
-};
-
-export default LogInOutBtn;
-
-const LogInOutWrapper = styled.button`
- height: 4rem;
- padding: 1rem 1.6rem;
-
- color: ${({ theme }) => theme.colors.gray70};
- white-space: nowrap;
-
- cursor: pointer;
- border-radius: 8px;
-
- ${({ theme }) => theme.fonts.button3};
-
- :hover {
- color: ${({ theme }) => theme.colors.mainViolet};
-
- background-color: ${({ theme }) => theme.colors.gray10};
- transform: scale(0.95);
-
- transition: 0.5s;
- }
-
- :active {
- transform: scale(1.1);
-
- transition: 0.5s;
- }
-`;
diff --git a/src/components/commons/MyMobileSidebar.tsx b/src/components/commons/MyMobileSidebar.tsx
new file mode 100644
index 00000000..a646bf15
--- /dev/null
+++ b/src/components/commons/MyMobileSidebar.tsx
@@ -0,0 +1,147 @@
+import styled from '@emotion/styled';
+import useClickOutside from '../../hooks/useClickOutside';
+import logout from '../../utils/logout';
+import useNavigateToHome from '../../hooks/useNavigateHome';
+
+import { useRef } from 'react';
+import { LogInOutBtn } from './HeaderButton';
+import CreateGroupBtn from '../../pages/groupFeed/components/CreateGroupBtn';
+import useNavigateLoginWithPath from '../../hooks/useNavigateLoginWithPath';
+import { Moim } from '../../pages/groupFeed/apis/fetchHeaderGroup';
+import { useNavigate } from 'react-router-dom';
+
+export const MobileUnAuthorizedSidebar = ({ onClose }: { onClose: () => void }) => {
+ const sidebarRef = useRef(null);
+ const { navigateToLogin } = useNavigateLoginWithPath();
+
+ useClickOutside(sidebarRef, () => {
+ //헤더 이외부분 클릭시 닫히게
+ if (sidebarRef.current) onClose();
+ });
+
+ return (
+ <>
+
+ 로그인
+
+ >
+ );
+};
+
+interface AuthorizedPropTypes {
+ onClose: () => void;
+ groupCount: number;
+ groupData: Moim[] | [];
+}
+
+export const MobileAuthorizedSidebar = ({
+ onClose,
+ groupCount,
+ groupData,
+}: AuthorizedPropTypes) => {
+ const sidebarRef = useRef(null);
+ const { navigateToHome } = useNavigateToHome();
+ const navigate = useNavigate();
+
+ useClickOutside(sidebarRef, () => {
+ //헤더 이외부분 클릭시 닫히게
+ if (sidebarRef.current) onClose();
+ });
+ const handleLogOut = () => {
+ logout();
+ navigateToHome();
+ };
+
+ const handleRoutingGroupFeed = (groupId: string) => {
+ navigate(`/group/${groupId}`);
+ };
+
+ return (
+ <>
+
+
+ 로그아웃
+
+
+ 내 글 모임
+
+ {groupData?.length > 0 ? (
+ groupData.map(({ moimId, moimName }: Moim) => (
+ handleRoutingGroupFeed(moimId)}>
+ {moimName}
+
+ ))
+ ) : (
+ {`가입한 글 모임이\n 없습니다.`}
+ )}
+
+
+ >
+ );
+};
+
+const GroupList = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 0.8rem;
+`;
+
+const GroupData = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 15.9rem;
+ height: 4.4rem;
+
+ color: ${({ theme }) => theme.colors.gray70};
+
+ cursor: pointer;
+ border-radius: 0.8rem;
+ ${({ theme }) => theme.fonts.mSubtitle2};
+
+ :hover {
+ color: black;
+
+ background-color: ${({ theme }) => theme.colors.gray20};
+ }
+`;
+
+const MyGroup = styled.p`
+ display: flex;
+ justify-content: center;
+ ${({ theme }) => theme.fonts.mButton1};
+`;
+
+const Background = styled.div`
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+`;
+
+const CustomLine = styled.hr`
+ width: 161px;
+ height: 2px;
+ margin: 0.4rem 0;
+
+ background-color: ${({ theme }) => theme.colors.gray20};
+ border: none;
+ border-radius: 1px; /* 선의 끝을 둥글게 설정 */
+`;
+
+const SideBarLayout = styled.div`
+ position: fixed;
+ right: 0;
+ z-index: 3;
+ display: flex;
+ flex-direction: column;
+ gap: 1.2rem;
+ align-items: center;
+ width: 19.1rem;
+ height: 100vh;
+ padding: 1.2rem 1.6rem;
+
+ background-color: ${({ theme }) => theme.colors.white};
+ box-shadow: 0 4px 8px 0 rgb(0 0 0 / 16%);
+`;
diff --git a/src/pages/admin/Admin.tsx b/src/pages/admin/Admin.tsx
index 0f182703..74a33e2a 100644
--- a/src/pages/admin/Admin.tsx
+++ b/src/pages/admin/Admin.tsx
@@ -1,13 +1,11 @@
import styled from '@emotion/styled';
import { useNavigate, useParams } from 'react-router-dom';
-
import { useGroupInfo } from '../groupFeed/hooks/queries';
import Loading from '../loading/Loading';
import RenderAdminContent from './components/RenderAdminContent';
import { useFetchInvitationLink } from './hooks/queries';
-
import { AdminHomeIc } from '../../assets/svgs';
-import { AuthorizationHeader } from '../../components/commons/Header';
+import { AdminHeader } from '../../components/commons/Header';
import Responsive from '../../components/commons/Responsive/Responsive';
import Spacing from '../../components/commons/Spacing';
import { MOBILE_MEDIA_QUERY } from '../../styles/mediaQuery';
@@ -43,7 +41,7 @@ const Admin = () => {
}
return (
- {accessToken && }
+ {accessToken && }
diff --git a/src/pages/createGroup/CreateGroup.tsx b/src/pages/createGroup/CreateGroup.tsx
index a828e7f2..e8f6a046 100644
--- a/src/pages/createGroup/CreateGroup.tsx
+++ b/src/pages/createGroup/CreateGroup.tsx
@@ -156,81 +156,85 @@ const CreateGroup = () => {
};
return (
-
+
{localStorage.getItem('accessToken') ? : }
- {currentPage === 'GroupInfoPage' && (
-
- )}
- {currentPage === 'GroupLeaderInfoPage' && (
-
- )}
- {currentPage === 'GroupLeaderInfoPage' && (
-
-
- 생성하기
-
-
- 뒤로가기
-
-
- )}
-
-
-
-
-
- {/* 페이지 이탈 모달 */}
-
-
-
-
+
+ {currentPage === 'GroupInfoPage' && (
+
+ )}
+ {currentPage === 'GroupLeaderInfoPage' && (
+ <>
+
+
+
+ 생성하기
+
+
+ 뒤로가기
+
+
+ >
+ )}
+
+
+
+
+ {/* 페이지 이탈 모달 */}
+
+
+
+
+
);
};
export default CreateGroup;
+const GroupWrapper = styled.div`
+ width: 100%;
+`;
const BackPageBtn = styled.button`
display: flex;
align-items: center;
diff --git a/src/pages/groupFeed/components/CreateGroupBtn.tsx b/src/pages/groupFeed/components/CreateGroupBtn.tsx
index 8468698a..cdcbd3c4 100644
--- a/src/pages/groupFeed/components/CreateGroupBtn.tsx
+++ b/src/pages/groupFeed/components/CreateGroupBtn.tsx
@@ -1,4 +1,3 @@
-import styled from '@emotion/styled';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
@@ -6,6 +5,7 @@ import { MakeGroupPlusBtn, MakeGroupPlusHoverBtn } from '../../../assets/svgs';
import { FullModal, FullModalBtn } from '../../../components/commons/modal/FullModal';
import useModal from '../../../hooks/useModal';
import { MODAL } from '../constants/modalContent';
+import { CreateGroupBtnWrapper } from '../../../components/commons/HeaderButton';
interface groupCountProps {
groupCount: number;
@@ -52,37 +52,3 @@ const CreateGroupBtn = ({ groupCount }: groupCountProps) => {
};
export default CreateGroupBtn;
-
-const CreateGroupBtnWrapper = styled.button`
- display: flex;
- gap: 0.6rem;
- align-items: center;
- justify-content: center;
- width: auto;
- height: 4rem;
- padding: 1rem 1.6rem;
-
- color: ${({ theme }) => theme.colors.white};
- white-space: nowrap;
-
- background-color: ${({ theme }) => theme.colors.black};
- cursor: pointer;
- border-radius: 8px;
-
- :hover {
- color: ${({ theme }) => theme.colors.mainViolet};
-
- background-color: ${({ theme }) => theme.colors.white};
- box-shadow: 0 4px 8px 0 rgb(0 0 0 / 16%);
- transform: scale(0.95);
-
- transition: 0.5s;
- }
- ${({ theme }) => theme.fonts.button3};
-
- :active {
- transform: scale(1.1);
-
- transition: 0.5s;
- }
-`;
diff --git a/src/pages/groupFeed/components/MyGroupDropDown.tsx b/src/pages/groupFeed/components/MyGroupDropDown.tsx
index ec8a1e03..06bbfd7f 100644
--- a/src/pages/groupFeed/components/MyGroupDropDown.tsx
+++ b/src/pages/groupFeed/components/MyGroupDropDown.tsx
@@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import { useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
-
+import { MyGroupBtn } from '../../../components/commons/HeaderButton';
import { Moim } from '../apis/fetchHeaderGroup';
import useClickOutside from '../../../hooks/useClickOutside';
@@ -29,7 +29,7 @@ const MyGroupDropDown = ({ groupData }: CreateGroupBtnProps) => {
return (
- 내 글 모임
+ 내 글 모임
{groupData?.length > 0 ? (
groupData.map(({ moimId, moimName }: Moim) => (
@@ -59,39 +59,6 @@ const MyGroupDropDownWrapper = styled.section`
align-items: center;
`;
-const MyGroupBtnLayout = styled.button`
- display: flex;
- align-items: center;
- justify-content: center;
- width: 9.5rem;
- height: 4rem;
- padding: 1rem 1.6rem;
-
- color: ${({ theme }) => theme.colors.gray70};
- white-space: nowrap;
- text-align: center;
-
- cursor: pointer;
-
- ${({ theme }) => theme.fonts.subtitle6}
-
- :hover {
- color: ${({ theme }) => theme.colors.mainViolet};
-
- background-color: ${({ theme }) => theme.colors.gray10};
- transform: scale(0.95);
- border-radius: 0.8rem;
-
- transition: 0.5s;
- }
-
- :active {
- transform: scale(1.1);
-
- transition: 0.5s;
- }
-`;
-
const MyGroupListLayout = styled.div<{ $isOpen: boolean }>`
position: absolute;
top: 6rem;
diff --git a/src/pages/groupFeed/hooks/queries.ts b/src/pages/groupFeed/hooks/queries.ts
index 9c8fdb5d..7584cc94 100644
--- a/src/pages/groupFeed/hooks/queries.ts
+++ b/src/pages/groupFeed/hooks/queries.ts
@@ -119,7 +119,9 @@ export const useFetchHeaderGroup = () => {
queryFn: () => fetchHeaderGroup(),
retry: 3,
});
- return { data };
+
+ const moimsData = data?.data?.moims;
+ return { moimsData };
};
export const useFetchWriterInfo = (
diff --git a/src/pages/groupInvite/GroupInvite.tsx b/src/pages/groupInvite/GroupInvite.tsx
index 953b7fc7..1ce8d067 100644
--- a/src/pages/groupInvite/GroupInvite.tsx
+++ b/src/pages/groupInvite/GroupInvite.tsx
@@ -25,7 +25,7 @@ const GroupInvite = () => {
useGetGroupInfo(groupId);
// 글모임 5개 가입 제한
- const { data } = useFetchHeaderGroup();
+ const { moimsData } = useFetchHeaderGroup();
useEffect(() => {
if (isError && isAxiosError(error)) {
@@ -53,15 +53,15 @@ const GroupInvite = () => {
}, [error, isError, groupId]);
useEffect(() => {
- if (data?.data.moims && data?.data.moims.length >= 5) {
+ if (moimsData && moimsData?.length >= 5) {
handleShowModal();
}
- }, [data?.data.moims.length]);
+ }, [moimsData?.length]);
return (
- <>
+
+
-
@@ -79,7 +79,6 @@ const GroupInvite = () => {
-
{
}}
/>
- >
+
);
};
export default GroupInvite;
+const InviteWrapper = styled.div`
+ display: flex;
+ width: 100%;
+`;
+
const GroupInviteWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 82.6rem;
+ margin: 0 auto;
`;
diff --git a/src/pages/groupJoinCongrats/GroupJoinCongrats.tsx b/src/pages/groupJoinCongrats/GroupJoinCongrats.tsx
index 014579db..a6160db4 100644
--- a/src/pages/groupJoinCongrats/GroupJoinCongrats.tsx
+++ b/src/pages/groupJoinCongrats/GroupJoinCongrats.tsx
@@ -17,34 +17,43 @@ const GroupJoinCongrats = () => {
navigate(`/group/${groupId}`);
};
return (
-
+
-
-
-
- {location?.state?.moimTitle} 가입을 축하해요!
- 글 모임에서 당신의 소중한 이야기를 들려주세요.
-
-
-
-
- 모임 페이지 보러가기
-
-
+
+
+
+
+ {location?.state?.moimTitle} 가입을 축하해요!
+ 글 모임에서 당신의 소중한 이야기를 들려주세요.
+
+
+
+
+
+ 모임 페이지 보러가기
+
+
+
+
);
};
export default GroupJoinCongrats;
+const JoinWrapper = styled.div`
+ display: flex;
+ width: 100%;
+`;
+
const GroupJoinCongratsWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
- width: 82.6rem;
+ width: 100%;
`;
const GroupJoinCongratsContainer = styled.main`