diff --git a/FE/.eslintrc.js b/FE/.eslintrc.js index 327c6cb..9851afb 100644 --- a/FE/.eslintrc.js +++ b/FE/.eslintrc.js @@ -26,6 +26,8 @@ module.exports = { "prettier/prettier": ["error", { endOfLine: "auto" }], "react/jsx-filename-extension": [1, { extensions: [".js", ".jsx"] }], "react/prop-types": "off", + "import/no-extraneous-dependencies": ["off"], + "react/no-danger": "off", }, settings: { "import/resolver": { diff --git a/FE/package-lock.json b/FE/package-lock.json index 43a40e7..a19a33c 100644 --- a/FE/package-lock.json +++ b/FE/package-lock.json @@ -8,7 +8,7 @@ "name": "fe", "version": "0.1.0", "dependencies": { - "@react-three/drei": "^9.88.17", + "@react-three/drei": "^9.89.0", "@react-three/fiber": "^8.15.10", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", @@ -3423,9 +3423,9 @@ "integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==" }, "node_modules/@react-three/drei": { - "version": "9.88.17", - "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.88.17.tgz", - "integrity": "sha512-WEYAkikzw0juG3F1aMy1AEeuRmsGmKytb8ETZARd4E6Q61Z1ceoL7fRvrnrXE/A2MHKgSzJgkckMEhKlbbJlyw==", + "version": "9.89.0", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.89.0.tgz", + "integrity": "sha512-iddG7OAfng3a99nAO7erzb1wlwaY1Zlaz9EVfnW9ZiLm4rM322vXHnLX1zhrH5/AeRB/1t4bEu8uAHvXX3XwWA==", "dependencies": { "@babel/runtime": "^7.11.2", "@mediapipe/tasks-vision": "0.10.8", diff --git a/FE/package.json b/FE/package.json index 1f5e35d..9c2f622 100644 --- a/FE/package.json +++ b/FE/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { - "@react-three/drei": "^9.88.17", + "@react-three/drei": "^9.89.0", "@react-three/fiber": "^8.15.10", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", diff --git a/FE/src/App.js b/FE/src/App.js index 0089b67..a3464b1 100644 --- a/FE/src/App.js +++ b/FE/src/App.js @@ -16,6 +16,7 @@ const GlobalStyle = createGlobalStyle` body { font-family: "Pretendard-Medium"; + background-color: #000000; } * { diff --git a/FE/src/atoms/shapeAtom.js b/FE/src/atoms/shapeAtom.js new file mode 100644 index 0000000..6cfc8ac --- /dev/null +++ b/FE/src/atoms/shapeAtom.js @@ -0,0 +1,8 @@ +import { atom } from "recoil"; + +const shapeAtom = atom({ + key: "shapeState", + default: [], +}); + +export default shapeAtom; diff --git a/FE/src/components/DiaryModal/DiaryCreateModal.js b/FE/src/components/DiaryModal/DiaryCreateModal.js index bb5b369..49c9765 100644 --- a/FE/src/components/DiaryModal/DiaryCreateModal.js +++ b/FE/src/components/DiaryModal/DiaryCreateModal.js @@ -1,11 +1,10 @@ -/* eslint-disable */ - import React, { useEffect, useState } from "react"; import { useRecoilValue, useSetRecoilState } from "recoil"; -import { useMutation, useQuery } from "react-query"; +import { useMutation } from "react-query"; import styled from "styled-components"; 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 deleteIcon from "../../assets/deleteIcon.svg"; @@ -18,7 +17,7 @@ function DiaryCreateModal(props) { const setDiaryState = useSetRecoilState(diaryAtom); // TODO: 날짜 선택 기능 구현 - const [diaryData, setDiaryData] = React.useState({ + const [diaryData, setDiaryData] = useState({ title: "", content: "", date: "2023-11-19", @@ -26,7 +25,6 @@ function DiaryCreateModal(props) { tags: [], shapeUuid: "", }); - const [newShapeData, setNewShapeData] = useState(null); useEffect(() => { const handleBeforeUnload = (e) => { @@ -62,15 +60,6 @@ function DiaryCreateModal(props) { setDiaryData({ ...diaryData, tags: diaryData.tags.slice(0, -1) }); }; - async function getShapeFn() { - return fetch("http://223.130.129.145:3005/shapes/default", { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }).then((res) => res.json()); - } - async function createDiaryFn(data) { return fetch("http://223.130.129.145:3005/diaries", { method: "POST", @@ -90,56 +79,6 @@ function DiaryCreateModal(props) { }); } - const { - data: shapeData, - // isLoading: shapeIsLoading, - // isError: shapeIsError, - } = useQuery("shape", getShapeFn, { - onSuccess: (dataList) => { - setDiaryData((prev) => ({ ...prev, shapeUuid: dataList[0].uuid })); - const newDataList = dataList.map((data) => { - const getPromise = () => - fetch(`http://223.130.129.145:3005/shapes/${data.uuid}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${userState.accessToken}`, - }, - }); - - return getPromise() - .then((res) => { - const reader = res.body.getReader(); - return new ReadableStream({ - start(controller) { - function pump() { - return reader.read().then(({ done, value }) => { - if (done) { - controller.close(); - return; - } - controller.enqueue(value); - return pump(); - }); - } - return pump(); - }, - }); - }) - .then((stream) => new Response(stream)) - .then((res) => res.blob()) - .then((blob) => URL.createObjectURL(blob)) - .then((url) => { - data.shapeData = url; - }); - }); - - Promise.all(newDataList).then(() => { - setNewShapeData(dataList); - }); - }, - }); - const { mutate: createDiary, // isLoading: diaryIsLoading, @@ -197,10 +136,7 @@ function DiaryCreateModal(props) { }} /> - + { @@ -226,7 +162,8 @@ function DiaryCreateModal(props) { } function DiaryModalShapeSelectBox(props) { - const { shapeData, setDiaryData } = props; + const { setDiaryData } = props; + const shapeState = useRecoilValue(shapeAtom); return ( @@ -235,18 +172,14 @@ function DiaryModalShapeSelectBox(props) { 직접 그리기 - {shapeData?.map((shape) => ( + {shapeState?.map((shape) => ( - setDiaryData((prev) => ({ ...prev, shapeUuid: shape.uuid })) - } + onClick={() => { + setDiaryData((prev) => ({ ...prev, shapeUuid: shape.uuid })); + }} > - shape +
))} diff --git a/FE/src/components/DiaryModal/DiaryListModal.js b/FE/src/components/DiaryModal/DiaryListModal.js index 544e572..397d90e 100644 --- a/FE/src/components/DiaryModal/DiaryListModal.js +++ b/FE/src/components/DiaryModal/DiaryListModal.js @@ -1,3 +1,5 @@ +/* eslint-disable */ + import React, { useEffect, useLayoutEffect } from "react"; import styled from "styled-components"; import { useRecoilState } from "recoil"; @@ -19,6 +21,7 @@ function DiaryListModal() { setDiaryState((prev) => ({ ...prev, diaryUuid: selectedDiary?.uuid, + diaryPoint: `${selectedDiary?.coordinate.x},${selectedDiary?.coordinate.y},${selectedDiary?.coordinate.z}`, })); } }, [selectedDiary]); diff --git a/FE/src/components/DiaryModal/DiaryReadModal.js b/FE/src/components/DiaryModal/DiaryReadModal.js index 7feecf9..494476c 100644 --- a/FE/src/components/DiaryModal/DiaryReadModal.js +++ b/FE/src/components/DiaryModal/DiaryReadModal.js @@ -1,11 +1,10 @@ -/* eslint-disable */ - import React from "react"; import { useQuery } from "react-query"; import styled from "styled-components"; import { useRecoilState, useRecoilValue } from "recoil"; import diaryAtom from "../../atoms/diaryAtom"; import userAtom from "../../atoms/userAtom"; +import shapeAtom from "../../atoms/shapeAtom"; import ModalWrapper from "../../styles/Modal/ModalWrapper"; import DiaryDeleteModal from "./DiaryDeleteModal"; import editIcon from "../../assets/edit.svg"; @@ -57,46 +56,19 @@ function DiaryReadModal(props) { const { refetch } = props; const [diaryState, setDiaryState] = useRecoilState(diaryAtom); const userState = useRecoilValue(userAtom); + const shapeState = useRecoilValue(shapeAtom); const [shapeData, setShapeData] = React.useState(""); const { data, isLoading, isError } = useQuery( "diary", () => getDiary(userState.accessToken, diaryState.diaryUuid), { - onSuccess: (_data) => { - const getPromise = () => - fetch(`http://223.130.129.145:3005/shapes/${_data.shapeUuid}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${userState.accessToken}`, - }, - }); - - return getPromise() - .then((res) => { - const reader = res.body.getReader(); - return new ReadableStream({ - start(controller) { - function pump() { - return reader.read().then(({ done, value }) => { - if (done) { - controller.close(); - return; - } - controller.enqueue(value); - return pump(); - }); - } - return pump(); - }, - }); - }) - .then((stream) => new Response(stream)) - .then((res) => res.blob()) - .then((blob) => URL.createObjectURL(blob)) - .then((url) => { - setShapeData(url); - }); + onSuccess: (loadedData) => { + const foundShapeData = shapeState.find( + (item) => item.uuid === loadedData.shapeUuid, + ); + if (foundShapeData) { + setShapeData(foundShapeData.data); + } }, }, ); @@ -185,13 +157,9 @@ function DiaryReadModal(props) { }} /> - star diff --git a/FE/src/components/DiaryModal/DiaryUpdateModal.js b/FE/src/components/DiaryModal/DiaryUpdateModal.js index 3c8fedd..85d34df 100644 --- a/FE/src/components/DiaryModal/DiaryUpdateModal.js +++ b/FE/src/components/DiaryModal/DiaryUpdateModal.js @@ -1,22 +1,14 @@ -import React, { useEffect, useRef } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { useRecoilState, useRecoilValue } from "recoil"; import { useMutation, useQuery } from "react-query"; import styled from "styled-components"; 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 deleteIcon from "../../assets/deleteIcon.svg"; -async function getShapeFn() { - return fetch("http://223.130.129.145:3005/shapes/default", { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }).then((res) => res.json()); -} - async function getDiary(accessToken, diaryUuid) { return fetch(`http://223.130.129.145:3005/diaries/${diaryUuid}`, { method: "GET", @@ -32,17 +24,17 @@ function DiaryUpdateModal(props) { const { refetch } = props; const titleRef = useRef(null); const contentRef = useRef(null); - const [isInput, setIsInput] = React.useState(true); + const [isInput, setIsInput] = useState(true); const userState = useRecoilValue(userAtom); const [diaryState, setDiaryState] = useRecoilState(diaryAtom); - const [diaryData, setDiaryData] = React.useState({ - title: "test", - content: "test", - date: "2023-11-20", + const [diaryData, setDiaryData] = useState({ + uuid: diaryState.diaryUuid, + title: "", + content: "", + date: "2023-11-19", point: diaryState.diaryPoint, tags: [], - shapeUuid: "cf3a074a-0707-40c4-a598-c7c17a654476", - uuid: diaryState.diaryUuid, + shapeUuid: "", }); async function updateDiaryFn(data) { @@ -99,12 +91,6 @@ function DiaryUpdateModal(props) { setDiaryData({ ...diaryData, tags: diaryData.tags.slice(0, -1) }); }; - const { - data: shapeData, - // isLoading: shapeIsLoading, - // isError: shapeIsError, - } = useQuery("shape", getShapeFn); - const { mutate: updateDiary, // isLoading: diaryIsLoading, @@ -206,7 +192,7 @@ function DiaryUpdateModal(props) { }} /> - + delete @@ -228,7 +214,8 @@ function DiaryUpdateModal(props) { } function DiaryModalShapeSelectBox(props) { - const { shapeData } = props; + const { setDiaryData } = props; + const shapeState = useRecoilValue(shapeAtom); return ( @@ -237,9 +224,14 @@ function DiaryModalShapeSelectBox(props) { 직접 그리기 - {shapeData?.map((shape) => ( - - {shape.shapePath} + {shapeState?.map((shape) => ( + { + setDiaryData((prev) => ({ ...prev, shapeUuid: shape.uuid })); + }} + > +
))} diff --git a/FE/src/components/LoginModal/LoginModal.js b/FE/src/components/LoginModal/LoginModal.js index 261364c..b86036b 100644 --- a/FE/src/components/LoginModal/LoginModal.js +++ b/FE/src/components/LoginModal/LoginModal.js @@ -95,7 +95,9 @@ function LoginModal() { { + setKeepLogin((prev) => !prev); + }} />
로그인 유지
diff --git a/FE/src/pages/MainPage.js b/FE/src/pages/MainPage.js index 9f638e0..1fb104d 100644 --- a/FE/src/pages/MainPage.js +++ b/FE/src/pages/MainPage.js @@ -1,8 +1,11 @@ +/* eslint-disable */ + import React, { useEffect } from "react"; import { useQuery } from "react-query"; import styled from "styled-components"; -import { useRecoilState, useRecoilValue } from "recoil"; +import { useRecoilState, useSetRecoilState, useRecoilValue } from "recoil"; import diaryAtom from "../atoms/diaryAtom"; +import shapeAtom from "../atoms/shapeAtom"; import userAtom from "../atoms/userAtom"; import DiaryCreateModal from "../components/DiaryModal/DiaryCreateModal"; import DiaryReadModal from "../components/DiaryModal/DiaryReadModal"; @@ -14,6 +17,7 @@ import StarPage from "./StarPage"; function MainPage() { const [diaryState, setDiaryState] = useRecoilState(diaryAtom); const userState = useRecoilValue(userAtom); + const [shapeState, setShapeState] = useRecoilState(shapeAtom); const { refetch } = useQuery( "diaryList", @@ -44,6 +48,44 @@ function MainPage() { window.history.pushState(newState, "", ""); return newState; }); + + async function getShapeFn() { + return fetch("http://223.130.129.145:3005/shapes/default", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }) + .then((res) => res.json()) + .then(async (data) => { + const shapeDataList = data.map((shape) => + fetch(`http://223.130.129.145:3005/shapes/${shape.uuid}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${userState.accessToken}`, + }, + }).then(async (res) => ({ + uuid: shape.uuid, + data: await res.text(), + })), + ); + + setShapeState( + await Promise.all(shapeDataList).then((res) => + res.map((shape) => { + const newShape = { + ...shape, + data: shape.data.replace(/<\?xml.*?\?>/, ""), + }; + return newShape; + }), + ), + ); + }); + } + + getShapeFn(); }, []); return (