From 50425351d9b6287fcd26b768040c69245e158c51 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Sat, 24 Aug 2024 03:24:41 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20api=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=AC=B4?= =?UTF-8?q?=ED=95=9C=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/review.model.ts | 44 ++++++++++++++++++++++++ src/store/api/review/index.ts | 63 +++++++++++++++++++++++++++++++++++ src/store/index.ts | 2 ++ 3 files changed, 109 insertions(+) create mode 100644 src/model/review.model.ts create mode 100644 src/store/api/review/index.ts diff --git a/src/model/review.model.ts b/src/model/review.model.ts new file mode 100644 index 0000000..6a83a30 --- /dev/null +++ b/src/model/review.model.ts @@ -0,0 +1,44 @@ +export interface ReviewListResponse { + total_count: number, + current_count: number, + current_page: number, + reviews: ReviewContent[] +} + +export interface ReviewContent { + reviewId: number, + rating: number, + nickName: string, + content: string, + imageUrls: string[], + menuNames: string[], + isModified: boolean, + isHaveUnhandledReport: boolean, + createdAt: string, + reports: ReportedReviewContent[] + shop: { + shopId: number, + shopName: string, + } +} + +export interface ReportedReviewContent { + reportId: number, + title: string, + content: string, + nickName: string, + status: string, +} + +export interface GetReviewListParam { + page: number; + limit: number; + isReported: boolean; +} + +export interface SetReviewParam { + id: number; + body: { + report_status: string + } +} diff --git a/src/store/api/review/index.ts b/src/store/api/review/index.ts new file mode 100644 index 0000000..8dd75d8 --- /dev/null +++ b/src/store/api/review/index.ts @@ -0,0 +1,63 @@ +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; +import { API_PATH } from 'constant'; +import { GetReviewListParam, ReviewListResponse, SetReviewParam } from 'model/review.model'; +import { RootState } from 'store'; + +export const reviewApi = createApi({ + reducerPath: 'reviews', + tagTypes: ['reviews'], + + baseQuery: fetchBaseQuery({ + baseUrl: `${API_PATH}`, + prepareHeaders: (headers, { getState }) => { + const { token } = (getState() as RootState).auth; + if (token) { + headers.set('authorization', `Bearer ${token}`); + } + return headers; + }, + }), + + endpoints: (builder) => ({ + getReviewList: builder.query({ + query: ({ page, limit, isReported }) => ({ url: `admin/shops/reviews?page=${page}&limit=${limit}&${isReported ? 'is_reported=true' : ''}` }), + providesTags: () => [{ type: 'reviews' }], + serializeQueryArgs: ({ queryArgs }) => { + return `${queryArgs.isReported}`; // 캐시 키를 `isReported` 값을 포함하도록 수정 + }, + merge: (cached, newItem, { arg }) => { + if (arg.page === 1) return newItem; + cached.reviews.push(...newItem.reviews); + return cached; + }, + forceRefetch({ currentArg, previousArg }) { + return currentArg?.page !== previousArg?.page; + }, + }), + + setReviewDismissed: builder.mutation({ + query({ id, body }) { + return { + url: `admin/shops/reviews/${id}`, + method: 'put', + body, + }; + }, + invalidatesTags: [{ type: 'reviews' }], + }), + + deleteReview: builder.mutation({ + query(id) { + return { + url: `/admin/shops/reviews/${id}`, + method: 'delete', + }; + }, + invalidatesTags: [{ type: 'reviews' }], + }), + }), +}); + +export const { + useGetReviewListQuery, useSetReviewDismissedMutation, useDeleteReviewMutation, +} = reviewApi; diff --git a/src/store/index.ts b/src/store/index.ts index 45fff46..b79bf7f 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -11,6 +11,7 @@ import { storeMenuApi } from './api/storeMenu'; import { menuCategoriesApi } from './api/storeMenu/category'; import { ownerRequestApi } from './api/ownerRequest'; import { ownerApi } from './api/owner'; +import { reviewApi } from './api/review'; const apiList = [ authApi, @@ -24,6 +25,7 @@ const apiList = [ menuCategoriesApi, ownerRequestApi, ownerApi, + reviewApi, ]; const apiMiddleware = apiList.map((api) => api.middleware); From 6a1a96c0492ae99fd7b61fef6289e7c465e9ff14 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Sat, 24 Aug 2024 03:24:55 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=ED=83=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/SideNav/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/common/SideNav/index.tsx b/src/components/common/SideNav/index.tsx index e7aeada..293af77 100644 --- a/src/components/common/SideNav/index.tsx +++ b/src/components/common/SideNav/index.tsx @@ -2,7 +2,7 @@ import { AppstoreOutlined, UserOutlined, CarOutlined, ShopOutlined, HomeOutlined, UserSwitchOutlined, UsergroupDeleteOutlined, FolderOpenOutlined, ControlOutlined, - UserAddOutlined, BoldOutlined, + UserAddOutlined, BoldOutlined, SnippetsOutlined, } from '@ant-design/icons'; import { Menu, MenuProps } from 'antd'; import { Link, useLocation, useNavigate } from 'react-router-dom'; @@ -31,6 +31,7 @@ const items: MenuProps['items'] = [ getItem('주변상점', 'service-store', , [ getItem('상점 관리', '/store', ), getItem('카테고리', '/category', ), + getItem('리뷰 관리', '/review', ), ]), getItem('버스 정보', '/bus', ), getItem('복덕방', '/room', ), From 2c720e7bd7de590f86b2b38ed16c9db00e0cbc79 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Sat, 24 Aug 2024 03:25:10 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 2 + .../Services/Review/ReviewCard.style.tsx | 61 ++++++ src/pages/Services/Review/ReviewCard.tsx | 189 ++++++++++++++++++ .../Services/Review/ReviewList.style.tsx | 24 +++ src/pages/Services/Review/ReviewList.tsx | 69 +++++++ 5 files changed, 345 insertions(+) create mode 100644 src/pages/Services/Review/ReviewCard.style.tsx create mode 100644 src/pages/Services/Review/ReviewCard.tsx create mode 100644 src/pages/Services/Review/ReviewList.style.tsx create mode 100644 src/pages/Services/Review/ReviewList.tsx diff --git a/src/App.tsx b/src/App.tsx index 46ec20f..26f5c5c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -19,6 +19,7 @@ import OwnerList from 'pages/UserManage/Owner/OwnerList'; import OwnerRequestList from 'pages/UserManage/OwnerRequest/OwnerRequestList'; import OwnerRequestDetail from 'pages/UserManage/OwnerRequest/OwnerRequestDetail'; import OwnerDetail from 'pages/UserManage/Owner/OwnerDetail'; +import ReviewList from 'pages/Services/Review/ReviewList'; function RequireAuth() { const location = useLocation(); @@ -56,6 +57,7 @@ function App() { } /> } /> } /> + } /> 404} /> diff --git a/src/pages/Services/Review/ReviewCard.style.tsx b/src/pages/Services/Review/ReviewCard.style.tsx new file mode 100644 index 0000000..9722405 --- /dev/null +++ b/src/pages/Services/Review/ReviewCard.style.tsx @@ -0,0 +1,61 @@ +import styled from 'styled-components'; + +export const Shortcut = styled.a` + color: '#cacaca'; + text-decoration: none; +`; + +export const Container = styled.div<{ $isHandle: boolean }>` + display: flex; + flex-direction: column; + padding: 10px 15px; + background: ${(props) => (props.$isHandle ? '#ff000050' : '#00BFFF10')}; + border-radius: 10px; + transition: scale 0.3s, height 0.3s; + width: 100%; + gap: 10px; + + &:hover { + scale: 1.015; + } +`; + +export const Row = styled.div` + display: flex; + align-items: center; + justify-content: space-between; +`; + +export const RowItem = styled.div` + display: flex; + align-items: center; + gap: 20px; +`; + +export const Item = styled.div` + width: 150px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; + +export const ToggleButton = styled.button` + background: transparent; + border: none; + cursor: pointer; + height: 30px; +`; + +export const MenuImage = styled.img` + width: 250px; + height: 250px; + object-fit: cover; + border-radius: 10px; +`; + +export const AroundRow = styled.div` + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; +`; diff --git a/src/pages/Services/Review/ReviewCard.tsx b/src/pages/Services/Review/ReviewCard.tsx new file mode 100644 index 0000000..7e239cd --- /dev/null +++ b/src/pages/Services/Review/ReviewCard.tsx @@ -0,0 +1,189 @@ +import { ReviewContent } from 'model/review.model'; +import { Button, message, Modal } from 'antd'; +import { useState } from 'react'; +import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons'; +import { useDeleteReviewMutation, useSetReviewDismissedMutation } from 'store/api/review'; +import * as S from './ReviewCard.style'; + +interface Props { + review: ReviewContent +} + +const KOIN_URL = process.env.REACT_APP_API_PATH?.includes('stage') ? 'https://stage.koreatech.in' : 'https://koreatech.in'; + +export default function ReviewCard({ review }: Props) { + const [isOpen, setIsOpen] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); + const [isReportOpen, setIsReportOpen] = useState(false); + const toggle = () => { + setIsOpen((prev) => !prev); + }; + + const [deleteReview, { + isLoading: isDeleteLoading, + isError: isDeleteError, + }] = useDeleteReviewMutation(); + const [dismissReview, { + isLoading: isDismissLoading, + isError: isDismissError, + }] = useSetReviewDismissedMutation(); + + if (isDeleteError) { + message.error('리뷰 삭제에 실패했습니다'); + } + if (isDismissError) { + message.error('리뷰 상태 변경에 실패했습니다.'); + } + + const deleteSpecificReview = () => { + deleteReview(review.reviewId); + }; + + const dismissSpecificReview = () => { + dismissReview({ + id: review.reviewId, + body: { + report_status: 'DISMISSED', + }, + }); + }; + + return ( + + + + + {review.shop.shopName} + + + {review.createdAt} + + + + + 식당 페이지 바로가기 + + + + + + + + + + 별점: + {' '} + {review.rating} + + {!isOpen && ( + + {review.content} + + )} + + + {isOpen && ( + <> + +
+ 리뷰 내용: + {' '} + {review.content} +
+
+ +
+ 사진: + {' '} + {review.imageUrls.length > 0 ? review.imageUrls.map((image) => ( + + )) : '없음'} +
+
+ +
+ 이용 메뉴: + {' '} + {review.menuNames.length > 0 ? review.menuNames.map((menu) =>
{menu}
) : '미기재'} +
+
+ +
+ 수정이력: + {' '} + {review.isModified ? 'O' : 'X'} +
+
+ + + {review.isHaveUnhandledReport ? '신고정보' : '신고이력'} + + + {review.reports.length > 0 + ? ( + + + + + {review.isHaveUnhandledReport + && ( + + + + )} + + + ) : '없음'} + + )} + + {isOpen ? : } + + setIsModalOpen(false)}> + + 정말로 삭제하시겠습니까? + + + + + + + setIsReportOpen(false)} footer={null}> + {review.reports.map((report, idx) => ( + + {idx + 1} + . + {' '} + {report.content} + + ))} + +
+ ); +} diff --git a/src/pages/Services/Review/ReviewList.style.tsx b/src/pages/Services/Review/ReviewList.style.tsx new file mode 100644 index 0000000..9b067da --- /dev/null +++ b/src/pages/Services/Review/ReviewList.style.tsx @@ -0,0 +1,24 @@ +import styled from 'styled-components'; + +export const Container = styled.div` + height: 100vh; + min-width: 1000px; + display: flex; + flex-direction: column; + box-sizing: border-box; + gap: 30px; +`; + +export const Filter = styled.div` + display: flex; + align-items: center; + gap: 15px; +`; + +export const DataContainer = styled.div` + display: flex; + align-items: center; + flex-direction: column; + gap: 15px; + width: 100%; +`; diff --git a/src/pages/Services/Review/ReviewList.tsx b/src/pages/Services/Review/ReviewList.tsx new file mode 100644 index 0000000..f86266f --- /dev/null +++ b/src/pages/Services/Review/ReviewList.tsx @@ -0,0 +1,69 @@ +import { Checkbox, Skeleton } from 'antd'; +import { + useEffect, useRef, useState, +} from 'react'; +import { useGetReviewListQuery } from 'store/api/review'; +import * as Common from 'styles/List.style'; +import ReviewCard from './ReviewCard'; +import * as S from './ReviewList.style'; + +const LIMIT = 10; + +export default function ReviewList() { + const [page, setPage] = useState(1); + const [isReported, setIsReported] = useState(false); + const { + data, isLoading, isFetching, + } = useGetReviewListQuery({ page, limit: LIMIT, isReported }); + const endOfPage = useRef(null); + + const filterReportedReview = () => { + setIsReported((prev) => !prev); + setPage(1); + }; + + useEffect(() => { + const getNextPage = (entries: IntersectionObserverEntry[]) => { + if (entries[0].isIntersecting + && data && data.total_count > LIMIT * page + && !isLoading && !isFetching) { + setPage((prev) => prev + 1); + } + }; + + const observer = new IntersectionObserver(getNextPage); + + if (endOfPage.current) { + observer.observe(endOfPage.current); + } + + return () => { + observer.disconnect(); + }; + }, [data, isLoading, page, isFetching]); + + return ( + + + 리뷰 목록 + + {isLoading ? [1, 2, 3, 4, 5].map((key) => ) : ( + <> + + + 신고된 리뷰만 모아보기 + + + {data && data.reviews.map((review) => ( + + ))} +
+ + + )} + + ); +} From ce57269b95407dc9a252e1493a06d2c701665c1b Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Sat, 24 Aug 2024 03:35:15 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=EB=A7=A8=20=EC=9C=84=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=20=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Services/Review/ReviewList.style.tsx | 9 +++++++++ src/pages/Services/Review/ReviewList.tsx | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/pages/Services/Review/ReviewList.style.tsx b/src/pages/Services/Review/ReviewList.style.tsx index 9b067da..5cb0689 100644 --- a/src/pages/Services/Review/ReviewList.style.tsx +++ b/src/pages/Services/Review/ReviewList.style.tsx @@ -7,6 +7,7 @@ export const Container = styled.div` flex-direction: column; box-sizing: border-box; gap: 30px; + position: relative; `; export const Filter = styled.div` @@ -22,3 +23,11 @@ export const DataContainer = styled.div` gap: 15px; width: 100%; `; + +export const RightDownButton = styled.div` + position: fixed; + bottom: 100px; + right: 100px; + font-size: 40px; + cursor: pointer; +`; diff --git a/src/pages/Services/Review/ReviewList.tsx b/src/pages/Services/Review/ReviewList.tsx index f86266f..8d10290 100644 --- a/src/pages/Services/Review/ReviewList.tsx +++ b/src/pages/Services/Review/ReviewList.tsx @@ -4,6 +4,7 @@ import { } from 'react'; import { useGetReviewListQuery } from 'store/api/review'; import * as Common from 'styles/List.style'; +import { UpCircleOutlined } from '@ant-design/icons'; import ReviewCard from './ReviewCard'; import * as S from './ReviewList.style'; @@ -17,6 +18,10 @@ export default function ReviewList() { } = useGetReviewListQuery({ page, limit: LIMIT, isReported }); const endOfPage = useRef(null); + const scrollUp = () => { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }; + const filterReportedReview = () => { setIsReported((prev) => !prev); setPage(1); @@ -64,6 +69,9 @@ export default function ReviewList() { )} + + + ); } From fbb73fd0750615646c1726dc10befd44abf4238f Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Sun, 25 Aug 2024 19:27:30 +0900 Subject: [PATCH 5/9] =?UTF-8?q?refactor:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EC=85=98=EC=9C=BC=EB=A1=9C=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/Review/ReviewCard.style.tsx | 4 -- src/pages/Services/Review/ReviewCard.tsx | 10 +++-- src/pages/Services/Review/ReviewList.tsx | 38 ++++++------------- src/store/api/review/index.ts | 19 ++-------- 4 files changed, 22 insertions(+), 49 deletions(-) diff --git a/src/pages/Services/Review/ReviewCard.style.tsx b/src/pages/Services/Review/ReviewCard.style.tsx index 9722405..5ae1dcf 100644 --- a/src/pages/Services/Review/ReviewCard.style.tsx +++ b/src/pages/Services/Review/ReviewCard.style.tsx @@ -14,10 +14,6 @@ export const Container = styled.div<{ $isHandle: boolean }>` transition: scale 0.3s, height 0.3s; width: 100%; gap: 10px; - - &:hover { - scale: 1.015; - } `; export const Row = styled.div` diff --git a/src/pages/Services/Review/ReviewCard.tsx b/src/pages/Services/Review/ReviewCard.tsx index 7e239cd..8783474 100644 --- a/src/pages/Services/Review/ReviewCard.tsx +++ b/src/pages/Services/Review/ReviewCard.tsx @@ -6,12 +6,13 @@ import { useDeleteReviewMutation, useSetReviewDismissedMutation } from 'store/ap import * as S from './ReviewCard.style'; interface Props { - review: ReviewContent + review: ReviewContent; + currentPage: number; } const KOIN_URL = process.env.REACT_APP_API_PATH?.includes('stage') ? 'https://stage.koreatech.in' : 'https://koreatech.in'; -export default function ReviewCard({ review }: Props) { +export default function ReviewCard({ review, currentPage }: Props) { const [isOpen, setIsOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false); const [isReportOpen, setIsReportOpen] = useState(false); @@ -36,7 +37,10 @@ export default function ReviewCard({ review }: Props) { } const deleteSpecificReview = () => { - deleteReview(review.reviewId); + deleteReview({ + id: review.reviewId, + page: currentPage, + }); }; const dismissSpecificReview = () => { diff --git a/src/pages/Services/Review/ReviewList.tsx b/src/pages/Services/Review/ReviewList.tsx index 8d10290..85ee96b 100644 --- a/src/pages/Services/Review/ReviewList.tsx +++ b/src/pages/Services/Review/ReviewList.tsx @@ -1,7 +1,5 @@ -import { Checkbox, Skeleton } from 'antd'; -import { - useEffect, useRef, useState, -} from 'react'; +import { Checkbox, Skeleton, Pagination } from 'antd'; +import { useState } from 'react'; import { useGetReviewListQuery } from 'store/api/review'; import * as Common from 'styles/List.style'; import { UpCircleOutlined } from '@ant-design/icons'; @@ -14,9 +12,8 @@ export default function ReviewList() { const [page, setPage] = useState(1); const [isReported, setIsReported] = useState(false); const { - data, isLoading, isFetching, + data, isLoading, } = useGetReviewListQuery({ page, limit: LIMIT, isReported }); - const endOfPage = useRef(null); const scrollUp = () => { window.scrollTo({ top: 0, behavior: 'smooth' }); @@ -27,26 +24,6 @@ export default function ReviewList() { setPage(1); }; - useEffect(() => { - const getNextPage = (entries: IntersectionObserverEntry[]) => { - if (entries[0].isIntersecting - && data && data.total_count > LIMIT * page - && !isLoading && !isFetching) { - setPage((prev) => prev + 1); - } - }; - - const observer = new IntersectionObserver(getNextPage); - - if (endOfPage.current) { - observer.observe(endOfPage.current); - } - - return () => { - observer.disconnect(); - }; - }, [data, isLoading, page, isFetching]); - return ( @@ -63,9 +40,16 @@ export default function ReviewList() { ))} -
+ {data && ( + setPage(num)} + /> + )} )} diff --git a/src/store/api/review/index.ts b/src/store/api/review/index.ts index 8dd75d8..9fc2d4d 100644 --- a/src/store/api/review/index.ts +++ b/src/store/api/review/index.ts @@ -21,18 +21,7 @@ export const reviewApi = createApi({ endpoints: (builder) => ({ getReviewList: builder.query({ query: ({ page, limit, isReported }) => ({ url: `admin/shops/reviews?page=${page}&limit=${limit}&${isReported ? 'is_reported=true' : ''}` }), - providesTags: () => [{ type: 'reviews' }], - serializeQueryArgs: ({ queryArgs }) => { - return `${queryArgs.isReported}`; // 캐시 키를 `isReported` 값을 포함하도록 수정 - }, - merge: (cached, newItem, { arg }) => { - if (arg.page === 1) return newItem; - cached.reviews.push(...newItem.reviews); - return cached; - }, - forceRefetch({ currentArg, previousArg }) { - return currentArg?.page !== previousArg?.page; - }, + providesTags: (result, error, { page }) => [{ type: 'reviews', id: page }], }), setReviewDismissed: builder.mutation({ @@ -46,14 +35,14 @@ export const reviewApi = createApi({ invalidatesTags: [{ type: 'reviews' }], }), - deleteReview: builder.mutation({ - query(id) { + deleteReview: builder.mutation({ + query({ id }) { return { url: `/admin/shops/reviews/${id}`, method: 'delete', }; }, - invalidatesTags: [{ type: 'reviews' }], + invalidatesTags: (result, error, { page }) => [{ type: 'reviews', id: page }], }), }), }); From dd2ac3a43361c211e2c37e049b3a7d191259726d Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Sun, 25 Aug 2024 19:53:23 +0900 Subject: [PATCH 6/9] =?UTF-8?q?refactor:=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=A1=B0=EC=A0=95=20=EB=B0=8F=20=EA=B0=92=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/model/review.model.ts | 1 + src/pages/Services/Review/ReviewCard.tsx | 1 + src/pages/Services/Review/ReviewList.style.tsx | 1 + src/pages/Services/Review/ReviewList.tsx | 12 +++++++----- src/store/api/review/index.ts | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/model/review.model.ts b/src/model/review.model.ts index 6a83a30..91ec205 100644 --- a/src/model/review.model.ts +++ b/src/model/review.model.ts @@ -38,6 +38,7 @@ export interface GetReviewListParam { export interface SetReviewParam { id: number; + page: number; body: { report_status: string } diff --git a/src/pages/Services/Review/ReviewCard.tsx b/src/pages/Services/Review/ReviewCard.tsx index 8783474..a5a6206 100644 --- a/src/pages/Services/Review/ReviewCard.tsx +++ b/src/pages/Services/Review/ReviewCard.tsx @@ -46,6 +46,7 @@ export default function ReviewCard({ review, currentPage }: Props) { const dismissSpecificReview = () => { dismissReview({ id: review.reviewId, + page: currentPage, body: { report_status: 'DISMISSED', }, diff --git a/src/pages/Services/Review/ReviewList.style.tsx b/src/pages/Services/Review/ReviewList.style.tsx index 5cb0689..777ee53 100644 --- a/src/pages/Services/Review/ReviewList.style.tsx +++ b/src/pages/Services/Review/ReviewList.style.tsx @@ -22,6 +22,7 @@ export const DataContainer = styled.div` flex-direction: column; gap: 15px; width: 100%; + margin-bottom: 30px; `; export const RightDownButton = styled.div` diff --git a/src/pages/Services/Review/ReviewList.tsx b/src/pages/Services/Review/ReviewList.tsx index 85ee96b..ce8d533 100644 --- a/src/pages/Services/Review/ReviewList.tsx +++ b/src/pages/Services/Review/ReviewList.tsx @@ -44,11 +44,13 @@ export default function ReviewList() { /> ))} {data && ( - setPage(num)} - /> + + setPage(num)} + /> + )} diff --git a/src/store/api/review/index.ts b/src/store/api/review/index.ts index 9fc2d4d..f35d379 100644 --- a/src/store/api/review/index.ts +++ b/src/store/api/review/index.ts @@ -32,7 +32,7 @@ export const reviewApi = createApi({ body, }; }, - invalidatesTags: [{ type: 'reviews' }], + invalidatesTags: (result, error, { page }) => [{ type: 'reviews', id: page }], }), deleteReview: builder.mutation({ From 443092af32c82f9043f46534ff9759b8bffaccb2 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Mon, 26 Aug 2024 17:16:14 +0900 Subject: [PATCH 7/9] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EC=97=85=20=EB=B2=84=ED=8A=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/ScrollUpButton/ScrollUpButton.tsx | 22 +++++++++++++++++++ src/pages/Services/Review/ReviewList.tsx | 12 +++------- 2 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/components/common/ScrollUpButton/ScrollUpButton.tsx diff --git a/src/components/common/ScrollUpButton/ScrollUpButton.tsx b/src/components/common/ScrollUpButton/ScrollUpButton.tsx new file mode 100644 index 0000000..487ed84 --- /dev/null +++ b/src/components/common/ScrollUpButton/ScrollUpButton.tsx @@ -0,0 +1,22 @@ +import { UpCircleOutlined } from '@ant-design/icons'; +import styled from 'styled-components'; + +const RightDownButton = styled.div` + position: fixed; + bottom: 100px; + right: 100px; + font-size: 40px; + cursor: pointer; +`; + +export default function ScrollUpButton() { + const scrollUp = () => { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }; + + return ( + + + + ); +} diff --git a/src/pages/Services/Review/ReviewList.tsx b/src/pages/Services/Review/ReviewList.tsx index ce8d533..9005387 100644 --- a/src/pages/Services/Review/ReviewList.tsx +++ b/src/pages/Services/Review/ReviewList.tsx @@ -2,7 +2,7 @@ import { Checkbox, Skeleton, Pagination } from 'antd'; import { useState } from 'react'; import { useGetReviewListQuery } from 'store/api/review'; import * as Common from 'styles/List.style'; -import { UpCircleOutlined } from '@ant-design/icons'; +import ScrollUpButton from 'components/common/ScrollUpButton/ScrollUpButton'; import ReviewCard from './ReviewCard'; import * as S from './ReviewList.style'; @@ -15,10 +15,6 @@ export default function ReviewList() { data, isLoading, } = useGetReviewListQuery({ page, limit: LIMIT, isReported }); - const scrollUp = () => { - window.scrollTo({ top: 0, behavior: 'smooth' }); - }; - const filterReportedReview = () => { setIsReported((prev) => !prev); setPage(1); @@ -32,7 +28,7 @@ export default function ReviewList() { {isLoading ? [1, 2, 3, 4, 5].map((key) => ) : ( <> - + 신고된 리뷰만 모아보기 @@ -55,9 +51,7 @@ export default function ReviewList() { )} - - - + ); } From 4327b731f3a53db0239435724f6613ee9a44d1d8 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Mon, 26 Aug 2024 17:16:42 +0900 Subject: [PATCH 8/9] =?UTF-8?q?refactor:=20=EC=BD=94=EC=9D=B8=20Url=20?= =?UTF-8?q?=EA=B3=B5=EC=9A=A9=20=EC=83=81=EC=88=98=EB=A1=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constant/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/constant/index.ts b/src/constant/index.ts index cf312aa..7738016 100644 --- a/src/constant/index.ts +++ b/src/constant/index.ts @@ -2,6 +2,8 @@ export const API_PATH = process.env.REACT_APP_API_PATH; export const SECOND_PASSWORD = process.env.REACT_APP_SECOND_PASSWORD; +export const KOIN_URL = process.env.REACT_APP_API_PATH?.includes('stage') ? 'https://stage.koreatech.in' : 'https://koreatech.in'; + // 테이블 헤더 Title 매핑 export const TITLE_MAPPER: Record = { id: 'ID', From 8746fa868490986d4901302f66350ebada004d22 Mon Sep 17 00:00:00 2001 From: chaeseungyun Date: Mon, 26 Aug 2024 17:16:59 +0900 Subject: [PATCH 9/9] =?UTF-8?q?refactor:=20props=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EA=B7=9C=EC=B9=99=20=EC=A4=80=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Services/Review/ReviewCard.style.tsx | 4 ++-- src/pages/Services/Review/ReviewCard.tsx | 5 ++--- src/pages/Services/Review/ReviewList.style.tsx | 8 -------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/pages/Services/Review/ReviewCard.style.tsx b/src/pages/Services/Review/ReviewCard.style.tsx index 5ae1dcf..a803ebc 100644 --- a/src/pages/Services/Review/ReviewCard.style.tsx +++ b/src/pages/Services/Review/ReviewCard.style.tsx @@ -5,11 +5,11 @@ export const Shortcut = styled.a` text-decoration: none; `; -export const Container = styled.div<{ $isHandle: boolean }>` +export const Container = styled.div<{ isHandle: boolean }>` display: flex; flex-direction: column; padding: 10px 15px; - background: ${(props) => (props.$isHandle ? '#ff000050' : '#00BFFF10')}; + background: ${(props) => (props.isHandle ? '#ff000050' : '#00BFFF10')}; border-radius: 10px; transition: scale 0.3s, height 0.3s; width: 100%; diff --git a/src/pages/Services/Review/ReviewCard.tsx b/src/pages/Services/Review/ReviewCard.tsx index a5a6206..f1a4247 100644 --- a/src/pages/Services/Review/ReviewCard.tsx +++ b/src/pages/Services/Review/ReviewCard.tsx @@ -3,6 +3,7 @@ import { Button, message, Modal } from 'antd'; import { useState } from 'react'; import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons'; import { useDeleteReviewMutation, useSetReviewDismissedMutation } from 'store/api/review'; +import { KOIN_URL } from 'constant'; import * as S from './ReviewCard.style'; interface Props { @@ -10,8 +11,6 @@ interface Props { currentPage: number; } -const KOIN_URL = process.env.REACT_APP_API_PATH?.includes('stage') ? 'https://stage.koreatech.in' : 'https://koreatech.in'; - export default function ReviewCard({ review, currentPage }: Props) { const [isOpen, setIsOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false); @@ -54,7 +53,7 @@ export default function ReviewCard({ review, currentPage }: Props) { }; return ( - + diff --git a/src/pages/Services/Review/ReviewList.style.tsx b/src/pages/Services/Review/ReviewList.style.tsx index 777ee53..8f18d5f 100644 --- a/src/pages/Services/Review/ReviewList.style.tsx +++ b/src/pages/Services/Review/ReviewList.style.tsx @@ -24,11 +24,3 @@ export const DataContainer = styled.div` width: 100%; margin-bottom: 30px; `; - -export const RightDownButton = styled.div` - position: fixed; - bottom: 100px; - right: 100px; - font-size: 40px; - cursor: pointer; -`;