Skip to content

Commit

Permalink
[FE] feat : 리뷰 연결 페이지에서 비밀번호 조회 api 적용 (#436)
Browse files Browse the repository at this point in the history
* chore: ReviewGroupTestPage 삭제

* fix: PasswordResponse 타입 수정

* refactor: 비밀번호 일치 조회 api 변경에 따른 코드 수정

* chore: PasswordTestPage 삭제

* chore: PasswordModal의 InputContainer 태그 변경 (div-> form) ,button 타입을 submit으로 수정

* style: PasswordModal 스타일 코드 stylelint 적용

* feat : 리뷰 연결 페이지에서 비밀번호 조회 api 적용

* fix:useCheckPasswordValidation의 staleTime 복구

* chore: 비밀번호 조회 endpont 명 변경

* fix: 복수형 상수 네이밍 단수로 수정

- 파일명도 같이 수정
  • Loading branch information
BadaHertz52 authored Aug 19, 2024
1 parent e8027cf commit fa4f70d
Show file tree
Hide file tree
Showing 20 changed files with 104 additions and 147 deletions.
7 changes: 2 additions & 5 deletions frontend/src/apis/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ export const REVIEW_WRITING_API_PARAMS = {
export const REVIEW_PASSWORD_API_PARAMS = {
resource: 'groups',
queryString: {
code: 'code',
reviewRequestCode: 'reviewRequestCode',
check: 'check',
},
};

Expand All @@ -34,7 +33,6 @@ export const REVIEW_GROUP_DATA_API_PARAMS = {
},
};

export const REVIEW_PASSWORD_API_URL = `${process.env.API_BASE_URL}/${VERSION2}/${REVIEW_PASSWORD_API_PARAMS.resource}/${REVIEW_PASSWORD_API_PARAMS.queryString.code}`;
export const REVIEW_GROUP_DATA_API_URL = `${process.env.API_BASE_URL}/${VERSION2}/${REVIEW_GROUP_DATA_API_PARAMS.resource}`;

const endPoint = {
Expand All @@ -44,8 +42,7 @@ const endPoint = {
`${REVIEW_WRITING_API_URL}/${REVIEW_WRITING_API_PARAMS.queryString.write}?${REVIEW_WRITING_API_PARAMS.queryString.reviewRequestCode}=${reviewRequestCode}`,
gettingReviewList: `${process.env.API_BASE_URL}/${VERSION2}/reviews`,
postingDataForReviewRequestCode: `${process.env.API_BASE_URL}/${VERSION2}/groups`,
gettingPasswordValidation: (reviewRequestCode: string) =>
`${REVIEW_PASSWORD_API_URL}?${REVIEW_PASSWORD_API_PARAMS.queryString.reviewRequestCode}=${reviewRequestCode}`,
checkingPassword: `${process.env.API_BASE_URL}/${VERSION2}/${REVIEW_PASSWORD_API_PARAMS.resource}/${REVIEW_PASSWORD_API_PARAMS.queryString.check}`,
gettingReviewGroupData: (reviewRequestCode: string) =>
`${REVIEW_GROUP_DATA_API_URL}?${REVIEW_GROUP_DATA_API_PARAMS.queryString.reviewRequestCode}=${reviewRequestCode}`,
};
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/apis/group.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { json } from 'react-router';

import { INVALID_REVIEW_PASSWORD_MESSAGE } from '@/constants';
import { PasswordResponse, ReviewGroupData } from '@/types';

Expand Down Expand Up @@ -35,16 +37,16 @@ export interface GetPasswordValidationApiParams {
/**
* @param groupAccessCode L 비밀번호
*/
export const getPasswordValidationApi = async ({
export const postPasswordValidationApi = async ({
groupAccessCode,
reviewRequestCode,
}: GetPasswordValidationApiParams) => {
const response = await fetch(endPoint.gettingPasswordValidation(reviewRequestCode), {
method: 'GET',
const response = await fetch(endPoint.checkingPassword, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
GroupAccessCode: groupAccessCode,
},
body: JSON.stringify({ reviewRequestCode, groupAccessCode }),
});
//요청 실패
if (response.status === 401) return new Error(INVALID_REVIEW_PASSWORD_MESSAGE);
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/constants/errorMessage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
interface ApiErrorMessages {
interface ApiErrorMessage {
[key: number]: string;
serverError: string;
}

export const API_ERROR_MESSAGE: ApiErrorMessages = {
export const API_ERROR_MESSAGE: ApiErrorMessage = {
400: '잘못된 요청이에요.',
401: '인증을 실패했어요.',
403: '요청권한이 없어요.',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * from './page';
export * from './errorMessage';
export * from './review';
export * from './queryKeys';
export * from './queryKey';
export * from './system';
export * from './routerParam';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO: 내용이 배열이 아니므로 단수형으로 수정하기
export const REVIEW_QUERY_KEYS = {
export const REVIEW_QUERY_KEY = {
detailedReview: 'detailedReview',
reviews: 'reviews',
writingReviewInfo: 'writingReviewInfo',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO: ROUTES -> ROUTE 및 상수 인덱스에 추가하기
export const ROUTES = {
// TODO: ROUTE -> ROUTE 및 상수 인덱스에 추가하기
export const ROUTE = {
home: '/',
reviewList: 'user/review-list',
reviewWriting: 'user/review-writing',
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/hooks/review/useGetDetailedReview/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useSuspenseQuery } from '@tanstack/react-query';

import { getDetailedReviewApi } from '@/apis/review';
import { REVIEW_QUERY_KEYS } from '@/constants';
import { REVIEW_QUERY_KEY } from '@/constants';
import { DetailReviewData } from '@/types';

interface UseGetDetailedReviewProps {
Expand All @@ -21,7 +21,7 @@ const useGetDetailedReview = ({ reviewId, groupAccessCode }: UseGetDetailedRevie
};

const result = useSuspenseQuery<DetailReviewData>({
queryKey: [REVIEW_QUERY_KEYS.detailedReview, reviewId],
queryKey: [REVIEW_QUERY_KEY.detailedReview, reviewId],
queryFn: () => fetchDetailedReview({ reviewId, groupAccessCode }),
});

Expand Down
6 changes: 3 additions & 3 deletions frontend/src/hooks/review/useGetReviewList/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { useSuspenseQuery } from '@tanstack/react-query';

import { getReviewListApi } from '@/apis/review';
import { REVIEW_QUERY_KEYS } from '@/constants';
import { REVIEW_QUERY_KEY } from '@/constants';

const useGetReviewList = (groupAccessCode: string) => {
const { data, isLoading, error, isSuccess } = useSuspenseQuery({
queryKey: [REVIEW_QUERY_KEYS.reviews],
queryKey: [REVIEW_QUERY_KEY.reviews],
queryFn: () => getReviewListApi(groupAccessCode),
});

// NOTE: 무한스크롤 관련 코드 일단 주석 처리
// const { data, fetchNextPage, hasNextPage, isLoading, error } = useInfiniteQuery({
// queryKey: [REVIEW_QUERY_KEYS.reviews],
// queryKey: [REVIEW_QUERY_KEY.reviews],
// queryFn: ({ pageParam }) => getReviewListApi(pageParam),
// initialPageParam: GROUP_ACCESS_CODE,
// getNextPageParam: (data) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useSuspenseQuery } from '@tanstack/react-query';

import { getDataToWriteReviewApi } from '@/apis/review';
import { REVIEW_QUERY_KEYS } from '@/constants';
import { REVIEW_QUERY_KEY } from '@/constants';
import { ReviewWritingFrom } from '@/types';

interface UseGetDataToWriteProps {
Expand All @@ -16,7 +16,7 @@ const useGetDataToWrite = ({ reviewRequestCode }: UseGetDataToWriteProps) => {
};

const result = useSuspenseQuery<ReviewWritingFrom>({
queryKey: [REVIEW_QUERY_KEYS.writingReviewInfo, reviewRequestCode],
queryKey: [REVIEW_QUERY_KEY.writingReviewInfo, reviewRequestCode],
queryFn: () => fetchReviewFormData(reviewRequestCode),
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';

import { postReviewApi } from '@/apis/review';
import { REVIEW_QUERY_KEYS } from '@/constants';
import { REVIEW_QUERY_KEY } from '@/constants';
import { ReviewWritingFormResult } from '@/types';

interface UseMutateReviewProps {
Expand All @@ -13,7 +13,7 @@ const useMutateReview = ({ executeAfterMutateSuccess }: UseMutateReviewProps) =>
const reviewMutation = useMutation({
mutationFn: (formResult: ReviewWritingFormResult) => postReviewApi(formResult),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [REVIEW_QUERY_KEYS.postReview] });
queryClient.invalidateQueries({ queryKey: [REVIEW_QUERY_KEY.postReview] });
executeAfterMutateSuccess();
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useQuery } from '@tanstack/react-query';
import { useEffect } from 'react';

import { getPasswordValidationApi, GetPasswordValidationApiParams } from '@/apis/group';
import { postPasswordValidationApi, GetPasswordValidationApiParams } from '@/apis/group';
import { GROUP_QUERY_KEY, INVALID_REVIEW_PASSWORD_MESSAGE } from '@/constants';
import { PasswordResponse } from '@/types';

Expand All @@ -22,16 +22,15 @@ const useCheckPasswordValidation = ({
onError,
}: UseCheckPasswordValidationProps) => {
const fetchPasswordValidation = async (params: GetPasswordValidationApiParams) => {
const result = await getPasswordValidationApi(params);

const result = await postPasswordValidationApi(params);
return result;
};

const result = useQuery<PasswordResponse | Error>({
queryKey: [GROUP_QUERY_KEY.password, groupAccessCode, reviewRequestCode],
queryFn: () => fetchPasswordValidation({ groupAccessCode, reviewRequestCode }),
staleTime: 1000 * 60 * 5,
enabled: !!groupAccessCode && !!reviewRequestCode,
staleTime: 1000 * 60 * 5,
});

/**
Expand All @@ -49,7 +48,7 @@ const useCheckPasswordValidation = ({
// case2 요청 성공
// data 속 비밀번호 유효성 여부에 따른 액션
// 2-1 유효하지 않은 비밀번호
if (!data?.isValidAccess) {
if (!data?.hasAccess) {
return onError(new Error(INVALID_REVIEW_PASSWORD_MESSAGE));
}
// 2-2 유효한 비밀번호
Expand Down
14 changes: 7 additions & 7 deletions frontend/src/hooks/useBreadcrumbPaths.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import { useLocation } from 'react-router-dom';

import { Path } from '@/components/common/Breadcrumb';
import { ROUTES } from '@/constants/routes';
import { ROUTE } from '@/constants/route';

const useBreadcrumbPaths = () => {
const { pathname } = useLocation();

const breadcrumbPathList: Path[] = [
{ pageName: '연결 페이지', path: ROUTES.home }, // TODO: 연결 페이지 경로 결정되면 수정 필요
{ pageName: '연결 페이지', path: ROUTE.home }, // TODO: 연결 페이지 경로 결정되면 수정 필요
];

if (pathname === `/${ROUTES.reviewList}`) {
if (pathname === `/${ROUTE.reviewList}`) {
breadcrumbPathList.push({ pageName: '목록 페이지', path: pathname });
}

if (pathname.includes(`/${ROUTES.reviewWriting}/`)) {
if (pathname.includes(`/${ROUTE.reviewWriting}/`)) {
breadcrumbPathList.push({ pageName: '작성 페이지', path: pathname });
}

if (pathname === `/${ROUTES.reviewWritingComplete}`) {
if (pathname === `/${ROUTE.reviewWritingComplete}`) {
breadcrumbPathList.push({ pageName: '작성 페이지', path: -1 }, { pageName: '작성 완료 페이지', path: pathname });
}

if (pathname.includes(ROUTES.detailedReview)) {
if (pathname.includes(ROUTE.detailedReview)) {
breadcrumbPathList.push(
{ pageName: '목록 페이지', path: ROUTES.reviewList },
{ pageName: '목록 페이지', path: ROUTE.reviewList },
{ pageName: '상세 페이지', path: pathname },
);
}
Expand Down
19 changes: 7 additions & 12 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ import {

import { ErrorSuspenseContainer } from './components';
import { DEV_ENVIRONMENT, ROUTE_PARAM } from './constants';
import { ROUTES } from './constants/routes';
import PasswordTestPage from './pages/PasswordTestPage';
import { ROUTE } from './constants/route';
import globalStyles from './styles/globalStyles';
import theme from './styles/theme';

Expand Down Expand Up @@ -50,7 +49,7 @@ const queryClient = new QueryClient({

const router = createBrowserRouter([
{
path: ROUTES.home,
path: ROUTE.home,
element: <App />,
errorElement: <ErrorPage />,
children: [
Expand All @@ -62,22 +61,18 @@ const router = createBrowserRouter([
path: 'user',
element: <div>user</div>,
},
{ path: `${ROUTES.reviewWriting}/:${ROUTE_PARAM.reviewRequestCode}`, element: <ReviewWritingCardFormPage /> },
{ path: ROUTES.reviewWritingComplete, element: <ReviewWritingCompletePage /> },
{ path: `${ROUTE.reviewWriting}/:${ROUTE_PARAM.reviewRequestCode}`, element: <ReviewWritingCardFormPage /> },
{ path: ROUTE.reviewWritingComplete, element: <ReviewWritingCompletePage /> },
{
path: ROUTES.reviewList,
path: ROUTE.reviewList,
element: <ReviewListPage />,
},
{
path: `${ROUTES.detailedReview}/:${ROUTE_PARAM.reviewId}`,
path: `${ROUTE.detailedReview}/:${ROUTE_PARAM.reviewId}`,
element: <DetailedReviewPage />,
},
{
path: 'password-check/:reviewRequestCode',
element: <PasswordTestPage />,
},
{
path: `${ROUTES.reviewZone}/:${ROUTE_PARAM.reviewRequestCode}`, // NOTE: 임시 경로, 추후 논의 및 상수화 필요
path: `${ROUTE.reviewZone}/:${ROUTE_PARAM.reviewRequestCode}`,
element: (
<ErrorSuspenseContainer>
<ReviewZonePage />
Expand Down
34 changes: 16 additions & 18 deletions frontend/src/mocks/handlers/group.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { http, HttpResponse } from 'msw';

import endPoint, {
REVIEW_GROUP_DATA_API_PARAMS,
REVIEW_GROUP_DATA_API_URL,
REVIEW_PASSWORD_API_PARAMS,
REVIEW_PASSWORD_API_URL,
} from '@/apis/endpoints';
import endPoint, { REVIEW_GROUP_DATA_API_PARAMS, REVIEW_GROUP_DATA_API_URL } from '@/apis/endpoints';
import { API_ERROR_MESSAGE } from '@/constants';
import { PasswordResponse } from '@/types';

Expand All @@ -30,22 +25,25 @@ const postDataForReviewRequestCode = () => {
// });
// };

const getPassWordValidation = () => {
return http.get(new RegExp(`^${REVIEW_PASSWORD_API_URL}`), async ({ request }) => {
const url = new URL(request.url);
const params = new URLSearchParams(url.search);
const { queryString } = REVIEW_PASSWORD_API_PARAMS;
// 가로채는 요청 url이 맞는 지 확인(reviewRequestCode 쿼리 키가 있어야함)
if (!params.has(queryString.reviewRequestCode)) return;
const postPassWordValidation = () => {
return http.post(endPoint.checkingPassword, async ({ request }) => {
// password가 있는 경우
if (!request.body) return HttpResponse.json({ error: API_ERROR_MESSAGE[400] }, { status: 400 });

const rawBody = await request.body.getReader().read();
const textDecoder = new TextDecoder();
const bodyText = textDecoder.decode(rawBody.value);

// password가 유효한 패스워드인지 확인
const password = request.headers.get('GroupAccessCode');
const { reviewRequestCode, groupAccessCode: password } = JSON.parse(bodyText);

// reviewRequestCode가 없는 경우
//password가 없을 경우
if (!password) return HttpResponse.json({ error: API_ERROR_MESSAGE[400] }, { status: 400 });

if (!password || !reviewRequestCode) return HttpResponse.json({ error: API_ERROR_MESSAGE[400] }, { status: 400 });
// password가 있는 경우

const response: PasswordResponse = {
isValidAccess: password === VALIDATED_PASSWORD,
hasAccess: password === VALIDATED_PASSWORD,
};

return HttpResponse.json(response, { status: 200 });
Expand Down Expand Up @@ -74,6 +72,6 @@ const getReviewGroupData = () => {
return HttpResponse.json({ error: '잘못된 리뷰 그룹 데이터 요청' }, { status: 404 });
});
};
const groupHandler = [postDataForReviewRequestCode(), getReviewGroupData(), getPassWordValidation()];
const groupHandler = [postDataForReviewRequestCode(), getReviewGroupData(), postPassWordValidation()];

export default groupHandler;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';

import { DataForReviewRequestCode } from '@/apis/group';
import { Button, Input, EyeButton } from '@/components';
import { ROUTES } from '@/constants/routes';
import { ROUTE } from '@/constants/route';
import { useEyeButton } from '@/hooks';
import useModals from '@/hooks/useModals';
import { debounce } from '@/utils/debounce';
Expand Down Expand Up @@ -74,7 +74,7 @@ const URLGeneratorForm = () => {
};

const getCompleteReviewZoneURL = (reviewRequestCode: string) => {
return `${window.location.origin}/${ROUTES.reviewZone}/${reviewRequestCode}`;
return `${window.location.origin}/${ROUTE.reviewZone}/${reviewRequestCode}`;
};

const handleNameInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
Expand Down
Loading

0 comments on commit fa4f70d

Please sign in to comment.