From 85185a17b536fe0808251d5c5530ff8aba37b19c Mon Sep 17 00:00:00 2001 From: JongHyun Date: Mon, 5 Aug 2024 23:42:12 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B8=B0=EA=B0=84=20=EB=A7=8C=EB=A3=8C?= =?UTF-8?q?=20=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/CompleteConfirmModal.jsx | 75 +++++++++++-------- .../components/CompleteGoalModal.jsx | 5 +- src/diaryListPage/components/GoalCard.jsx | 5 +- .../goals/CreateGoalModal/CreateGoalModal.jsx | 48 +++++++++--- src/homepage/component/goals/Goals.jsx | 39 ++++++++-- 5 files changed, 116 insertions(+), 56 deletions(-) diff --git a/src/diaryListPage/components/CompleteConfirmModal.jsx b/src/diaryListPage/components/CompleteConfirmModal.jsx index 9737d5e..850ecc5 100644 --- a/src/diaryListPage/components/CompleteConfirmModal.jsx +++ b/src/diaryListPage/components/CompleteConfirmModal.jsx @@ -1,69 +1,78 @@ import React from "react"; import styled from "styled-components"; +import updateGoal from "../../apis/updateGoal"; + +const parseDate = (dateString) => { + if (!dateString) return ""; // dateString이 없을 경우 빈 문자열 반환 + const [year, month, day] = dateString.split(".").map(Number); + const fullYear = year < 50 ? 2000 + year : 1900 + year; + return `${fullYear}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`; +}; function CompleteConfirmModal({ - status, - setGoalInfo, + goalInfo, setIsConfirmModalOpen, - goalId, csrfToken, setIsCompModalOpen, + expiredData, + setIsModalOpen, }) { const closeConfirmModal = () => { setIsConfirmModalOpen(false); }; - const completeGoal = async () => { - // console.log("current status before update is : " + status); - - const updatedGoalInfo = { - goal: { status: "CLOSED" }, - }; - setGoalInfo((prevGoalInfo) => ({ - ...prevGoalInfo, - goal: { ...prevGoalInfo.goal, status: "CLOSED" }, - })); + const handleClickCancle = () => { + setIsConfirmModalOpen(false); + if (expiredData !== undefined) { + setIsModalOpen(true); + } + }; + console.log("dmdkr glaemfj", expiredData); - console.log("current status after update is : " + status); - // 모달 닫기 + const completeGoal = async () => { + const data = expiredData || goalInfo.goal; + if (!data) { + console.error("No valid data provided"); + return; + } try { - const response = await fetch(`/api/goals/${goalId}`, { - method: "POST", - headers: { - "Content-Type": "application/json", - "X-CSRF-Token": csrfToken, - }, - body: JSON.stringify(updatedGoalInfo), - }); + const { title, startDate, endDate, thumbnail, goalId } = data; - if (!response.ok) { - throw new Error("Failed to update goal status"); - } + const formDataToSend = new FormData(); + formDataToSend.append("title", title); + formDataToSend.append("startDate", parseDate(startDate)); // 날짜 형식 변환 + formDataToSend.append("endDate", parseDate(endDate)); // 날짜 형식 변환 + formDataToSend.append("status", "CLOSED"); - console.log("Goal status updated successfully"); + if (thumbnail) { + formDataToSend.append("thumbnail", thumbnail); + } else { + formDataToSend.append("thumbnail", ""); + } + await updateGoal(formDataToSend, csrfToken, goalId); + setIsConfirmModalOpen(false); + setIsCompModalOpen(true); } catch (error) { console.error("Error updating goal status:", error); } - - setIsConfirmModalOpen(false); - setIsCompModalOpen(true); }; return (
- +

도전을 완료하시겠어요?

+ {expiredData !== undefined &&
목표 기간이 만료되었어요.
} 완료한 도전은 재도전이 불가합니다.
도전을 완료하시겠어요?
- + @@ -110,7 +119,7 @@ const Wrapper = styled.div` transform: translate(-50%, -50%); background: #ffffff; width: 350px; // 로딩모달 크기 - height: 180px; + height: ${(props) => (props.isExpired ? "187px" : "180px")}; border-radius: 12px; padding-top: 5px; z-index: 5; diff --git a/src/diaryListPage/components/CompleteGoalModal.jsx b/src/diaryListPage/components/CompleteGoalModal.jsx index d68913c..3ef515a 100644 --- a/src/diaryListPage/components/CompleteGoalModal.jsx +++ b/src/diaryListPage/components/CompleteGoalModal.jsx @@ -8,7 +8,7 @@ function CompleteGoalModal({ setIsCompModalOpen }) { const completeGoal = () => { setIsCompModalOpen(false); - + window.location.reload(); /* 여기에 빵빠레 효과 넣어줘야할듯 ? */ @@ -28,8 +28,7 @@ function CompleteGoalModal({ setIsCompModalOpen }) { >

도전 완료를 축하드려요

- 축하드려요! 꾸준히 성장 일지를 작성한 chicky님의 모습에 큰 감동을 - 받았습니다 + 축하드려요! 꾸준히 성장 일지를 작성한 chicky님의 모습에 큰 감동을 받았습니다
계속해서 멋진 성장을 이루어나갈 수 있도록 stepper가 함께할게요 :D
diff --git a/src/diaryListPage/components/GoalCard.jsx b/src/diaryListPage/components/GoalCard.jsx index b2d637a..4062edc 100644 --- a/src/diaryListPage/components/GoalCard.jsx +++ b/src/diaryListPage/components/GoalCard.jsx @@ -48,6 +48,7 @@ function GoalCard() { const daysFromStart = calculateDaysFromStart(fetchedGoalInfo.goal.startDate); setStartedFrom(daysFromStart); + console.log("목표정보", goalInfo); } catch (error) { console.error("Error fetching goal info:", error); } @@ -106,10 +107,8 @@ function GoalCard() {
{isConfirmModalOpen && ( diff --git a/src/homepage/component/goals/CreateGoalModal/CreateGoalModal.jsx b/src/homepage/component/goals/CreateGoalModal/CreateGoalModal.jsx index 4d1b5b0..07438e7 100644 --- a/src/homepage/component/goals/CreateGoalModal/CreateGoalModal.jsx +++ b/src/homepage/component/goals/CreateGoalModal/CreateGoalModal.jsx @@ -31,6 +31,7 @@ function CreateGoalModal({ isUpdate, setIsUpdate, setIsGoalEditedModalOpen, + expiredData, }) { const [isDateSetting, setIsDateSetting] = useState(true); const csrfToken = useRecoilValue(tokenState); @@ -43,15 +44,28 @@ function CreateGoalModal({ const titleInputRef = useRef(null); const [formData, setFormData] = useState({ - title: isUpdate && updateData?.title ? updateData.title : "", - startDate: isUpdate && updateData?.startDate ? parseDate(updateData.startDate) : "", - endDate: isUpdate && updateData?.endDate ? parseDate(updateData.endDate) : "", - thumbnail: isUpdate && updateData?.thumbnail ? updateData.thumbnail : "", + title: isUpdate && updateData?.title ? updateData.title : expiredData?.title ? expiredData.title : "", + startDate: + isUpdate && updateData?.startDate + ? parseDate(updateData.startDate) + : expiredData?.startDate + ? parseDate(expiredData.startDate) + : "", + endDate: + isUpdate && updateData?.endDate + ? parseDate(updateData.endDate) + : expiredData?.endDate + ? parseDate(expiredData.endDate) + : "", + thumbnail: + isUpdate && updateData?.thumbnail ? updateData.thumbnail : expiredData?.thumbnail ? expiredData.thumbnail : "", }); - const goalId = isUpdate && updateData.goalId; - const status = isUpdate && updateData.status; - const [previewUrl, setPreviewUrl] = useState(isUpdate && updateData?.thumbnail ? updateData.thumbnail : null); + const goalId = isUpdate && updateData.goalId ? updateData.goalId : expiredData?.goalId; + const status = isUpdate && updateData.status ? updateData.status : expiredData?.status; + const [previewUrl, setPreviewUrl] = useState( + isUpdate && updateData?.thumbnail ? updateData.thumbnail : expiredData?.thumbnail ? expiredData.thumbnail : null + ); useEffect(() => { console.log("formData updated:", formData, csrfToken, updateData, isUpdate); @@ -147,16 +161,17 @@ function CreateGoalModal({ console.log("Form Data Submitted: ", formData); try { const { title, startDate, endDate } = formData; + const updateDataSource = expiredData || updateData; // expiredData가 있으면 사용, 없으면 updateData 사용 const formDataToSend = new FormData(); formDataToSend.append("title", title); formDataToSend.append( "startDate", - dateChanged.startDate ? startDate : isDateSetting ? parseDate(updateData.startDate) : "" + dateChanged.startDate ? startDate : isDateSetting ? parseDate(updateDataSource.startDate) : "" ); formDataToSend.append( "endDate", - dateChanged.endDate ? endDate : isDateSetting ? parseDate(updateData.endDate) : "" + dateChanged.endDate ? endDate : isDateSetting ? parseDate(updateDataSource.endDate) : "" ); formDataToSend.append("status", status); @@ -193,11 +208,12 @@ function CreateGoalModal({ - {isUpdate ? "목표 수정하기" : "목표 추가하기"} + {expiredData || isUpdate ? "목표 수정하기" : "목표 추가하기"} + {expiredData !== undefined && 만료된 기간을 수정해주세요!} @@ -272,7 +288,7 @@ function CreateGoalModal({ - {isUpdate ? ( + {expiredData || isUpdate ? ( 수정 완료하기 ) : ( 목표 추가하기 @@ -392,6 +408,16 @@ const ExitButton = styled.div` } `; +const ExpiredText = styled.div` + color: #fd5e2b; + border-bottom: 1px solid #fd7e55; + height: 25px; + display: flex; + justify-content: center; + font-size: 12px; + font-weight: bold; +`; + const MainContainer = styled.div` display: flex; flex-direction: column; diff --git a/src/homepage/component/goals/Goals.jsx b/src/homepage/component/goals/Goals.jsx index 66e84e1..e697879 100644 --- a/src/homepage/component/goals/Goals.jsx +++ b/src/homepage/component/goals/Goals.jsx @@ -17,6 +17,8 @@ import img1 from "../../../asset/Random/random1.svg"; import img2 from "../../../asset/Random/random2.svg"; import GoalCreatedModal from "./CreateGoalModal/GoalCreatedModal"; import GoalEditedModal from "./goalEditDropdown/GoalEditedModal"; +import CompleteGoalModal from "../../../diaryListPage/components/CompleteGoalModal"; +import CompleteConfirmModal from "../../../diaryListPage/components/CompleteConfirmModal"; const backgroundArr = [img1, img2]; @@ -25,6 +27,8 @@ function Goals() { const [isGoalCreatedModalOpen, setIsGoalCreatedModalOpen] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [isGoalEditedModalOpen, setIsGoalEditedModalOpen] = useState(false); + const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false); + const [isCompModalOpen, setIsCompModalOpen] = useState(false); const [currentTab, setCurrentTab] = useState("도전 중"); const [currentSort, setCurrentSort] = useState("최신순"); const [goalList, setGoalList] = useState({ goals: [] }); @@ -36,6 +40,9 @@ function Goals() { const [isUpdate, setIsUpdate] = useState(false); const [updateData, setUpdateData] = useState(null); + const [isExpiredBox, setIsExpiredBox] = useState(false); + const [expiredData, setExpiredData] = useState(null); + useEffect(() => { if (!csrfToken) return; const fetchGoalList = async () => { @@ -91,7 +98,7 @@ function Goals() { if (currentTab === "도전 중") { goals = goals.filter((goal) => goal.status === "OPEN"); } else if (currentTab === "완료한 도전") { - goals = goals.filter((goal) => goal.status === "CLOSE"); + goals = goals.filter((goal) => goal.status === "CLOSED"); } if (currentSort === "오름차순") { @@ -188,9 +195,20 @@ function Goals() { const randomIndex = Math.floor(Math.random() * backgroundArr.length); const backgroundImg = backgroundArr[randomIndex]; const daysLeft = getDaysLeft(goal.endDate); + const expired = isExpired(goal.endDate); return ( - handleClickGoal(goal.goalId)}> + { + if (expired) { + setIsExpiredBox(true); + setIsConfirmModalOpen(true); + setExpiredData(goal); + } else { + handleClickGoal(goal.goalId); + } + }} + > {goal.thumbnail ? ( @@ -212,14 +230,12 @@ function Goals() { D-{daysLeft} )} - {isExpired(goal.endDate) && ( + {expired && ( 기한이 지났어요! )} - {daysLeft === null || daysLeft > 5 - ? !isExpired(goal.endDate) &&
- : null} + {daysLeft === null || daysLeft > 5 ? !expired &&
: null} {goal.title} {goal.streak >= 3 && ( @@ -255,6 +271,7 @@ function Goals() { isUpdate={isUpdate} setIsUpdate={setIsUpdate} setIsGoalEditedModalOpen={setIsGoalEditedModalOpen} + expiredData={expiredData} /> )} {isGoalCreatedModalOpen && ( @@ -266,6 +283,16 @@ function Goals() { )} {isDeleteModalOpen && } {isGoalEditedModalOpen && } + {isConfirmModalOpen && ( + + )} + {isCompModalOpen && } ); }