props.$ratio};
- height: 100%;
- background-color: ${(props) => props.color};
-`;
-
-const EmotionIndicatorArrow = styled.div`
- display: flex;
- justify-content: center;
- width: 0;
- height: 4rem;
-`;
-
-const EmotionTextWrapper = styled.div`
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-`;
-
-const EmotionText = styled.div`
- font-size: 0.9rem;
-`;
-
export default DiaryReadModal;
diff --git a/FE/src/components/DiaryModal/DiaryUpdateModal.js b/FE/src/components/DiaryModal/DiaryUpdateModal.js
index f24a593..53c7c34 100644
--- a/FE/src/components/DiaryModal/DiaryUpdateModal.js
+++ b/FE/src/components/DiaryModal/DiaryUpdateModal.js
@@ -1,6 +1,6 @@
/* eslint-disable */
-import React, { useState, useEffect, useRef } from "react";
+import React, { useState, useEffect, useLayoutEffect, useRef } from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { useMutation, useQuery } from "react-query";
import styled from "styled-components";
@@ -8,19 +8,9 @@ import userAtom from "../../atoms/userAtom";
import diaryAtom from "../../atoms/diaryAtom";
import shapeAtom from "../../atoms/shapeAtom";
import ModalWrapper from "../../styles/Modal/ModalWrapper";
-import DiaryModalHeader from "../../styles/Modal/DiaryModalHeader";
+import Calendar from "./Calendar";
import deleteIcon from "../../assets/deleteIcon.svg";
-import preventBeforeUnload from "../../utils/utils";
-
-async function getDiary(accessToken, diaryUuid) {
- return fetch(`http://223.130.129.145:3005/diaries/${diaryUuid}`, {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${accessToken}`,
- },
- }).then((res) => res.json());
-}
+import { preventBeforeUnload, getFormattedDate } from "../../utils/utils";
// TODO: 일기 데이터 수정 API 연결
function DiaryUpdateModal(props) {
@@ -34,7 +24,7 @@ function DiaryUpdateModal(props) {
uuid: diaryState.diaryUuid,
title: "",
content: "",
- date: "2023-11-19",
+ date: "",
point: diaryState.diaryPoint,
tags: [],
shapeUuid: diaryState.diaryList.find(
@@ -42,30 +32,19 @@ function DiaryUpdateModal(props) {
).shapeUuid,
});
- async function updateDiaryFn(data) {
- return fetch("http://223.130.129.145:3005/diaries", {
- method: "PUT",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${data.accessToken}`,
- },
- body: JSON.stringify(data.diaryData),
- }).then(() => {
- refetch();
- setDiaryState((prev) => ({
- ...prev,
- isLoading: true,
- }));
- });
- }
-
- useEffect(() => {
- window.addEventListener("beforeunload", preventBeforeUnload);
+ const {
+ mutate: updateDiary,
+ // isLoading: diaryIsLoading,
+ // isError: diaryIsError,
+ } = useMutation(updateDiaryFn);
- return () => {
- window.removeEventListener("beforeunload", preventBeforeUnload);
- };
- }, []);
+ const {
+ data: originData,
+ isLoading,
+ isError,
+ } = useQuery("diary", () =>
+ getDiary(userState.accessToken, diaryState.diaryUuid),
+ );
const closeModal = () => {
window.history.back();
@@ -92,27 +71,49 @@ function DiaryUpdateModal(props) {
setDiaryData({ ...diaryData, tags: diaryData.tags.slice(0, -1) });
};
- const {
- mutate: updateDiary,
- // isLoading: diaryIsLoading,
- // isError: diaryIsError,
- } = useMutation(updateDiaryFn);
+ async function updateDiaryFn(data) {
+ const diaryData = {
+ uuid: data.diaryData.uuid,
+ title: data.diaryData.title,
+ content: data.diaryData.content,
+ date: getFormattedDate(data.diaryData.date),
+ point: data.diaryData.point,
+ tags: data.diaryData.tags,
+ shapeUuid: data.diaryData.shapeUuid,
+ };
- const {
- data: originData,
- isLoading,
- isError,
- } = useQuery("diary", () =>
- getDiary(userState.accessToken, diaryState.diaryUuid),
- );
+ return fetch("http://223.130.129.145:3005/diaries", {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${data.accessToken}`,
+ },
+ body: JSON.stringify(diaryData),
+ }).then(() => {
+ refetch();
+ setDiaryState((prev) => ({
+ ...prev,
+ isLoading: true,
+ }));
+ });
+ }
+ async function getDiary(accessToken, diaryUuid) {
+ return fetch(`http://223.130.129.145:3005/diaries/${diaryUuid}`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${accessToken}`,
+ },
+ }).then((res) => res.json());
+ }
- useEffect(() => {
+ useLayoutEffect(() => {
if (originData) {
setDiaryData({
...diaryData,
title: originData.title,
content: originData.content,
- date: originData.date,
+ date: new Date(originData.date),
tags: originData.tags,
});
titleRef.current && (titleRef.current.value = originData.title);
@@ -120,32 +121,31 @@ function DiaryUpdateModal(props) {
}
}, [originData]);
+ useEffect(() => {
+ window.addEventListener("beforeunload", preventBeforeUnload);
+
+ return () => {
+ window.removeEventListener("beforeunload", preventBeforeUnload);
+ };
+ }, []);
+
if (isLoading)
return (
-
+
Loading...
);
if (isError)
return (
-
+
에러 발생
);
return (
-
-
- 바뀐 별의 이야기를 적어주세요.
-
- {new Date().toLocaleDateString("ko-KR", {
- year: "numeric",
- month: "long",
- day: "numeric",
- })}
-
-
+
+
props.width || "2.5rem"};
height: 2.5rem;
- background-color: rgba(255, 255, 255, 0.3);
+ background-color: rgba(255, 255, 255, 0.2);
border-radius: 2rem;
z-index: 1001;
@@ -346,8 +346,7 @@ const ModalSideButton = styled.div`
cursor: pointer;
&:hover {
- background-color: rgba(255, 255, 255, 0.5);
- transition: 0.25s;
+ background-color: rgba(255, 255, 255, 0.3);
}
`;
@@ -355,10 +354,6 @@ const DiaryModalTitle = styled.h1`
font-size: 1.5rem;
`;
-const DiaryModalDate = styled.div`
- color: rgba(0, 0, 0, 0.55);
-`;
-
const DiaryModalInputBox = styled.input`
width: 100%;
height: 3rem;
@@ -442,7 +437,7 @@ const DiaryModalTagBox = styled.div`
padding: 0.5rem 1rem;
border-radius: 1.5rem;
border: 1px solid #ffffff;
- background-color: rgba(255, 255, 255, 0.3);
+ background-color: rgba(255, 255, 255, 0.2);
flex-shrink: 0;
diff --git a/FE/src/components/DiaryModal/EmotionIndicator/DiaryEmotionIndicator.js b/FE/src/components/DiaryModal/EmotionIndicator/DiaryEmotionIndicator.js
new file mode 100644
index 0000000..38eee75
--- /dev/null
+++ b/FE/src/components/DiaryModal/EmotionIndicator/DiaryEmotionIndicator.js
@@ -0,0 +1,107 @@
+import React, { useState } from "react";
+import styled from "styled-components";
+import EmotionPicket from "./EmotionPicket";
+import indicatorArrowIcon from "../../../assets/indicator-arrow.svg";
+
+function DiaryEmotionIndicator({ emotion, width, text }) {
+ const [isHover, setIsHover] = useState("");
+ return (
+
+
+ setIsHover("positive")}
+ onMouseLeave={() => setIsHover("")}
+ >
+ {isHover === "positive" ? (
+
+ ) : null}
+
+
+
+
+ setIsHover("neutral")}
+ onMouseLeave={() => setIsHover("")}
+ >
+ {isHover === "neutral" ? (
+
+ ) : null}
+
+
+
+
+ setIsHover("negative")}
+ onMouseLeave={() => setIsHover("")}
+ >
+ {isHover === "negative" ? (
+
+ ) : null}
+
+
+ {text === true ? (
+
+ 긍정 {emotion.positive.toFixed(1)}%
+ 중립 {emotion.neutral.toFixed(1)}%
+ 부정 {emotion.negative.toFixed(1)}%
+
+ ) : null}
+
+ );
+}
+
+const EmotionIndicatorWrapper = styled.div`
+ width: 70%;
+ display: flex;
+ align-items: center;
+ gap: 1.5rem;
+`;
+
+const EmotionIndicatorBar = styled.div`
+ width: ${(props) => props.width || "20rem"};
+ height: 1rem;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+`;
+
+const EmotionIndicator = styled.div`
+ width: ${(props) => props.$ratio};
+ height: 100%;
+ background-color: ${(props) => props.color};
+ display: flex;
+ justify-content: center;
+`;
+
+const EmotionIndicatorArrow = styled.div`
+ display: flex;
+ justify-content: center;
+ width: 0;
+ height: 4rem;
+`;
+
+const EmotionTextWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+`;
+
+const EmotionText = styled.div`
+ font-size: 0.9rem;
+`;
+
+export default DiaryEmotionIndicator;
diff --git a/FE/src/components/DiaryModal/EmotionIndicator/EmotionPicket.js b/FE/src/components/DiaryModal/EmotionIndicator/EmotionPicket.js
new file mode 100644
index 0000000..4595d62
--- /dev/null
+++ b/FE/src/components/DiaryModal/EmotionIndicator/EmotionPicket.js
@@ -0,0 +1,36 @@
+import React from "react";
+import styled from "styled-components";
+import picket from "../../../assets/picket.svg";
+
+function EmotionPicket({ percent }) {
+ return (
+
+ {percent.toFixed(1)}%
+
+ );
+}
+
+const EmotionPicketWrapper = styled.div`
+ width: 5rem;
+ height: 3.3rem;
+ position: float;
+ display: flex;
+ justify-content: center;
+ align-items: flex-end;
+ font-size: 1rem;
+ color: #ffffff;
+`;
+
+const Picket = styled.div`
+ width: 100%;
+ height: 3rem;
+ background-image: url(${picket});
+ background-position: center;
+ background-repeat: no-repeat;
+ display: flex;
+ justify-content: center;
+ align-items: flex-end;
+ line-height: 2.3rem;
+`;
+
+export default EmotionPicket;
diff --git a/FE/src/components/SideBar/SideBar.js b/FE/src/components/SideBar/SideBar.js
index 3ccb2fb..be461a5 100644
--- a/FE/src/components/SideBar/SideBar.js
+++ b/FE/src/components/SideBar/SideBar.js
@@ -31,6 +31,7 @@ function SideBar() {
...prev,
isRead: false,
isList: false,
+ isAnalysis: false,
};
});
}}
@@ -51,6 +52,7 @@ function SideBar() {
isRead: false,
isUpdate: false,
isList: true,
+ isAnalysis: false,
},
"",
"",
@@ -61,13 +63,45 @@ function SideBar() {
isRead: false,
isUpdate: false,
isList: true,
+ isAnalysis: false,
};
});
}}
>
일기 목록
- 일기 분석
+ {
+ setHeaderState((prev) => ({
+ ...prev,
+ isSideBar: false,
+ }));
+ setDiaryState((prev) => {
+ window.history.pushState(
+ {
+ ...prev,
+ isCreate: false,
+ isRead: false,
+ isUpdate: false,
+ isList: false,
+ isAnalysis: true,
+ },
+ "",
+ "",
+ );
+ return {
+ ...prev,
+ isCreate: false,
+ isRead: false,
+ isUpdate: false,
+ isList: false,
+ isAnalysis: true,
+ };
+ });
+ }}
+ >
+ 일기 분석
+
환경 설정
별숲 상점
diff --git a/FE/src/pages/HomePage.js b/FE/src/pages/HomePage.js
index 1419921..a2de8df 100644
--- a/FE/src/pages/HomePage.js
+++ b/FE/src/pages/HomePage.js
@@ -2,7 +2,6 @@ import React from "react";
import styled from "styled-components";
import { useRecoilValue } from "recoil";
import headerAtom from "../atoms/headerAtom";
-
import homeBackground from "../assets/homeBackground.png";
import LoginModal from "../components/LoginModal/LoginModal";
import SignUpModal from "../components/SignUpModal/SignUpModal";
diff --git a/FE/src/pages/MainPage.js b/FE/src/pages/MainPage.js
index 68f2439..c45f2c0 100644
--- a/FE/src/pages/MainPage.js
+++ b/FE/src/pages/MainPage.js
@@ -10,10 +10,11 @@ import userAtom from "../atoms/userAtom";
import DiaryCreateModal from "../components/DiaryModal/DiaryCreateModal";
import DiaryReadModal from "../components/DiaryModal/DiaryReadModal";
import DiaryListModal from "../components/DiaryModal/DiaryListModal";
+import DiaryAnalysisModal from "../components/DiaryModal/DiaryAnalysisModal";
import DiaryUpdateModal from "../components/DiaryModal/DiaryUpdateModal";
import DiaryLoadingModal from "../components/DiaryModal/DiaryLoadingModal";
import StarPage from "./StarPage";
-import preventBeforeUnload from "../utils/utils";
+import { preventBeforeUnload } from "../utils/utils";
function MainPage() {
const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
@@ -23,7 +24,7 @@ function MainPage() {
const { refetch } = useQuery(
["diaryList", userState.accessToken],
- () => {
+ async () => {
return fetch("http://223.130.129.145:3005/diaries", {
method: "GET",
headers: {
@@ -140,6 +141,7 @@ function MainPage() {
{diaryState.isRead ? : null}
{diaryState.isUpdate ? : null}
{diaryState.isList ? : null}
+ {diaryState.isAnalysis ? : null}
{diaryState.isLoading ? : null}
>
) : null}
diff --git a/FE/src/pages/StarPage.js b/FE/src/pages/StarPage.js
index dc9cde2..effec0f 100644
--- a/FE/src/pages/StarPage.js
+++ b/FE/src/pages/StarPage.js
@@ -19,7 +19,7 @@ import arrow from "../assets/arrow.svg";
import paint from "../assets/paint.svg";
function StarPage() {
- const setDiaryState = useSetRecoilState(diaryAtom);
+ const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
const [starState, setStarState] = useRecoilState(starAtom);
return (
@@ -42,35 +42,37 @@ function StarPage() {
- {
- setStarState((prev) => ({
- ...prev,
- mode: "create",
- drag: true,
- selected: null,
- }));
- }}
- rightEvent={() => {
- setDiaryState((prev) => ({
- ...prev,
- isCreate: false,
- isRead: false,
- isUpdate: false,
- isDelete: false,
- }));
- setStarState((prev) => ({
- ...prev,
- mode: "stella",
- drag: false,
- selected: null,
- }));
- }}
- />
+ {!(diaryState.isList || diaryState.isAnalysis) ? (
+ {
+ setStarState((prev) => ({
+ ...prev,
+ mode: "create",
+ drag: true,
+ selected: null,
+ }));
+ }}
+ rightEvent={() => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isCreate: false,
+ isRead: false,
+ isUpdate: false,
+ isDelete: false,
+ }));
+ setStarState((prev) => ({
+ ...prev,
+ mode: "stella",
+ drag: false,
+ selected: null,
+ }));
+ }}
+ />
+ ) : null}
{starState.mode !== "create" ? (
- props.selected ? "#ffffff80" : "transparent"};
+ props.selected ? "rgba(255, 255, 255, 0.2)" : "transparent"};
border-radius: 1.5rem;
display: flex;
diff --git a/FE/src/styles/Modal/DiaryModalHeader.js b/FE/src/styles/Modal/DiaryModalHeader.js
deleted file mode 100644
index 898befb..0000000
--- a/FE/src/styles/Modal/DiaryModalHeader.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import styled from "styled-components";
-
-const DiaryModalHeader = styled.div`
- width: 100%;
- display: flex;
- align-items: flex-end;
- justify-content: space-between;
-`;
-
-export default DiaryModalHeader;
diff --git a/FE/src/styles/Modal/ModalWrapper.js b/FE/src/styles/Modal/ModalWrapper.js
index aff9da1..2034e31 100644
--- a/FE/src/styles/Modal/ModalWrapper.js
+++ b/FE/src/styles/Modal/ModalWrapper.js
@@ -12,7 +12,7 @@ const ModalWrapper = styled.div`
z-index: 1001;
width: ${(props) => props.width};
height: ${(props) => props.height};
- background-color: rgba(255, 255, 255, ${(props) => props.opacity || 0.3});
+ background-color: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
transform: translate(-50%, -50%);
border-radius: ${(props) => props.$borderRadius || "1rem"};
diff --git a/FE/src/styles/Modal/Tag.js b/FE/src/styles/Modal/Tag.js
new file mode 100644
index 0000000..9837c7a
--- /dev/null
+++ b/FE/src/styles/Modal/Tag.js
@@ -0,0 +1,17 @@
+import styled from "styled-components";
+
+const Tag = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0.5rem 1rem;
+ border-radius: 1rem;
+ background-color: rgba(255, 255, 255, 0.2);
+ box-sizing: border-box;
+ color: #ffffff;
+ outline: none;
+ white-space: nowrap;
+ font-size: 1rem;
+`;
+
+export default Tag;
diff --git a/FE/src/utils/utils.js b/FE/src/utils/utils.js
index a4dd834..dc2e9fd 100644
--- a/FE/src/utils/utils.js
+++ b/FE/src/utils/utils.js
@@ -3,4 +3,13 @@ const preventBeforeUnload = (e) => {
e.returnValue = "";
};
-export default preventBeforeUnload;
+const getFormattedDate = (date) => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+
+ const formattedDate = `${year}-${month}-${day}`;
+ return formattedDate;
+};
+
+export { preventBeforeUnload, getFormattedDate };