diff --git a/FE/src/App.js b/FE/src/App.js
index c135988..890b939 100644
--- a/FE/src/App.js
+++ b/FE/src/App.js
@@ -6,7 +6,6 @@ import { createGlobalStyle } from "styled-components";
import { useRecoilState, useSetRecoilState } from "recoil";
import { Route, Routes } from "react-router-dom";
import userAtom from "./atoms/userAtom";
-import diaryAtom from "./atoms/diaryAtom";
import Header from "./components/Header/Header";
import HomePage from "./pages/HomePage";
import MainPage from "./pages/MainPage";
@@ -42,7 +41,6 @@ const GlobalStyle = createGlobalStyle`
function App() {
const [userState, setUserState] = useRecoilState(userAtom);
- const setDiaryState = useSetRecoilState(diaryAtom);
useLayoutEffect(() => {
let accessToken = localStorage.getItem("accessToken");
@@ -68,12 +66,6 @@ function App() {
window.history.replaceState({}, "", "/");
}
}
-
- window.onpopstate = (event) => {
- if (event.state) {
- setDiaryState(event.state);
- }
- };
}, []);
return (
diff --git a/FE/src/components/Button/SwitchButton.js b/FE/src/components/Button/SwitchButton.js
index 432beaf..a0b55e8 100644
--- a/FE/src/components/Button/SwitchButton.js
+++ b/FE/src/components/Button/SwitchButton.js
@@ -2,9 +2,7 @@ import React, { useState } from "react";
import styled from "styled-components";
function SwitchButton(props) {
- // 위치 설정 관련 props
const { bottom, right } = props;
- // 버튼 내용 / 이벤트 관련 props
const { leftContent, rightContent, leftEvent, rightEvent } = props;
const [current, setCurrent] = useState(leftContent);
diff --git a/FE/src/components/DiaryModal/DiaryAnalysisModal.js b/FE/src/components/DiaryModal/DiaryAnalysisModal.js
index 7f0818d..c10bfa1 100644
--- a/FE/src/components/DiaryModal/DiaryAnalysisModal.js
+++ b/FE/src/components/DiaryModal/DiaryAnalysisModal.js
@@ -12,8 +12,11 @@ import Tag from "../../styles/Modal/Tag";
import leftIcon from "../../assets/leftIcon.svg";
import rightIcon from "../../assets/rightIcon.svg";
import logoNoText from "../../assets/logo-notext.svg";
+import handleResponse from "../../utils/handleResponse";
function DiaryAnalysisModal() {
+ const [userState, setUserState] = useRecoilState(userAtom);
+ const setDiaryState = useSetRecoilState(diaryAtom);
const [buttonDisabled, setButtonDisabled] = useState(false);
const [currentYear, setCurrentYear] = useState(dayjs("2023"));
const [emotion, setEmotion] = useState({
@@ -22,8 +25,6 @@ function DiaryAnalysisModal() {
neutral: 0,
});
const [monthAnalysis, setMonthAnalysis] = useState(Array(12).fill(0));
- const [userState, setUserState] = useRecoilState(userAtom);
- const setDiaryState = useSetRecoilState(diaryAtom);
const [hoverData, setHoverData] = useState({
top: 0,
left: 0,
@@ -40,40 +41,24 @@ function DiaryAnalysisModal() {
Authorization: `Bearer ${userState.accessToken}`,
},
},
- ).then((res) => {
- if (res.status === 200) {
- return res.json();
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- });
- }
- return {};
- });
+ ).then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 200,
+ onSuccessCallback: () => res.json(),
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ },
+ }),
+ );
}
const { data: tagsRankData, refetch: tagsRankRefetch } = useQuery(
@@ -195,14 +180,11 @@ function DiaryAnalysisModal() {
{day}
))}
- {
- // dayjs로 1월 1일 이 무슨 요일인지 알아내서 그거에 맞게 빈칸 넣어주기
- Array.from({ length: currentYear.day() }, (v, i) => i + 1).map(
- (day) => (
-
- ),
- )
- }
+ {Array.from({ length: currentYear.day() }, (v, i) => i + 1).map(
+ (day) => (
+
+ ),
+ )}
{Array.from(
{
length:
@@ -470,7 +452,6 @@ function ShapeRanking(props) {
);
}
-// 일기 나열 페이지와 중복되는 부분이 많아서 일단은 일기 나열 페이지를 재활용했습니다.
const DiaryAnalysisModalWrapper = styled.div`
width: 95%;
height: 97.5%;
diff --git a/FE/src/components/DiaryModal/DiaryCreateModal.js b/FE/src/components/DiaryModal/DiaryCreateModal.js
index 1ad9e89..3d15295 100644
--- a/FE/src/components/DiaryModal/DiaryCreateModal.js
+++ b/FE/src/components/DiaryModal/DiaryCreateModal.js
@@ -12,14 +12,14 @@ import Calendar from "./Calendar";
import close from "../../assets/close.svg";
import getFormattedDate from "../../utils/utils";
import ModalBackground from "../ModalBackground/ModalBackground";
+import handleResponse from "../../utils/handleResponse";
function DiaryCreateModal(props) {
const { refetch } = props;
- const [isInput, setIsInput] = useState(false);
const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
const [userState, setUserState] = useRecoilState(userAtom);
+ const [isInput, setIsInput] = useState(false);
- // TODO: 날짜 선택 기능 구현
const [diaryData, setDiaryData] = useState({
title: "",
content: "",
@@ -68,41 +68,24 @@ function DiaryCreateModal(props) {
},
body: JSON.stringify(formattedDiaryData),
})
- .then((res) => {
- if (res.status === 201) {
- return res.json();
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- createDiary({ diaryData, accessToken: data.accessToken });
- });
- }
- throw new Error("다이어리 생성에 실패했습니다.");
- })
+ .then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 201,
+ onSuccessCallback: () => res.json(),
+ on403Callback: () =>
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ })),
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ createDiary({ diaryData, accessToken });
+ },
+ }),
+ )
.then(() => {
refetch();
setDiaryState((prev) => ({
@@ -112,11 +95,7 @@ function DiaryCreateModal(props) {
});
}
- const {
- mutate: createDiary,
- // isLoading: diaryIsLoading,
- // isError: diaryIsError,
- } = useMutation(createDiaryFn);
+ const { mutate: createDiary } = useMutation(createDiaryFn);
return (
<>
diff --git a/FE/src/components/DiaryModal/DiaryDeleteModal.js b/FE/src/components/DiaryModal/DiaryDeleteModal.js
index 0f9f404..c625ca8 100644
--- a/FE/src/components/DiaryModal/DiaryDeleteModal.js
+++ b/FE/src/components/DiaryModal/DiaryDeleteModal.js
@@ -6,6 +6,7 @@ import diaryAtom from "../../atoms/diaryAtom";
import userAtom from "../../atoms/userAtom";
import lastPageAtom from "../../atoms/lastPageAtom";
import ModalWrapper from "../../styles/Modal/ModalWrapper";
+import handleResponse from "../../utils/handleResponse";
function DiaryDeleteModal(props) {
const { refetch, pointsRefetch } = props;
@@ -24,55 +25,35 @@ function DiaryDeleteModal(props) {
},
},
)
- .then((res) => {
- if (res.status === 204) {
- return res;
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${data.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- deleteDiary({
- diaryUuid: diaryState.diaryUuid,
- accessToken: data.accessToken,
- });
+ .then((res) =>
+ handleResponse(res, data.accessToken, {
+ successStatus: 204,
+ onSuccessCallback: () => {},
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ deleteDiary({
+ diaryUuid: diaryState.diaryUuid,
+ accessToken,
});
- }
- throw new Error("일기 삭제 실패");
- })
+ },
+ }),
+ )
.then(() => {
refetch();
pointsRefetch();
});
}
- const {
- mutate: deleteDiary,
- // isLoading,
- // error,
- } = useMutation(deleteDiaryFn);
+ const { mutate: deleteDiary } = useMutation(deleteDiaryFn);
return (
diff --git a/FE/src/components/DiaryModal/DiaryListModal.js b/FE/src/components/DiaryModal/DiaryListModal.js
index 76906ac..755df85 100644
--- a/FE/src/components/DiaryModal/DiaryListModal.js
+++ b/FE/src/components/DiaryModal/DiaryListModal.js
@@ -1,6 +1,6 @@
/* eslint-disable */
-import React, { useEffect, useLayoutEffect } from "react";
+import React, { useEffect, useLayoutEffect, useState } from "react";
import styled from "styled-components";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import DatePicker from "react-datepicker";
@@ -13,11 +13,11 @@ import zoomIn from "../../assets/zoomIn.svg";
import search from "../../assets/search.svg";
function DiaryListModal() {
- const [selectedDiary, setSelectedDiary] = React.useState(null);
const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
const shapeState = useRecoilValue(shapeAtom);
const setLastPageState = useSetRecoilState(lastPageAtom);
- const [filterState, setFilterState] = React.useState({
+ const [selectedDiary, setSelectedDiary] = useState(null);
+ const [filterState, setFilterState] = useState({
date: {
start: null,
end: null,
@@ -30,7 +30,7 @@ function DiaryListModal() {
shape: [],
tag: [],
});
- const [filteredDiaryList, setFilteredDiaryList] = React.useState([]);
+ const [filteredDiaryList, setFilteredDiaryList] = useState([]);
useLayoutEffect(() => {
if (diaryState.diaryList) {
diff --git a/FE/src/components/DiaryModal/DiaryReadModal.js b/FE/src/components/DiaryModal/DiaryReadModal.js
index fdbcade..1bbc183 100644
--- a/FE/src/components/DiaryModal/DiaryReadModal.js
+++ b/FE/src/components/DiaryModal/DiaryReadModal.js
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useState } from "react";
import { useQuery } from "react-query";
import styled from "styled-components";
import { useRecoilState, useRecoilValue } from "recoil";
@@ -14,6 +14,7 @@ import editIcon from "../../assets/edit.svg";
import deleteIcon from "../../assets/delete.svg";
import close from "../../assets/close.svg";
import ModalBackground from "../ModalBackground/ModalBackground";
+import handleResponse from "../../utils/handleResponse";
async function getDiary(accessToken, diaryUuid, setUserState, setDiaryState) {
return fetch(`${process.env.REACT_APP_BACKEND_URL}/diaries/${diaryUuid}`, {
@@ -22,40 +23,24 @@ async function getDiary(accessToken, diaryUuid, setUserState, setDiaryState) {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
- }).then((res) => {
- if (res.status === 200) {
- return res.json();
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- });
- }
- return {};
- });
+ }).then((res) =>
+ handleResponse(res, accessToken, {
+ successStatus: 200,
+ onSuccessCallback: () => res.json(),
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ },
+ }),
+ );
}
function DiaryReadModal(props) {
@@ -64,7 +49,8 @@ function DiaryReadModal(props) {
const [userState, setUserState] = useRecoilState(userAtom);
const [lastPageState, setLastPageState] = useRecoilState(lastPageAtom);
const shapeState = useRecoilValue(shapeAtom);
- const [shapeData, setShapeData] = React.useState("");
+ const [shapeData, setShapeData] = useState("");
+
const { data, isLoading, isError } = useQuery(
["diary", userState.accessToken],
() =>
@@ -213,7 +199,6 @@ function DiaryReadModal(props) {
);
}
-// ToDo: 통합 필요
const DiaryModalHeader = styled.div`
width: 100%;
display: flex;
diff --git a/FE/src/components/DiaryModal/DiaryUpdateModal.js b/FE/src/components/DiaryModal/DiaryUpdateModal.js
index 4c6a593..b89b4e3 100644
--- a/FE/src/components/DiaryModal/DiaryUpdateModal.js
+++ b/FE/src/components/DiaryModal/DiaryUpdateModal.js
@@ -12,15 +12,15 @@ import Calendar from "./Calendar";
import close from "../../assets/close.svg";
import getFormattedDate from "../../utils/utils";
import ModalBackground from "../ModalBackground/ModalBackground";
+import handleResponse from "../../utils/handleResponse";
-// TODO: 일기 데이터 수정 API 연결
function DiaryUpdateModal(props) {
const { refetch } = props;
+ const [userState, setUserState] = useRecoilState(userAtom);
+ const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
const titleRef = useRef(null);
const contentRef = useRef(null);
const [isInput, setIsInput] = useState(true);
- const [userState, setUserState] = useRecoilState(userAtom);
- const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
const [diaryData, setDiaryData] = useState({
uuid: diaryState.diaryUuid,
title: "",
@@ -33,11 +33,7 @@ function DiaryUpdateModal(props) {
)?.shapeUuid,
});
- const {
- mutate: updateDiary,
- // isLoading: diaryIsLoading,
- // isError: diaryIsError,
- } = useMutation(updateDiaryFn);
+ const { mutate: updateDiary } = useMutation(updateDiaryFn);
const {
data: originData,
@@ -98,48 +94,34 @@ function DiaryUpdateModal(props) {
Authorization: `Bearer ${data.accessToken}`,
},
body: JSON.stringify(formattedDiaryData),
- }).then((res) => {
- if (res.status === 204) {
- refetch();
- setDiaryState((prev) => ({
- ...prev,
- isRead: true,
- }));
- }
- if (res.status === 403) {
- console.log("권한 없음");
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${data.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- updateDiary({
- diaryData: diaryData,
- accessToken: data.accessToken,
- });
+ }).then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 204,
+ onSuccessCallback: () => {
+ refetch();
+ setDiaryState((prev) => ({
+ ...prev,
+ isRead: true,
+ }));
+ },
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ updateDiary({
+ diaryData: diaryData,
+ accessToken,
});
- }
- });
+ },
+ }),
+ );
}
async function getDiary(accessToken, diaryUuid) {
diff --git a/FE/src/components/DiaryModal/EmotionIndicator/DiaryEmotionIndicator.js b/FE/src/components/DiaryModal/EmotionIndicator/DiaryEmotionIndicator.js
index dc3f3d5..946b6cb 100644
--- a/FE/src/components/DiaryModal/EmotionIndicator/DiaryEmotionIndicator.js
+++ b/FE/src/components/DiaryModal/EmotionIndicator/DiaryEmotionIndicator.js
@@ -5,6 +5,7 @@ import indicatorArrowIcon from "../../../assets/indicator-arrow.svg";
function DiaryEmotionIndicator({ emotion, width, text }) {
const [isHover, setIsHover] = useState("");
+
return (
diff --git a/FE/src/components/DiaryModal/EmotionIndicator/EmotionPicket.js b/FE/src/components/DiaryModal/EmotionIndicator/EmotionPicket.js
index 4595d62..440dc04 100644
--- a/FE/src/components/DiaryModal/EmotionIndicator/EmotionPicket.js
+++ b/FE/src/components/DiaryModal/EmotionIndicator/EmotionPicket.js
@@ -2,7 +2,9 @@ import React from "react";
import styled from "styled-components";
import picket from "../../../assets/picket.svg";
-function EmotionPicket({ percent }) {
+function EmotionPicket(props) {
+ const { percent } = props;
+
return (
{percent.toFixed(1)}%
diff --git a/FE/src/components/LoginModal/LoginModal.js b/FE/src/components/LoginModal/LoginModal.js
index 46647a7..8927e83 100644
--- a/FE/src/components/LoginModal/LoginModal.js
+++ b/FE/src/components/LoginModal/LoginModal.js
@@ -13,11 +13,11 @@ import kakao from "../../assets/kakao.png";
import naver from "../../assets/naver.png";
function LoginModal() {
+ const setUserState = useSetRecoilState(userAtom);
+ const setHeaderState = useSetRecoilState(headerAtom);
const [userId, setUserId] = useState("");
const [keepLogin, setKeepLogin] = useState(false);
const [password, setPassword] = useState("");
- const setUserState = useSetRecoilState(userAtom);
- const setHeaderState = useSetRecoilState(headerAtom);
const errorRef = useRef();
const { mutate: login } = useMutation(() => {
diff --git a/FE/src/components/PurchaseModal/PurchaseModal.js b/FE/src/components/PurchaseModal/PurchaseModal.js
index 275d75c..6b9d327 100644
--- a/FE/src/components/PurchaseModal/PurchaseModal.js
+++ b/FE/src/components/PurchaseModal/PurchaseModal.js
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import { useQuery, useMutation } from "react-query";
import styled from "styled-components";
-import { useRecoilState } from "recoil";
+import { useRecoilState, useSetRecoilState } from "recoil";
import userAtom from "../../atoms/userAtom";
import leftIcon from "../../assets/leftIcon.svg";
import rightIcon from "../../assets/rightIcon.svg";
@@ -9,13 +9,17 @@ import oneStar from "../../assets/onestar.svg";
import twoStar from "../../assets/twostar.svg";
import threeStar from "../../assets/threestar.svg";
import fourStar from "../../assets/fourstar.svg";
+import diaryAtom from "../../atoms/diaryAtom";
+import handleResponse from "../../utils/handleResponse";
-function PurchaseModal() {
- const [x, setX] = useState(0);
+function PurchaseModal(props) {
+ const { premiumRefetch } = props;
const [userState, setUserState] = useRecoilState(userAtom);
+ const setDiaryState = useSetRecoilState(diaryAtom);
+ const [x, setX] = useState(0);
const { data: creditData, refetch: creditRefetch } = useQuery(
- ["credit"],
+ ["credit", userState.accessToken],
async () =>
fetch(`${process.env.REACT_APP_BACKEND_URL}/purchase/credit`, {
method: "GET",
@@ -23,34 +27,24 @@ function PurchaseModal() {
"Content-Type": "application/json",
Authorization: `Bearer ${userState.accessToken}`,
},
- }).then(async (res) => {
- if (res.status === 200) {
- return res.json();
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- });
- }
- return {};
- }),
+ }).then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 200,
+ onSuccessCallback: () => res.json(),
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ },
+ }),
+ ),
);
const { mutate: purchase } = useMutation((data) => {
@@ -61,7 +55,7 @@ function PurchaseModal() {
method: "POST",
headers: {
"Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
+ Authorization: `Bearer ${data.accessToken}`,
},
};
@@ -73,38 +67,30 @@ function PurchaseModal() {
fetch(
`${process.env.REACT_APP_BACKEND_URL}/purchase/${data.item}`,
fetchData,
- ).then(async (res) => {
- if (res.status === 201) {
- alert("구매가 완료되었습니다.");
- creditRefetch();
- }
- if (res.status === 400) {
- alert((await res.json()).message);
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
+ ).then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 201,
+ onSuccessCallback: () => {
+ alert("구매가 완료되었습니다.");
+ creditRefetch();
+ premiumRefetch();
+ },
+ on400Callback: async () => {
+ alert((await res.json()).message);
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ purchase({
+ credit: data.credit,
+ item: data.item,
+ accessToken,
});
- }
- return {};
- });
+ },
+ }),
+ );
}
});
@@ -139,7 +125,11 @@ function PurchaseModal() {
{
- purchase({ credit: 100, item: "premium" });
+ purchase({
+ credit: 350,
+ item: "premium",
+ accessToken: userState.accessToken,
+ });
}}
>
광고 제거
diff --git a/FE/src/components/SignUpModal/SignUpModal.js b/FE/src/components/SignUpModal/SignUpModal.js
index 781996c..13264c7 100644
--- a/FE/src/components/SignUpModal/SignUpModal.js
+++ b/FE/src/components/SignUpModal/SignUpModal.js
@@ -11,12 +11,12 @@ import ModalBackground from "../ModalBackground/ModalBackground";
import SignUpRuleGuide from "./SignUpRuleGuide";
function SignUpModal() {
+ const setHeaderState = useSetRecoilState(headerAtom);
const [email, setEmail] = useState("");
const [userId, setUserId] = useState("");
const [nickname, setNickname] = useState("");
const [password, setPassword] = useState("");
const [passwordCheck, setPasswordCheck] = useState("");
- const setHeaderState = useSetRecoilState(headerAtom);
const errorRef = useRef();
const { mutate: signUp } = useMutation(() => {
diff --git a/FE/src/constants/constants.js b/FE/src/constants/constants.js
deleted file mode 100644
index e69de29..0000000
diff --git a/FE/src/index.js b/FE/src/index.js
index 2916fd3..9cedc6a 100644
--- a/FE/src/index.js
+++ b/FE/src/index.js
@@ -6,9 +6,18 @@ import { RecoilRoot } from "recoil";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ },
+ },
+});
+
root.render(
-
+
diff --git a/FE/src/pages/LoadingPage.js b/FE/src/pages/LoadingPage.js
index 7619d12..3cf74a5 100644
--- a/FE/src/pages/LoadingPage.js
+++ b/FE/src/pages/LoadingPage.js
@@ -45,7 +45,6 @@ function LoadingPage() {
);
}
-// TODO: 배경 이미지 제거하고 영상으로 대체할 것
const LoadingPageWrapper = styled.div`
height: 100vh;
background-image: url(${homeBackground});
diff --git a/FE/src/pages/MainPage.js b/FE/src/pages/MainPage.js
index b2de85e..1ab0c6a 100644
--- a/FE/src/pages/MainPage.js
+++ b/FE/src/pages/MainPage.js
@@ -17,6 +17,7 @@ import DiaryLoadingModal from "../components/DiaryModal/DiaryLoadingModal";
import PurchaseModal from "../components/PurchaseModal/PurchaseModal";
import StarPage from "./StarPage";
import RedirectToHomepage from "./Redirection";
+import handleResponse from "../utils/handleResponse";
function MainPage() {
const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
@@ -34,41 +35,27 @@ function MainPage() {
"Content-Type": "application/json",
Authorization: `Bearer ${userState.accessToken}`,
},
- }).then((res) => {
- if (res.status === 200) {
- setLoaded(true);
- return res.json();
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- });
- }
- return [];
- });
+ }).then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 200,
+ onSuccessCallback: () => {
+ setLoaded(true);
+ return res.json();
+ },
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ },
+ }),
+ );
},
{
onSuccess: (data) => {
@@ -85,41 +72,31 @@ function MainPage() {
const { refetch: pointsRefetch } = useQuery(
["points", userState.accessToken],
- () =>
+ async () =>
fetch(`${process.env.REACT_APP_BACKEND_URL}/lines`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${userState.accessToken}`,
},
- }).then((res) => {
- if (res.status === 200) {
- return res.json();
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- });
- }
- return [];
- }),
+ }).then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 200,
+ onSuccessCallback: () => res.json(),
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ },
+ }),
+ ),
{
onSuccess: (data) => {
data.forEach((point) => {
@@ -146,34 +123,24 @@ function MainPage() {
"Content-Type": "application/json",
Authorization: `Bearer ${userState.accessToken}`,
},
- }).then((res) => {
- if (res.status === 200) {
- return res.json();
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${userState.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- });
- }
- return {};
- }),
+ }).then((res) =>
+ handleResponse(res, userState.accessToken, {
+ successStatus: 200,
+ onSuccessCallback: () => res.json(),
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ },
+ }),
+ ),
{
onSuccess: (data) => {
if (data?.premium === "TRUE") {
diff --git a/FE/src/pages/StarPage.js b/FE/src/pages/StarPage.js
index b12fccc..5e8f5b1 100644
--- a/FE/src/pages/StarPage.js
+++ b/FE/src/pages/StarPage.js
@@ -21,6 +21,7 @@ import hand from "../assets/hand.svg";
import stella from "../assets/stella.svg";
import arrow from "../assets/arrow.svg";
import paint from "../assets/paint.svg";
+import handleResponse from "../utils/handleResponse";
function StarPage({ refetch, pointsRefetch }) {
const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
@@ -197,14 +198,13 @@ function Scene() {
}
function StarView({ refetch, pointsRefetch, setHoverData }) {
- const { scene, raycaster, camera } = useThree();
const [diaryState, setDiaryState] = useRecoilState(diaryAtom);
const [userState, setUserState] = useRecoilState(userAtom);
const [starState, setStarState] = useRecoilState(starAtom);
- const { mode, selected } = starState;
const shapeState = useRecoilValue(shapeAtom);
const [texture, setTexture] = useState({});
- let clickedPoint = [0, 0, 0];
+ const { scene, raycaster, camera } = useThree();
+ const { mode, selected } = starState;
async function updateDiaryFn(data) {
setDiaryState((prev) => ({
@@ -219,56 +219,38 @@ function StarView({ refetch, pointsRefetch, setHoverData }) {
Authorization: `Bearer ${data.accessToken}`,
},
body: JSON.stringify(data.diaryData),
- }).then((res) => {
- if (res.status === 204) {
- refetch();
- pointsRefetch();
- setStarState((prev) => ({
- ...prev,
- selected: null,
- }));
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${data.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
-
- updateDiary({
- accessToken: data.accessToken,
- diaryData,
- });
+ }).then((res) =>
+ handleResponse(res, data.accessToken, {
+ successStatus: 204,
+ onSuccessCallback: () => {
+ refetch();
+ pointsRefetch();
+ setStarState((prev) => ({
+ ...prev,
+ selected: null,
+ }));
+ },
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ updateDiary({
+ accessToken,
+ diaryData,
});
- }
- });
+ },
+ }),
+ );
}
- const {
- mutate: updateDiary,
- // isLoading: diaryIsLoading,
- // isError: diaryIsError,
- } = useMutation(updateDiaryFn);
+ const { mutate: updateDiary } = useMutation(updateDiaryFn);
useEffect(() => {
scene.children.forEach((child) => {
@@ -294,18 +276,8 @@ function StarView({ refetch, pointsRefetch, setHoverData }) {
setTexture(newTexture);
}, [shapeState]);
- // const shapeData = shapeState.find((shape)
- // => shape.uuid === shapeUuid)?.data;
- // const blob = new Blob([shapeData], { type: "image/svg+xml" });
- // const urlObject = URL.createObjectURL(blob);
-
- // const loader = new THREE.TextureLoader();
- // const svgTexture = loader.load(urlObject);
-
const material = new THREE.ShaderMaterial({
uniforms: {
- // color1: { value: new THREE.Color("#656990") },
- // color2: { value: new THREE.Color("#182683") },
color1: { value: new THREE.Color("#454980") },
color2: { value: new THREE.Color("#182663") },
gradientStart: { value: 0.001 },
@@ -456,17 +428,18 @@ function StarView({ refetch, pointsRefetch, setHoverData }) {
);
}
-function Star({
- uuid,
- title,
- date,
- position,
- sentiment,
- texture,
- moveToStar,
- refetch,
- setHoverData,
-}) {
+function Star(props) {
+ const {
+ uuid,
+ title,
+ date,
+ position,
+ sentiment,
+ texture,
+ moveToStar,
+ refetch,
+ setHoverData,
+ } = props;
const setDiaryState = useSetRecoilState(diaryAtom);
const [userState, setUserState] = useRecoilState(userAtom);
const [starState, setStarState] = useRecoilState(starAtom);
@@ -506,45 +479,29 @@ function Star({
uuid2: data.uuid2,
}),
})
- .then(async (res) => {
- if (res.status === 201) {
- return res.json();
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${data.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- createLine({
- uuid1: selected.uuid,
- uuid2: uuid,
- accessToken: data.accessToken,
- });
+ .then((res) =>
+ handleResponse(res, data.accessToken, {
+ successStatus: 201,
+ onSuccessCallback: () => res.json(),
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ createLine({
+ uuid1: selected.uuid,
+ uuid2: uuid,
+ accessToken,
});
- }
- throw new Error("라인 생성 실패");
- })
+ },
+ }),
+ )
.then(() => {
refetch();
});
@@ -559,44 +516,28 @@ function Star({
Authorization: `Bearer ${data.accessToken}`,
},
})
- .then((res) => {
- if (res.status === 204) {
- return res;
- }
- if (res.status === 403) {
- setDiaryState((prev) => ({
- ...prev,
- isRedirect: true,
- }));
- }
- if (res.status === 401) {
- return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${data.accessToken}`,
- },
- })
- .then((res) => res.json())
- .then((data) => {
- if (localStorage.getItem("accessToken")) {
- localStorage.setItem("accessToken", data.accessToken);
- }
- if (sessionStorage.getItem("accessToken")) {
- sessionStorage.setItem("accessToken", data.accessToken);
- }
- setUserState((prev) => ({
- ...prev,
- accessToken: data.accessToken,
- }));
- deleteLine({
- id,
- accessToken: data.accessToken,
- });
+ .then((res) =>
+ handleResponse(res, data.accessToken, {
+ successStatus: 204,
+ onSuccessCallback: () => res,
+ on403Callback: () => {
+ setDiaryState((prev) => ({
+ ...prev,
+ isRedirect: true,
+ }));
+ },
+ on401Callback: (accessToken) => {
+ setUserState((prev) => ({
+ ...prev,
+ accessToken,
+ }));
+ deleteLine({
+ id,
+ accessToken,
});
- }
- throw new Error("라인 삭제 실패");
- })
+ },
+ }),
+ )
.then(() => {
refetch();
});
@@ -700,7 +641,7 @@ function Star({
new THREE.Matrix4().lookAt(
new THREE.Vector3(),
new THREE.Vector3(...position),
- new THREE.Vector3(0, 1, 0), // Up vector
+ new THREE.Vector3(0, 1, 0),
),
)}
position={position}
@@ -709,7 +650,6 @@ function Star({
e.object.scale.set(1.5, 1.5, 1.5);
e.object.material.emissiveIntensity = 1;
- // e.object 좌표를 스크린 좌표로 변환
const vector = e.object.position.clone();
vector.project(e.camera);
const x = ((vector.x + 1) / 2) * window.innerWidth;
@@ -747,7 +687,7 @@ function Star({
new THREE.Matrix4().lookAt(
new THREE.Vector3(),
new THREE.Vector3(...position),
- new THREE.Vector3(0, 1, 0), // Up vector
+ new THREE.Vector3(0, 1, 0),
),
)}
position={position.map((p) => p * 1.01)}
diff --git a/FE/src/utils/handleResponse.js b/FE/src/utils/handleResponse.js
new file mode 100644
index 0000000..d79045c
--- /dev/null
+++ b/FE/src/utils/handleResponse.js
@@ -0,0 +1,52 @@
+function setStorage(accessToken) {
+ if (localStorage.getItem("accessToken"))
+ localStorage.setItem("accessToken", accessToken);
+ if (sessionStorage.getItem("accessToken"))
+ sessionStorage.setItem("accessToken", accessToken);
+}
+
+function handleResponse(
+ res,
+ accessToken,
+ options = {
+ successStatus: 200,
+ onSuccessCallback: () => {},
+ on400Callback: () => {},
+ on403Callback: () => {},
+ on401Callback: () => {},
+ },
+) {
+ const {
+ successStatus,
+ onSuccessCallback,
+ on400Callback,
+ on403Callback,
+ on401Callback,
+ } = options;
+ if (res.status === successStatus) {
+ return onSuccessCallback();
+ }
+ if (res.status === 400) {
+ return on400Callback();
+ }
+ if (res.status === 403) {
+ return on403Callback();
+ }
+ if (res.status === 401) {
+ return fetch(`${process.env.REACT_APP_BACKEND_URL}/auth/reissue`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${accessToken}`,
+ },
+ })
+ .then((res) => res.json())
+ .then((data) => {
+ setStorage(data.accessToken);
+ on401Callback(data.accessToken);
+ });
+ }
+ throw new Error("error");
+}
+
+export default handleResponse;