diff --git a/src/api/article.js b/src/api/article.js deleted file mode 100644 index 1f4b15d7..00000000 --- a/src/api/article.js +++ /dev/null @@ -1,46 +0,0 @@ -import { DELETE, GET, POST, PUT } from "../utils/axios"; - -export const getArticleList = async (type, page) => - await GET(`/article?type=${type}&page=${page}`); - -export const getArticleDetail = async (articleId) => - await GET(`/article/${articleId}`, true); - -export const getMyArticleList = async (page) => - await GET(`/article/my?page=${page}`, true); - -export const getMyCommentList = async (page) => - await GET(`/article/comment/my?page=${page}`, true); - -export const postNewArticle = async (body) => - await POST(`/article`, body, true); - -export const updateMyArticle = async (articleId, body) => - await PUT(`/article/${articleId}`, body, true); - -export const deleteMyArticle = async (articleId) => - await DELETE(`/article/${articleId}`, true); - -export const postNewComment = async (articleId, comment) => - await POST(`/article/comment/${articleId}?content=${comment}`, {}, true); - -export const deleteMyComment = async (commentId) => - await DELETE(`/article/comment/${commentId}`, true); - -export const postNewReply = async (commentId, reply) => - await POST(`/article/reply/${commentId}?content=${reply}`, {}, true); - -export const deleteMyReply = async (replyId) => - await DELETE(`/article/reply/${replyId}`, true); - -export const likeArticle = async (articleId) => - await POST(`/article/dibs/${articleId}`, {}, true); - -export const unLikeArticle = async (articleId) => - await DELETE(`/article/dibs/${articleId}`, true); - -export const searchArticle = async (keyword, type, page) => - await GET( - `/article/search?type=${type}&keyword=${keyword}&page=${page}`, - true - ); diff --git a/src/api/article.ts b/src/api/article.ts new file mode 100644 index 00000000..aebd4530 --- /dev/null +++ b/src/api/article.ts @@ -0,0 +1,44 @@ +import { DELETE, GET, POST, PUT } from "../utils/axios"; + +export const getArticleList = async (type: string, page: number) => + await GET(`/article?type=${type}&page=${page}`); + +export const getArticleDetail = async (articleId: string) => + await GET(`/article/${articleId}`, true); + +export const getMyArticleList = async (page: number) => + await GET(`/article/my?page=${page}`, true); + +export const getMyCommentList = async (page: number) => + await GET(`/article/comment/my?page=${page}`, true); + +export const postNewArticle = async (body: any) => + await POST(`/article`, body, true); + +export const updateMyArticle = async (articleId: string, body: any) => + await PUT(`/article/${articleId}`, body, true); + +export const deleteMyArticle = async (articleId: number) => + await DELETE(`/article/${articleId}`, true); + +export const postNewComment = async (articleId: string, comment: string) => + await POST(`/article/comment/${articleId}?content=${comment}`, {}, true); + +export const deleteMyComment = async (commentId: number) => + await DELETE(`/article/comment/${commentId}`, true); + +export const postNewReply = async (commentId: number, reply: string) => + await POST(`/article/reply/${commentId}?content=${reply}`, {}, true); + +export const deleteMyReply = async (replyId: number) => + await DELETE(`/article/reply/${replyId}`, true); + +export const searchArticle = async ( + keyword: string, + type: string, + page: number +) => + await GET( + `/article/search?type=${type}&keyword=${keyword}&page=${page}`, + true + ); diff --git a/src/api/card.js b/src/api/card.ts similarity index 68% rename from src/api/card.js rename to src/api/card.ts index 7527b6fe..88d4220d 100644 --- a/src/api/card.js +++ b/src/api/card.ts @@ -2,11 +2,11 @@ import { GET, POST, DELETE } from "../utils/axios"; export const getCard = async () => await GET("/card", true); -export const postCard = async (body) => await POST("/card", body, true); +export const postCard = async (body: any) => await POST("/card", body, true); export const deleteCard = async () => await DELETE("/card", true); -export const postPaymentAgain = async (reservationId) => +export const postPaymentAgain = async (reservationId: number) => await POST(`/card/${reservationId}`, {}, true); export const getMyPaymentList = async () => await GET("/payment/my", true); diff --git a/src/api/chat.js b/src/api/chat.ts similarity index 55% rename from src/api/chat.js rename to src/api/chat.ts index 4ca262ca..77615384 100644 --- a/src/api/chat.js +++ b/src/api/chat.ts @@ -2,31 +2,31 @@ import { DELETE, GET, POST } from "../utils/axios"; export const getChatList = async () => await GET("/chat/list", true); -export const getChatRoomData = async (chatRoomId) => +export const getChatRoomData = async (chatRoomId: number) => await GET(`/chat/${chatRoomId}`, true); -export const inviteMemberAPI = async (chatRoomId, userIds) => +export const inviteMemberAPI = async (chatRoomId: number, userIds: string) => await POST(`/chat/invite/${chatRoomId}?userId=${userIds}`, {}, true); -export const leaveChat = async (chatRoomId) => +export const leaveChat = async (chatRoomId: number) => await DELETE(`/chat/leave/${chatRoomId}`, true); -export const makeNewGroupChat = async (userIds, roomName) => +export const makeNewGroupChat = async (userIds: string, roomName: string) => await GET(`/chat/groupChat?userId=${userIds}&roomName=${roomName}`, true); -export const makeNewCoupleChat = async (userId) => +export const makeNewCoupleChat = async (userId: number) => await GET(`/chat/coupleChat?userId=${userId}`, true); -export const getPartyChatId = async (partyId) => +export const getPartyChatId = async (partyId: number) => await GET(`/chat/party/${partyId}`, true); export const getChatBlockList = async () => await GET("/chat/block", true); -export const blockUser = async (userId) => +export const blockUser = async (userId: number) => await POST(`/chat/block/${userId}`, {}, true); -export const nonBlockUser = async (userId) => +export const nonBlockUser = async (userId: number) => await DELETE(`/chat/block/${userId}`, true); -export const kickPartyChatUser = async (chatRoomId, userId) => +export const kickPartyChatUser = async (chatRoomId: number, userId: number) => await DELETE(`/chat/party/${chatRoomId}?userId=${userId}`, true); diff --git a/src/api/course.js b/src/api/course.js deleted file mode 100644 index 2fdd064f..00000000 --- a/src/api/course.js +++ /dev/null @@ -1,12 +0,0 @@ -import { DELETE, GET, POST, PUT } from "../utils/axios"; - -export const getCourseDetail = async (courseId) => - await GET(`/course/${courseId}`, true); - -export const postNewCourse = async (data) => await POST("/course", data, true); - -export const putCourseDetail = async (courseId, body) => - await PUT(`/course/${courseId}`, body, true); - -export const deleteCourse = async (courseId) => - await DELETE(`/course/${courseId}`, true); diff --git a/src/api/course.ts b/src/api/course.ts new file mode 100644 index 00000000..e085879f --- /dev/null +++ b/src/api/course.ts @@ -0,0 +1,13 @@ +import { DELETE, GET, POST, PUT } from "../utils/axios"; + +export const getCourseDetail = async (courseId: number | string) => + await GET(`/course/${courseId}`, true); + +export const postNewCourse = async (body: any) => + await POST("/course", body, true); + +export const putCourseDetail = async (courseId: string, body: any) => + await PUT(`/course/${courseId}`, body, true); + +export const deleteCourse = async (courseId: string) => + await DELETE(`/course/${courseId}`, true); diff --git a/src/api/destination.js b/src/api/destination.js deleted file mode 100644 index a0dfe037..00000000 --- a/src/api/destination.js +++ /dev/null @@ -1,39 +0,0 @@ -import { GET, POST, PUT, DELETE } from "../utils/axios"; - -export const getAllMarkers = async () => await GET("/destination/map", true); - -export const getSearchInfo = async (searchKeyword) => - await GET(`/destination?keyword=${searchKeyword}`, true); - -export const getDestinationDetail = async (destinationId) => - await GET(`/destination/${destinationId}`, true); - -export const postDestinationComment = async (data, destinationId) => - await POST(`/destination/review/${destinationId}`, data, true); - -export const putDestinationComment = async (data, reviewId) => - await PUT(`/destination/review/${reviewId}`, data, true); - -export const deleteDestinationComment = async (reviewId) => - await DELETE(`/destination/review/${reviewId}`, true); - -export const postLikeDestination = async (destinationId) => - await POST(`/destination/dibs/${destinationId}`, {}, true); - -export const deleteUnLikeDestination = async (destinationId) => - await DELETE(`/destination/dibs/${destinationId}`, true); - -export const getLikeDestination = async () => - await GET(`/destination/dibs`, true); - -export const postNewDestinationUser = async (body) => - await POST("/destination/by-user", body, true); - -export const postNewDestinationAdmin = async (body) => - await POST("/destination", body, true); - -export const putDestinationAdmin = async (data, destinationId) => - await PUT(`/destination/${destinationId}`, data, true); - -export const deleteDestinationAdmin = async (destinationId) => - await DELETE(`/destination/${destinationId}`, true); diff --git a/src/api/destination.ts b/src/api/destination.ts new file mode 100644 index 00000000..d827da41 --- /dev/null +++ b/src/api/destination.ts @@ -0,0 +1,41 @@ +import { GET, POST, PUT, DELETE } from "../utils/axios"; + +export const getAllMarkers = async () => await GET("/destination/map", true); + +export const getSearchInfo = async (searchKeyword: string) => + await GET(`/destination?keyword=${searchKeyword}`, true); + +export const getDestinationDetail = async (destinationId: number) => + await GET(`/destination/${destinationId}`, true); + +export const postDestinationComment = async ( + data: any, + destinationId: number +) => await POST(`/destination/review/${destinationId}`, data, true); + +export const putDestinationComment = async (data: any, reviewId: number) => + await PUT(`/destination/review/${reviewId}`, data, true); + +export const deleteDestinationComment = async (reviewId: number) => + await DELETE(`/destination/review/${reviewId}`, true); + +export const postLikeDestination = async (destinationId: number) => + await POST(`/destination/dibs/${destinationId}`, {}, true); + +export const deleteUnLikeDestination = async (destinationId: number) => + await DELETE(`/destination/dibs/${destinationId}`, true); + +export const getLikeDestination = async () => + await GET(`/destination/dibs`, true); + +export const postNewDestinationUser = async (body: any) => + await POST("/destination/by-user", body, true); + +export const postNewDestinationAdmin = async (body: any) => + await POST("/destination", body, true); + +export const putDestinationAdmin = async (data: any, destinationId: number) => + await PUT(`/destination/${destinationId}`, data, true); + +export const deleteDestinationAdmin = async (destinationId: number) => + await DELETE(`/destination/${destinationId}`, true); diff --git a/src/api/driver.js b/src/api/driver.ts similarity index 55% rename from src/api/driver.js rename to src/api/driver.ts index fed3788c..1d9f3907 100644 --- a/src/api/driver.js +++ b/src/api/driver.ts @@ -1,34 +1,38 @@ import { POST, GET, PUT, DELETE } from "../utils/axios"; -export const getRegionDriver = async (region, member, date) => +export const getRegionDriver = async ( + region: string, + member: number, + date: string +) => await GET( `/driver/search?region=${region}&headcount=${member}&startDate=${date}`, true ); -export const getDriverInfo = async (driverId) => +export const getDriverInfo = async (driverId: string | number) => await GET(`/driver/${driverId}`, true); -export const postComment = async (data, driverId) => +export const postComment = async (data: any, driverId: number) => await POST(`/driver/review/${driverId}`, data, true); -export const putComment = async (data, reviewId) => +export const putComment = async (data: any, reviewId: number) => await PUT(`/driver/review/${reviewId}`, data, true); -export const deleteComment = async (reviewId) => +export const deleteComment = async (reviewId: number) => await DELETE(`/driver/review/${reviewId}`, true); export const getDriverMyInfo = async () => await GET("/driver/my", true); -export const putDriverMyInfo = async (data) => +export const putDriverMyInfo = async (data: any) => await PUT("/driver/my", data, true); export const getDriverApply = async () => await GET("/driver/apply", true); -export const postDriverApply = async (data) => +export const postDriverApply = async (data: any) => await POST("/driver/apply", data, true); -export const putDriverApply = async (data) => +export const putDriverApply = async (data: any) => await PUT("/driver/apply", data, true); export const deleteDriverApply = async () => @@ -37,5 +41,7 @@ export const deleteDriverApply = async () => export const getDriverApplyAdmin = async () => await GET("/driver/accept", true); -export const putDriverApplyAcceptAdmin = async (driverId, accept) => - await PUT(`/driver/accept/${driverId}?accept=${accept}`, {}, true); +export const putDriverApplyAcceptAdmin = async ( + driverId: string, + accept: boolean +) => await PUT(`/driver/accept/${driverId}?accept=${accept}`, {}, true); diff --git a/src/api/image.js b/src/api/image.ts similarity index 78% rename from src/api/image.js rename to src/api/image.ts index b26910a0..8b84c048 100644 --- a/src/api/image.js +++ b/src/api/image.ts @@ -1,12 +1,13 @@ +import { BASE_SERVER_URL } from "../utils/env"; import axios from "axios"; -export const uploadProfileImage = async (image) => { +export const uploadProfileImage = async (image: File) => { try { const formData = new FormData(); formData.append("file", image); const config = { - baseURL: import.meta.env.VITE_BASE_SERVER_URL, + baseURL: BASE_SERVER_URL, withCredentials: true, headers: { "Contest-Type": "multipart/form-data", @@ -20,13 +21,13 @@ export const uploadProfileImage = async (image) => { } }; -export const uploadImage = async (image) => { +export const uploadImage = async (image: File) => { try { const formData = new FormData(); formData.append("file", image); const config = { - baseURL: import.meta.env.VITE_BASE_SERVER_URL, + baseURL: BASE_SERVER_URL, withCredentials: true, headers: { "Contest-Type": "multipart/form-data", diff --git a/src/api/income.js b/src/api/income.ts similarity index 74% rename from src/api/income.js rename to src/api/income.ts index 8baa6045..300de172 100644 --- a/src/api/income.js +++ b/src/api/income.ts @@ -1,6 +1,6 @@ import { GET } from "../utils/axios"; -export const getDriverMonthlyIncome = async (month) => +export const getDriverMonthlyIncome = async (month: string) => await GET(`/income/monthly?month=${month}`, true); export const getCommisionRate = async () => diff --git a/src/api/notification.js b/src/api/notification.ts similarity index 55% rename from src/api/notification.js rename to src/api/notification.ts index c4d595ee..b60467c5 100644 --- a/src/api/notification.js +++ b/src/api/notification.ts @@ -1,18 +1,18 @@ -import { GET, PUT, DELETE, POST } from "../utils/axios"; +import { GET, PUT, DELETE } from "../utils/axios"; export const getNotification = async () => await GET("/notification", true); -export const putNotification = async (notificationId) => +export const putNotification = async (notificationId: number) => await PUT(`/notification/${notificationId}`, {}, true); -export const deleteNotification = async (notificationId) => +export const deleteNotification = async (notificationId: number) => await DELETE(`/notification/${notificationId}`, true); export const putAllNotification = async () => await PUT("/notification/all", {}, true); -export const putFirebaseToken = async (body) => +export const putFirebaseToken = async (body: any) => await PUT("/firebase", body, true); -export const deleteFirebaseToken = async (body) => +export const deleteFirebaseToken = async (body: any) => await DELETE("/firebase", true, body); diff --git a/src/api/party.js b/src/api/party.ts similarity index 55% rename from src/api/party.js rename to src/api/party.ts index ffee2163..401183d7 100644 --- a/src/api/party.js +++ b/src/api/party.ts @@ -1,49 +1,54 @@ import { DELETE, GET, POST, PUT } from "../utils/axios"; -export const getPartyList = async (region, nowDate, num, price) => +export const getPartyList = async ( + region: string, + nowDate: string[], + num: number, + price: string | number +) => await GET( `/party/search?region=${region}&headcount=${num}&startDate=${nowDate[0]}&endDate=${nowDate[1]}&maxPrice=${price}` ); -export const getPartyDetail = async (partyId) => +export const getPartyDetail = async (partyId: string) => await GET(`/party/${partyId}`, true); -export const postLikeParty = async (partyId) => +export const postLikeParty = async (partyId: number) => await POST(`/party/dibs/${partyId}`, {}, true); -export const deleteUnLikeParty = async (partyId) => +export const deleteUnLikeParty = async (partyId: number) => await DELETE(`/party/dibs/${partyId}`, true); export const getLikeParty = async () => await GET("/party/dibs", true); -export const postPartyJoin = async (partyId, data) => +export const postPartyJoin = async (partyId: string, data: any) => await POST(`/party/join/${partyId}`, data, true); -export const putMallangReady = async (partyId, ready) => +export const putMallangReady = async (partyId: string, ready: boolean) => await PUT(`/party/ready/${partyId}?ready=${ready}`, {}, true); -export const putPartyCourse = async (partyId, body) => +export const putPartyCourse = async (partyId: string, body: any) => await PUT(`/party/course/${partyId}`, body, true); -export const putProposalAccept = async (proposalId, accept) => +export const putProposalAccept = async (proposalId: number, accept: boolean) => await PUT(`/party/proposal/${proposalId}?accept=${accept}`, {}, true); -export const deleteProposalCancel = async (proposalId) => +export const deleteProposalCancel = async (proposalId: number) => await DELETE(`/party/proposal/${proposalId}`, true); -export const deleteQuitParty = async (partyId) => +export const deleteQuitParty = async (partyId: string) => await DELETE(`/party/quit/${partyId}`, true); -export const deleteQuitReservationParty = async (partyId) => +export const deleteQuitReservationParty = async (partyId: string) => await DELETE(`/party/reservation/${partyId}`, true); -export const postNewParty = async (data) => +export const postNewParty = async (data: any) => await POST("/party/create", data, true); -export const deleteNewParty = async (partyId) => +export const deleteNewParty = async (partyId: string) => await DELETE(`/party/create/${partyId}`, true); -export const putNewPartyAccept = async (partyId, accept) => +export const putNewPartyAccept = async (partyId: string, accept: boolean) => await PUT(`/party/create/${partyId}?accept=${accept}`, {}, true); export const getPartyHistory = async () => await GET("/party/history", true); diff --git a/src/api/profile.js b/src/api/profile.js deleted file mode 100644 index 10a42117..00000000 --- a/src/api/profile.js +++ /dev/null @@ -1,5 +0,0 @@ -import { PUT } from "../utils/axios"; - -export const putProfile = async (data) => await PUT(`/profile`, data, true); - -export const putPassword = async (data) => await PUT(`/password`, data, true); diff --git a/src/api/profile.ts b/src/api/profile.ts new file mode 100644 index 00000000..368c4cd0 --- /dev/null +++ b/src/api/profile.ts @@ -0,0 +1,7 @@ +import { PUT } from "../utils/axios"; + +export const putProfile = async (data: any) => + await PUT(`/profile`, data, true); + +export const putPassword = async (data: any) => + await PUT(`/password`, data, true); diff --git a/src/api/region.js b/src/api/region.ts similarity index 54% rename from src/api/region.js rename to src/api/region.ts index 4d722528..bf61e298 100644 --- a/src/api/region.js +++ b/src/api/region.ts @@ -2,14 +2,14 @@ import { GET, POST, PUT, DELETE } from "../utils/axios"; export const getPartyRegionList = async () => await GET("/region"); -export const postNewPartyRegion = async (body) => +export const postNewPartyRegion = async (body: any) => await POST("/region", body, true); -export const putPartyRegion = async (regionId, body) => +export const putPartyRegion = async (regionId: number, body: any) => await PUT(`/region/${regionId}`, body, true); -export const deletePartyRegion = async (regionId) => +export const deletePartyRegion = async (regionId: number) => await DELETE(`/region/${regionId}`, true); -export const getPartyRegionDriverList = async (regionId) => +export const getPartyRegionDriverList = async (regionId: string) => await GET(`/region/driver/${regionId}`, true); diff --git a/src/api/users.js b/src/api/users.js deleted file mode 100644 index cbb0a8d1..00000000 --- a/src/api/users.js +++ /dev/null @@ -1,33 +0,0 @@ -import { GET, POST, PUT, DELETE } from "../utils/axios"; - -export const signup = async (data) => await POST("/signup", data); - -export const login = async (data) => await POST("/login", data); - -export const auth = async () => await GET("/auth", true); - -export const refresh = async () => await GET("/refresh-token", true); - -export const checkDuplication = async (type, value) => - await GET(`/check-duplication?type=${type}&value=${value}`); - -export const getCertificationCode = async (phoneNumber) => - await GET(`/certification?phoneNumber=${phoneNumber}`); - -export const searchId = async (phoneNumber, code) => - await GET(`/certification/id?phoneNumber=${phoneNumber}&code=${code}`); - -export const searchPassword = async (phoneNumber, code) => - await GET(`/certification/password?phoneNumber=${phoneNumber}&code=${code}`); - -export const putNewPassword = async (data) => - await PUT(`/certification/password`, data); - -export const searchUser = async (nickName) => - await GET(`/user/search?nickname=${nickName}`, true); - -export const getUserInfo = async (userId) => await GET(`/user/info/${userId}`); - -export const deleteUser = async () => await DELETE("/user/withdrawal", true); - -export const postNewReport = async (body) => await POST("/report", body, true); diff --git a/src/api/users.ts b/src/api/users.ts new file mode 100644 index 00000000..c778e1ed --- /dev/null +++ b/src/api/users.ts @@ -0,0 +1,35 @@ +import { GET, POST, PUT, DELETE } from "../utils/axios"; + +export const signup = async (data: any) => await POST("/signup", data); + +export const login = async (data: any) => await POST("/login", data); + +export const auth = async () => await GET("/auth", true); + +export const refresh = async () => await GET("/refresh-token", true); + +export const checkDuplication = async (type: string, value: string) => + await GET(`/check-duplication?type=${type}&value=${value}`); + +export const getCertificationCode = async (phoneNumber: string) => + await GET(`/certification?phoneNumber=${phoneNumber}`); + +export const searchId = async (phoneNumber: string, code: string) => + await GET(`/certification/id?phoneNumber=${phoneNumber}&code=${code}`); + +export const searchPassword = async (phoneNumber: string, code: string) => + await GET(`/certification/password?phoneNumber=${phoneNumber}&code=${code}`); + +export const putNewPassword = async (data: any) => + await PUT(`/certification/password`, data); + +export const searchUser = async (nickName: string) => + await GET(`/user/search?nickname=${nickName}`, true); + +export const getUserInfo = async (userId: number) => + await GET(`/user/info/${userId}`); + +export const deleteUser = async () => await DELETE("/user/withdrawal", true); + +export const postNewReport = async (body: any) => + await POST("/report", body, true); diff --git a/src/components/PartyPlan/index.tsx b/src/components/PartyPlan/index.tsx index 6c390a03..8f279cd0 100644 --- a/src/components/PartyPlan/index.tsx +++ b/src/components/PartyPlan/index.tsx @@ -6,7 +6,7 @@ interface Props { edit: boolean; startDate: string; editHandler?: () => void; - comment?: boolean; + comment?: string; course: Course; } diff --git a/src/components/PassCheck/index.tsx b/src/components/PassCheck/index.tsx index 35e6bf3d..ab447a5b 100644 --- a/src/components/PassCheck/index.tsx +++ b/src/components/PassCheck/index.tsx @@ -1,5 +1,5 @@ import { memo, useCallback, useEffect, useState } from "react"; -import { passPopupURL } from "../../utils/pass"; +import { passPopupURL } from "../../utils/env"; import ConfirmModal from "../ConfirmModal"; import passLogo from "../../assets/images/PASS-Logo.png"; import passArrow from "../../assets/svg/Pass-Mobile-Arrow.svg"; diff --git a/src/components/PlaceMap/DestinationModal/index.tsx b/src/components/PlaceMap/DestinationModal/index.tsx index 2e98b02b..0c2deb58 100644 --- a/src/components/PlaceMap/DestinationModal/index.tsx +++ b/src/components/PlaceMap/DestinationModal/index.tsx @@ -87,6 +87,7 @@ function DestinationModal({ }, [courseData, clickedData]); const heartClickHandler = useCallback(async () => { + if (!clickedData?.destinationId) return; if (!user.auth) return setShowLoginModal(true); try { diff --git a/src/components/PlaceMap/index.tsx b/src/components/PlaceMap/index.tsx index 80ff0be6..ee65dd03 100644 --- a/src/components/PlaceMap/index.tsx +++ b/src/components/PlaceMap/index.tsx @@ -18,7 +18,7 @@ import NewPlaceModal from "./NewPlaceModal"; interface Props { search: boolean; - keyword: string; + keyword?: string; searchPage: boolean; onlyAllPlace: boolean; courseData?: Destination[]; diff --git a/src/components/ProfileModal/ButtonBox/AdminButtonList/index.tsx b/src/components/ProfileModal/ButtonBox/AdminButtonList/index.tsx index 5b35685d..9456ac90 100644 --- a/src/components/ProfileModal/ButtonBox/AdminButtonList/index.tsx +++ b/src/components/ProfileModal/ButtonBox/AdminButtonList/index.tsx @@ -32,6 +32,7 @@ function AdminButtonList({ const [showConfirmModal, setShowConfirmModal] = useState(false); const goCoupleChat = useCallback(async () => { + if (!userId) return; try { const result = await makeNewCoupleChat(userId); dispatch(setPartyRoomId(result.payload.chatRoomId)); diff --git a/src/components/ProfileModal/ButtonBox/ButtonList/BlockModal/index.tsx b/src/components/ProfileModal/ButtonBox/ButtonList/BlockModal/index.tsx index ebc8f7fd..f5dfb4de 100644 --- a/src/components/ProfileModal/ButtonBox/ButtonList/BlockModal/index.tsx +++ b/src/components/ProfileModal/ButtonBox/ButtonList/BlockModal/index.tsx @@ -36,6 +36,7 @@ function BlockModal({ const blockChatUser = useCallback(async () => { if (loading) return; + if (!userId) return; try { setLoading(true); diff --git a/src/components/ProfileModal/ButtonBox/ButtonList/index.tsx b/src/components/ProfileModal/ButtonBox/ButtonList/index.tsx index ca5c49a6..5ce0dca2 100644 --- a/src/components/ProfileModal/ButtonBox/ButtonList/index.tsx +++ b/src/components/ProfileModal/ButtonBox/ButtonList/index.tsx @@ -35,6 +35,7 @@ function ButtonList({ userId, setShowModal, nickname, chatRoomId }: Props) { const [isChatBlock, setIsChatBlock] = useState(false); const goCoupleChat = useCallback(async () => { + if (!userId) return; if (!user.auth) return setShowLoginModal(true); if (isChatBlock) return setShowErrorModal(true); diff --git a/src/components/ProfileModal/ProfileInfo/index.tsx b/src/components/ProfileModal/ProfileInfo/index.tsx index dd1ae462..f93c0d12 100644 --- a/src/components/ProfileModal/ProfileInfo/index.tsx +++ b/src/components/ProfileModal/ProfileInfo/index.tsx @@ -8,7 +8,7 @@ interface Props { nickname: string | undefined; introduction: string | undefined; createdAt: string | undefined; - driverName: boolean; + driverName: string | boolean; } function ProfileInfo({ diff --git a/src/components/ProfileModal/index.tsx b/src/components/ProfileModal/index.tsx index 6a5b93e5..76637852 100644 --- a/src/components/ProfileModal/index.tsx +++ b/src/components/ProfileModal/index.tsx @@ -23,7 +23,7 @@ interface Props { userId?: number; chatRoomId?: number; reportId?: number; - driverName: boolean; + driverName: string | boolean; } function ProfileModal({ diff --git a/src/components/PushNotification/index.tsx b/src/components/PushNotification/index.tsx index bb7b61c3..5b7f1ddb 100644 --- a/src/components/PushNotification/index.tsx +++ b/src/components/PushNotification/index.tsx @@ -2,7 +2,8 @@ import { memo, useCallback, useEffect, useState } from "react"; import { useSelector } from "react-redux"; import { RootState } from "../../redux/store"; import { getToken, isSupported } from "firebase/messaging"; -import { messaging, vapidKey } from "../../utils/firebase"; +import { messaging } from "../../utils/firebase"; +import { vapidKey } from "../../utils/env"; import { putFirebaseToken } from "../../api/notification"; import CheckModal from "./CheckModal"; diff --git a/src/pages/AdminPage/CustomerService/Help/EditForm/index.tsx b/src/pages/AdminPage/CustomerService/Help/EditForm/index.tsx index 4e639741..e058783e 100644 --- a/src/pages/AdminPage/CustomerService/Help/EditForm/index.tsx +++ b/src/pages/AdminPage/CustomerService/Help/EditForm/index.tsx @@ -59,7 +59,9 @@ function EditForm({ images .filter((image) => image) .map(async (image) => - typeof image === "string" ? image : await uploadImage(image) + typeof image === "string" + ? image + : image && (await uploadImage(image)) ) ); const body = { diff --git a/src/pages/AdminPage/Management/Party/PartyDetail/index.tsx b/src/pages/AdminPage/Management/Party/PartyDetail/index.tsx index e3247554..6f490f98 100644 --- a/src/pages/AdminPage/Management/Party/PartyDetail/index.tsx +++ b/src/pages/AdminPage/Management/Party/PartyDetail/index.tsx @@ -62,16 +62,9 @@ function PartyDetail({ partyId }: Props) { {partyData.partyStatus === "CANCELED_BY_DRIVER_REFUSED" || partyData.partyStatus === "CANCELED_BY_PROPOSER" || diff --git a/src/pages/AdminPage/Management/Place/DestinationModal/index.tsx b/src/pages/AdminPage/Management/Place/DestinationModal/index.tsx index 53b380c6..16e02b28 100644 --- a/src/pages/AdminPage/Management/Place/DestinationModal/index.tsx +++ b/src/pages/AdminPage/Management/Place/DestinationModal/index.tsx @@ -185,9 +185,11 @@ function DestinationModal({ ) : ( <> typeof image === "string" - )} + images={ + destinationInfo.images.filter( + (image) => typeof image === "string" + ) as string[] + } name={destinationInfo.name} />
diff --git a/src/pages/AdminPage/Management/Region/RegionDriver/index.tsx b/src/pages/AdminPage/Management/Region/RegionDriver/index.tsx index b375d053..492380c3 100644 --- a/src/pages/AdminPage/Management/Region/RegionDriver/index.tsx +++ b/src/pages/AdminPage/Management/Region/RegionDriver/index.tsx @@ -15,6 +15,8 @@ function RegionDriver() { const regionName = searchParams.get("region_name"); const getPartyRegionDriverListFunc = useCallback(async () => { + if (!regionId) return; + try { const result = await getPartyRegionDriverList(regionId); setRegionDriverData(result.payload); diff --git a/src/pages/AdminPage/Management/Region/RegionList/NewRegion/FormModal/index.tsx b/src/pages/AdminPage/Management/Region/RegionList/NewRegion/FormModal/index.tsx index 6fde9d2a..f7fdcc4e 100644 --- a/src/pages/AdminPage/Management/Region/RegionList/NewRegion/FormModal/index.tsx +++ b/src/pages/AdminPage/Management/Region/RegionList/NewRegion/FormModal/index.tsx @@ -32,7 +32,10 @@ function FormModal({ showModal, setShowModal, getPartyRegionListFunc }: Props) { if (!regionImg) return alert("지역 사진을 입력해주세요."); try { - const regionImgURL = await uploadImage(regionImg); + const regionImgURL = + typeof regionImg === "string" + ? regionImg + : await uploadImage(regionImg); const body = { name: region, image: regionImgURL, diff --git a/src/pages/AdminPage/Management/Region/RegionList/index.tsx b/src/pages/AdminPage/Management/Region/RegionList/index.tsx index 93d9d195..688cb55e 100644 --- a/src/pages/AdminPage/Management/Region/RegionList/index.tsx +++ b/src/pages/AdminPage/Management/Region/RegionList/index.tsx @@ -1,5 +1,5 @@ import { Dispatch, memo, SetStateAction, useState } from "react"; -import { RegionData } from ".."; +import { RegionData } from "../../../../../types"; import NewRegion from "./NewRegion"; import RegionItem from "./RegionItem"; import EditFormModal from "./EditFormModal"; diff --git a/src/pages/AdminPage/Management/Region/index.tsx b/src/pages/AdminPage/Management/Region/index.tsx index ab39d8df..07277f47 100644 --- a/src/pages/AdminPage/Management/Region/index.tsx +++ b/src/pages/AdminPage/Management/Region/index.tsx @@ -1,19 +1,13 @@ import { memo, useCallback, useEffect, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { getPartyRegionList } from "../../../../api/region"; +import { RegionData } from "../../../../types"; import Title from "../../../../components/Title"; import ConfirmModal from "../../../../components/ConfirmModal"; import SearchBar from "./SearchBar"; import RegionList from "./RegionList"; import RegionDriver from "./RegionDriver"; -export interface RegionData { - image: string; - name: string; - province: string; - regionId: number; -} - function Region() { const [searchParams] = useSearchParams(); const [searchKeyword, setSearchKeyword] = useState(""); diff --git a/src/pages/AdminPage/User/DriverRegistration/DriverDetail/AcceptButton/index.tsx b/src/pages/AdminPage/User/DriverRegistration/DriverDetail/AcceptButton/index.tsx index a88e010a..fe3877de 100644 --- a/src/pages/AdminPage/User/DriverRegistration/DriverDetail/AcceptButton/index.tsx +++ b/src/pages/AdminPage/User/DriverRegistration/DriverDetail/AcceptButton/index.tsx @@ -17,6 +17,7 @@ function AcceptButton({ getDriverApplyAdminFunc }: Props) { const driverApplyAcceptHandler = useCallback( async (accept: boolean) => { + if (!driverId) return; try { await putDriverApplyAcceptAdmin(driverId, accept); @@ -33,8 +34,9 @@ function AcceptButton({ getDriverApplyAdminFunc }: Props) { ); const goDriverChat = useCallback(async () => { + if (!driverId) return; try { - const result = await makeNewCoupleChat(driverId); + const result = await makeNewCoupleChat(Number(driverId)); dispatch(setPartyRoomId(result.payload.chatRoomId)); navigation("/talk"); } catch (e) { diff --git a/src/pages/AdminPage/User/UserInfo/UserTable/RegionModal/index.tsx b/src/pages/AdminPage/User/UserInfo/UserTable/RegionModal/index.tsx index 08895f6f..5c9812ff 100644 --- a/src/pages/AdminPage/User/UserInfo/UserTable/RegionModal/index.tsx +++ b/src/pages/AdminPage/User/UserInfo/UserTable/RegionModal/index.tsx @@ -12,6 +12,7 @@ import { createPortal } from "react-dom"; import { useNavigate } from "react-router-dom"; import { postApplyDriver } from "../../../../../../api/admin"; import { getPartyRegionList } from "../../../../../../api/region"; +import { RegionData } from "../../../../../../types"; import RegionButton from "./RegionButton"; import clsx from "clsx"; @@ -25,13 +26,7 @@ function RegionModal({ showModal, setShowModal, userId }: Props) { const navigation = useNavigate(); const modalRef = useRef(null); const [selectedRegion, setSelectedRegion] = useState([]); - const [regionData, setRegionData] = useState< - { - image: string; - name: string; - regionId: number; - }[] - >([]); + const [regionData, setRegionData] = useState([]); const regionClickHandler = useCallback(async () => { try { diff --git a/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentForm/index.tsx b/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentForm/index.tsx index 2bad6c8a..641df5e8 100644 --- a/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentForm/index.tsx +++ b/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentForm/index.tsx @@ -17,6 +17,7 @@ function CommentForm({ getArticleDetailFunc }: Props) { const commentSubmitHandler = useCallback( async (event: FormEvent) => { event.preventDefault(); + if (!articleId) return; try { await postNewComment(articleId, newComment); diff --git a/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/ReplyItem/index.tsx b/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/ReplyItem/index.tsx index 44f5e32e..59b168af 100644 --- a/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/ReplyItem/index.tsx +++ b/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/ReplyItem/index.tsx @@ -68,7 +68,7 @@ function ReplyItem({

{nickname}

- {dateToGapKorean(createdAt)} + {dateToGapKorean(createdAt, false)}

diff --git a/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/index.tsx b/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/index.tsx index 49675b1b..3ed1adbd 100644 --- a/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/index.tsx +++ b/src/pages/CommunityPage/ArticleDetail/ArticleComment/CommentItem/index.tsx @@ -71,7 +71,7 @@ function CommentItem({

{nickname}

- {dateToGapKorean(createdAt)} + {dateToGapKorean(createdAt, false)}

diff --git a/src/pages/CommunityPage/ArticleDetail/index.tsx b/src/pages/CommunityPage/ArticleDetail/index.tsx index f6d286f0..3cf1d8e7 100644 --- a/src/pages/CommunityPage/ArticleDetail/index.tsx +++ b/src/pages/CommunityPage/ArticleDetail/index.tsx @@ -33,6 +33,7 @@ function ArticleDetail({ getArticleListFunc }: Props) { }); const getArticleDetailFunc = useCallback(async () => { + if (!articleId) return; try { const result = await getArticleDetail(articleId); diff --git a/src/pages/CommunityPostPage/ArticleInfoForm/ImageInputBox/ImageInput/index.tsx b/src/pages/CommunityPostPage/ArticleInfoForm/ImageInputBox/ImageInput/index.tsx index 590d56fa..59945a2e 100644 --- a/src/pages/CommunityPostPage/ArticleInfoForm/ImageInputBox/ImageInput/index.tsx +++ b/src/pages/CommunityPostPage/ArticleInfoForm/ImageInputBox/ImageInput/index.tsx @@ -4,6 +4,7 @@ import { MouseEvent, SetStateAction, useCallback, + useMemo, useRef, useState, } from "react"; @@ -40,24 +41,32 @@ function ImageInput({ images, setImages, index }: Props) { [images, index] ); + const image = useMemo(() => images[index], [images, index]); + + const imagesSrc = useMemo( + () => + typeof image === "string" + ? image + : image instanceof File + ? URL.createObjectURL(image) + : undefined, + [image] + ); + return ( <>
imageRef.current?.click()} > - {images[index] ? ( + {imagesSrc ? (
setDeleteMode(true)} onMouseLeave={() => setDeleteMode(false)} > Article_Image diff --git a/src/pages/CommunityPostPage/index.tsx b/src/pages/CommunityPostPage/index.tsx index 7dba9a56..82529401 100644 --- a/src/pages/CommunityPostPage/index.tsx +++ b/src/pages/CommunityPostPage/index.tsx @@ -56,6 +56,7 @@ function CommunityPostPage() { async (event: FormEvent) => { event.preventDefault(); + if (!articleId) return; if (selectedType === "선택해주세요.") return showModalHandler("게시판을 선택해주세요."); if (title === "") return showModalHandler("제목을 입력해주세요."); @@ -117,6 +118,7 @@ function CommunityPostPage() { ); const getArticleData = useCallback(async () => { + if (!articleId) return; try { const result = await getArticleDetail(articleId); diff --git a/src/pages/CommunitySearchPage/index.tsx b/src/pages/CommunitySearchPage/index.tsx index 933bf63c..bf9e188e 100644 --- a/src/pages/CommunitySearchPage/index.tsx +++ b/src/pages/CommunitySearchPage/index.tsx @@ -20,6 +20,7 @@ function CommunitySearchPage() { const getArticleData = useCallback(async () => { if (page >= totalPages) return; + if (!keyword) return; try { const result = await searchArticle(keyword, "all", page); diff --git a/src/pages/DestinationPage/index.tsx b/src/pages/DestinationPage/index.tsx index 47051808..3b4473a9 100644 --- a/src/pages/DestinationPage/index.tsx +++ b/src/pages/DestinationPage/index.tsx @@ -30,8 +30,9 @@ function DestinationPage() { }); const getDestinationInfo = useCallback(async () => { + if (!destinationId) return; try { - const result = await getDestinationDetail(destinationId); + const result = await getDestinationDetail(Number(destinationId)); setDestinationInfo(result.payload); } catch (e) { console.log(e); diff --git a/src/pages/DriverApplyPage/RegionList/index.tsx b/src/pages/DriverApplyPage/RegionList/index.tsx index 56719796..43e07cfb 100644 --- a/src/pages/DriverApplyPage/RegionList/index.tsx +++ b/src/pages/DriverApplyPage/RegionList/index.tsx @@ -7,15 +7,9 @@ import { useState, } from "react"; import { getPartyRegionList } from "../../../api/region"; +import { RegionData } from "../../../types"; import Region from "./Region"; -interface RegionType { - image: string; - name: string; - province: string; - regionId: number; -} - interface Props { setActiveNext: Dispatch>; region: string[]; @@ -23,7 +17,7 @@ interface Props { } function RegionList({ setActiveNext, region, setRegion }: Props) { - const [regionData, setRegionData] = useState([]); + const [regionData, setRegionData] = useState([]); const getPartyRegionListFunc = useCallback(async () => { try { diff --git a/src/pages/DriverCoursePage/index.tsx b/src/pages/DriverCoursePage/index.tsx index 5de10ae7..849c7985 100644 --- a/src/pages/DriverCoursePage/index.tsx +++ b/src/pages/DriverCoursePage/index.tsx @@ -23,8 +23,8 @@ import CourseImage from "./CourseImage"; import CourseInfo from "./CourseInfo"; import PriceList from "./PriceList"; -interface DestinationState extends Destination { - image?: string | string[]; +interface DestinationImage extends Destination { + image?: string | File; } function DriverCoursePage() { @@ -36,7 +36,7 @@ function DriverCoursePage() { const [capacity, setCapacity] = useState(0); const [prices, setPrices] = useState<{ hours: number; price: number }[]>([]); const [priceIndex, setPriceIndex] = useState(0); - const [destinations, setDestinations] = useState([]); + const [destinations, setDestinations] = useState([]); const [startTime, setStartTime] = useState("10:00"); const [endTime, setEndTime] = useState(""); const [errorMessage, setErrorMessage] = useState(""); @@ -47,6 +47,8 @@ function DriverCoursePage() { const [courseRegion, setCourseRegion] = useState(""); const saveCourse = useCallback(async () => { + if (!courseId) return; + const destinationImages = destinations.reduce((acc, cur) => { if (typeof cur.image === "string") { acc.push(cur.image); @@ -147,7 +149,7 @@ function DriverCoursePage() { setPrices(driverResult.payload.prices); setDriverRegion(driverResult.payload.region); - if (courseId !== "new") { + if (courseId !== "new" && courseId) { const courseResult = await getCourseDetail(courseId); setCourseRegion(courseResult.payload.region); setName(courseResult.payload.name); diff --git a/src/pages/DriverProfilePage/IconBox/index.tsx b/src/pages/DriverProfilePage/IconBox/index.tsx index bd7efc75..a6456c8b 100644 --- a/src/pages/DriverProfilePage/IconBox/index.tsx +++ b/src/pages/DriverProfilePage/IconBox/index.tsx @@ -25,9 +25,10 @@ function IconBox({ images, name, introduction }: Props) { const goDriverChat = useCallback(async () => { if (!user.auth) return setShowLoginModal(true); + if (!driverId) return; try { - const result = await makeNewCoupleChat(driverId); + const result = await makeNewCoupleChat(Number(driverId)); dispatch(setPartyRoomId(result.payload.chatRoomId)); navigation("/talk"); } catch (e) { diff --git a/src/pages/DriverProfilePage/index.tsx b/src/pages/DriverProfilePage/index.tsx index 03c57471..736a47af 100644 --- a/src/pages/DriverProfilePage/index.tsx +++ b/src/pages/DriverProfilePage/index.tsx @@ -61,6 +61,7 @@ function DriverProfilePage() { ); const settingDriverInfo = useCallback(async () => { + if (!driverId) return; try { const result = await getDriverInfo(driverId); setDriverInfo(result.payload); diff --git a/src/pages/LandingPage/PartyFilter/RegionModal/index.tsx b/src/pages/LandingPage/PartyFilter/RegionModal/index.tsx index dff88952..612ab2f8 100644 --- a/src/pages/LandingPage/PartyFilter/RegionModal/index.tsx +++ b/src/pages/LandingPage/PartyFilter/RegionModal/index.tsx @@ -13,16 +13,10 @@ import { useDispatch, useSelector } from "react-redux"; import { setRegion } from "../../../../redux/modules/partyFilterSlice"; import { getPartyRegionList } from "../../../../api/region"; import { RootState } from "../../../../redux/store"; +import { RegionData } from "../../../../types"; import RegionButton from "./RegionButton"; import clsx from "clsx"; -interface RegionType { - image: string; - name: string; - province: string | null; - regionId: number; -} - interface Props { showModal: boolean; setShowModal: Dispatch>; @@ -38,7 +32,7 @@ function RegionModal({ const modalRef = useRef(null); const region = useSelector((state: RootState) => state.partyFilter.region); const [selectedRegion, setSelectedRegion] = useState(""); - const [regionData, setRegionData] = useState([]); + const [regionData, setRegionData] = useState([]); const regionClickHandler = useCallback((target: string) => { setShowModal(false); diff --git a/src/pages/MyHeartPage/HeartItem/index.tsx b/src/pages/MyHeartPage/HeartItem/index.tsx index f6611d17..032d6a4d 100644 --- a/src/pages/MyHeartPage/HeartItem/index.tsx +++ b/src/pages/MyHeartPage/HeartItem/index.tsx @@ -32,6 +32,7 @@ function HeartItem({ const heartClickHandler = useCallback( async (e: MouseEvent) => { e.stopPropagation(); + if (!destinationId) return; try { heart diff --git a/src/pages/MyProfilePage/DriverProfile/BasicInfo/RegionModal/index.tsx b/src/pages/MyProfilePage/DriverProfile/BasicInfo/RegionModal/index.tsx index a4926779..025b9eac 100644 --- a/src/pages/MyProfilePage/DriverProfile/BasicInfo/RegionModal/index.tsx +++ b/src/pages/MyProfilePage/DriverProfile/BasicInfo/RegionModal/index.tsx @@ -9,17 +9,10 @@ import { useState, } from "react"; import { getPartyRegionList } from "../../../../../api/region"; -import { DriverInfo } from "../../../../../types"; +import { DriverInfo, RegionData } from "../../../../../types"; import Region from "./Region"; import clsx from "clsx"; -interface RegionData { - image: string; - name: string; - province: string | null; - regionId: number; -} - interface Props { showModal: boolean; setShowModal: Dispatch>; diff --git a/src/pages/NewPartyPage/Region/index.tsx b/src/pages/NewPartyPage/Region/index.tsx index da663169..56cd7671 100644 --- a/src/pages/NewPartyPage/Region/index.tsx +++ b/src/pages/NewPartyPage/Region/index.tsx @@ -7,7 +7,7 @@ import { useState, } from "react"; import { getPartyRegionList } from "../../../api/region"; -import { DriverInfo, Review } from "../../../types"; +import { DriverInfo, RegionData, Review } from "../../../types"; import CheckModal from "../../../components/CheckModal"; import Title from "../../../components/Title"; import RegionButton from "./RegionButton"; @@ -19,13 +19,6 @@ interface DriverInfoType extends DriverInfo { reviews: Review[]; } -interface RegionData { - image: string; - name: string; - province: string | null; - regionId: number; -} - interface Props { setRegion: Dispatch>; member: number; diff --git a/src/pages/PartyPage/CancelNewPartyButton/CancelModal/index.jsx b/src/pages/PartyPage/CancelNewPartyButton/CancelModal/index.tsx similarity index 63% rename from src/pages/PartyPage/CancelNewPartyButton/CancelModal/index.jsx rename to src/pages/PartyPage/CancelNewPartyButton/CancelModal/index.tsx index dd858252..81e4ca60 100644 --- a/src/pages/PartyPage/CancelNewPartyButton/CancelModal/index.jsx +++ b/src/pages/PartyPage/CancelNewPartyButton/CancelModal/index.tsx @@ -1,17 +1,32 @@ -import { useEffect, useRef, useState } from "react"; +import { + Dispatch, + memo, + MouseEvent, + SetStateAction, + useCallback, + useEffect, + useRef, + useState, +} from "react"; import { useNavigate, useParams } from "react-router-dom"; import { deleteNewParty } from "../../../../api/party"; +import clsx from "clsx"; -function CancelModal({ showModal, setShowModal }) { +interface Props { + showModal: boolean; + setShowModal: Dispatch>; +} + +function CancelModal({ showModal, setShowModal }: Props) { const navigation = useNavigate(); - const modalRef = useRef(); + const modalRef = useRef(null); const { partyId } = useParams(); const [message, setMessage] = useState(""); const [complete, setComplete] = useState(false); const [loading, setLoading] = useState(false); - const CancelHandler = async () => { - if (loading) return; + const CancelHandler = useCallback(async () => { + if (loading || !partyId) return; try { setLoading(true); @@ -25,24 +40,30 @@ function CancelModal({ showModal, setShowModal }) { } finally { setLoading(false); } - }; + }, [loading, partyId]); - const closeModal = () => { + const closeModal = useCallback(() => { if (complete) navigation("/", { replace: true }); setShowModal(false); - }; + }, [complete]); - const modalOutSideClick = (e) => { - if (modalRef.current === e.target) closeModal(); - }; + const modalOutSideClick = useCallback( + (event: MouseEvent) => { + if (modalRef.current === event.target) closeModal(); + }, + [modalRef] + ); - const handleKeyPress = (event) => { - if (event.key === "Escape") closeModal(); - else if (event.key === "Enter") { - if (!complete) return CancelHandler(); - else navigation("/", { replace: true }); - } - }; + const handleKeyPress = useCallback( + (event: KeyboardEvent) => { + if (event.key === "Escape") closeModal(); + else if (event.key === "Enter") { + if (!complete) return CancelHandler(); + else navigation("/", { replace: true }); + } + }, + [complete] + ); useEffect(() => { if (!showModal) return document.body.classList.remove("overflow-hidden"); @@ -59,11 +80,12 @@ function CancelModal({ showModal, setShowModal }) { return (
modalOutSideClick(e)} + onClick={modalOutSideClick} >
@@ -97,4 +119,4 @@ function CancelModal({ showModal, setShowModal }) { ); } -export default CancelModal; +export default memo(CancelModal); diff --git a/src/pages/PartyPage/CancelNewPartyButton/index.jsx b/src/pages/PartyPage/CancelNewPartyButton/index.tsx similarity index 80% rename from src/pages/PartyPage/CancelNewPartyButton/index.jsx rename to src/pages/PartyPage/CancelNewPartyButton/index.tsx index 6825a11a..a3df10a6 100644 --- a/src/pages/PartyPage/CancelNewPartyButton/index.jsx +++ b/src/pages/PartyPage/CancelNewPartyButton/index.tsx @@ -1,8 +1,12 @@ -import { useState } from "react"; +import { memo, useState } from "react"; import CancelModal from "./CancelModal"; import BottomButton from "../../../components/BottomButton"; -function CancelNewPartyButton({ isDriver }) { +interface Props { + isDriver: boolean; +} + +function CancelNewPartyButton({ isDriver }: Props) { const [showModal, setShowModal] = useState(false); if (isDriver) return null; @@ -25,4 +29,4 @@ function CancelNewPartyButton({ isDriver }) { ); } -export default CancelNewPartyButton; +export default memo(CancelNewPartyButton); diff --git a/src/pages/PartyPage/CourseDnD/index.jsx b/src/pages/PartyPage/CourseDnD/index.tsx similarity index 69% rename from src/pages/PartyPage/CourseDnD/index.jsx rename to src/pages/PartyPage/CourseDnD/index.tsx index f7a92b65..2dd7c185 100644 --- a/src/pages/PartyPage/CourseDnD/index.jsx +++ b/src/pages/PartyPage/CourseDnD/index.tsx @@ -1,10 +1,35 @@ -import { useEffect, useState } from "react"; +import { + Dispatch, + ForwardedRef, + memo, + SetStateAction, + useCallback, + useEffect, + useState, +} from "react"; import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd"; import { dateToStringHan } from "../../../utils"; +import { Course, Destination } from "../../../types"; import dragIcon from "../../../assets/svg/dragIcon.svg"; import deleteIcon from "../../../assets/svg/x-modal-icon.svg"; import ConfirmModal from "../../../components/ConfirmModal"; import TimeModal from "../../DriverCoursePage/CourseDnD/TimeModal"; +import clsx from "clsx"; + +interface Props { + name: string; + setName: Dispatch>; + course: Course; + startDate: string; + hours: number; + courseData: Destination[]; + setCourseData: Dispatch>; + startTime: string; + endTime: string; + setStartTime: Dispatch>; + shakeCourse?: boolean; + courseRef?: ForwardedRef; +} function CourseDnD({ name, @@ -19,24 +44,29 @@ function CourseDnD({ setStartTime, shakeCourse, courseRef, -}) { +}: Props) { const [showText, setShowText] = useState(false); const [showModal, setShowModal] = useState(false); const [showTimeModal, setShowTimeModal] = useState(false); - const handleChange = (result) => { - if (!result.destination) return; - const items = [...courseData]; - const [reorderedItem] = items.splice(result.source.index, 1); - items.splice(result.destination.index, 0, reorderedItem); - setCourseData(items); - }; - - const deleteHandler = (targetIndex) => { - if (courseData.length === 2) return setShowModal(true); + const handleChange = useCallback( + (result: any) => { + if (!result.destination) return; + const items = [...courseData]; + const [reorderedItem] = items.splice(result.source.index, 1); + items.splice(result.destination.index, 0, reorderedItem); + setCourseData(items); + }, + [courseData] + ); - setCourseData(courseData.filter((_, index) => index !== targetIndex)); - }; + const deleteHandler = useCallback( + (targetIndex: number) => { + if (courseData.length === 2) return setShowModal(true); + setCourseData(courseData.filter((_, index) => index !== targetIndex)); + }, + [courseData] + ); useEffect(() => { if (courseData.length === 0) { @@ -49,7 +79,7 @@ function CourseDnD({ }, [shakeCourse]); return ( -
+
setName(e.target.value)} /> -
+
{courseData.length === 0 && "여행지를 추가해주세요!"}
@@ -85,9 +117,10 @@ function CourseDnD({ {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef} - className={`bg-white w-4/5 md:w-[700px] h-[83px] mx-auto text-boldblue text-lg md:text-xl text-bold flex items-center ${ + className={clsx( + "bg-white w-4/5 md:w-[700px] h-[83px] mx-auto text-boldblue text-lg md:text-xl text-bold flex items-center", snapshot.isDragging && "border-2 border-primary" - }`} + )} >
{item.name}
index === 0 && setShowTimeModal(true)} > {index === 0 @@ -137,4 +173,4 @@ function CourseDnD({ ); } -export default CourseDnD; +export default memo(CourseDnD); diff --git a/src/pages/PartyPage/CreditInfo/index.tsx b/src/pages/PartyPage/CreditInfo/index.tsx index cba48212..e5cd2c6f 100644 --- a/src/pages/PartyPage/CreditInfo/index.tsx +++ b/src/pages/PartyPage/CreditInfo/index.tsx @@ -1,14 +1,13 @@ import { memo, useCallback, useEffect, useState } from "react"; import { priceToString, dateToKoreanDataTime } from "../../../utils"; import { postPaymentAgain } from "../../../api/card"; -import { partyStatusObj } from "../../../utils/data"; import CheckModal from "../../../components/CheckModal"; import ConfirmModal from "../../../components/ConfirmModal"; interface Props { totalPrice: number; capacity: number; - partyStatus?: keyof typeof partyStatusObj; + partyStatus?: string; paymentAmount?: number; createdAt?: string; receiptUrl?: string | null; @@ -34,6 +33,7 @@ function CreditInfo({ const [message, setMessage] = useState(""); const repaymentHandler = useCallback(async () => { + if (!reservationId || !paymentAmount) return; try { const result = await postPaymentAgain(reservationId); if (result.statusCode === 200) @@ -66,7 +66,7 @@ function CreditInfo({ partyStatus === "WAITING_COURSE_CHANGE_APPROVAL") && (status === "PAYMENT_COMPLETE" ? ( - {`(${dateToKoreanDataTime(createdAt)} 결제 완료)`} + {`(${dateToKoreanDataTime(createdAt || "")} 결제 완료)`} ) : ( @@ -77,7 +77,7 @@ function CreditInfo({ {partyStatus === "SEALED" || partyStatus === "WAITING_COURSE_CHANGE_APPROVAL" ? (

- {`${priceToString(paymentAmount)}원`} + {`${priceToString(paymentAmount || 0)}원`} {status === "PAYMENT_COMPLETE" && ( - -

-
- - - ); -} - -export default ToggleButton; diff --git a/src/pages/PartyPage/EditMap/ToggleButton/index.tsx b/src/pages/PartyPage/EditMap/ToggleButton/index.tsx new file mode 100644 index 00000000..b0241831 --- /dev/null +++ b/src/pages/PartyPage/EditMap/ToggleButton/index.tsx @@ -0,0 +1,59 @@ +import { Dispatch, memo, SetStateAction, useCallback, useState } from "react"; +import ConfirmModal from "../../../../components/ConfirmModal"; +import clsx from "clsx"; + +interface Props { + showSearchMap: boolean; + setShowSearchMap: Dispatch>; + canToggle: boolean; +} + +function ToggleButton({ showSearchMap, setShowSearchMap, canToggle }: Props) { + const [showModal, setShowModal] = useState(false); + + const toggleHandler = useCallback( + (isSearchMode: boolean) => { + if (!canToggle) return setShowModal(true); + setShowSearchMap(isSearchMode); + }, + [canToggle] + ); + + return ( + <> +
+ + +
+
+ + + ); +} + +export default memo(ToggleButton); diff --git a/src/pages/PartyPage/EditMap/index.jsx b/src/pages/PartyPage/EditMap/index.tsx similarity index 57% rename from src/pages/PartyPage/EditMap/index.jsx rename to src/pages/PartyPage/EditMap/index.tsx index dede9fd8..6a596d09 100644 --- a/src/pages/PartyPage/EditMap/index.jsx +++ b/src/pages/PartyPage/EditMap/index.tsx @@ -1,31 +1,48 @@ -import { useEffect, useState } from "react"; +import { + Dispatch, + memo, + SetStateAction, + useCallback, + useEffect, + useState, +} from "react"; import { getPartyRegionList } from "../../../api/region"; +import { Destination, RegionData } from "../../../types"; import CourseMap from "../../../components/CourseMap"; import PlaceMap from "../../../components/PlaceMap"; import ToggleButton from "./ToggleButton"; -function EditMap({ courseData, setCourseData, setRegion }) { +interface Props { + courseData: Destination[]; + setCourseData: Dispatch>; + setRegion: Dispatch>; +} + +function EditMap({ courseData, setCourseData, setRegion }: Props) { const [showSearchMap, setShowSearchMap] = useState(true); - const [regionData, setRegionData] = useState([]); + const [regionData, setRegionData] = useState([]); - const findRegion = (index) => { - if (courseData.length === index) return null; + const findRegion = useCallback( + (index: number): string => { + if (courseData.length === index) return ""; - const targetRegion = regionData.filter((region) => - courseData[index]?.address?.includes(region.name) - )[0]; + const targetRegion = regionData.filter((region) => + courseData[index]?.address?.includes(region.name) + )[0]; - return targetRegion?.name || findRegion(index + 1); - }; + return targetRegion?.name || findRegion(index + 1); + }, + [regionData, courseData] + ); - const getPartyRegionListFunc = async () => { + const getPartyRegionListFunc = useCallback(async () => { try { const result = await getPartyRegionList(); setRegionData(result.payload); } catch (e) { console.log(e); } - }; + }, []); useEffect(() => { getPartyRegionListFunc(); @@ -51,7 +68,6 @@ function EditMap({ courseData, setCourseData, setRegion }) { {showSearchMap ? ( >; + content: string; + memberCount: number; + companions: { + name: string; + phoneNumber: string; + }[]; + getPartyData: (toScrollTop?: boolean) => void; + capacity: number; + headcount: number; + totalPrice: number; + partyName: string; + course: Course; + myParty: boolean; + courseData: Destination[]; + region: string; + name: string; + startTime: string; + endTime: string; + promotionId: number; +} function EditModal({ showModal, @@ -23,17 +61,21 @@ function EditModal({ startTime, endTime, promotionId, -}) { +}: Props) { const navigation = useNavigate(); - const modalRef = useRef(); + const modalRef = useRef(null); const { partyId } = useParams(); - const [message, setMessage] = useState(""); + const [message, setMessage] = useState(""); const [loading, setLoading] = useState(false); const [complete, setComplete] = useState(false); - const isMemberFull = headcount + memberCount === capacity; - const editPartyHandler = async () => { - if (loading) return; + const isMemberFull = useMemo( + () => headcount + memberCount === capacity, + [headcount, memberCount, capacity] + ); + + const editPartyHandler = useCallback(async () => { + if (loading || !partyId) return; try { setLoading(true); @@ -111,14 +153,7 @@ function EditModal({ ); setComplete(true); - const GA_TRACKING_ID = import.meta.env.VITE_GA_TRACKING_ID; - const META_PIXEL_TRACKING_ID = import.meta.env - .VITE_META_PIXEL_TRACKING_ID; - if ( - GA_TRACKING_ID && - META_PIXEL_TRACKING_ID && - !window.location.href.includes("localhost") - ) { + if (isGAlive()) { ReactGA.event({ category: "기존 파티 참여", action: "15_exsting_suggestionsent_voting", @@ -129,24 +164,40 @@ function EditModal({ } finally { setLoading(false); } - }; + }, [ + loading, + partyId, + myParty, + course, + courseData, + startTime, + endTime, + region, + name, + partyName, + content, + memberCount, + companions, + ]); - const closeModal = () => { + const closeModal = useCallback(() => { if (complete) { - navigation(-1, { replace: true }); + navigation(-1); getPartyData(true); } - setShowModal(false); - }; + }, [complete]); - const modalOutSideClick = (e) => { - if (modalRef.current === e.target) closeModal(); - }; + const modalOutSideClick = useCallback( + (event: MouseEvent) => { + if (modalRef.current === event.target) closeModal(); + }, + [modalRef] + ); - const handleKeyPress = (event) => { + const handleKeyPress = useCallback((event: KeyboardEvent) => { if (event.key === "Escape") closeModal(); - }; + }, []); useEffect(() => { if (!showModal) return document.body.classList.remove("overflow-hidden"); @@ -200,13 +251,7 @@ function EditModal({
); - const GA_TRACKING_ID = import.meta.env.VITE_GA_TRACKING_ID; - const META_PIXEL_TRACKING_ID = import.meta.env.VITE_META_PIXEL_TRACKING_ID; - if ( - GA_TRACKING_ID && - META_PIXEL_TRACKING_ID && - !window.location.href.includes("localhost") - ) { + if (isGAlive()) { ReactGA.event({ category: "기존 파티 참여", action: "14_exsting_joinsuggestion_voting", @@ -221,11 +266,12 @@ function EditModal({ return (
modalOutSideClick(e)} + onClick={modalOutSideClick} >
@@ -259,4 +305,4 @@ function EditModal({ ); } -export default EditModal; +export default memo(EditModal); diff --git a/src/pages/PartyPage/JoinAgreement/AgreeItem/index.jsx b/src/pages/PartyPage/JoinAgreement/AgreeItem/index.tsx similarity index 65% rename from src/pages/PartyPage/JoinAgreement/AgreeItem/index.jsx rename to src/pages/PartyPage/JoinAgreement/AgreeItem/index.tsx index df46830a..e4451b61 100644 --- a/src/pages/PartyPage/JoinAgreement/AgreeItem/index.jsx +++ b/src/pages/PartyPage/JoinAgreement/AgreeItem/index.tsx @@ -1,7 +1,16 @@ +import { ChangeEvent, memo } from "react"; import { useNavigate } from "react-router-dom"; -import { ReactComponent as Check } from "../../../../assets/svg/agree-check.svg"; +import Check from "../../../../assets/svg/agree-check.svg"; -function AgreeItem({ checkedHandler, checked, id, title, url }) { +interface Props { + checkedHandler: (e: ChangeEvent, id: number) => void; + checked: boolean; + id: number; + title: string; + url: string; +} + +function AgreeItem({ checkedHandler, checked, id, title, url }: Props) { const navigation = useNavigate(); return ( @@ -19,7 +28,9 @@ function AgreeItem({ checkedHandler, checked, id, title, url }) { className="flex items-center cursor-pointer" >
- {checked && } + {checked && ( + + )}
{title} @@ -34,4 +45,4 @@ function AgreeItem({ checkedHandler, checked, id, title, url }) { ); } -export default AgreeItem; +export default memo(AgreeItem); diff --git a/src/pages/PartyPage/JoinAgreement/index.jsx b/src/pages/PartyPage/JoinAgreement/index.jsx deleted file mode 100644 index f385d0c8..00000000 --- a/src/pages/PartyPage/JoinAgreement/index.jsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useEffect, useState } from "react"; -import { ReactComponent as Check } from "../../../assets/svg/agree-check.svg"; -import AgreeItem from "./AgreeItem"; - -const agreementData = [ - { - id: 0, - title: "말랑트립 서비스 이용약관(일반회원용) (필수)", - url: "/policy/user/service", - }, - { - id: 1, - title: "말랑트립 개인정보 처리방침(일반회원용) (필수)", - url: "/policy/user/privacy", - }, -]; - -function JoinAgreement({ checked, setChecked, shakeAgree, agreementRef }) { - const [allChecked, setAllChecked] = useState(false); - const [showText, setShowText] = useState(false); - - const allCheckedHandler = (e) => { - setAllChecked(e.target.checked); - setChecked(checked.map((_) => e.target.checked)); - }; - - const checkedHandler = (e, num) => { - const newChecked = [...checked]; - newChecked[num] = e.target.checked; - setChecked(newChecked); - }; - - useEffect(() => { - if (checked.indexOf(false) < 0) setAllChecked(true); - else setAllChecked(false); - }, [checked]); - - useEffect(() => { - if (shakeAgree) setShowText(true); - }, [shakeAgree]); - - useEffect(() => { - if (allChecked) setShowText(false); - }, [allChecked]); - - return ( -
-
-
필수 약관
-
- 필수 약관에 동의해 주세요! -
-
-
-
- - -
- {agreementData.map((item, index) => ( - - ))} -
-
- ); -} - -export default JoinAgreement; diff --git a/src/pages/PartyPage/JoinAgreement/index.tsx b/src/pages/PartyPage/JoinAgreement/index.tsx new file mode 100644 index 00000000..1cf3cd3c --- /dev/null +++ b/src/pages/PartyPage/JoinAgreement/index.tsx @@ -0,0 +1,122 @@ +import { + ChangeEvent, + Dispatch, + ForwardedRef, + memo, + SetStateAction, + useCallback, + useEffect, + useMemo, + useState, +} from "react"; +import Check from "../../../assets/svg/agree-check.svg"; +import AgreeItem from "./AgreeItem"; +import clsx from "clsx"; + +interface Props { + checked: boolean[]; + setChecked: Dispatch>; + shakeAgree: boolean; + agreementRef: ForwardedRef; +} + +function JoinAgreement({ + checked, + setChecked, + shakeAgree, + agreementRef, +}: Props) { + const [allChecked, setAllChecked] = useState(false); + const [showText, setShowText] = useState(false); + + const agreementData = useMemo( + () => [ + { + id: 0, + title: "말랑트립 서비스 이용약관(일반회원용) (필수)", + url: "/policy/user/service", + }, + { + id: 1, + title: "말랑트립 개인정보 처리방침(일반회원용) (필수)", + url: "/policy/user/privacy", + }, + ], + [] + ); + + const allCheckedHandler = useCallback( + (e: ChangeEvent) => { + setAllChecked(e.target.checked); + setChecked(checked.map((_) => e.target.checked)); + }, + [checked] + ); + + const checkedHandler = useCallback( + (e: ChangeEvent, id: number) => { + const newChecked = [...checked]; + newChecked[id] = e.target.checked; + setChecked(newChecked); + }, + [checked] + ); + + useEffect(() => { + if (checked.indexOf(false) < 0) setAllChecked(true); + else setAllChecked(false); + }, [checked]); + + useEffect(() => { + if (shakeAgree) setShowText(true); + }, [shakeAgree]); + + useEffect(() => { + if (allChecked) setShowText(false); + }, [allChecked]); + + return ( +
+
+
필수 약관
+
+ 필수 약관에 동의해 주세요! +
+
+
+
+ + +
+ {agreementData.map((item, index) => ( + + ))} +
+
+ ); +} + +export default memo(JoinAgreement); diff --git a/src/pages/PartyPage/JoinButton/index.jsx b/src/pages/PartyPage/JoinButton/index.tsx similarity index 63% rename from src/pages/PartyPage/JoinButton/index.jsx rename to src/pages/PartyPage/JoinButton/index.tsx index d89ab4c3..f6eda030 100644 --- a/src/pages/PartyPage/JoinButton/index.jsx +++ b/src/pages/PartyPage/JoinButton/index.tsx @@ -1,18 +1,27 @@ -import { useEffect, useState } from "react"; +import { memo, useEffect, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; +import { RootState } from "../../../redux/store"; import BottomButton from "../../../components/BottomButton"; -function JoinButton({ joinHandler, partyStatus }) { - const user = useSelector((state) => state.user); +interface Props { + joinHandler: () => void; + partyStatus: string; +} + +function JoinButton({ joinHandler, partyStatus }: Props) { + const user = useSelector((state: RootState) => state.user); const { type } = useParams(); const [scrollPosition, setScrollPosition] = useState(0); - const buttonText = { - detail: "파티 가입하기", - join: "가입 완료하기", - edit: "제안 보내기", - }; + const buttonText = useMemo( + () => ({ + detail: "파티 가입하기", + join: "가입 완료하기", + edit: "제안 보내기", + }), + [] + ); useEffect(() => { const handleScroll = () => { @@ -26,6 +35,7 @@ function JoinButton({ joinHandler, partyStatus }) { }, []); if (user.role === "ROLE_DRIVER" || partyStatus !== "RECRUITING") return null; + if (type !== "detail" && type !== "join" && type !== "edit") return null; return ( <>
@@ -43,4 +53,4 @@ function JoinButton({ joinHandler, partyStatus }) { ); } -export default JoinButton; +export default memo(JoinButton); diff --git a/src/pages/PartyPage/JoinGreeting/index.jsx b/src/pages/PartyPage/JoinGreeting/index.tsx similarity index 55% rename from src/pages/PartyPage/JoinGreeting/index.jsx rename to src/pages/PartyPage/JoinGreeting/index.tsx index 0cd86bb1..a228d875 100644 --- a/src/pages/PartyPage/JoinGreeting/index.jsx +++ b/src/pages/PartyPage/JoinGreeting/index.tsx @@ -1,6 +1,13 @@ -function JoinGreeting({ content, setContent }) { +import { Dispatch, memo, SetStateAction } from "react"; + +interface Props { + content: string; + setContent: Dispatch>; +} + +function JoinGreeting({ content, setContent }: Props) { return ( -
+