From 4d170d6b1a2d5726c4ab9545dcb718352429377c Mon Sep 17 00:00:00 2001 From: mnbvcxzyj Date: Tue, 8 Oct 2024 15:35:19 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EA=B3=B5=ED=86=B5=20=EC=9D=BC?= =?UTF-8?q?=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/schedule/scheduleAPI.ts | 17 +++ src/components/modal/OneBtnModal.tsx | 101 ++++++++++++++++++ src/hooks/useChangeCoupleSchedule.ts | 26 +++++ .../calendar/components/TimeTableView.tsx | 35 +++++- src/pages/main/components/ScheduleList.tsx | 8 +- src/types/ISModalProps.ts | 2 +- 6 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 src/components/modal/OneBtnModal.tsx create mode 100644 src/hooks/useChangeCoupleSchedule.ts diff --git a/src/api/schedule/scheduleAPI.ts b/src/api/schedule/scheduleAPI.ts index 6ca41b7..03452b0 100644 --- a/src/api/schedule/scheduleAPI.ts +++ b/src/api/schedule/scheduleAPI.ts @@ -122,3 +122,20 @@ export const updateScheduleStatus = async ({ throw new Error(`일정 상태 업데이트 실패: ${error}`); } }; + +// 공통 일정으로 변경 +export const changeCommonSchedule = async (scheduleNo: number) => { + try { + const response = await scheduleAxiosInstance.put( + `/schedule/${scheduleNo}/common-schedule`, + {} + ); + return response.data; + } catch (error) { + console.error("공통일정으로 변경 중 오류 발생:", error); + if (axios.isAxiosError(error) && error.response) { + console.warn(`에러 상태 코드: ${error.response.status}`); + } + throw new Error(`공통일정으로 변경 업데이트 실패: ${error}`); + } +}; diff --git a/src/components/modal/OneBtnModal.tsx b/src/components/modal/OneBtnModal.tsx new file mode 100644 index 0000000..3d8e627 --- /dev/null +++ b/src/components/modal/OneBtnModal.tsx @@ -0,0 +1,101 @@ +import React from "react"; +import { ISModalProps } from "../../types/ISModalProps"; +import { styled } from "styled-components"; + +const OneBtnModal: React.FC = ({ + title, + description, + imageSrc, + confirmText = "확인", + onConfirm, +}) => { + return ( + <> + {console.log("모달 열림")} + + + {imageSrc && } + {title} + {description && {description}} + + {confirmText} + + + + + ); +}; + +export default OneBtnModal; + +const ModalOverlay = styled.div` + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 10; +`; + +const ModalContent = styled.div` + padding: 20px; + border-radius: 20px; + background: #fff; + display: flex; + flex-direction: column; + align-items: center; +`; + +const ModalTitle = styled.h2` + color: var(--Black, #3b3634); + + text-align: center; + font-family: SUIT; + font-size: 10px; + font-style: normal; + font-weight: 400; + line-height: normal; +`; + +const ModalDescription = styled.div` + margin-top: 5px; + color: var(--Primary, #f14040); + font-family: SUIT; + font-size: 8px; + font-style: normal; + font-weight: 400; + line-height: normal; +`; + +const ModalImage = styled.img` + width: 100px; + height: 100px; +`; + +const ModalButtonWrapper = styled.div` + display: flex; + margin-top: 10px; + gap: 20px; +`; + +const ModalButton = styled.button` + border-radius: 10px; + width: 90px; + padding: 9px 0px 8px 0px; + + border-radius: 10px; + background: #f25454; + box-shadow: 0px 0px 4px 1px rgba(0, 0, 0, 0.25); + + color: #fff; + text-align: center; + font-family: SUIT; + font-size: 10px; + font-style: normal; + font-weight: 400; + line-height: normal; +`; diff --git a/src/hooks/useChangeCoupleSchedule.ts b/src/hooks/useChangeCoupleSchedule.ts new file mode 100644 index 0000000..86d50cb --- /dev/null +++ b/src/hooks/useChangeCoupleSchedule.ts @@ -0,0 +1,26 @@ +import { useMutation } from "@tanstack/react-query"; +import { changeCommonSchedule } from "../api/schedule/scheduleAPI"; +import { AxiosError } from "axios"; + +export const useChangeCommonSchedule = () => { + return useMutation({ + mutationFn: (scheduleNo: number) => changeCommonSchedule(scheduleNo), + onError: (error: unknown) => { + if (error instanceof AxiosError) { + if (error.response) { + console.error( + "서버 에러:", + error.response.status, + error.response.data + ); + } else if (error.request) { + console.error("Request failed 실패:", error.request); + } else { + console.error("Error message 에러:", error.message); + } + } else { + console.error("Unknown error:", error); + } + }, + }); +}; diff --git a/src/pages/calendar/components/TimeTableView.tsx b/src/pages/calendar/components/TimeTableView.tsx index 4b10c99..7473b08 100644 --- a/src/pages/calendar/components/TimeTableView.tsx +++ b/src/pages/calendar/components/TimeTableView.tsx @@ -15,6 +15,9 @@ import { useDeleteSchedule } from "../../../hooks/useDeleteSchedule"; import tearEmoji from "../../../images/emoji/이모지_눈물.png"; import { scheduleModalButtons } from "../../../utils/scheduleModalBtn"; import ScheduleDetailModal from "./ScheduleDetailModal"; +import coupleEmoji from "../../../images/emoji/이모지_커플.png"; +import { useChangeCommonSchedule } from "../../../hooks/useChangeCoupleSchedule"; +import OneBtnModal from "../../../components/modal/OneBtnModal"; // (1시간 = 26px) const timeToPosition = (dateTime: string): number => { @@ -55,12 +58,14 @@ const TimeTableView: React.FC<{ date: string }> = ({ date }) => { const { data: partnerScheduleList } = useFetchPartnerScheduleList(date); const { data: commonScheduleList } = useFetchCommonScheduleList(date); const { mutate: deleteSchedule } = useDeleteSchedule(); + const { mutate: changeCommonSchedule } = useChangeCommonSchedule(); const navigate = useNavigate(); const [activeModal, setActiveModal] = useState(null); const [isClosing, setIsClosing] = useState(false); const [touchStartY, setTouchStartY] = useState(0); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [isChangeCommonModalOpen, setIsChangeCommonModalOpen] = useState(false); const [selectedSchedule, setSelectedSchedule] = useState( null @@ -97,6 +102,21 @@ const TimeTableView: React.FC<{ date: string }> = ({ date }) => { } }; + const handleChangeCommonSchedule = () => { + if (selectedSchedule?.scheduleNo) { + changeCommonSchedule(selectedSchedule.scheduleNo, { + onSuccess: () => { + setIsChangeCommonModalOpen(false); + console.log("공통일정으로 변경되었습니다."); + }, + onError: (error) => { + console.log("변경 오류 : ", error); + alert("공통일정 변경 중 오류가 발생했습니다:"); + }, + }); + } + }; + const handleOutsideClick = (e: React.MouseEvent) => { if (modalRef.current && !modalRef.current.contains(e.target as Node)) { closeModal(); @@ -257,6 +277,17 @@ const TimeTableView: React.FC<{ date: string }> = ({ date }) => { /> )} + {/* 공통 일정 변경 모달 */} + {isChangeCommonModalOpen && ( + + )} + {/* 일정 상세 모달 */} {activeModal === "schedule" && selectedSchedule && ( @@ -270,7 +301,9 @@ const TimeTableView: React.FC<{ date: string }> = ({ date }) => { isCommonSchedule: commonScheduleList?.includes(selectedSchedule), onDelete: () => setIsDeleteModalOpen(true), onEdit: () => console.log("일정 수정"), - onCommon: () => console.log("공통 일정으로 변경"), + onCommon: () => { + setIsChangeCommonModalOpen(true); + }, onEmoji: () => console.log("이모지 남기기"), onEditRequest: () => console.log("일정 수정 요청"), })} diff --git a/src/pages/main/components/ScheduleList.tsx b/src/pages/main/components/ScheduleList.tsx index 4281324..b2c0af3 100644 --- a/src/pages/main/components/ScheduleList.tsx +++ b/src/pages/main/components/ScheduleList.tsx @@ -52,10 +52,14 @@ const ScheduleList = () => { navigate(`/calendar/${formattedDate}`); }; + const myName = coupleInfo ? coupleInfo.nickNameA : myInfo?.name; + const partnerName = coupleInfo ? coupleInfo.nickNameB : "커플로 등록해주세요!"; + console.log(coupleInfo); + return ( @@ -85,7 +89,7 @@ const ScheduleList = () => { /> - {myInfo.name}의 일정 + {myName}의 일정 @@ -113,7 +117,7 @@ const ScheduleList = () => { /> - {myInfo?.name}의 일정 + {myName}의 일정 현재 등록된 일정이 없습니다. diff --git a/src/types/ISModalProps.ts b/src/types/ISModalProps.ts index d6fe861..feb0744 100644 --- a/src/types/ISModalProps.ts +++ b/src/types/ISModalProps.ts @@ -5,5 +5,5 @@ export interface ISModalProps { confirmText?: string; cancelText?: string; onConfirm: () => void; - onCancel: () => void; + onCancel?: () => void; } From 03ab15ed907591b34d2bc94a3fff5c65575a90ff Mon Sep 17 00:00:00 2001 From: mnbvcxzyj Date: Tue, 8 Oct 2024 15:52:27 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EC=9D=BC=EC=A0=95=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20.=20=ED=9B=84=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/components/TimeTableView.tsx | 19 ++++++++++++++++--- src/pages/schedule/AddMySchedulePage.tsx | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/pages/calendar/components/TimeTableView.tsx b/src/pages/calendar/components/TimeTableView.tsx index 7473b08..9bbb7b8 100644 --- a/src/pages/calendar/components/TimeTableView.tsx +++ b/src/pages/calendar/components/TimeTableView.tsx @@ -1,8 +1,8 @@ -import React, { useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import styled, { keyframes } from "styled-components"; import { getBusyBackgroundColor, getBusyColor } from "../../../utils/colors"; -import { useNavigate } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; import { useFetchCommonScheduleList, useFetchMyScheduleList, @@ -54,7 +54,8 @@ interface ScheduleItemProps { type ModalType = "empty" | "schedule" | null; const TimeTableView: React.FC<{ date: string }> = ({ date }) => { - const { data: myScheduleList } = useFetchMyScheduleList(date); + const { data: myScheduleList, refetch: refetchMyScheduleList } = + useFetchMyScheduleList(date); const { data: partnerScheduleList } = useFetchPartnerScheduleList(date); const { data: commonScheduleList } = useFetchCommonScheduleList(date); const { mutate: deleteSchedule } = useDeleteSchedule(); @@ -71,6 +72,15 @@ const TimeTableView: React.FC<{ date: string }> = ({ date }) => { null ); + const location = useLocation(); + useEffect(() => { + if (location.state?.refetch) { + refetchMyScheduleList(); + + navigate(location.pathname, { replace: true, state: {} }); + } + }, [location, refetchMyScheduleList]); + const modalRef = useRef(null); const openModal = (type: ModalType) => { @@ -92,6 +102,8 @@ const TimeTableView: React.FC<{ date: string }> = ({ date }) => { deleteSchedule(selectedSchedule.scheduleNo, { onSuccess: () => { setIsDeleteModalOpen(false); + closeModal(); + refetchMyScheduleList(); console.log("일정이 성공적으로 삭제되었습니다."); }, onError: (error) => { @@ -107,6 +119,7 @@ const TimeTableView: React.FC<{ date: string }> = ({ date }) => { changeCommonSchedule(selectedSchedule.scheduleNo, { onSuccess: () => { setIsChangeCommonModalOpen(false); + closeModal(); console.log("공통일정으로 변경되었습니다."); }, onError: (error) => { diff --git a/src/pages/schedule/AddMySchedulePage.tsx b/src/pages/schedule/AddMySchedulePage.tsx index fb87ac0..fee6836 100644 --- a/src/pages/schedule/AddMySchedulePage.tsx +++ b/src/pages/schedule/AddMySchedulePage.tsx @@ -15,7 +15,7 @@ const AddMySchedulePage = () => { console.log("서버에 전송하려는 데이터 :", formData); saveSchedule(formData, { onSuccess: () => { - navigate(`/calendar/${date}`); + navigate(`/calendar/${date}`, { state: { refetch: true } }); }, }); };