From 8fef6b73eadbf7aa7b71ee9c9ef4ebff568f841e Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:22:57 +0900 Subject: [PATCH 01/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20InputLabel?= =?UTF-8?q?=20components=20to=20use=20react-hook-form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/ui/InputLabel/InputLabel.tsx | 121 +++++++++++++----------- 1 file changed, 64 insertions(+), 57 deletions(-) diff --git a/src/shared/ui/InputLabel/InputLabel.tsx b/src/shared/ui/InputLabel/InputLabel.tsx index 4b34d0d..a580c34 100644 --- a/src/shared/ui/InputLabel/InputLabel.tsx +++ b/src/shared/ui/InputLabel/InputLabel.tsx @@ -1,4 +1,5 @@ import { Input } from ".."; +import { forwardRef } from "react"; import { twMerge } from "tailwind-merge"; interface InputLabelProps { @@ -8,78 +9,84 @@ interface InputLabelProps { status?: InputLabelStatus; type?: string; message?: string; + value?: string; + error?: boolean; + onChange?: (e: React.ChangeEvent) => void; // onChange 핸들러 추가 + onBlur?: () => void; // onBlur 핸들러 추가 } -type InputLabelStatus = "default" | "correct" | "error"; +export type InputLabelStatus = "default" | "correct" | "error"; -const InputLabel = ({ - labelContent, - placeholder, - disabled, - status = "default", - type = "text", - message, -}: InputLabelProps) => { - const containerClassName = () => { - if (message) { +const InputLabel = forwardRef( + ( + { + labelContent, + placeholder, + value, + disabled, + status = "default", + type = "text", + message, + error, + onChange, + onBlur, + }, + ref, + ) => { + const containerClassName = () => { return "flex flex-col w-full gap-2"; - } - return "flex flex-col w-full"; - }; - - const borderColor = () => { - if (disabled) { - return "border-custom-disabled"; - } - if (status === "error") { - return "border-custom-error"; - } - if (status === "correct") { - return "border-custom-correct"; - } - return "border-custom-purple"; - }; + }; - const textColor = () => { - if (disabled) { - return "text-custom-textDescriptionGrayColor"; - } - }; + const borderColor = () => { + if (disabled) { + return "border-custom-disabled"; + } + if (status === "error") { + return "border-custom-error"; + } + if (status === "correct") { + return "border-custom-correct"; + } + return "border-custom-purple"; + }; - const messageTextColor = () => { - { + const textColor = () => { if (status === "error") { return "text-custom-error"; } + if (status === "correct") { return "text-custom-correct"; } - } - }; + }; - return ( -
-
-
- {labelContent} + return ( +
+
+
+ {labelContent} +
+
+ +
-
- +
+ {message} {/* 오류 메시지 표시 */}
-
- {message} -
-
- ); -}; + ); + }, +); + +InputLabel.displayName = "InputLabel"; export default InputLabel; From c1e35d26d423027d3e800014ad13ac9cffbea77c Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:23:26 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20IconButton?= =?UTF-8?q?=20to=20use=20like=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/ui/IconButton/IconButton.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/ui/IconButton/IconButton.tsx b/src/shared/ui/IconButton/IconButton.tsx index 7d86616..bf959ed 100644 --- a/src/shared/ui/IconButton/IconButton.tsx +++ b/src/shared/ui/IconButton/IconButton.tsx @@ -29,6 +29,7 @@ const IconButton = ({ "flex flex-col items-center justify-center content-center w-[32px] h-[32px] hover:bg-gray-200", `w-[${buttonWidth}px], h-[${buttonHeight}px]`, )} + onClick={handleClick} > {alt} From 5ca0eab51f7841e3f42e0c6aa4d6adfe1eefa32b Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:27:04 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20HeaderFeatur?= =?UTF-8?q?es=20by=20using=20accessToken?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Header/HeaderFeatures/HeaderFeatures.tsx | 84 ++++++++++++------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/src/shared/ui/Header/HeaderFeatures/HeaderFeatures.tsx b/src/shared/ui/Header/HeaderFeatures/HeaderFeatures.tsx index aa955f6..0de35fe 100644 --- a/src/shared/ui/Header/HeaderFeatures/HeaderFeatures.tsx +++ b/src/shared/ui/Header/HeaderFeatures/HeaderFeatures.tsx @@ -1,23 +1,26 @@ "use client"; +import { useEffect, useState } from "react"; + import { Button } from "../../Button"; import Image from "next/image"; import Link from "next/link"; +import { LoginUserInfo } from "@/entities/user/model/user"; import { UnifiedDialog } from "../../UnifiedDialog"; -import { User } from "@/entities/user/model/user"; +import { getCookie } from "cookies-next"; +import useLoginedUserStore from "@/shared/store/user"; import { useRouter } from "next/navigation"; -import { useState } from "react"; const HeaderFeatures = () => { - // TODO: 전역 상태 관리 - 로그인 된 유저 여부 판단 - const [loginedUser, setLoginedUser] = useState(); - - /* FIXME: isLogin 개발 편의상 임시 처리 */ - const [isLogin, setIsLogin] = useState(false); + const [loginedUser, setLoginedUser] = useState(); const [openLike, setOpenLike] = useState(false); const [openUser, setOpenUser] = useState(false); const router = useRouter(); + const { loginedUser: loginedUserInfo } = useLoginedUserStore(); + + const accessToken = getCookie("accessToken"); + const handleOpenLikeDialog = () => { setOpenLike(true); }; @@ -32,6 +35,12 @@ const HeaderFeatures = () => { router.push("/login"); }; + useEffect(() => { + if (loginedUserInfo) { + setLoginedUser(loginedUserInfo); + } + }, [loginedUserInfo]); + const dialogContent = () => { return (
@@ -61,19 +70,23 @@ const HeaderFeatures = () => { const renderLikeIcon = () => { // 개발 편의상 임시 처리 - if (loginedUser && isLogin) { + if (loginedUser && loginedUserInfo && accessToken) { return ( - -
- heart-icons -
-
- +
+ +
+ heart-icons +
+ 찜 +
+
+ +
); } return ( @@ -102,21 +115,28 @@ const HeaderFeatures = () => { }; const renderUserIcon = () => { - if (loginedUser && isLogin) { + if ( + loginedUser && + loginedUserInfo && + loginedUserInfo.nickname && + accessToken + ) { return ( - -
- user-icons -
- 마이페이지 +
+ +
+ user-icons +
+ 마이페이지 +
-
- + +
); } From bf87f9b19ada0763f1b1dab75d7912c38cd51a85 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:31:39 +0900 Subject: [PATCH 04/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20keyFactory?= 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"], From 007efdae0dcc9e964b0efe2b1171dcef1e9eab09 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:32:49 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20entire=20pag?= =?UTF-8?q?e=20using=20get=20entire=20lecture=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/entire/page.tsx | 69 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/src/app/entire/page.tsx b/src/app/entire/page.tsx index 043b13d..b785863 100755 --- a/src/app/entire/page.tsx +++ b/src/app/entire/page.tsx @@ -1,22 +1,73 @@ "use client"; +import { + LectureInfo, + LecturePayload, + LectureSize, +} from "@/entities/lecture/model/lecture"; import { LectureList, SkeletonCard } from "@/entities/lecture/ui"; import { useEffect, useState } from "react"; -import { Lecture } from "@/entities/lecture/model/lecture"; -import useEntireLecture from "@/entities/lecture/api/useEntireLecture"; +import { useGeoLocation } from "@/shared/lib/useGeolocation"; +import useLectureList from "@/entities/lecture/api/useLectureList"; +import useLoginedUserStore from "@/shared/store/user"; const EntirePage = () => { - const [lectureListData, setLectureListData] = useState(); + const [lectureListData, setLectureListData] = useState(); + const [user, setUser] = useState(); + const [lectureSize, setLectureSize] = useState({ + page: 0, + size: 9, + dist: 500, + }); - // TODO: 전체 클래스 가져오는 API로 수정 필요 - const { data, isLoading, isSuccess } = useEntireLecture(); + const getLectureList = useLectureList(); + const isLoading = getLectureList.isIdle || getLectureList.isPending; + + const geolocation = useGeoLocation(); + + useEffect(() => { + if (user && user.latitude && user.longitude) { + getLectureList.mutate( + { + params: { + page: lectureSize.page, + size: lectureSize.size, + dist: lectureSize.dist, + }, + payload: { latitude: user.latitude, longitude: user.longitude }, + }, + { + onSuccess: (data) => { + const lectureListData = data.data.data.data; + setLectureListData(lectureListData); + }, + onError: () => {}, + }, + ); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [lectureSize.page, lectureSize.size, user]); useEffect(() => { - if (isSuccess) { - setLectureListData(data.data.data); + if ( + geolocation.curLocation && + geolocation.curLocation.latitude && + geolocation.curLocation.longitude + ) { + setUser((prev) => { + return { + ...prev, + latitude: geolocation.curLocation + ? geolocation.curLocation.latitude + : 0, + longitude: geolocation.curLocation + ? geolocation.curLocation.longitude + : 0, + }; + }); } - }, [data, isSuccess]); + }, [geolocation.curLocation]); const renderEntireCardContent = () => { if (isLoading) { @@ -36,6 +87,8 @@ const EntirePage = () => { return
클래스가 존재하지 않습니다
; }; + // TODO: 무한 스크롤 + return (
From 775fe3e1d8673bf6abec8252bc964cae9796b4f8 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:33:17 +0900 Subject: [PATCH 06/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20home=20page?= =?UTF-8?q?=20using=20get=20home=20lecture=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/page.tsx | 174 ++++++++++++++++++++++++++++++----------------- 1 file changed, 111 insertions(+), 63 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 35526d6..899cc77 100755 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,73 +1,81 @@ "use client"; import { Description, LectureList, SkeletonCard } from "@/entities/lecture/ui"; +import { + LectureInfo, + LectureSize, + PickLectureInfo, +} from "@/entities/lecture/model/lecture"; import { useEffect, useState } from "react"; -import { Lecture } from "@/entities/lecture/model/lecture"; +import { Button } from "@/shared/ui"; +import { LoginUserInfo } from "@/entities/user/model/user"; import Map from "@/features/map/ui/Map/Map"; import MapSkeleton from "@/features/map/ui/MapSkeleton/MapSkeleton"; -import { User } from "@/entities/user/model/user"; import { useGeoLocation } from "@/shared/lib/useGeolocation"; -import useLectureList from "@/entities/lecture/api/useLectureList"; +import useGetLoginUserInfo from "@/entities/user/api/useGetLoginUserInfo"; +import useHomeLectureList from "@/entities/lecture/api/useHomeLectureList"; +import useLoginedUserStore from "@/shared/store/user"; +import { useRouter } from "next/navigation"; const Home = () => { - const [lectureListData, setLectureListData] = useState(); - - // TODO: 로그인 유저 정보 전역으로 변경 - const [loginedUser, setLoginedUser] = useState({ - id: 1, - account_email: "jkb2221@gmail.com", - profile_image: - "https://avatars.githubusercontent.com/u/33307948?s=400&u=a642bbeb47b47e203f37b47db12d2d92d8f98580&v=4", - name: "kyubumjang", + const [lectureListData, setLectureListData] = useState(); + const [pickLectureListData, sePickLectureListData] = + useState(); + const [lectureSize, setLectureSize] = useState({ + page: 0, + size: 9, + dist: 500, + }); + const [loginedUser, setLoginedUser] = useState({ + id: 0, + email: "", + nickname: "", gender: "male", - age_range: "20~29", - applied_class: [ - { - id: 1, - name: "디지털카메라초급(눈으로 사진찍기)", - description: - "컴팩트 카메라부터 DSLR 카메라까지 디지털 카메라에 대해서 이해하고 카메라의 모든 기능을 200% 활용하는데 목적을 둔다 ** 사진입문자를 위한 수업입니다. ** 3개월 동안 사진 완전초보를 벗어날 수 있도록 도와드립니다. **야외수업시 보험가입 필수 (1일 보험료 별도) 보험가입증서 제출 또는 동의서 작성", - price: 90000, - day_of_week: "수", - time: "2024-09-16 18:00:00", - capacity: 15, - link: "https://www.songpawoman.org/2024/epit_contents.asp?epit_num=10501042&om=202410&ucode=&period=3", - location: "서울 송파", - latitude: 37.5059054977082, - longitude: 127.109788230628, - target: "사진 입문자", - status: "모집 중", - thumbnail: - "https://images.unsplash.com/photo-1601134991665-a020399422e3?q=80&w=2787&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - like: true, - location_detail: "송파여성문화회관 미디어1실(101호)", - hosted_by: "송파여성문화회관", - address: "서울특별시 송파구 백제고분로42길 5", - division: "oneDay", - distance: "1km", - category: "문화", - condition: "", - period: { startData: "2024-09-09", endDate: "2024-09-09", total: 1 }, - detail: "", - certification: "", - textbookName: "", - textbookPrice: 0, - need: "", - instructorName: "", - instructorHistory: [], - educationPlan: "", - }, - ], - latitude: 37.5059054977082, - longitude: 127.109788230628, - city: "서울특별시", + age_range: "", + birth: "", + phone_number: "", + latitude: 0, + longitude: 0, + location: "", }); - const { data, isLoading, isSuccess } = useLectureList(); + const { setLoginedUser: setLoginedUserStore } = useLoginedUserStore(); + + const { + data: loginUserData, + isLoading: isLoginUserLoading, + isSuccess: isLoginUserSuccess, + } = useGetLoginUserInfo(); + + const getHomeLectureList = useHomeLectureList(); + const isLoading = getHomeLectureList.isIdle || getHomeLectureList.isPending; const geolocation = useGeoLocation(); + const router = useRouter(); + // TODO: 멘토님 확인 필요 console.log("1"); 많이 찍히는 문제 + + // FIXME: useEffect 정리 필요 + useEffect(() => { + if (isLoginUserSuccess) { + setLoginedUser((prev) => { + const loginedUserInfo = loginUserData.data.data; + return { + ...prev, + id: loginedUserInfo.id, + email: loginedUserInfo.email, + nickname: loginedUserInfo.nickname, + gender: loginedUserInfo.gender, + age_range: loginedUserInfo.age_range, + birth: loginedUserInfo.birth, + phone_number: loginedUserInfo.phone_number, + location: loginedUserInfo.location, + }; + }); + } + }, [isLoginUserSuccess, loginUserData, setLoginedUserStore]); + useEffect(() => { if ( geolocation.curLocation && @@ -89,10 +97,41 @@ const Home = () => { }, [geolocation.curLocation]); useEffect(() => { - if (isSuccess) { - setLectureListData(data); + if (loginedUser.latitude && loginedUser.longitude) { + getHomeLectureList.mutate( + { + params: { + page: lectureSize.page, + size: lectureSize.size, + dist: lectureSize.dist, + }, + payload: { + latitude: loginedUser.latitude, + longitude: loginedUser.longitude, + }, + // { latitude: 37.4996992, longitude: 127.1169024 }, + }, + { + onSuccess: (data) => { + const lectureListData = data.data.data.data; + const pickLectureListData = data.data.data.pickClasses; + setLectureListData(lectureListData); + sePickLectureListData(pickLectureListData); + }, + onError: () => {}, + }, + ); } - }, [data, isSuccess]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [lectureSize.page, lectureSize.size, loginedUser]); + + useEffect(() => { + setLoginedUserStore(loginedUser); + }, [loginedUser, setLoginedUserStore]); + + const linkToEntireLecture = () => { + router.push("/entire"); + }; const renderColLectureList = () => { if (isLoading) { @@ -124,8 +163,8 @@ const Home = () => { ); } - if (lectureListData && lectureListData.length > 0) { - return ; + if (pickLectureListData && pickLectureListData.length > 0) { + return ; } return ( @@ -133,13 +172,23 @@ const Home = () => { ); }; + // TODO: 캐러셀 + // TODO: 캐러셀 더 불러오기 상태관리 + return (
-
-
📍 내 주변 클래스
-
둘러보기
+
+
+
📍 내 주변 클래스
+
둘러보기
+
+
+ +
{isLoading && } {lectureListData && ( @@ -149,7 +198,6 @@ const Home = () => { lectureListData={lectureListData} /> )} - {/* 로그인 한 사용자의 경우 */}
가장 가까운 순으로 클래스 정보를 보여드릴게요! From 3af09b469d902f4bff6e78af2e2b65cf7fa8a3e8 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:34:06 +0900 Subject: [PATCH 07/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20lecture=20de?= =?UTF-8?q?tail=20page=20using=20get=20lecture=20info=20by=20lectureId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/class/[id]/page.tsx | 47 +++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/app/class/[id]/page.tsx b/src/app/class/[id]/page.tsx index e50a676..f8c4916 100755 --- a/src/app/class/[id]/page.tsx +++ b/src/app/class/[id]/page.tsx @@ -1,5 +1,6 @@ "use client"; +import { Lecture, LecturePayload } from "@/entities/lecture/model/lecture"; import { LectureDetail, LectureFooter, @@ -8,7 +9,7 @@ import { } from "@/entities/lecture/ui"; import { useEffect, useState } from "react"; -import { Lecture } from "@/entities/lecture/model/lecture"; +import { useGeoLocation } from "@/shared/lib/useGeolocation"; import useLectureInfo from "@/entities/lecture/api/useLectureInfo"; import { useParams } from "next/navigation"; @@ -16,15 +17,51 @@ export const runtime = "edge"; const LectureInfoPage = () => { const [lectureInfo, setLectureInfo] = useState(); + const [user, setUser] = useState(); const { id } = useParams(); - const { data, isLoading, isSuccess } = useLectureInfo(Number(id)); + + const getLectureInfo = useLectureInfo(Number(id)); + const isLoading = getLectureInfo.isIdle || getLectureInfo.isPending; + + const geolocation = useGeoLocation(); + + useEffect(() => { + if (user) { + getLectureInfo.mutate( + { + lectureId: Number(id), + payload: { latitude: user.latitude, longitude: user.longitude }, + }, + { + onSuccess: (data) => { + setLectureInfo(data.data.data); + }, + }, + ); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [user, id]); useEffect(() => { - if (isSuccess) { - setLectureInfo(data); + if ( + geolocation.curLocation && + geolocation.curLocation.latitude && + geolocation.curLocation.longitude + ) { + setUser((prev) => { + return { + ...prev, + latitude: geolocation.curLocation + ? geolocation.curLocation.latitude + : 0, + longitude: geolocation.curLocation + ? geolocation.curLocation.longitude + : 0, + }; + }); } - }, [data, isSuccess]); + }, [geolocation.curLocation]); return (
From 67f1bae3b0085618513d99df0455dfb4b619faab Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:34:48 +0900 Subject: [PATCH 08/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20like=20page?= =?UTF-8?q?=20by=20using=20get=20like=20lecuter=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/like/page.tsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/app/like/page.tsx b/src/app/like/page.tsx index cbe11cf..413a067 100755 --- a/src/app/like/page.tsx +++ b/src/app/like/page.tsx @@ -3,16 +3,28 @@ import { LectureList, SkeletonCard } from "@/entities/lecture/ui"; import { useEffect, useState } from "react"; -import { Lecture } from "@/entities/lecture/model/lecture"; +import { HeartsLectureListResDataInfo } from "@/features/like/model/like"; +import { LectureSize } from "@/entities/lecture/model/lecture"; import useLikeLectureList from "@/features/like/api/useLikeLectureList"; const LikePage = () => { - const [lectureListData, setLectureListData] = useState(); - const { data, isLoading, isSuccess } = useLikeLectureList(); + const [lectureListData, setLectureListData] = + useState(); + const [lectureSize, setLectureSize] = useState({ + page: 1, + size: 2, + dist: 500, + }); + + const { data, isLoading, isSuccess } = useLikeLectureList({ + page: lectureSize.page, + size: lectureSize.size, + dist: lectureSize.dist, + }); useEffect(() => { if (isSuccess) { - setLectureListData(data); + setLectureListData(data.data.data); } }, [data, isSuccess]); From 88ad0f54bea3c6dd0c41baed6bae9ca17192fc78 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:35:11 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=E2=9C=A8=20feat:=20update=20Map=20compon?= =?UTF-8?q?ents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/map/ui/Map/Map.tsx | 108 +++++++++++++++++--------------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/src/features/map/ui/Map/Map.tsx b/src/features/map/ui/Map/Map.tsx index dbe0a69..9d170e3 100755 --- a/src/features/map/ui/Map/Map.tsx +++ b/src/features/map/ui/Map/Map.tsx @@ -2,14 +2,14 @@ import { useCallback, useEffect, useMemo, useState } from "react"; -import { Lecture } from "@/entities/lecture/model/lecture"; +import { LectureInfo } from "@/entities/lecture/model/lecture"; export type NaverMap = naver.maps.Map; interface MapProps { latitude: number; longitude: number; - lectureListData: Lecture[]; + lectureListData: LectureInfo[]; } const Map = ({ latitude, longitude, lectureListData }: MapProps) => { @@ -23,6 +23,7 @@ const Map = ({ latitude, longitude, lectureListData }: MapProps) => { return []; }, []); + // 커스텀 훅을 만들어서 useMapInit() -> createPositionMarker 현재 위치 마커, 함수로 ClassMarker 클래스 마커 생성, infoWindow 도 훅으로 그 아래 마커 업데이트는 함수로 생성, 언마운트 하는 코드도 작성 필요성이 있음 const initMap = useCallback(() => { const location = new naver.maps.LatLng(latitude, longitude); @@ -52,57 +53,60 @@ const Map = ({ latitude, longitude, lectureListData }: MapProps) => { }); // 클래스 Marker + lectureListData.forEach((lectureData) => { - const classMarker = new naver.maps.Marker({ - position: new naver.maps.LatLng( - lectureData.latitude, - lectureData.longitude, - ), - title: lectureData.hosted_by, - clickable: true, - map: map, - icon: { - content: `클래스 위치`, - size: new naver.maps.Size(35, 35), - anchor: new naver.maps.Point(11, 35), - }, - }); - - const hostedBy = lectureData.hosted_by; - - // InfoWindow 생성 - const infoWindow = new naver.maps.InfoWindow({ - content: ` -
-
-
- -
-
- ${hostedBy} -
-
-
- 서울 송파구 백제고분로42길 5 송파여성문화회관 -
-
`, - borderWidth: 0, - disableAnchor: true, - backgroundColor: "transparent", - pixelOffset: new naver.maps.Point(0, -8), - }); - - markers.push(classMarker); - infoWindows.push(infoWindow); - - // 마커 클릭 시 InfoWindow 열기 - naver.maps.Event.addListener(classMarker, "click", function () { - // 이미 열려있는 InfoWindow가 있다면 닫기 - infoWindows.forEach((iw) => iw.close()); - - // 클릭한 마커에 해당하는 InfoWindow 열기 - infoWindow.open(map, classMarker); - }); + if (lectureData.latitude && lectureData.longitude) { + const classMarker = new naver.maps.Marker({ + position: new naver.maps.LatLng( + lectureData.latitude, + lectureData.longitude, + ), + title: lectureData.hosted_by, + clickable: true, + map: map, + icon: { + content: `클래스 위치`, + size: new naver.maps.Size(35, 35), + anchor: new naver.maps.Point(11, 35), + }, + }); + + const hostedBy = lectureData.hosted_by; + + // InfoWindow 생성 + const infoWindow = new naver.maps.InfoWindow({ + content: ` +
+
+
+ +
+
+ ${hostedBy} +
+
+
+ 서울 송파구 백제고분로42길 5 송파여성문화회관 +
+
`, + borderWidth: 0, + disableAnchor: true, + backgroundColor: "transparent", + pixelOffset: new naver.maps.Point(0, -8), + }); + + markers.push(classMarker); + infoWindows.push(infoWindow); + + // 마커 클릭 시 InfoWindow 열기 + naver.maps.Event.addListener(classMarker, "click", function () { + // 이미 열려있는 InfoWindow가 있다면 닫기 + infoWindows.forEach((iw) => iw.close()); + + // 클릭한 마커에 해당하는 InfoWindow 열기 + infoWindow.open(map, classMarker); + }); + } }); // 지도 상태가 변경될 때 마커 업데이트 From 517d3ef173326135ba4cb1df3d2156a251b49a02 Mon Sep 17 00:00:00 2001 From: Lawrene Jang Date: Mon, 7 Oct 2024 03:35:34 +0900 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=90=9B=20fix:=20update=20console.lo?= =?UTF-8?q?g=20to=20console.error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/lib/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/lib/utils.ts b/src/shared/lib/utils.ts index 9d140fa..b843ad5 100755 --- a/src/shared/lib/utils.ts +++ b/src/shared/lib/utils.ts @@ -11,6 +11,6 @@ export const handleCopyClipBoard = async (text: string) => { await navigator.clipboard.writeText(text); toast("링크를 복사했어요."); } catch (err) { - console.log(err); + console.error(err); } };