From ee6ebeb6fa100007c00d32ddac8cade15dd35c37 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 02:32:44 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20lecture=20api=20t?= =?UTF-8?q?ypes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/lecture/model/lecture.ts | 191 +++++++++++++++++++++----- 1 file changed, 160 insertions(+), 31 deletions(-) diff --git a/src/entities/lecture/model/lecture.ts b/src/entities/lecture/model/lecture.ts index c16d7df..4dc6c4a 100755 --- a/src/entities/lecture/model/lecture.ts +++ b/src/entities/lecture/model/lecture.ts @@ -1,35 +1,57 @@ +import { Payload } from "@/shared/model/api"; + +export interface LectureImage { + id: number; + url: string; +} + +export interface LectureInstructorHistory { + id: number; + content: string; +} +export interface LectureInstructor { + id: number; + name: string; + instructor_history: LectureInstructorHistory[]; +} + +export interface LecturePeriod { + startDate: string; + endDate: string; + total: number; +} export interface Lecture { id: number; name: string; description: string; price: number; - day_of_week: string; time: string; capacity: number; link: string; location: string; - latitude: number; - longitude: number; - target: string; status: string; thumbnail: string; - like: boolean; - location_detail: string; - hosted_by: string; + heart: boolean; address: string; - period: { startData: string; endDate: string; total: number }; - division: "oneDay" | "long"; - distance: string; + period: LecturePeriod[]; + division: string; category: string; condition: string; detail: string; certification: string; - textbookName: string; - textbookPrice: number; need: string; - instructorName: string; - instructorHistory: Array; - educationPlan: string; + distance: string; + estimatedTime: string; + images: LectureImage[]; + day_of_week: string; + hosted_by: string; + d_day: number; + text_book_name: string; + text_book_price: number; + instructor_name: LectureInstructor[]; + latitude: number; + longitude: number; + // educationPlan: string; } type LectureTitleType = @@ -51,10 +73,12 @@ export const LectureTitleEnum = { location: "장소", } as const; -export interface LectureSummaryListProps { +export interface LectureSummaryListProps< + T extends LectureTitleType = LectureTitleType, +> { src: string; - type: LectureTitleType; - render: (content: Lecture[keyof Lecture]) => string; + type: T; + render: (content: Lecture[T]) => string; } export const lectureSummaryList: Array = [ @@ -76,7 +100,15 @@ export const lectureSummaryList: Array = [ { src: "/icons/calendar_filled.svg", type: "period", - render: (content) => `${content}`, + render: (content) => { + const lectureContent = content as LecturePeriod[]; + + if (lectureContent[0].startDate === lectureContent[0].endDate) { + return `${lectureContent[0].startDate}`; + } + + return `${lectureContent[0].startDate}~${lectureContent[0].endDate} 총 ${lectureContent[0].total}회`; + }, }, { src: "/icons/time.svg", @@ -86,7 +118,7 @@ export const lectureSummaryList: Array = [ { src: "/icons/price.svg", type: "price", - render: (content) => `${content.toLocaleString("ko-KR")}원`, + render: (content) => `${content}`, }, { src: "/icons/location.svg", @@ -96,19 +128,18 @@ export const lectureSummaryList: Array = [ ]; type LectureDetailTitleType = - | "target" | "description" | "certification" - | "textbookName" - | "textbookPrice" + | "text_book_name" + | "text_book_price" | "need"; export const LectureDetailTitleEnum = { target: "수강자격", description: "교육내용", certification: "자격증 관련사항", - textbookName: "교재명", - textbookPrice: "교재비", + text_book_name: "교재명", + text_book_price: "교재비", need: "준비물", } as const; @@ -118,10 +149,6 @@ export interface LectureDetailListProps { } export const lectureDetailList: Array = [ - { - type: "target", - render: (content) => `${content}`, - }, { type: "description", render: (content) => `${content}`, @@ -131,11 +158,11 @@ export const lectureDetailList: Array = [ render: (content) => `${content}`, }, { - type: "textbookName", + type: "text_book_name", render: (content) => `${content}`, }, { - type: "textbookPrice", + type: "text_book_price", render: (content) => `${content}`, }, { @@ -143,3 +170,105 @@ export const lectureDetailList: Array = [ render: (content) => `${content}`, }, ]; + +export interface GetLectureListDto { + params: LectureSize; + payload: LecturePayload; +} + +export interface LectureInfo { + id: number; + thumbnail: string; + name: string; + time: string; + target: string; + status: boolean; + address: string; + link: string; + heart: boolean; + start_date: string; + end_date: string; + day_of_week: string; + hosted_by: string; + latitude: number; + longitude: number; +} + +export interface LectureListResData { + data: LectureInfo[]; + hasNext: boolean; +} +export interface GetLectureListRes { + data: LectureListResData; + message: string; + status: string; +} + +export type GetLectureList = Payload< + undefined, + undefined, + GetLectureListDto, + GetLectureListRes +>; + +export interface LectureSize { + page: number; + size: number; + dist: number; +} + +export interface LecturePayload { + latitude: number; + longitude: number; +} + +export interface PickLectureInfo { + id: number; + view: number; + thumbnail: string; + name: string; + time: string; + target: string; + status: boolean; + heart: boolean; + address: string | null; + link: string; + start_date: string; + end_date: string; + day_of_week: string; +} + +export interface LectureListResData { + data: LectureInfo[]; + pickClasses: PickLectureInfo[]; + hasNext: boolean; +} +export interface GetHomeLectureListRes { + data: LectureListResData; + message: string; + status: string; +} + +export type GetHomeLectureList = Payload< + undefined, + undefined, + GetLectureListDto, + GetHomeLectureListRes +>; + +export interface GetLectureDto { + latitude: number; + longitude: number; +} +export interface GetLectureRes { + data: Lecture; + message: string; + status: string; +} + +export type GetLecture = Payload< + undefined, + undefined, + GetLectureDto, + GetLectureRes +>; From b54400850f25aea8eb1412de50ac327dce572657 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 02:34:29 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20lecture=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/lecture/api/index.ts | 55 +++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/entities/lecture/api/index.ts b/src/entities/lecture/api/index.ts index 0d5546c..b9030f7 100755 --- a/src/entities/lecture/api/index.ts +++ b/src/entities/lecture/api/index.ts @@ -1,19 +1,46 @@ -import { Lecture } from "@/entities/lecture/model/lecture"; +import { + GetHomeLectureList, + GetLecture, + GetLectureList, + Lecture, +} from "@/entities/lecture/model/lecture"; + import apiRequest from "@/shared/api"; -// TODO: BASE_PATH "/lectures"로 변경 필요 -const BASE_PATH = "/class"; -const API_BASE_PATH = "/lectures"; +const BASE_PATH = "/api/lectures"; +const HOME_BASE_PATH = "/api/home"; -export const getLectureList = () => - apiRequest.get(`${BASE_PATH}`, {}); +export const getLectureList = ({ + params, + payload, +}: { + params: GetLectureList["Request"]["body"]["params"]; + payload: GetLectureList["Request"]["body"]["payload"]; +}) => + apiRequest.post(`${BASE_PATH}`, payload, { + params, + }); -export const getLectureInfo = (id: number) => - apiRequest.get(`${BASE_PATH}/${id}`, {}); +export const getHomeLectureList = ({ + params, + payload, +}: { + params: GetHomeLectureList["Request"]["body"]["params"]; + payload: GetHomeLectureList["Request"]["body"]["payload"]; +}) => + apiRequest.post( + `${HOME_BASE_PATH}`, + payload, + { + params, + }, + ); -export const getEntireLecture = () => - apiRequest.get<{ - status: string; - message: string; - data: { data: Lecture[]; hasNext: boolean }; - }>(`${API_BASE_PATH}`, {}); +export const getLectureInfo = ({ + lectureId, + payload, +}: { + lectureId: number; + payload: GetLecture["Request"]["body"]; +}) => + apiRequest.post(`${BASE_PATH}/${lectureId}`, payload); From b30b3e2bc78719db0996d87e56c1c755a1e38a08 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 02:35:09 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20lecture=20api=20h?= =?UTF-8?q?ooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/lecture/api/useEntireLecture.ts | 16 ----------- .../lecture/api/useHomeLectureList.ts | 25 +++++++++++++++++ src/entities/lecture/api/useLectureInfo.ts | 28 ++++++++++++++----- src/entities/lecture/api/useLectureList.ts | 24 +++++++++++----- 4 files changed, 63 insertions(+), 30 deletions(-) delete mode 100755 src/entities/lecture/api/useEntireLecture.ts create mode 100644 src/entities/lecture/api/useHomeLectureList.ts diff --git a/src/entities/lecture/api/useEntireLecture.ts b/src/entities/lecture/api/useEntireLecture.ts deleted file mode 100755 index 09b605f..0000000 --- a/src/entities/lecture/api/useEntireLecture.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { LECTURE_KEYS } from "@/shared/api/keyFactory"; -import { getEntireLecture } from "."; -import { useQuery } from "@tanstack/react-query"; - -const useEntireLecture = () => { - return useQuery({ - queryKey: LECTURE_KEYS.list(), - queryFn: () => getEntireLecture(), - select: (response) => response.data, - meta: { - errorMessage: "Failed to fetch Entire Lecture", - }, - }); -}; - -export default useEntireLecture; diff --git a/src/entities/lecture/api/useHomeLectureList.ts b/src/entities/lecture/api/useHomeLectureList.ts new file mode 100644 index 0000000..bac8670 --- /dev/null +++ b/src/entities/lecture/api/useHomeLectureList.ts @@ -0,0 +1,25 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; + +import { GetLectureListDto } from "../model/lecture"; +import { HOME_LECTURE_KEYS } from "@/shared/api/keyFactory"; +import { getHomeLectureList } from "."; + +const useHomeLectureList = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (lectureListReq: GetLectureListDto) => + getHomeLectureList({ + payload: lectureListReq.payload, + params: lectureListReq.params, + }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: HOME_LECTURE_KEYS.lists() }); + queryClient.invalidateQueries({ + queryKey: HOME_LECTURE_KEYS.list({ page: 1, size: 10 }), + }); + }, + }); +}; + +export default useHomeLectureList; diff --git a/src/entities/lecture/api/useLectureInfo.ts b/src/entities/lecture/api/useLectureInfo.ts index e7a57f9..0c1c7e9 100755 --- a/src/entities/lecture/api/useLectureInfo.ts +++ b/src/entities/lecture/api/useLectureInfo.ts @@ -1,14 +1,28 @@ +import { GetLecture, GetLectureDto } from "../model/lecture"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; + import { LECTURE_KEYS } from "@/shared/api/keyFactory"; import { getLectureInfo } from "."; -import { useQuery } from "@tanstack/react-query"; const useLectureInfo = (lectureId: number) => { - return useQuery({ - queryKey: LECTURE_KEYS.detail({ lectureId }), - queryFn: () => getLectureInfo(lectureId), - select: (response) => response.data, - meta: { - errorMessage: "Failed to fetch Entire Class", + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({ + lectureId, + payload, + }: { + lectureId: number; + payload: GetLecture["Request"]["body"]; + }) => + getLectureInfo({ + lectureId: lectureId, + payload: payload, + }), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: LECTURE_KEYS.detail({ lectureId }), + }); }, }); }; diff --git a/src/entities/lecture/api/useLectureList.ts b/src/entities/lecture/api/useLectureList.ts index 759dee3..e8d98d2 100755 --- a/src/entities/lecture/api/useLectureList.ts +++ b/src/entities/lecture/api/useLectureList.ts @@ -1,14 +1,24 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; + +import { GetLectureList } from "../model/lecture"; import { LECTURE_KEYS } from "@/shared/api/keyFactory"; import { getLectureList } from "."; -import { useQuery } from "@tanstack/react-query"; const useLectureList = () => { - return useQuery({ - queryKey: LECTURE_KEYS.list(), - queryFn: () => getLectureList(), - select: (response) => response.data, - meta: { - errorMessage: "Failed to fetch Lecture List", + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (lectureListReq: GetLectureList["Request"]["body"]) => + getLectureList({ + payload: lectureListReq.payload, + params: lectureListReq.params, + }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: LECTURE_KEYS.lists() }); + // TODO: 무한 스크롤 처리하면서 queryKey 바꿔줘야됨 + queryClient.invalidateQueries({ + queryKey: LECTURE_KEYS.list({ page: 1, size: 10 }), + }); }, }); }; From 46f65177f4f51d218009f8580aa3a0fc9055e87d Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 02:40:28 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20react=20query?= =?UTF-8?q?=20key=20factory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/api/keyFactory.ts | 54 ++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/shared/api/keyFactory.ts b/src/shared/api/keyFactory.ts index 4ebdf1c..0b574c6 100755 --- a/src/shared/api/keyFactory.ts +++ b/src/shared/api/keyFactory.ts @@ -2,6 +2,7 @@ const KEY_DOMAINS = { authUser: "authUser", logout: "logout", lecture: "lecture", + homeLecture: "homeLecture", likeClass: "likeClass", user: "user", you: "you", @@ -17,18 +18,20 @@ export const LECTURE_KEYS = { lists: () => [...LECTURE_KEYS.all, "list"], // FIXME: lecture 타입 전체 수정됨, 업데이트 필요 list: (filters?: { - name: string; - description: string; - price: number; - day_of_week: string; - time: string; - capacity: number; - link: string; - location: string; - latitude: number; - longitude: number; - target: string; - status: string; + id?: number; + thumbnail?: string; + name?: string; + time?: string; + target?: string; + status?: boolean; + address?: string; + link?: string; + heart?: boolean; + start_date?: string; + end_date?: string; + day_of_week?: string; + page?: number; + size?: number; }) => [...LECTURE_KEYS.all, "list", filters], details: () => [...LECTURE_KEYS.all, "detail"], detail: (filters: { lectureId: number }) => [ @@ -37,6 +40,33 @@ export const LECTURE_KEYS = { ], }; +export const HOME_LECTURE_KEYS = { + all: [KEY_DOMAINS.homeLecture], + lists: () => [...HOME_LECTURE_KEYS.all, "list"], + // FIXME: lecture 타입 전체 수정됨, 업데이트 필요 + list: (filters?: { + id?: number; + thumbnail?: string; + name?: string; + time?: string; + target?: string; + status?: boolean; + address?: string; + link?: string; + heart?: boolean; + start_date?: string; + end_date?: string; + day_of_week?: string; + page?: number; + size?: number; + }) => [...HOME_LECTURE_KEYS.all, "list", filters], + details: () => [...HOME_LECTURE_KEYS.all, "detail"], + detail: (filters: { lectureId: number }) => [ + ...HOME_LECTURE_KEYS.details(), + filters, + ], +}; + export const LIKE_LECTURE_KEYS = { all: [KEY_DOMAINS.likeClass], lists: () => [...LIKE_LECTURE_KEYS.all, "list"],