From ac9208fdfd22b8d73330f684a869058094660ed9 Mon Sep 17 00:00:00 2001 From: giho Date: Fri, 19 Jul 2024 18:47:35 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=EC=9C=A0=EC=A0=80=20Profile=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Main/MyProfile/MyProfile.hook.tsx | 74 ------- src/pages/Main/MyProfile/MyProfile.tsx | 120 ----------- src/pages/Main/Profile/Profile.hook.tsx | 10 + src/pages/Main/Profile/Profile.tsx | 203 ++++++++++++++++++ .../SiderBar/NavigatorContainer.hook.tsx | 4 +- src/router/index.tsx | 4 +- 6 files changed, 217 insertions(+), 198 deletions(-) delete mode 100644 src/pages/Main/MyProfile/MyProfile.hook.tsx delete mode 100644 src/pages/Main/MyProfile/MyProfile.tsx create mode 100644 src/pages/Main/Profile/Profile.hook.tsx create mode 100644 src/pages/Main/Profile/Profile.tsx diff --git a/src/pages/Main/MyProfile/MyProfile.hook.tsx b/src/pages/Main/MyProfile/MyProfile.hook.tsx deleted file mode 100644 index bb8a94d..0000000 --- a/src/pages/Main/MyProfile/MyProfile.hook.tsx +++ /dev/null @@ -1,74 +0,0 @@ -// hooks -import useUpdateUser from '@/apis/hooks/useUpdateUser'; -import { useUserStore } from '@/store/useUserStore'; -import { useRef, useState } from 'react'; - -// types -import { User } from '@/types/user'; - -export default function useMyProfile() { - const UploadUpdateUserMutation = useUpdateUser(); - const { user } = useUserStore(); - const [edittedUser, setEdittedUser] = useState(user); - const [profileImageFile, setProfileImageFile] = useState(user?.profileImage || null); - const [previewProfileImageUrl, setpreviewProfileImageUrl] = useState(null); - const fileInputRef = useRef(null); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - - /** - * 일반적으로 바이너리 데이터를 전송할 때는 FormData를 사용한다. - * FormData는 multipart/form-data 형식으로 데이터를 전송한다. - * - * 이외의 경우는 JSON 형식으로 데이터를 전송한다. - */ - const formData = new FormData(); - if (edittedUser) { - formData.append('id', edittedUser.id || ''); - formData.append('email', edittedUser.email || ''); - formData.append('nickName', edittedUser.nickName || ''); - } - if (profileImageFile instanceof File) { - formData.append('profileImage', profileImageFile); - } - - UploadUpdateUserMutation.mutate({ userId: user?.id, user: formData }); - }; - - const handleProfileImageClick = (e: React.MouseEvent) => { - e.preventDefault(); - if (fileInputRef.current) { - fileInputRef.current.click(); - } - }; - - const handleFileChange = (e: React.ChangeEvent) => { - // 이전 파일 제거 - setpreviewProfileImageUrl(null); - setProfileImageFile(null); - - if (!e.target.files) return; - const file = e.target.files?.[0]; - setProfileImageFile(file); - - // 파일 미리보기 - const fileUrl = URL.createObjectURL(file); - setpreviewProfileImageUrl(fileUrl); - }; - - const handleInputChanege = (e: React.ChangeEvent) => { - const { name, value } = e.target; - setEdittedUser((prev) => (prev ? { ...prev, [name]: value } : null)); - }; - - return { - previewProfileImageUrl, - edittedUser, - fileInputRef, - handleSubmit, - handleFileChange, - handleInputChanege, - handleProfileImageClick, - }; -} diff --git a/src/pages/Main/MyProfile/MyProfile.tsx b/src/pages/Main/MyProfile/MyProfile.tsx deleted file mode 100644 index 58f07e4..0000000 --- a/src/pages/Main/MyProfile/MyProfile.tsx +++ /dev/null @@ -1,120 +0,0 @@ -// libraries -import styled from 'styled-components'; - -// hooks -import useMyProfile from './MyProfile.hook'; - -// components -import MainTitle from '@/components/Atoms/Text/MainTitle'; -import { ButtonWrapper, Form, FormField, Input, Label } from '@/components/Atoms/Modal/StyledComponents'; -import Button from '@/components/Atoms/Modal/Button'; - -export default function MyProfile() { - // logics - const { - previewProfileImageUrl, - edittedUser, - fileInputRef, - handleSubmit, - handleFileChange, - handleInputChanege, - handleProfileImageClick, - } = useMyProfile(); - - // view - return ( - - MyPage - - -
- - profileImage - - 프로필 이미지 - - - - - - - - - - - - - - - - - -
-
-
- ); -} - -const Wrapper = styled.div` - width: 100%; - height: 100%; - - display: flex; - flex-direction: column; - padding: 0 32px; - - @media (max-width: 768px) { - padding: 0 16px; - } -`; - -const FormWrapper = styled.div` - width: 400px; - - padding-top: 32px; - - @media (max-width: 768px) { - width: 100%; - - padding-top: 16px; - } -`; - -const ProfileImageWrapper = styled.button` - border-radius: 16px; - width: 240px; - height: 240px; - - overflow: hidden; - padding: 0; - - cursor: pointer; - - img { - width: 100%; - height: 100%; - object-fit: cover; - cursor: pointer; - } -`; - -const ProfileImageLabel = styled(Label)``; - -const FileInput = styled.input` - display: none; -`; - -const EmailInput = styled(Input)` - color: var(--grey-grey600); -`; diff --git a/src/pages/Main/Profile/Profile.hook.tsx b/src/pages/Main/Profile/Profile.hook.tsx new file mode 100644 index 0000000..d6fb902 --- /dev/null +++ b/src/pages/Main/Profile/Profile.hook.tsx @@ -0,0 +1,10 @@ +// hooks +import { useUserStore } from '@/store/useUserStore'; + +export default function useProfile() { + const { user } = useUserStore(); + + return { + user, + }; +} diff --git a/src/pages/Main/Profile/Profile.tsx b/src/pages/Main/Profile/Profile.tsx new file mode 100644 index 0000000..70d9a35 --- /dev/null +++ b/src/pages/Main/Profile/Profile.tsx @@ -0,0 +1,203 @@ +// libraries +import styled from 'styled-components'; + +// hooks +import useProfile from './Profile.hook'; + +// components +import MainTitle from '@/components/Atoms/Text/MainTitle'; + +export default function Profile() { + // logics + const { user } = useProfile(); + + // view + + if (!user) return 유저 정보를 불러오지 못했습니다. 로그인을 다시 해주세요.; + return ( + + Profile + + + UserInfo + + + + profile + + + 안녕하세요 +
+ {user.nickName} 님! +
+
+ + + Email + {user.email} + + + NickName + {user.nickName} + +
+ + Notice + 유저 정보를 수정하고 싶다면 Google에서 수정해주세요. + +
+
+ ); +} + +const Wrapper = styled.div` + width: 100%; + height: 100%; + + display: flex; + flex-direction: column; + + padding: 0 32px; + + @media (max-width: 768px) { + padding: 0 16px; + } +`; + +const NoUser = styled.div` + width: 100%; + height: 100%; + + display: flex; + justify-content: center; + align-items: center; + + font-size: 24px; + color: var(--grey-grey600); +`; + +const UserInfoBox = styled.div` + border-radius: 16px; + + display: flex; + gap: 32px; + + margin-top: 32px; + + @media (max-width: 992px) { + flex-direction: column; + gap: 16px; + } + + @media (max-width: 768px) { + width: 100%; + + margin-top: 16px; + } +`; + +const NoticeBox = styled.div` + border-radius: 16px; + border: 1px solid var(--grey-grey300); + width: 320px; + height: 160px; + + display: flex; + flex-direction: column; + gap: 16px; + + padding: 32px; + background-color: var(--grey-grey150); + + @media (max-width: 992px) { + width: 100%; + + padding: 16px; + } +`; + +const NoticeText = styled.span` + font-size: 16px; + + color: var(--grey-grey600); +`; + +const UserInfoContent = styled.div` + flex-grow: 1; + max-width: 640px; + border: 1px solid var(--grey-grey300); + border-radius: 16px; + + display: flex; + flex-direction: column; + gap: 16px; + + padding: 32px; + + background-color: var(--grey-grey150); + + @media (max-width: 992px) { + width: 100%; + max-width: none; + padding: 16px; + } +`; + +const ContentTitle = styled.div` + font-size: 20px; + color: var(--grey-grey900); +`; + +const Middle = styled.div` + display: flex; + align-items: center; + gap: 16px; +`; + +const ProfileImageWrapper = styled.div` + border-radius: 50%; + width: 48x; + height: 48px; + + overflow: hidden; + padding: 0; + cursor: pointer; + + img { + width: 100%; + height: 100%; + object-fit: cover; + cursor: pointer; + } +`; + +const WelcomeMessage = styled.div` + font-size: 16px; + color: var(--grey-grey600); +`; + +const WelcomeUserName = styled.span` + font-size: 20px; + font-weight: bold; + color: var(--grey-grey900); +`; + +const InfoContentItem = styled.div` + border-radius: 16px; + + display: flex; + justify-content: space-between; + + background-color: var(--grey-grey200); + padding: 16px; +`; + +const InfoContentItemName = styled.div` + font-size: 18px; + color: var(--grey-grey600); +`; + +const InfoContentItemValue = styled.div` + font-size: 16px; + color: var(--grey-grey900); +`; diff --git a/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx b/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx index 67395d8..f048cee 100644 --- a/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx +++ b/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx @@ -25,8 +25,8 @@ export default function useNavigatorContainer() { icon: [homeSvg, homeFocusedSvg], // [default, focused] }, { - name: 'MyProfile', - path: '/main/myProfile', + name: 'Profile', + path: '/main/Profile', icon: [personSvg, personFocusedSvg], }, { diff --git a/src/router/index.tsx b/src/router/index.tsx index ecb6a50..2f2e225 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -5,9 +5,9 @@ import ChannelContainer from '@/pages/Main/_compoenets/Content/ChannelContainer' import Channel from '@/pages/Main/Channel/Channel'; import MainPage from '@/pages/Main/MainPage'; import MyOwnChannels from '@/pages/Main/MyOwnChannels/MyOwnChannels'; -import MyProfile from '@/pages/Main/MyProfile/MyProfile'; import NotFoundPage from '@/pages/NotFound/NotFoundPage'; import SignInPage from '@/pages/Signin/SignInPage'; +import Profile from '@/pages/Main/Profile/Profile'; export default function Router() { // view @@ -18,7 +18,7 @@ export default function Router() { }> } /> } /> - } /> + } /> } /> } /> From d2566044704838b8a3cf790ed17e3aa312942dc9 Mon Sep 17 00:00:00 2001 From: giho Date: Fri, 19 Jul 2024 21:27:33 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=B1=84=EB=84=90=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=AA=A8=EB=8B=AC=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=94=84=EB=A1=9C=ED=95=84=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/hooks/useDeleteChannel.ts | 2 +- src/apis/hooks/useGetChannelById.ts | 11 ++ src/apis/hooks/useGetMyChannel.ts | 2 +- src/apis/hooks/useGetMyOwnChannels.ts | 2 +- src/apis/hooks/useRenewTokens.ts | 6 +- src/apis/hooks/useUpdateChannel.ts | 5 +- src/apis/services/auth.ts | 7 +- src/apis/services/channel.ts | 12 +- .../Atoms/Modal/StyledComponents.tsx | 42 +++++ src/components/Molecules/.gitkeep | 0 src/components/Molecules/Description.tsx | 46 ++++++ .../Modal/CreateChannelModal.hook.tsx | 2 +- .../Organisms/Modal/CreateChannelModal.tsx | 55 +----- .../Organisms/Modal/EditChannelModal.hook.tsx | 156 ++++++++++++++++++ .../Organisms/Modal/EditChannelModal.tsx | 142 ++++++++++++++++ .../Main/EditChannels/EditChannels.hook.tsx | 11 ++ src/pages/Main/EditChannels/EditChannels.tsx | 92 +++++++++++ .../_components/ChannelItem.hook.tsx | 12 +- .../EditChannels/_components/ChannelItem.tsx | 103 ++++++++++++ .../_components/ChannelItem.type.tsx | 2 - .../Main/MyOwnChannels/MyOwnChannels.hook.tsx | 19 --- .../Main/MyOwnChannels/MyOwnChannels.tsx | 100 ----------- .../_components/ChannelEditor.hook.tsx | 67 -------- .../_components/ChannelEditor.tsx | 102 ------------ .../_components/ChannelEditor.type.tsx | 12 -- .../MyOwnChannels/_components/ChannelItem.tsx | 100 ----------- src/pages/Main/Profile/Profile.tsx | 32 +--- .../SiderBar/NavigatorContainer.hook.tsx | 4 +- .../Main/_compoenets/SiderBar/SideBar.tsx | 3 +- src/router/index.tsx | 4 +- src/styles/GlobalStyles.tsx | 2 +- 31 files changed, 644 insertions(+), 511 deletions(-) create mode 100644 src/apis/hooks/useGetChannelById.ts delete mode 100644 src/components/Molecules/.gitkeep create mode 100644 src/components/Molecules/Description.tsx create mode 100644 src/components/Organisms/Modal/EditChannelModal.hook.tsx create mode 100644 src/components/Organisms/Modal/EditChannelModal.tsx create mode 100644 src/pages/Main/EditChannels/EditChannels.hook.tsx create mode 100644 src/pages/Main/EditChannels/EditChannels.tsx rename src/pages/Main/{MyOwnChannels => EditChannels}/_components/ChannelItem.hook.tsx (57%) create mode 100644 src/pages/Main/EditChannels/_components/ChannelItem.tsx rename src/pages/Main/{MyOwnChannels => EditChannels}/_components/ChannelItem.type.tsx (55%) delete mode 100644 src/pages/Main/MyOwnChannels/MyOwnChannels.hook.tsx delete mode 100644 src/pages/Main/MyOwnChannels/MyOwnChannels.tsx delete mode 100644 src/pages/Main/MyOwnChannels/_components/ChannelEditor.hook.tsx delete mode 100644 src/pages/Main/MyOwnChannels/_components/ChannelEditor.tsx delete mode 100644 src/pages/Main/MyOwnChannels/_components/ChannelEditor.type.tsx delete mode 100644 src/pages/Main/MyOwnChannels/_components/ChannelItem.tsx diff --git a/src/apis/hooks/useDeleteChannel.ts b/src/apis/hooks/useDeleteChannel.ts index afbc00a..9d8e615 100644 --- a/src/apis/hooks/useDeleteChannel.ts +++ b/src/apis/hooks/useDeleteChannel.ts @@ -11,7 +11,7 @@ export default function useDeleteChannel() { mutationFn: ({ channelId }) => deleteChannel(channelId), onSuccess: () => { queryClient.invalidateQueries({ - queryKey: ['myOwnChannels', 'myChannels'], + queryKey: ['channels'], }); }, }); diff --git a/src/apis/hooks/useGetChannelById.ts b/src/apis/hooks/useGetChannelById.ts new file mode 100644 index 0000000..aae10cb --- /dev/null +++ b/src/apis/hooks/useGetChannelById.ts @@ -0,0 +1,11 @@ +import { useQuery } from '@tanstack/react-query'; +import { Channel } from '../../types/channel'; +import { getChannelById } from '../services/channel'; + +export default function useGetChannelById(channelId: string | undefined) { + const queryKey = ['channels', channelId]; + return useQuery({ + queryKey: queryKey, + queryFn: () => getChannelById(channelId), + }); +} diff --git a/src/apis/hooks/useGetMyChannel.ts b/src/apis/hooks/useGetMyChannel.ts index f1a441d..e8ec3d2 100644 --- a/src/apis/hooks/useGetMyChannel.ts +++ b/src/apis/hooks/useGetMyChannel.ts @@ -3,7 +3,7 @@ import { getMyChannelList } from '../services/user'; import { Channel } from '../../types/channel'; export default function useGetMyChannel(userId: string | undefined) { - const queryKey = ['myChannels']; + const queryKey = ['channels']; return useQuery({ queryKey: queryKey, queryFn: () => getMyChannelList(userId), diff --git a/src/apis/hooks/useGetMyOwnChannels.ts b/src/apis/hooks/useGetMyOwnChannels.ts index 7548919..ac33ada 100644 --- a/src/apis/hooks/useGetMyOwnChannels.ts +++ b/src/apis/hooks/useGetMyOwnChannels.ts @@ -3,7 +3,7 @@ import { getMyOwnChannels } from '../services/user'; import { Channel } from '../../types/channel'; export default function useGetMyOwnChannels(userId: string) { - const queryKey = ['myOwnChannels', 'myChannels']; + const queryKey = ['channels']; return useQuery({ queryKey: queryKey, queryFn: () => getMyOwnChannels(userId), diff --git a/src/apis/hooks/useRenewTokens.ts b/src/apis/hooks/useRenewTokens.ts index e21b7f0..a4b2bd2 100644 --- a/src/apis/hooks/useRenewTokens.ts +++ b/src/apis/hooks/useRenewTokens.ts @@ -1,13 +1,13 @@ import { useQuery } from '@tanstack/react-query'; import { renewTokens } from '../services/auth'; -interface AccessToken { - accessToken: string; +interface ApplicationAccessToken { + applicationAccessToken: string; } export default function useRenewTokens() { const queryKey = ['tokens']; - return useQuery({ + return useQuery({ queryKey: queryKey, queryFn: renewTokens, }); diff --git a/src/apis/hooks/useUpdateChannel.ts b/src/apis/hooks/useUpdateChannel.ts index 332dcd5..5e870ef 100644 --- a/src/apis/hooks/useUpdateChannel.ts +++ b/src/apis/hooks/useUpdateChannel.ts @@ -1,10 +1,9 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { Channel } from '../../types/channel'; import { updateChannel } from '../services/channel'; interface updateChannelParams { channelId: string; - channel: Channel; + channel: FormData; } export default function useUpdateChannel() { @@ -13,7 +12,7 @@ export default function useUpdateChannel() { mutationFn: ({ channelId, channel }) => updateChannel(channelId, channel), onSuccess: () => { queryClient.invalidateQueries({ - queryKey: ['myOwnChannels, myChannels'], + queryKey: ['channels'], }); }, }); diff --git a/src/apis/services/auth.ts b/src/apis/services/auth.ts index 97001c1..f3db786 100644 --- a/src/apis/services/auth.ts +++ b/src/apis/services/auth.ts @@ -1,19 +1,16 @@ import { axiosInstance } from '../instances'; import axios from 'axios'; -interface RenewTokenResponse { - applicationAccessToken: string; -} - // accessToken 만료시 token들을 재발급 export const renewTokens = async () => { try { - const response = await axiosInstance.post('/auth/renewTokens'); + const response = await axiosInstance.post('/auth/renewTokens'); return response.data.applicationAccessToken; } catch (error: unknown) { if (axios.isAxiosError(error)) { console.error(error.response?.status); window.location.href = '/signIn'; + throw new Error('토큰이 만료되었습니다. 다시 로그인해주세요.'); } return null; } diff --git a/src/apis/services/channel.ts b/src/apis/services/channel.ts index 6adc275..d25daa6 100644 --- a/src/apis/services/channel.ts +++ b/src/apis/services/channel.ts @@ -1,5 +1,4 @@ import { axiosInstanceWithToken } from '../instances'; -import { Channel } from '../../types/channel'; import { Music } from '@/types/music'; export const getAllchannelLists = async () => { @@ -11,7 +10,7 @@ export const getAllchannelLists = async () => { } }; -export const getChannelById = async (channelId: string) => { +export const getChannelById = async (channelId: string | undefined) => { try { const response = await axiosInstanceWithToken.get(`/channels/${channelId}`); return response.data; @@ -33,9 +32,14 @@ export const createChannel = async (channel: FormData) => { } }; -export const updateChannel = async (channelId: string, channel: Channel) => { +export const updateChannel = async (channelId: string, channel: FormData) => { + console.log(channelId, channel); try { - const response = await axiosInstanceWithToken.patch(`/channels/${channelId}`, { channel }); + const response = await axiosInstanceWithToken.patch(`/channels/${channelId}`, channel, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); return response.data; } catch (error) { console.error(error); diff --git a/src/components/Atoms/Modal/StyledComponents.tsx b/src/components/Atoms/Modal/StyledComponents.tsx index 9cbf8bb..6995db7 100644 --- a/src/components/Atoms/Modal/StyledComponents.tsx +++ b/src/components/Atoms/Modal/StyledComponents.tsx @@ -97,3 +97,45 @@ export const Tag = styled.div` background-color: var(--mint7); } `; + +export const ChannelImageWrapper = styled.button` + border-radius: 16px; + width: 120px; + height: 120px; + + overflow: hidden; + padding: 0; + + cursor: pointer; + + img { + width: 100%; + height: 100%; + object-fit: cover; + cursor: pointer; + } +`; + +export const EmptyImage = styled.div` + width: 100%; + height: 100%; + + display: flex; + justify-content: center; + align-items: center; + + color: var(--grey-grey600); + background-color: var(--grey-grey150); + + cursor: pointer; + + &:hover { + background-color: var(--grey-grey200); + } +`; + +export const ChannelImageLabel = styled(Label)``; + +export const FileInput = styled.input` + display: none; +`; diff --git a/src/components/Molecules/.gitkeep b/src/components/Molecules/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/Molecules/Description.tsx b/src/components/Molecules/Description.tsx new file mode 100644 index 0000000..13d3940 --- /dev/null +++ b/src/components/Molecules/Description.tsx @@ -0,0 +1,46 @@ +import styled from 'styled-components'; + +interface DescriptionProps { + title: string; + text: string; +} + +export default function Description({ title, text }: DescriptionProps) { + return ( + + {title} + {text} + + ); +} + +const Wrapper = styled.div` + border-radius: 16px; + border: 1px solid var(--grey-grey300); + width: 320px; + height: 160px; + + display: flex; + flex-direction: column; + gap: 16px; + + padding: 32px; + background-color: var(--grey-grey150); + + @media (max-width: 992px) { + width: 100%; + + padding: 16px; + } +`; + +const Title = styled.div` + font-size: 20px; + color: var(--grey-grey900); +`; + +const Text = styled.span` + font-size: 16px; + + color: var(--grey-grey600); +`; diff --git a/src/components/Organisms/Modal/CreateChannelModal.hook.tsx b/src/components/Organisms/Modal/CreateChannelModal.hook.tsx index 23c92e0..81a5d1b 100644 --- a/src/components/Organisms/Modal/CreateChannelModal.hook.tsx +++ b/src/components/Organisms/Modal/CreateChannelModal.hook.tsx @@ -19,10 +19,10 @@ export default function useCreateChannelModal() { description: '', image: '', }); - const [tagValue, setTagValue] = useState(''); const [previewChannelImageUrl, setPreviewChannelImageUrl] = useState(null); const fileInputRef = useRef(null); const [profileImageFile, setProfileImageFile] = useState(null); + const [tagValue, setTagValue] = useState(''); const uploadCreateChannel = useCreateChannel(); const handleChannelImageClick = (e: React.MouseEvent) => { diff --git a/src/components/Organisms/Modal/CreateChannelModal.tsx b/src/components/Organisms/Modal/CreateChannelModal.tsx index e05fd24..ec74bd7 100644 --- a/src/components/Organisms/Modal/CreateChannelModal.tsx +++ b/src/components/Organisms/Modal/CreateChannelModal.tsx @@ -1,6 +1,3 @@ -// libraries -import styled from 'styled-components'; - // hooks import useCreateChannelModal from './CreateChannelModal.hook'; @@ -18,14 +15,18 @@ import { ButtonWrapper, TagContainer, Tag, + ChannelImageLabel, + ChannelImageWrapper, + EmptyImage, + FileInput, } from '../../Atoms/Modal/StyledComponents'; export default function CreateChannelModal() { // logics - const hookData = useCreateChannelModal(); + const logics = useCreateChannelModal(); // useCreateChannelModal hook에서 null을 반환할 수 있으므로 null 체크 - if (!hookData) return null; + if (!logics) return null; const { channelData, @@ -40,7 +41,7 @@ export default function CreateChannelModal() { handleDeleteTag, handleSubmit, closeModal, - } = hookData; + } = logics; // view return ( @@ -131,45 +132,3 @@ export default function CreateChannelModal() { ); } - -const ChannelImageWrapper = styled.button` - border-radius: 16px; - width: 120px; - height: 120px; - - overflow: hidden; - padding: 0; - - cursor: pointer; - - img { - width: 100%; - height: 100%; - object-fit: cover; - cursor: pointer; - } -`; - -const EmptyImage = styled.div` - width: 100%; - height: 100%; - - display: flex; - justify-content: center; - align-items: center; - - color: var(--grey-grey600); - background-color: var(--grey-grey150); - - cursor: pointer; - - &:hover { - background-color: var(--grey-grey200); - } -`; - -const ChannelImageLabel = styled(Label)``; - -const FileInput = styled.input` - display: none; -`; diff --git a/src/components/Organisms/Modal/EditChannelModal.hook.tsx b/src/components/Organisms/Modal/EditChannelModal.hook.tsx new file mode 100644 index 0000000..5078a9d --- /dev/null +++ b/src/components/Organisms/Modal/EditChannelModal.hook.tsx @@ -0,0 +1,156 @@ +// hooks +import useGetChannelById from '@/apis/hooks/useGetChannelById'; +import useUpdateChannel from '@/apis/hooks/useUpdateChannel'; +import useModalStore from '@/store/useModalStore'; +import { useUserStore } from '@/store/useUserStore'; +import { useEffect, useRef, useState } from 'react'; + +// type +import { ModalType } from '@/types/enum'; + +export default function useEditChannelModal() { + const { type, closeModal, props } = useModalStore(); + + if (type !== ModalType.EDIT_CHANNEL) return null; + + const modalProps = props as { channelId: string; channelName: string }; + const { user } = useUserStore(); + const { data, isLoading, isError } = useGetChannelById(modalProps.channelId); + const [channelData, setChannelData] = useState({ + name: '', + tags: [] as string[], + description: '', + image: '', + }); + const upLoadUpdateChannelMutation = useUpdateChannel(); + const [previewChannelImageUrl, setPreviewChannelImageUrl] = useState(null); + const fileInputRef = useRef(null); + const [profileImageFile, setProfileImageFile] = useState(null); + const [tagValue, setTagValue] = useState(''); + + const handleChannelImageClick = (e: React.MouseEvent) => { + e.preventDefault(); + if (fileInputRef.current) { + fileInputRef.current.click(); + } + }; + + const handleFileChange = (e: React.ChangeEvent) => { + // 이전 파일 제거 + setPreviewChannelImageUrl(null); + setProfileImageFile(null); + + if (!e.target.files) return; + const file = e.target.files?.[0]; + setProfileImageFile(file); + + // 파일 미리보기 + const fileUrl = URL.createObjectURL(file); + setPreviewChannelImageUrl(fileUrl); + }; + + const handleAddTagKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + if (tagValue.trim() === '') { + return console.log('태그를 입력하세요.'); + } + if (tagValue.length > 10) { + return console.log('태그는 10자 이내로 입력하세요.'); + } + if (channelData.tags.length > 5) { + return console.log('태그는 5개까지만 입력할 수 있습니다.'); + } + if (channelData.tags.includes(tagValue)) { + return console.log('이미 입력된 태그입니다.'); + } + + setChannelData({ + ...channelData, + tags: [...channelData.tags, tagValue], + }); + setTagValue(''); + } + }; + + const handleDeleteTag = (tag: string) => { + setChannelData({ + ...channelData, + tags: channelData.tags.filter((t) => t !== tag), + }); + }; + + const handleChangeChannelData = (e: React.ChangeEvent) => { + setChannelData({ + ...channelData, + [e.target.name]: e.target.value, + }); + }; + + const handleChangeTagValue = (e: React.ChangeEvent) => { + setTagValue(e.target.value); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + updateChannel(); + closeModal(); + setChannelData({ + name: '', + tags: [], + description: '', + image: '', + }); + }; + + const updateChannel = async () => { + const updatedChannel = new FormData(); + if (channelData) { + updatedChannel.append('name', channelData.name); + // FormData의 경우 배열을 받을 수 없기 때문에 JSON.stringify를 사용하여 문자열로 변환하여 전송 + // 이후 서버에서 JSON.parse를 통해 배열로 변환하고 사용 + updatedChannel.append('tags', JSON.stringify(channelData.tags)); + updatedChannel.append('description', channelData.description); + updatedChannel.append('ownerId', user?.id || ''); + } + // 이미지 파일을 업로드한 경우 + if (profileImageFile) { + updatedChannel.append('image', profileImageFile); + } else { + // 업로드 하지 않은 경우 기존 이미지 URL 전송 + updatedChannel.append('image', channelData.image); + } + console.log('tags', updatedChannel.get('tags')); + upLoadUpdateChannelMutation.mutate({ channelId: modalProps.channelId, channel: updatedChannel }); + }; + + useEffect(() => { + if (data) { + setChannelData({ + name: data.name, + tags: data.tags, + description: data.description, + image: data.image, + }); + setPreviewChannelImageUrl(data.image); + } + }, [data]); + + return { + channelData, + tagValue, + previewChannelImageUrl, + fileInputRef, + modalProps, + isLoading, + isError, + handleChannelImageClick, + handleFileChange, + handleChangeTagValue, + handleDeleteTag, + handleSubmit, + handleAddTagKeyDown, + handleChangeChannelData, + closeModal, + }; +} diff --git a/src/components/Organisms/Modal/EditChannelModal.tsx b/src/components/Organisms/Modal/EditChannelModal.tsx new file mode 100644 index 0000000..e995ab2 --- /dev/null +++ b/src/components/Organisms/Modal/EditChannelModal.tsx @@ -0,0 +1,142 @@ +// libraries + +// hooks +import useEditChannelModal from './EditChannelModal.hook'; + +// components +import { + ButtonWrapper, + ChannelImageLabel, + ChannelImageWrapper, + Description, + EmptyImage, + FileInput, + Form, + FormField, + Input, + Label, + Tag, + TagContainer, + Title, + Wrapper, +} from '@/components/Atoms/Modal/StyledComponents'; +import Button from '@/components/Atoms/Modal/Button'; +import Dimmed from '@/components/Atoms/Modal/Dimmed'; + +export default function EditChannelModal() { + // logics + const logics = useEditChannelModal(); + + if (!logics) return null; + + const { + channelData, + tagValue, + previewChannelImageUrl, + fileInputRef, + modalProps, + isLoading, + isError, + handleChannelImageClick, + handleFileChange, + handleChangeTagValue, + handleDeleteTag, + handleSubmit, + handleAddTagKeyDown, + handleChangeChannelData, + closeModal, + } = logics; + + // view + if (isLoading) return
Loading...
; + if (isError) return
Error...
; + + return ( + + +
+ 채널 수정 + {`'${modalProps.channelName}' 채널 정보를 수정해보세요!`} + + + channelImage + + {previewChannelImageUrl ? ( + 프로필 이미지 + ) : ( + + 채널 이미지 +
+ 업로드 +
+ )} +
+ +
+ + + + + + + + + + {channelData?.tags.map((tag) => ( + { + handleDeleteTag(tag); + }} + > + {tag} + + ))} + + + + + + + + + + + + + +
+
+
+ ); +} diff --git a/src/pages/Main/EditChannels/EditChannels.hook.tsx b/src/pages/Main/EditChannels/EditChannels.hook.tsx new file mode 100644 index 0000000..f33d226 --- /dev/null +++ b/src/pages/Main/EditChannels/EditChannels.hook.tsx @@ -0,0 +1,11 @@ +// hooks +import useGetMyOwnChannels from '@/apis/hooks/useGetMyOwnChannels'; +import { useUserStore } from '@/store/useUserStore'; + +export default function useEditChannels() { + const { user } = useUserStore(); + + const { data: channels, isLoading, isError } = useGetMyOwnChannels(user?.id as string); + + return { channels, isLoading, isError }; +} diff --git a/src/pages/Main/EditChannels/EditChannels.tsx b/src/pages/Main/EditChannels/EditChannels.tsx new file mode 100644 index 0000000..6d14097 --- /dev/null +++ b/src/pages/Main/EditChannels/EditChannels.tsx @@ -0,0 +1,92 @@ +// libraries +import styled from 'styled-components'; + +// components +import ChannelItem from './_components/ChannelItem'; +import MainTitle from '../../../components/Atoms/Text/MainTitle'; +import Description from '@/components/Molecules/Description'; + +// hooks +import useEditChannels from './EditChannels.hook'; + +export default function EditChannels() { + // logics + const { channels, isLoading, isError } = useEditChannels(); + + // view + if (isLoading) { + return
loading...
; + } + + if (isError) { + return
error...
; + } + + return ( + + EditChannels + + + + List + {channels?.map((channel) => )} + + + + ); +} + +const Wrapper = styled.div` + width: 100%; + height: 100%; + + display: flex; + flex-direction: column; + padding: 0 32px 32px 32px; + + @media (max-width: 992px) { + padding: 0 16px 16px 16px; + } +`; + +const Content = styled.div` + display: flex; + gap: 32px; + + margin-top: 32px; + + @media (max-width: 992px) { + gap: 16px; + flex-direction: column; + + margin-top: 16px; + } +`; + +const Container = styled.ul` + flex-grow: 1; + border-radius: 16px; + border: 1px solid var(--grey-grey300); + max-width: 640px; + + display: flex; + flex-direction: column; + gap: 8px; + + padding: 32px; + + background-color: var(--grey-grey150); + + @media (max-width: 992px) { + width: 100%; + max-width: none; + + padding: 16px; + } +`; + +const ContentTitle = styled.h2` + font-size: 20px; + + margin-bottom: 8px; +`; diff --git a/src/pages/Main/MyOwnChannels/_components/ChannelItem.hook.tsx b/src/pages/Main/EditChannels/_components/ChannelItem.hook.tsx similarity index 57% rename from src/pages/Main/MyOwnChannels/_components/ChannelItem.hook.tsx rename to src/pages/Main/EditChannels/_components/ChannelItem.hook.tsx index 8544f2e..def8f3a 100644 --- a/src/pages/Main/MyOwnChannels/_components/ChannelItem.hook.tsx +++ b/src/pages/Main/EditChannels/_components/ChannelItem.hook.tsx @@ -7,20 +7,22 @@ import DeleteChannelModal from '@/components/Organisms/Modal/DeleteChannelModal' // types import { Channel } from '@/types/channel'; import { ModalType } from '@/types/enum'; +import EditChannelModal from '@/components/Organisms/Modal/EditChannelModal'; interface ChannelItemProps { channel: Channel; - EdittedChannel: Channel | null; } -export default function useChannelItem({ channel, EdittedChannel }: ChannelItemProps) { +export default function useChannelItem({ channel }: ChannelItemProps) { const { openModal } = useModalStore(); - const isEditted = channel.id === EdittedChannel?.id; - const handleDeleteModalButtonClick = () => { openModal(ModalType.DELETE_CHANNEL, , { channelId: channel.id, channelName: channel.name }); }; - return { isEditted, handleDeleteModalButtonClick }; + const handleEditModalButtonClick = () => { + openModal(ModalType.EDIT_CHANNEL, , { channelId: channel.id, channelName: channel.name }); + }; + + return { handleDeleteModalButtonClick, handleEditModalButtonClick }; } diff --git a/src/pages/Main/EditChannels/_components/ChannelItem.tsx b/src/pages/Main/EditChannels/_components/ChannelItem.tsx new file mode 100644 index 0000000..e7ba26f --- /dev/null +++ b/src/pages/Main/EditChannels/_components/ChannelItem.tsx @@ -0,0 +1,103 @@ +// libraries +import styled from 'styled-components'; + +// images +import playListSvg from '@/images/svg/playlist.svg'; +import deleteSvg from '@/images/svg/delete.svg'; +import editSvg from '@/images/svg/edit.svg'; + +// hooks +import useChannelItem from './ChannelItem.hook'; + +// types +import { ChannelItemProps } from './ChannelItem.type'; + +export default function ChannelItem({ channel }: ChannelItemProps) { + // logics + const { handleDeleteModalButtonClick, handleEditModalButtonClick } = useChannelItem({ channel }); + + // view + return ( + + + + 채널 아이콘 이미지 + + {channel.name} + + + + 수정 아이콘 이미지 + + + 삭제 아이콘 이미지 + + + + ); +} + +const Wrapper = styled.li` + width: 100%; + border: 1px solid var(--grey-grey300); + border-radius: 8px; + + display: flex; + justify-content: space-between; + align-items: center; + gap: 16px; + + background-color: var(--grey-grey200); + padding: 16px; +`; + +const IconButton = styled.button` + width: 24px; + height: 24px; + + padding: 0; + + transition: all 0.2s; + + img { + width: 100%; + height: 100%; + cursor: pointer; + } + + &:hover { + scale: 1.1; + } +`; + +const Left = styled.div` + display: flex; + align-items: center; + gap: 16px; +`; + +const ImageWrapper = styled.div` + border-radius: 50%; + width: 32px; + height: 32px; + + overflow: hidden; + + img { + width: 100%; + height: 100%; + + object-fit: cover; + } +`; + +const Name = styled.span` + font-size: 16px; + color: var(--grey-grey600); +`; + +const Right = styled.div` + display: flex; + align-items: center; + gap: 16px; +`; diff --git a/src/pages/Main/MyOwnChannels/_components/ChannelItem.type.tsx b/src/pages/Main/EditChannels/_components/ChannelItem.type.tsx similarity index 55% rename from src/pages/Main/MyOwnChannels/_components/ChannelItem.type.tsx rename to src/pages/Main/EditChannels/_components/ChannelItem.type.tsx index 9c32d89..b128a14 100644 --- a/src/pages/Main/MyOwnChannels/_components/ChannelItem.type.tsx +++ b/src/pages/Main/EditChannels/_components/ChannelItem.type.tsx @@ -2,6 +2,4 @@ import { Channel } from '@/types/channel'; export interface ChannelItemProps { channel: Channel; - EdittedChannel: Channel | null; - onEditButtonClick: (channel: Channel) => void; } diff --git a/src/pages/Main/MyOwnChannels/MyOwnChannels.hook.tsx b/src/pages/Main/MyOwnChannels/MyOwnChannels.hook.tsx deleted file mode 100644 index fc0bd03..0000000 --- a/src/pages/Main/MyOwnChannels/MyOwnChannels.hook.tsx +++ /dev/null @@ -1,19 +0,0 @@ -// hooks -import { useState } from 'react'; -import useGetMyOwnChannels from '@/apis/hooks/useGetMyOwnChannels'; -import { useUserStore } from '@/store/useUserStore'; - -// types -import { Channel } from '@/types/channel'; - -export default function useMyOwnChannels() { - const { user } = useUserStore(); - - const [EdittedChannel, setEdittedChannel] = useState(null); - const { data: channels, isLoading, isError } = useGetMyOwnChannels(user?.id as string); - - const handleEditButtonClick = (channel: Channel) => { - setEdittedChannel(channel); - }; - return { EdittedChannel, setEdittedChannel, channels, isLoading, isError, handleEditButtonClick }; -} diff --git a/src/pages/Main/MyOwnChannels/MyOwnChannels.tsx b/src/pages/Main/MyOwnChannels/MyOwnChannels.tsx deleted file mode 100644 index 49efc25..0000000 --- a/src/pages/Main/MyOwnChannels/MyOwnChannels.tsx +++ /dev/null @@ -1,100 +0,0 @@ -// libraries -import styled from 'styled-components'; - -// components -import ChannelItem from './_components/ChannelItem'; -import ChannelEditor from './_components/ChannelEditor'; -import MainTitle from '../../../components/Atoms/Text/MainTitle'; -import useMyOwnChannels from './MyOwnChannels.hook'; - -export default function MyOwnChannels() { - // logics - const { EdittedChannel, setEdittedChannel, channels, isLoading, isError, handleEditButtonClick } = useMyOwnChannels(); - - // view - if (isLoading) { - return
loading...
; - } - - if (isError) { - return
error...
; - } - - return ( - - MyOwnChannels - - - - ChannelList - {channels?.map((channel) => ( - - ))} - - - - - ChannelEditor - - - - - ); -} - -const Wrapper = styled.div` - width: 100%; - height: 100%; - - display: flex; - flex-direction: column; - padding: 0 32px; -`; - -const Content = styled.div` - flex-grow: 1; - - display: flex; - - padding-bottom: 64px; -`; - -const Left = styled.div` - width: 50%; - - padding-top: 16px; - padding-right: 32px; - padding-left: 32px; -`; - -const ContentTitle = styled.h2` - font-size: 24px; - font-weight: 700; - - margin-bottom: 16px; -`; - -const Container = styled.ul` - display: flex; - flex-direction: column; - gap: 8px; -`; - -const CenterLine = styled.div` - width: 1px; - height: 100%; - background-color: var(--grey-grey300); -`; - -const Rignt = styled.div` - width: 50%; - - padding-top: 16px; - padding-right: 32px; - padding-left: 32px; -`; diff --git a/src/pages/Main/MyOwnChannels/_components/ChannelEditor.hook.tsx b/src/pages/Main/MyOwnChannels/_components/ChannelEditor.hook.tsx deleted file mode 100644 index 8e60c84..0000000 --- a/src/pages/Main/MyOwnChannels/_components/ChannelEditor.hook.tsx +++ /dev/null @@ -1,67 +0,0 @@ -// hooks -import useUpdateChannel from '@/apis/hooks/useUpdateChannel'; -import { useState } from 'react'; -import { useChannelEditorProps } from './ChannelEditor.type'; - -export default function useChannelEditor({ setEdittedChannel, EdittedChannel }: useChannelEditorProps) { - if (!EdittedChannel) return null; - - const upLoadUpdateChannelMutate = useUpdateChannel(); - const [tagValue, setTagValue] = useState(''); - - const handleChangeTagValue = (e: React.ChangeEvent) => { - setTagValue(e.target.value); - }; - - const handleDeleteTag = (tag: string) => { - setEdittedChannel({ - ...EdittedChannel, - tags: EdittedChannel.tags.filter((t) => t !== tag), - }); - }; - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - - upLoadUpdateChannelMutate.mutate({ - channelId: EdittedChannel.id, - channel: EdittedChannel, - }); - }; - - const handleAddTagKeyDown = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - e.preventDefault(); - - if ( - tagValue === '' || - tagValue.length > 10 || - EdittedChannel?.tags.length > 5 || - EdittedChannel?.tags.includes(tagValue) - ) - return; - - setEdittedChannel({ - ...EdittedChannel, - tags: [...EdittedChannel.tags, tagValue], - }); - setTagValue(''); - } - }; - - const handleChangeChannelData = (e: React.ChangeEvent) => { - setEdittedChannel({ - ...EdittedChannel, - [e.target.name]: e.target.value, - }); - }; - - return { - tagValue, - handleChangeTagValue, - handleDeleteTag, - handleSubmit, - handleAddTagKeyDown, - handleChangeChannelData, - }; -} diff --git a/src/pages/Main/MyOwnChannels/_components/ChannelEditor.tsx b/src/pages/Main/MyOwnChannels/_components/ChannelEditor.tsx deleted file mode 100644 index e9b5ed6..0000000 --- a/src/pages/Main/MyOwnChannels/_components/ChannelEditor.tsx +++ /dev/null @@ -1,102 +0,0 @@ -// libraries -import styled from 'styled-components'; - -// hooks -import useChannelEditor from './ChannelEditor.hook'; - -// components -import { - ButtonWrapper, - Form, - FormField, - Input, - Label, - Tag, - TagContainer, -} from '@/components/Atoms/Modal/StyledComponents'; -import Button from '@/components/Atoms/Modal/Button'; - -// types -import { ChannelEditorProps } from './ChannelEditor.type'; - -export default function ChannelEditor({ EdittedChannel, setEdittedChannel }: ChannelEditorProps) { - // logics - const logics = useChannelEditor({ setEdittedChannel, EdittedChannel }); - - if (!logics) return null; - - const { - tagValue, - handleChangeTagValue, - handleDeleteTag, - handleSubmit, - handleAddTagKeyDown, - handleChangeChannelData, - } = logics; - - // view - return ( - -
- - - - - - - - - {EdittedChannel?.tags.map((tag) => ( - { - handleDeleteTag(tag); - }} - > - {tag} - - ))} - - - - - - - - - - - - -
-
- ); -} - -const Wrapper = styled.div` - display: flex; - flex-direction: column; - padding: 32px; -`; diff --git a/src/pages/Main/MyOwnChannels/_components/ChannelEditor.type.tsx b/src/pages/Main/MyOwnChannels/_components/ChannelEditor.type.tsx deleted file mode 100644 index ec1c492..0000000 --- a/src/pages/Main/MyOwnChannels/_components/ChannelEditor.type.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Channel } from '@/types/channel'; -import { Dispatch, SetStateAction } from 'react'; - -export interface ChannelEditorProps { - EdittedChannel: Channel | null; - setEdittedChannel: Dispatch>; -} - -export interface useChannelEditorProps { - setEdittedChannel: (channel: Channel) => void; - EdittedChannel: Channel | null; -} diff --git a/src/pages/Main/MyOwnChannels/_components/ChannelItem.tsx b/src/pages/Main/MyOwnChannels/_components/ChannelItem.tsx deleted file mode 100644 index b4495b2..0000000 --- a/src/pages/Main/MyOwnChannels/_components/ChannelItem.tsx +++ /dev/null @@ -1,100 +0,0 @@ -// libraries -import styled from 'styled-components'; - -// images -import playListSvg from '@/images/svg/playlist.svg'; -import playListFocusedSvg from '@/images/svg/playlist-focused.svg'; -import deleteSvg from '@/images/svg/delete.svg'; -import deleteFocusedSvg from '@/images/svg/delete-focused.svg'; -import editSvg from '@/images/svg/edit.svg'; -import editFocusedSvg from '@/images/svg/edit-focused.svg'; - -// hooks -import useChannelItem from './ChannelItem.hook'; - -// types -import { ChannelItemProps } from './ChannelItem.type'; - -export default function ChannelItem({ channel, EdittedChannel, onEditButtonClick }: ChannelItemProps) { - // logics - const { isEditted, handleDeleteModalButtonClick } = useChannelItem({ channel, EdittedChannel }); - - // view - return ( - - - - 채널 아이콘 이미지 - - {channel.name} - - - { - onEditButtonClick(channel); - }} - > - 수정 아이콘 이미지 - - - 삭제 아이콘 이미지 - - - - ); -} - -const Wrapper = styled.li<{ - $isEditted: boolean; -}>` - width: 100%; - border: 1px solid ${(props) => (props.$isEditted ? 'var(--mint5)' : 'var(--grey-grey300)')}; - border-radius: 8px; - - display: flex; - justify-content: space-between; - align-items: center; - gap: 16px; - - background-color: ${(props) => (props.$isEditted ? 'var(--mint8)' : 'transparent')}; - padding: 16px; -`; - -const IconButton = styled.button` - width: 24px; - height: 24px; - - padding: 0; - - transition: all 0.2s; - - img { - width: 100%; - height: 100%; - cursor: pointer; - } - - &:hover { - scale: 1.1; - } -`; - -const Left = styled.div` - display: flex; - align-items: center; - gap: 16px; -`; - -const Name = styled.span<{ - $isEditted: boolean; -}>` - font-size: 16px; - color: ${(props) => (props.$isEditted ? 'var(--mint5)' : 'var(--grey-grey600)')}; -`; - -const Right = styled.div` - display: flex; - align-items: center; - gap: 16px; -`; diff --git a/src/pages/Main/Profile/Profile.tsx b/src/pages/Main/Profile/Profile.tsx index 70d9a35..5b7ae95 100644 --- a/src/pages/Main/Profile/Profile.tsx +++ b/src/pages/Main/Profile/Profile.tsx @@ -6,6 +6,7 @@ import useProfile from './Profile.hook'; // components import MainTitle from '@/components/Atoms/Text/MainTitle'; +import Description from '@/components/Molecules/Description'; export default function Profile() { // logics @@ -41,10 +42,7 @@ export default function Profile() { {user.nickName} - - Notice - 유저 정보를 수정하고 싶다면 Google에서 수정해주세요. - + ); @@ -96,32 +94,6 @@ const UserInfoBox = styled.div` } `; -const NoticeBox = styled.div` - border-radius: 16px; - border: 1px solid var(--grey-grey300); - width: 320px; - height: 160px; - - display: flex; - flex-direction: column; - gap: 16px; - - padding: 32px; - background-color: var(--grey-grey150); - - @media (max-width: 992px) { - width: 100%; - - padding: 16px; - } -`; - -const NoticeText = styled.span` - font-size: 16px; - - color: var(--grey-grey600); -`; - const UserInfoContent = styled.div` flex-grow: 1; max-width: 640px; diff --git a/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx b/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx index f048cee..76bec44 100644 --- a/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx +++ b/src/pages/Main/_compoenets/SiderBar/NavigatorContainer.hook.tsx @@ -30,8 +30,8 @@ export default function useNavigatorContainer() { icon: [personSvg, personFocusedSvg], }, { - name: 'MyOwnChannels', - path: '/main/myOwnChannels', + name: 'EditChannels', + path: '/main/EditChannels', icon: [channelListSvg, channelListFocusedSvg], }, ]; diff --git a/src/pages/Main/_compoenets/SiderBar/SideBar.tsx b/src/pages/Main/_compoenets/SiderBar/SideBar.tsx index fa9c14d..2b786d9 100644 --- a/src/pages/Main/_compoenets/SiderBar/SideBar.tsx +++ b/src/pages/Main/_compoenets/SiderBar/SideBar.tsx @@ -36,12 +36,11 @@ export default function SideBar() { } const BackGround = styled.nav` - height: 800px; - display: flex; flex-direction: column; align-items: center; padding-left: 24px; + padding-bottom: 24px; @media (max-width: 768px) { height: 100%; diff --git a/src/router/index.tsx b/src/router/index.tsx index 2f2e225..e0b5bf4 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -4,10 +4,10 @@ import LandingPage from '@/pages/Landing/LandingPage'; import ChannelContainer from '@/pages/Main/_compoenets/Content/ChannelContainer'; import Channel from '@/pages/Main/Channel/Channel'; import MainPage from '@/pages/Main/MainPage'; -import MyOwnChannels from '@/pages/Main/MyOwnChannels/MyOwnChannels'; import NotFoundPage from '@/pages/NotFound/NotFoundPage'; import SignInPage from '@/pages/Signin/SignInPage'; import Profile from '@/pages/Main/Profile/Profile'; +import EditChannels from '@/pages/Main/EditChannels/EditChannels'; export default function Router() { // view @@ -19,7 +19,7 @@ export default function Router() { } /> } /> } /> - } /> + } /> } /> diff --git a/src/styles/GlobalStyles.tsx b/src/styles/GlobalStyles.tsx index 53514de..4fdda8b 100644 --- a/src/styles/GlobalStyles.tsx +++ b/src/styles/GlobalStyles.tsx @@ -118,7 +118,7 @@ const GlobalStyles = createGlobalStyle` body { min-height: 100vh; - line-height: 1; + line-height: normal; } ol,