Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 마이페이지 리팩토링 #222

Merged
merged 15 commits into from
Jun 26, 2024
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
29 changes: 7 additions & 22 deletions src/home/apis/getUserPasswordMatch.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
import { AxiosError } from 'axios';

import { authClient } from '@/apis';
import { AuthErrorData } from '@/home/types/Auth.type';
import { GetPasswordResponse } from '@/home/types/password.type';
import { SessionTokenType } from '@/home/types/password.type';
import { api } from '@/service/TokenService';

interface getPasswordProps {
password: string;
}

export const getUserPasswordMatch = async (
props: getPasswordProps
): Promise<GetPasswordResponse> => {
const { password } = props;

try {
const res = await authClient.get('/auth/verification/password', {
params: { password },
headers: api.headers,
});
return { data: res.data };
} catch (error: unknown) {
return { error: error as AxiosError<AuthErrorData> };
}
export const getUserPasswordMatch = async (password: string): Promise<SessionTokenType> => {
const res = await authClient.get('/auth/verification/password', {
params: { password },
headers: api.headers,
});
return res.data;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,28 @@ import { Link } from 'react-router-dom';
import styled from 'styled-components';

export const StyledChangePasswordFrame = styled.div`
flex: 1;

display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 24px;
`;

margin-bottom: 101px;
export const StyledLink = styled(Link)``;

export const StyledHiddenDiv = styled.div`
transform: rotate(180deg);
visibility: hidden;
`;

export const StyledLink = styled(Link)`
export const StyledLogo = styled.img`
width: 180px;
height: 29px;
`;

export const StyledLogo = styled.img`
width: 100%;
height: 100%;
export const StyledHiddenLogo = styled.img`
width: 180px;
height: 29px;
`;

export const StyledContainer = styled.div`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
StyledContainer,
StyledLink,
StyledLogo,
StyledHiddenLogo,
StyledHiddenDiv,
} from './ChangePasswordFrame.style';

interface ChangePasswordFrameProps {
Expand All @@ -18,6 +20,9 @@ export const ChangePasswordFrame = ({ children }: ChangePasswordFrameProps) => {
<StyledLogo src={Logo} alt="soomsil" />
</StyledLink>
<StyledContainer>{children}</StyledContainer>
<StyledHiddenDiv>
<StyledHiddenLogo />
</StyledHiddenDiv>
Comment on lines +23 to +25
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hidden 붙은 컴포넌트들이 대충 요쯤에 있는 거라는 건 알아냈는데
역할을 모르겠어요
도와달라

image

Copy link
Collaborator Author

@jonique98 jonique98 Jun 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

피그마 기준으로 봤을 때, 상단 SOOMSIL 로고를 제외하고 비밀번호 변경 사각형 컴포넌트 기준으로 중앙 정렬을 하고 있더라구요.
그래서 요소를 상대위치로 정렬하기 위해 밑에도 SOOMSIL 로고 크기만큼 컴포넌트를 넣고 center로 정렬 했습니다.
어차피 반응형으로 안하는 것 같긴 하지만..

</StyledChangePasswordFrame>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface CurrentPasswordFormProps {
}

export const CurrentPasswordForm = (props: CurrentPasswordFormProps) => {
const { currentPassword, isError, handlePasswordChange, checkCurrentPassword } =
const { currentPassword, isPasswordError, handlePasswordChange, checkCurrentPassword } =
useCurrentPasswordForm(props);

return (
Expand All @@ -30,8 +30,8 @@ export const CurrentPasswordForm = (props: CurrentPasswordFormProps) => {
placeholder="비밀번호를 입력해주세요."
value={currentPassword}
onChange={(e) => handlePasswordChange(e.target.value)}
isNegative={isError}
helperLabel={isError ? '비밀번호가 일치하지 않습니다.' : ''}
isNegative={isPasswordError}
helperLabel={isPasswordError ? '비밀번호가 일치하지 않습니다.' : ''}
/>
</StyledInputContainer>
<StyledButtonContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from 'react';

import { useMutation } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { useRecoilValue } from 'recoil';

Expand All @@ -18,37 +19,40 @@ export const useCurrentPasswordForm = ({
setSessionToken,
setPreviousPassword,
}: CurrentPasswordFormProps) => {
const [currentPassword, setCurrentPassword] = useState('');
const [isError, setIsError] = useState(false);
const [currentPassword, setCurrentPassword] = useState<string>('');
const [isPasswordError, setIsPasswordError] = useState<boolean>(false);
const isLoggedIn = useRecoilValue(LogInState);
const navigate = useNavigate();

const checkCurrentPassword = async () => {
const passwordMatchMutation = useMutation({
mutationFn: getUserPasswordMatch,
onSuccess: (data) => {
setSessionToken(data);
setPreviousPassword(currentPassword);
onConfirm();
},
onError: () => {
setIsPasswordError(true);
},
});

const checkCurrentPassword = () => {
if (!isLoggedIn) {
navigate('/Login');
return;
}

const { error, data } = await getUserPasswordMatch({
password: currentPassword,
});

if (data) {
setIsError(false);
setSessionToken(data as SessionTokenType);
setPreviousPassword(currentPassword);
onConfirm();
} else if (error) setIsError(true);
passwordMatchMutation.mutate(currentPassword);
};

const handlePasswordChange = (password: string) => {
if (isError) setIsError(false);
if (isPasswordError) setIsPasswordError(false);
setCurrentPassword(password);
};

return {
currentPassword,
isError,
isPasswordError,
handlePasswordChange,
checkCurrentPassword,
};
Expand Down
2 changes: 1 addition & 1 deletion src/home/components/Dialog/LogoutModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ interface LogoutModalProps {
}

export const LogoutModal = ({ open, onOpenChange }: LogoutModalProps) => {
const navigate = useNavigate();
const resetUserInfo = useResetUserInfo();
const navigate = useNavigate();

const handleLogout = () => {
resetUserInfo();
Expand Down
1 change: 1 addition & 0 deletions src/home/components/MyMenuList/MyMenuList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const MyMenuList = () => {
<StyledListItem onClick={() => navigate('/changePassword')}>
비밀번호 변경
</StyledListItem>
<StyledListItem onClick={() => navigate('/withdraw')}>계정탈퇴</StyledListItem>
<StyledListItem onClick={() => setIsOpenModal(true)}>로그아웃</StyledListItem>
</StyledMenuContainer>
<StyledMenuContainer>
Expand Down
24 changes: 24 additions & 0 deletions src/hooks/usePrivateRoute.tsx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저 근데 뒤늦게 든 의문이!! PrivateRoute가 훅이어야 할 이유가 있나요??
그냥 함수형 컴포넌트로 작성해도 될 거 같은데, 제가 이런 방식에 익숙하지 않아서 그런걸수도 ㅎ ㅎ 알려주십숑

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 그게 제가 이 코멘트 에서 적어놓은 고민해볼 사항 중 하나였습니다. 너무 생각없이 훅으로 짠 것 같아서요. 바꾸는 것 찬성입니다.
그 외에도 모달을 띄우는 건 어떨지, 경로 props로 받기 등 생각해볼 것이 있는 것 같아서 #238 에서 이어서 진행하면 어떨까 싶습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하!! 좋아요좋아요 어푸룹 하겠ㅅ습니다

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 컴포넌트로 작성하는게 좋을 것 같네요!

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Navigate, Outlet } from 'react-router-dom';
import { useRecoilValue } from 'recoil';

import { LogInState } from '@/home/recoil/LogInState';
import { api } from '@/service/TokenService';

import { useResetUserInfo } from './useResetUserInfo';

export const usePrivateRoute = () => {
const isLoggedIn = useRecoilValue(LogInState);
const accessToken = api.getAccessToken();

const resetUserInfo = useResetUserInfo();

const PrivateRoute = (): React.ReactNode => {
if (!isLoggedIn || !accessToken) {
resetUserInfo();
return <Navigate to="/login" />;
}
return <Outlet />;
};

return { PrivateRoute };
};
21 changes: 14 additions & 7 deletions src/router.tsx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

라인 138-139도 로그인 필요한 페이지인데 여기서 껴주실 수 있나요 뒷북 쏘 쏘리

// before
<Route path="register" element={<Register />} />
<Route path="myDrawers" element={<MyDrawer />} />
//after
<Route element={<PrivateRoute />}>
  <Route path="register" element={<Register />} />
  <Route path="myDrawers" element={<MyDrawer />} />
</Route>

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a14fcc3 반영했습니다

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Navigate, Route, Routes } from 'react-router-dom';

import { Fallback } from '@/components/Fallback/Fallback';
import { ProgressBar } from '@/components/ProgressBar/ProgressBar';
import { usePrivateRoute } from '@/hooks/usePrivateRoute';

const Search = lazy(() =>
import('./search/pages/Search/Search').then(({ Search }) => ({
Expand Down Expand Up @@ -112,6 +113,8 @@ export const Router = () => {
};
}, []);

const { PrivateRoute } = usePrivateRoute();

return (
<ErrorBoundary fallbackRender={(fallbackProps) => <Fallback {...fallbackProps} />}>
<Suspense
Expand All @@ -127,17 +130,21 @@ export const Router = () => {
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/signup" element={<Signup />}></Route>
<Route path="/resetpassword" element={<ResetPassword />} />
<Route path="/changePassword" element={<ChangePassword />} />
<Route path="/mypage" element={<Mypage />}></Route>
<Route path="/withdraw" element={<Withdraw />}></Route>
<Route path="/Signup" element={<Signup />}></Route>
<Route element={<PrivateRoute />}>
<Route path="/Mypage" element={<Mypage />}></Route>
<Route path="/changePassword" element={<ChangePassword />}></Route>
<Route path="/withdraw" element={<Withdraw />}></Route>
<Route path="/resetPassword" element={<ResetPassword />}></Route>
</Route>
<Route path="/drawer" element={<DrawerLayout />}>
<Route index element={<Navigate to="rankings" replace />}></Route>
<Route path="services/:serviceId" element={<ServiceDetail />} />
<Route path="rankings" element={<Ranking />} />
<Route path="register" element={<Register />} />
<Route path="myDrawers" element={<MyDrawer />} />
<Route element={<PrivateRoute />}>
<Route path="register" element={<Register />} />
<Route path="myDrawers" element={<MyDrawer />} />
</Route>
<Route path="/drawer/newRelease" element={<NewRelease />} />
<Route path="/drawer/starRanking" element={<StarRanking />} />
<Route path=":providerId" element={<Provider />} />
Expand Down