Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/user/mypage/myProfile/MyProfileWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as S from './MyPropfileWrapper.styled';
import * as S from './MyProfileWrapper.styled';

interface MyProfileWrapperProps {
children: React.ReactNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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%;
`;
Expand All @@ -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%;
`;
Expand Down
132 changes: 89 additions & 43 deletions src/components/user/mypage/myProfile/editProfile/EditProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@ 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';
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<typeof profileSchema>;
Expand All @@ -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 },
Expand All @@ -67,12 +61,44 @@ export default function EditProfile() {
mode: 'onChange',
});

const handleClickGithubValidation = () => {
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 = () => {
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
Expand All @@ -93,7 +119,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) => ({
Expand All @@ -105,7 +131,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' });

Expand Down Expand Up @@ -260,35 +286,55 @@ export default function EditProfile() {
{/* 깃허브 */}
<S.EditWrapper>
<label>깃허브</label>
<Controller
name='github'
control={control}
render={({ field }) => (
<S.InputWrapper>
<S.InputTextGithub>
<InputText
inputType='text'
placeholder='깃허브 주소를 입력해주세요.'
autoComplete='auto'
{...field}
/>
</S.InputTextGithub>
{errors.github && (
<S.ErrorMessage>{errors.github.message}</S.ErrorMessage>
)}
<Button
size='primary'
schema='primary'
radius='large'
type='button'
onClick={handleClickGithubValidation}
>
<S.GithubImg src={githubIcon} alt='깃허브 아이콘' />
인증
</Button>
</S.InputWrapper>
)}
/>
<S.GithubContainer>
<Controller
name='github'
control={control}
render={({ field }) => (
<S.InputWrapper>
<S.InputTextGithub>
<InputText
inputType='text'
placeholder='깃허브 주소를 인증하면 자동으로 가져옵니다.'
autoComplete='auto'
readOnly
{...field}
/>
</S.InputTextGithub>
{!field.value ? (
<Button
size='primary'
schema='primary'
radius='large'
type='button'
onClick={handleClickGithubValidation}
>
<S.GithubDeleteIcon>
<S.GithubImg src={githubIcon} alt='깃허브 아이콘' />
<S.GithubSpan>인증</S.GithubSpan>
</S.GithubDeleteIcon>
</Button>
) : (
<Button
size='primary'
schema='primary'
radius='large'
type='button'
onClick={handleClickDeleteGithubValue}
>
<S.GithubDeleteIcon>
<XMarkIcon />
<S.GithubSpan>삭제</S.GithubSpan>
</S.GithubDeleteIcon>
</Button>
)}
{errors.github && (
<S.ErrorMessage>{errors.github.message}</S.ErrorMessage>
)}
</S.InputWrapper>
)}
/>
</S.GithubContainer>
</S.EditWrapper>

{/* 경력 */}
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<Modal isOpen={isOpen} onClose={handleModalClose}>
{message}
</Modal>
);
}
27 changes: 16 additions & 11 deletions src/components/user/mypage/myProfile/profile/Profile.styled.ts
Original file line number Diff line number Diff line change
@@ -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`
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -174,3 +171,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;
`;
12 changes: 10 additions & 2 deletions src/components/user/mypage/myProfile/profile/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@ export default function Profile() {
<label>깃허브</label>
<S.BackgroundWrapper>
<span>
{userInfoData.github ||
{(userInfoData.github && (
<S.GithubLink to={userInfoData.github} target='_blank'>
{userInfoData.github}
</S.GithubLink>
)) ||
(myPage
? PROFILE_DEFAULT_MESSAGE.myGithub
: PROFILE_DEFAULT_MESSAGE.github)}
Expand Down Expand Up @@ -190,7 +194,11 @@ export default function Profile() {
</S.ChartBox>
</S.BackgroundBox>
</S.List>
{myPage && <Link to={ROUTES.changePw}>비밀번호 재설정</Link>}
{myPage && (
<S.ChangePasswordLink as={Link} to={ROUTES.changePw}>
비밀번호 재설정
</S.ChangePasswordLink>
)}
</S.ProfileSection>
);
}
5 changes: 3 additions & 2 deletions src/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const ROUTES = {
inquiry: '/inquiry',
evaluation: '/evaluation',
loginSuccess: '/oauth-redirect',
githubSuccess: '/oauth/github-success',
} as const;

export const ADMIN_ROUTE = {
Expand All @@ -50,8 +51,8 @@ export const ADMIN_ROUTE = {
log: 'log',
joinedProject: 'joined-project',
createdProject: 'created-project',
appliedProject: 'apply-project',
appliedProject: 'applied-project',
comments: 'comments',
checkingApplicant: 'checked-applicants',
applyingProject: 'applied-projects',
};
} as const;
2 changes: 2 additions & 0 deletions src/constants/user/modalMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ export const MODAL_MESSAGE = {
duplicationTag: '이미 존재하는 태그입니다.',
emptyTag: '태그명을 입력하세요.',
emptySkillImg: '스킬 이미지를 추가하세요.',
githubProfileFail: '깃허브 프로필 등록에 실패했습니다. 다시 시도해주세요.',
githubProfileSuccess: '깃허브 프로필이 성공적으로 등록되었습니다!',
} as const;
10 changes: 10 additions & 0 deletions src/routes/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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')
);
Expand Down Expand Up @@ -110,6 +116,10 @@ export const AppRoutes = () => {
path: ROUTES.loginSuccess,
element: <LoginApi />,
},
{
path: ROUTES.githubSuccess,
element: <ProfileGithubSuccess />,
},
{
path: ROUTES.signup,
element: isLoggedIn ? (
Expand Down