From 02a143fc6124b15fa99989eeefaac5cd0cacba96 Mon Sep 17 00:00:00 2001 From: YouD0313 <102004480+YouD0313@users.noreply.github.com> Date: Thu, 29 May 2025 19:37:06 +0900 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=20=EB=AA=A8=EB=8B=AC?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/admin/sidebar/AdminSidebar.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/common/admin/sidebar/AdminSidebar.tsx b/src/components/common/admin/sidebar/AdminSidebar.tsx index e91064f6..d277060e 100644 --- a/src/components/common/admin/sidebar/AdminSidebar.tsx +++ b/src/components/common/admin/sidebar/AdminSidebar.tsx @@ -7,14 +7,19 @@ import ContentBorder from '../../contentBorder/ContentBorder'; import useAuthStore from '../../../../store/authStore'; import { useNavigate } from 'react-router-dom'; import { ROUTES } from '../../../../constants/routes'; +import { useModal } from '../../../../hooks/useModal'; +import Modal from '../../modal/Modal'; +import { MODAL_MESSAGE } from '../../../../constants/user/modalMessage'; export default function AdminSidebar() { const navigate = useNavigate(); const logout = useAuthStore((state) => state.logout); + const { isOpen, message, handleModalOpen, handleModalClose } = useModal(); const handleClickLogout = () => { - logout(); + handleModalOpen(MODAL_MESSAGE.needAuth); setTimeout(() => { + logout(); navigate(ROUTES.main); }, 1000); }; @@ -39,6 +44,9 @@ export default function AdminSidebar() { + + {message} + ); } From 97b1814cde2eb3382e41d1829e921dcef15eeb20 Mon Sep 17 00:00:00 2001 From: YouD0313 <102004480+YouD0313@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:40:03 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=20-=20AdminSidebar=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EC=9D=98=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=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 --- .../common/admin/sidebar/AdminSidebar.tsx | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/src/components/common/admin/sidebar/AdminSidebar.tsx b/src/components/common/admin/sidebar/AdminSidebar.tsx index cbb698e5..1048c626 100644 --- a/src/components/common/admin/sidebar/AdminSidebar.tsx +++ b/src/components/common/admin/sidebar/AdminSidebar.tsx @@ -25,31 +25,6 @@ export default function AdminSidebar() { }; return ( -<<<<<<< HEAD - - - - - - Logout - - - - - - - - - - {message} - - -======= @@ -78,6 +53,5 @@ export default function AdminSidebar() { {message} ->>>>>>> origin ); } From 011ad30539e90d4e3c7073dbac02a2f73824227d Mon Sep 17 00:00:00 2001 From: YouD0313 <102004480+YouD0313@users.noreply.github.com> Date: Fri, 20 Jun 2025 18:33:59 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EA=B9=83=ED=97=88=EB=B8=8C=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B8=EC=A6=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../editProfile/EditProfile.styled.ts | 20 +++ .../myProfile/editProfile/EditProfile.tsx | 121 +++++++++++------- .../editProfile/ProfileGithubSuccess.tsx | 38 ++++++ .../myProfile/profile/Profile.styled.ts | 27 ++-- .../user/mypage/myProfile/profile/Profile.tsx | 12 +- src/constants/routes.ts | 5 +- src/constants/user/modalMessage.ts | 2 + src/routes/AppRoutes.tsx | 10 ++ 8 files changed, 177 insertions(+), 58 deletions(-) create mode 100644 src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx diff --git a/src/components/user/mypage/myProfile/editProfile/EditProfile.styled.ts b/src/components/user/mypage/myProfile/editProfile/EditProfile.styled.ts index 4761f6fd..10434a3e 100644 --- a/src/components/user/mypage/myProfile/editProfile/EditProfile.styled.ts +++ b/src/components/user/mypage/myProfile/editProfile/EditProfile.styled.ts @@ -43,6 +43,10 @@ export const InputBeginner = styled.input` accent-color: ${({ theme }) => theme.color.navy}; `; +export const GithubContainer = styled.div` + width: 85%; +`; + export const InputTextGithub = styled.div` width: 70%; `; @@ -53,6 +57,22 @@ export const GithubImg = styled.img` filter: invert(1); `; +export const GithubDeleteIcon = styled.div` + display: flex; + justify-content: center; + align-items: center; + gap: 0.5em; + + svg { + width: 1rem; + height: 1rem; + } +`; + +export const GithubSpan = styled.span` + width: auto; +`; + export const InputTextCareer = styled.div` width: 100%; `; diff --git a/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx b/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx index eb89563b..62b51463 100644 --- a/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx +++ b/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx @@ -7,7 +7,7 @@ import TextareaAutosize from 'react-textarea-autosize'; import InputText from '../../../auth/InputText'; import { z } from 'zod'; import { SquaresPlusIcon, XMarkIcon } from '@heroicons/react/24/outline'; -import { useNavigate, useOutletContext } from 'react-router-dom'; +import { useLocation, useNavigate, useOutletContext } from 'react-router-dom'; import MyProfileWrapper from '../MyProfileWrapper'; import type { UserInfo } from '../../../../../models/userInfo'; import { useSearchFilteringTags } from '../../../../../hooks/user/useSearchFilteringTags'; @@ -15,10 +15,7 @@ import { useEditMyProfileInfo } from '../../../../../hooks/user/useMyInfo'; import useNickNameVerification from '../../../../../hooks/user/useNicknameVerification'; import { ROUTES } from '../../../../../constants/routes'; import Button from '../../../../common/Button/Button'; -import { - ERROR_MESSAGES, - OAUTH_PROVIDERS, -} from '../../../../../constants/user/authConstants'; +import { ERROR_MESSAGES } from '../../../../../constants/user/authConstants'; import githubIcon from '../../../../../assets/githubIcon.svg'; type ProfileFormData = z.infer; @@ -39,17 +36,14 @@ export default function EditProfile() { const { nicknameMessage, handleDuplicationNickname } = useNickNameVerification(); const navigate = useNavigate(); + const location = useLocation(); + const githubUrl = location.state?.githubUrl; const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; - const github = { - ...OAUTH_PROVIDERS.filter((oauth) => oauth.name.includes('github'))[0], - }; - - const handleClickGithubValidation = () => { - window.location.href = `${BASE_URL}/${github.url}`; - }; + const github = import.meta.env.VITE_APP_BASE_URL_GITHUB_LINK; const { control, + setValue, handleSubmit, reset, formState: { errors }, @@ -67,12 +61,33 @@ export default function EditProfile() { mode: 'onChange', }); + const handleClickGithubValidation = () => { + window.location.href = `${BASE_URL}/${github}`; + }; + + const handleClickDeleteGithubValue = () => { + reset({ + ...control._defaultValues, + github: '', + }); + setValue('github', '', { shouldValidate: true, shouldDirty: true }); + }; + useEffect(() => { if (scrollRef.current) { scrollRef.current.scrollTop = 0; } }, [scrollRef]); + useEffect(() => { + if (githubUrl) { + setValue('github', githubUrl, { + shouldValidate: true, + shouldDirty: true, + }); + } + }, [githubUrl, setValue]); + useEffect(() => { if (userInfoData) { const skillTagIds = userInfoData.skills @@ -93,7 +108,7 @@ export default function EditProfile() { bio: userInfoData.bio || '', beginner: userInfoData.beginner, positionTagIds, - github: userInfoData.github || '', + github: userInfoData.github || githubUrl || '', skillTagIds, career: userInfoData.career?.length ? userInfoData.career.map((item) => ({ @@ -105,7 +120,7 @@ export default function EditProfile() { : [{ name: '', periodStart: '', periodEnd: '', role: '' }], }); } - }, [userInfoData, skillTagsData, positionTagsData, reset]); + }, [userInfoData, skillTagsData, positionTagsData, reset, githubUrl]); const { fields, append, remove } = useFieldArray({ control, name: 'career' }); @@ -260,35 +275,55 @@ export default function EditProfile() { {/* 깃허브 */} - ( - - - - - {errors.github && ( - {errors.github.message} - )} - - - )} - /> + + ( + + + + + {!field.value ? ( + + ) : ( + + )} + {errors.github && ( + {errors.github.message} + )} + + )} + /> + {/* 경력 */} diff --git a/src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx b/src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx new file mode 100644 index 00000000..05436891 --- /dev/null +++ b/src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx @@ -0,0 +1,38 @@ +import { useEffect } from 'react'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { ROUTES } from '../../../../../constants/routes'; +import { useModal } from '../../../../../hooks/useModal'; +import Modal from '../../../../common/modal/Modal'; +import { MODAL_MESSAGE } from '../../../../../constants/user/modalMessage'; + +export default function ProfileGithubSuccess() { + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const { isOpen, message, handleModalOpen, handleModalClose } = useModal(); + + useEffect(() => { + (async () => { + const githubUrl = searchParams.get('githubUrl'); + console.log(githubUrl); + if (githubUrl) { + handleModalOpen(MODAL_MESSAGE.githubProfileSuccess); + setTimeout(() => { + navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`, { + state: { githubUrl }, + }); + }, 1000); + } else { + handleModalOpen(MODAL_MESSAGE.githubProfileFail); + setTimeout(() => { + navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`); + }, 1000); + } + })(); + }, [searchParams, handleModalOpen, navigate]); + + return ( + + {message} + + ); +} diff --git a/src/components/user/mypage/myProfile/profile/Profile.styled.ts b/src/components/user/mypage/myProfile/profile/Profile.styled.ts index 17e46c7d..08282a10 100644 --- a/src/components/user/mypage/myProfile/profile/Profile.styled.ts +++ b/src/components/user/mypage/myProfile/profile/Profile.styled.ts @@ -1,20 +1,11 @@ +import { Link } from 'react-router-dom'; import styled from 'styled-components'; +import { SendButton } from '../../../customerService/inquiry/Inquiry.styled'; export const ProfileSection = styled.div` display: flex; flex-direction: column; gap: 1.25rem; - - a { - width: fit-content; - display: inline-block; - padding: 0.5rem 0.7rem; - border-radius: ${({ theme }) => theme.borderRadius.large}; - background-color: #3e5879; - color: ${({ theme }) => theme.color.white}; - font-size: 0.8rem; - margin-top: 1rem; - } `; export const BackgroundWrapper = styled.div` @@ -125,6 +116,12 @@ export const List = styled.div` } `; +export const GithubLink = styled(Link)` + &:hover { + color: ${({ theme }) => theme.color.lightnavy}; + } +`; + export const LabelBox = styled.div` display: flex; overflow: visible; @@ -172,3 +169,11 @@ export const Explain = styled.p` cursor: pointer; user-select: none; `; + +export const ChangePasswordLink = styled(SendButton)` + width: fit-content; + padding: 0.5rem 0.7rem; + background-color: #3e5879; + font-size: 0.8rem; + margin-top: 1rem; +`; diff --git a/src/components/user/mypage/myProfile/profile/Profile.tsx b/src/components/user/mypage/myProfile/profile/Profile.tsx index dbe1c1f2..dad73d33 100644 --- a/src/components/user/mypage/myProfile/profile/Profile.tsx +++ b/src/components/user/mypage/myProfile/profile/Profile.tsx @@ -99,7 +99,11 @@ export default function Profile() { - {userInfoData.github || + {(userInfoData.github && ( + + {userInfoData.github} + + )) || (myPage ? PROFILE_DEFAULT_MESSAGE.myGithub : PROFILE_DEFAULT_MESSAGE.github)} @@ -158,7 +162,11 @@ export default function Profile() { - {myPage && 비밀번호 재설정} + {myPage && ( + + 비밀번호 재설정 + + )} ); } diff --git a/src/constants/routes.ts b/src/constants/routes.ts index 3f1cc3c1..a7205d36 100644 --- a/src/constants/routes.ts +++ b/src/constants/routes.ts @@ -29,6 +29,7 @@ export const ROUTES = { inquiry: '/inquiry', evaluation: '/evaluation', loginSuccess: '/oauth-redirect', + githubSuccess: '/oauth/github-success', } as const; export const ADMIN_ROUTE = { @@ -50,5 +51,5 @@ export const ADMIN_ROUTE = { log: 'log', joinedProject: 'joined-project', createdProject: 'created-project', - appliedProject: 'apply-project', -}; + appliedProject: 'applied-project', +} as const; diff --git a/src/constants/user/modalMessage.ts b/src/constants/user/modalMessage.ts index 0556fbe4..09d59fe1 100644 --- a/src/constants/user/modalMessage.ts +++ b/src/constants/user/modalMessage.ts @@ -30,4 +30,6 @@ export const MODAL_MESSAGE = { duplicationTag: '이미 존재하는 태그입니다.', emptyTag: '태그명을 입력하세요.', emptySkillImg: '스킬 이미지를 추가하세요.', + githubProfileFail: '깃허브 프로필 등록에 실패했습니다. 다시 시도해주세요.', + githubProfileSuccess: '깃허브 프로필이 성공적으로 등록되었습니다!', } as const; diff --git a/src/routes/AppRoutes.tsx b/src/routes/AppRoutes.tsx index b65e2c7a..166be35e 100644 --- a/src/routes/AppRoutes.tsx +++ b/src/routes/AppRoutes.tsx @@ -47,6 +47,12 @@ const Profile = lazy( const ProfileEdit = lazy( () => import('../components/user/mypage/myProfile/editProfile/EditProfile') ); +const ProfileGithubSuccess = lazy( + () => + import( + '../components/user/mypage/myProfile/editProfile/ProfileGithubSuccess' + ) +); const MyProjectVolunteer = lazy( () => import('../pages/user/manage/myProjectVolunteer/MyProjectVolunteer') ); @@ -110,6 +116,10 @@ export const AppRoutes = () => { path: ROUTES.loginSuccess, element: , }, + { + path: ROUTES.githubSuccess, + element: , + }, { path: ROUTES.signup, element: isLoggedIn ? ( From d896213ad54a693b858e01a1d0804c7af452f1ac Mon Sep 17 00:00:00 2001 From: YouD0313 <102004480+YouD0313@users.noreply.github.com> Date: Mon, 23 Jun 2025 16:48:44 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=EB=B0=98?= =?UTF-8?q?=EC=98=81,=20=20MyProfileWrapper=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20EditProfile=EC=97=90=EC=84=9C=20GitHub=20OAuth=20UR?= =?UTF-8?q?L=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Wrapper.styled.ts => MyProfileWrapper.styled.ts} | 0 .../user/mypage/myProfile/MyProfileWrapper.tsx | 2 +- .../mypage/myProfile/editProfile/EditProfile.tsx | 13 ++++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) rename src/components/user/mypage/myProfile/{MyPropfileWrapper.styled.ts => MyProfileWrapper.styled.ts} (100%) diff --git a/src/components/user/mypage/myProfile/MyPropfileWrapper.styled.ts b/src/components/user/mypage/myProfile/MyProfileWrapper.styled.ts similarity index 100% rename from src/components/user/mypage/myProfile/MyPropfileWrapper.styled.ts rename to src/components/user/mypage/myProfile/MyProfileWrapper.styled.ts diff --git a/src/components/user/mypage/myProfile/MyProfileWrapper.tsx b/src/components/user/mypage/myProfile/MyProfileWrapper.tsx index b994e7fb..9af44a56 100644 --- a/src/components/user/mypage/myProfile/MyProfileWrapper.tsx +++ b/src/components/user/mypage/myProfile/MyProfileWrapper.tsx @@ -1,4 +1,4 @@ -import * as S from './MyPropfileWrapper.styled'; +import * as S from './MyProfileWrapper.styled'; interface MyProfileWrapperProps { children: React.ReactNode; diff --git a/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx b/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx index 62b51463..efbd2e5c 100644 --- a/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx +++ b/src/components/user/mypage/myProfile/editProfile/EditProfile.tsx @@ -62,7 +62,18 @@ export default function EditProfile() { }); const handleClickGithubValidation = () => { - window.location.href = `${BASE_URL}/${github}`; + if (!github || !BASE_URL) { + console.error('GitHub OAuth URL이 설정되지 않았습니다.'); + return; + } + const oauthUrl = `${BASE_URL}/${github}`; + try { + new URL(oauthUrl); + } catch { + console.error('유효하지 않은 OAuth URL입니다.'); + return; + } + window.location.href = oauthUrl; }; const handleClickDeleteGithubValue = () => {