From afe4e0023955b6e30b518aa9f5e645c79f26269d Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 28 Aug 2023 09:40:24 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EB=B0=8F=20=EA=B0=B1=EC=8B=A0=EC=97=90=20react=20query=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/reviews/useGetReviews.ts | 74 ++++++++----------- src/api/reviews/usePatchReviewsId.ts | 10 +-- .../reviewManagement/ReviewManagement.tsx | 37 ++++------ .../ReviewManagementListItem.tsx | 32 ++++---- 4 files changed, 65 insertions(+), 88 deletions(-) diff --git a/src/api/reviews/useGetReviews.ts b/src/api/reviews/useGetReviews.ts index e2fd1ddf..af48911a 100644 --- a/src/api/reviews/useGetReviews.ts +++ b/src/api/reviews/useGetReviews.ts @@ -1,52 +1,40 @@ -import { useState, useEffect } from "react"; -import { useApi } from "../../hook/useApi"; -import { Review } from "../../type"; +import type { contract } from "@jiphyeonjeon-42/contracts"; +import type { ClientInferRequest } from "@ts-rest/core"; +import { useState } from "react"; +import { client } from "~/util/tsRestClient"; -export const useGetReviews = () => { - const [params, setParams] = useState({ - titleOrNickname: "", - page: 1, - disabled: "-1", - }); - - const [result, setResult] = useState({ - reviewList: [], - lastPage: 5, - }); +type QueryArgs = ClientInferRequest["query"]; - const setPage = (page: number) => { - setParams({ ...params, page }); - }; - const setQuery = (query: string) => { - setParams({ ...params, titleOrNickname: query }); - }; - const setSelectedType = (type: string | undefined) => { - if (type) setParams({ ...params, disabled: type }); - }; - - const { request } = useApi("get", "reviews", { - ...params, - page: params.page - 1, - }); - - const refineResponse = (response: any) => { - const { items } = response.data; - const { totalPages } = response.data.meta; - - setResult({ reviewList: items, lastPage: totalPages }); +export const useGetReviews = () => { + const [search, setSearch] = useState(); + const [page, setPage] = useState(1); + const [visibility, setVisibility] = useState<"public" | "hidden" | "all">( + "all", + ); + + const queryArgs: QueryArgs = { + search, + page, + visibility, + perPage: 10, + sort: "desc", }; - useEffect(() => { - request(refineResponse); - }, [params]); + const query = client.reviews.get.useQuery( + ["reviews", queryArgs], + { query: queryArgs }, + { + keepPreviousData: true, + staleTime: 1000 * 60 * 60, + }, + ); return { - page: params.page, + page, setPage, - setQuery, - selectedType: params.disabled, - setSelectedType, - reviewList: result.reviewList as Review[], - lastPage: result.lastPage, + setSearch, + visibility, + setVisibility, + data: query.data?.body, }; }; diff --git a/src/api/reviews/usePatchReviewsId.ts b/src/api/reviews/usePatchReviewsId.ts index 16a2fa5a..f9ccc3b0 100644 --- a/src/api/reviews/usePatchReviewsId.ts +++ b/src/api/reviews/usePatchReviewsId.ts @@ -1,5 +1,4 @@ -import { useEffect, useState } from "react"; -import { useApi } from "../../hook/useApi"; +import { queryClient } from "~/index"; import { useNewDialog } from "../../hook/useNewDialog"; import { client } from "../../util/tsRestClient"; @@ -7,12 +6,7 @@ export const usePatchReviewsId = () => { const { addErrorDialog, addDialogWithTitleAndMessage } = useNewDialog(); const mutation = client.reviews.patch.useMutation({ - onSuccess: () => { - console.log("local success"); - addDialogWithTitleAndMessage("patched", "처리되었습니다", "", () => - window.location.reload(), - ); - }, + onSuccess: () => queryClient.invalidateQueries(["reviews"]), onError: err => { switch (err.status) { case 401: diff --git a/src/component/reviewManagement/ReviewManagement.tsx b/src/component/reviewManagement/ReviewManagement.tsx index 617da4a9..dd67fcef 100644 --- a/src/component/reviewManagement/ReviewManagement.tsx +++ b/src/component/reviewManagement/ReviewManagement.tsx @@ -1,29 +1,24 @@ import { useGetReviews } from "../../api/reviews/useGetReviews"; import { otherManagementTabList } from "../../constant/tablist"; import Banner from "../utils/Banner"; -import Tabs from "../utils/Tabs"; +import Filter from "../utils/Filter"; import Management from "../utils/Management"; +import Tabs from "../utils/Tabs"; import ReviewManagementListItem from "./ReviewManagementListItem"; -import Filter from "../utils/Filter"; + +type Visibility = "all" | "public" | "hidden"; const reviewFilterList = [ - { name: "공개만 보기", type: "0" }, - { name: "비공개만 보기", type: "1" }, -]; + { name: "공개만 보기", type: "public" }, + { name: "비공개만 보기", type: "hidden" }, +] satisfies { name: string; type: Visibility }[]; const ReviewManagement = () => { - const { - page, - setPage, - setQuery, - selectedType, - setSelectedType, - reviewList, - lastPage, - } = useGetReviews(); + const { page, setPage, data, visibility, setVisibility, setSearch } = + useGetReviews(); - const setUndefinedReSelected = (newType: string) => { - setSelectedType(newType === selectedType ? "-1" : newType); + const setVisiblityWithUnset = (value: "public" | "hidden") => { + setVisibility(visibility === value ? "all" : value); }; return ( @@ -32,7 +27,7 @@ const ReviewManagement = () => { ID @@ -46,17 +41,17 @@ const ReviewManagement = () => { <> void} /> - {reviewList.map(review => ( + {data?.items.map(review => ( ))} } page={page} setPage={setPage} - lastPage={lastPage} + lastPage={data?.meta.totalPages ?? 1} /> ); diff --git a/src/component/reviewManagement/ReviewManagementListItem.tsx b/src/component/reviewManagement/ReviewManagementListItem.tsx index 726932da..f81257fe 100644 --- a/src/component/reviewManagement/ReviewManagementListItem.tsx +++ b/src/component/reviewManagement/ReviewManagementListItem.tsx @@ -1,42 +1,42 @@ import { MouseEventHandler } from "react"; import { usePatchReviewsId } from "../../api/reviews/usePatchReviewsId"; -import { Review } from "../../type"; -import Edit from "../../asset/img/edit.svg"; -import Image from "../utils/Image"; import "../../asset/css/ReviewManagementList.css"; +import Edit from "../../asset/img/edit.svg"; import { useNewDialog } from "../../hook/useNewDialog"; +import Image from "../utils/Image"; + +import { contract } from "@jiphyeonjeon-42/contracts"; +import type { ClientInferResponseBody } from "@ts-rest/core"; + +type Review = ClientInferResponseBody< + typeof contract.reviews.get, + 200 +>["items"][number]; type Props = { review: Review; }; const ReviewManagementListItem = ({ review }: Props) => { - const { setReviewId } = usePatchReviewsId(); + const mutation = usePatchReviewsId(); const { addConfirmDialog } = useNewDialog(); - const requestConfirmToUpdate: MouseEventHandler = e => { + const requestConfirmToUpdate: MouseEventHandler = () => { const job = review.disabled ? "공개" : "비공개"; addConfirmDialog( "리뷰확인", `리뷰를 ${job}하시겠습니까?`, `[${review.title}]\n\n리뷰내용 : ${review.content}`, - () => { - setReviewId(review.reviewsId); - }, + () => mutation.mutate({ params: { reviewsId: review.id } }), ); }; return ( -
- {review.reviewsId} +
+ {review.id} - - {review.createdAt.slice(0, 5)} - - - {review.createdAt.slice(5, 10)} - + {review.createdAt.split("T")[0]} {review.nickname}