diff --git a/src/App.css b/src/App.css index 1f9bad4..83284eb 100644 --- a/src/App.css +++ b/src/App.css @@ -1,6 +1,6 @@ -:root { - font-family: "SUIT Variable", sans-serif; - text-align: center; - width: 100vw; - height: calc(var(--vh, 1vh) * 100); -} +:root { + font-family: "SUIT Variable", sans-serif; + text-align: center; + width: 100vw; + height: calc(var(--vh, 1vh) * 100); +} diff --git a/src/App.jsx b/src/App.jsx index 8fb6e4a..5f659c4 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,70 +1,70 @@ -import "./App.css"; -import { useEffect } from "react"; -import { Routes, Route, BrowserRouter, useParams } from "react-router-dom"; -import Login from "./pages/Login/Login"; -import Join from "./pages/Join/Join"; -import Main from "./pages/Main/Main"; -import Frame from "./pages/Frame/Frame"; -import MakeFrame from "./pages/Frame/MakeFrame"; -import Photobook from "./pages/Photobook/Photobook"; -import PhotobookUuid from "./pages/Photobook/PhotobookUuid"; -import { - BrowserView, - MobileView, -} from "react-device-detect"; -import FrameList from "./component/AllFrameCpn/FrameList"; -import PhotoSelect from "./pages/Photobook/PhotoSelect"; -// import { useAtom } from "jotai"; -// import axios from "axios"; -// import { accessTokenAtom, setAccessToken } from "./store/jotaiAtoms"; - -function App() { - function setScreenSize() { - let vh = window.innerHeight * 0.01; - document.documentElement.style.setProperty("--vh", `${vh}px`); - } - useEffect(() => { - setScreenSize(); - }); - - window.addEventListener("resize", setScreenSize); - - return ( - <> -
-
- - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - -
-
- - ); -} - -export default App; +import "./App.css"; +import { useEffect } from "react"; +import { Routes, Route, BrowserRouter, useParams } from "react-router-dom"; +import Login from "./pages/Login/Login"; +import Join from "./pages/Join/Join"; +import Main from "./pages/Main/Main"; +import Frame from "./pages/Frame/Frame"; +import MakeFrame from "./pages/Frame/MakeFrame"; +import ApplyFrame from "./pages/Frame/ApplyFrame"; +import Photobook from "./pages/Photobook/Photobook"; +import PhotobookUuid from "./pages/Photobook/PhotobookUuid"; +import { BrowserView, MobileView } from "react-device-detect"; +import FrameList from "./component/AllFrameCpn/FrameList"; +import PhotoSelect from "./pages/Photobook/PhotoSelect"; +// import { useAtom } from "jotai"; +// import axios from "axios"; +// import { accessTokenAtom, setAccessToken } from "./store/jotaiAtoms"; + +function App() { + function setScreenSize() { + let vh = window.innerHeight * 0.01; + document.documentElement.style.setProperty("--vh", `${vh}px`); + } + useEffect(() => { + setScreenSize(); + }); + + window.addEventListener("resize", setScreenSize); + + return ( + <> +
+
+ + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + +
+
+ + ); +} + +export default App; diff --git a/src/apis/getFrame.js b/src/apis/getFrame.js index d7f5b52..42fbdb0 100644 --- a/src/apis/getFrame.js +++ b/src/apis/getFrame.js @@ -1,13 +1,13 @@ -// import axios from "axios"; - -// export const getAllFrames = async () => { -// try { -// const res = await axios.get( -// "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame/find" -// ); -// return res.data; // API로부터 받은 데이터 반환 -// } catch (err) { -// console.err("Error fetching frames:", err); -// throw err; -// } -// }; +// import axios from "axios"; + +// export const getAllFrames = async () => { +// try { +// const res = await axios.get( +// "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame/find" +// ); +// return res.data; // API로부터 받은 데이터 반환 +// } catch (err) { +// console.err("Error fetching frames:", err); +// throw err; +// } +// }; diff --git a/src/apis/onLogin.js b/src/apis/onLogin.js index 310355b..004acee 100644 --- a/src/apis/onLogin.js +++ b/src/apis/onLogin.js @@ -1,6 +1,6 @@ -// import axios from 'axios'; -// import { accessTokenAtom } from '../store/jotaiAtoms'; -// import { useAtomValue, useSetAtom } from 'jotai'; - -export default function onLogin() { +// import axios from 'axios'; +// import { accessTokenAtom } from '../store/jotaiAtoms'; +// import { useAtomValue, useSetAtom } from 'jotai'; + +export default function onLogin() { } \ No newline at end of file diff --git a/src/apis/onSignUp.js b/src/apis/onSignUp.js index 02bcff9..dc462c2 100644 --- a/src/apis/onSignUp.js +++ b/src/apis/onSignUp.js @@ -1,19 +1,19 @@ -import axios from "axios"; -// import sha256 from "crypto-js/sha256"; - -export const onSignUp = (userInfo, router) => { - // let newUserInfo = { - // ...userInfo, - // // 비밀번호 암호화 로직 - // password: sha256(userInfo.password).toString(), - // }; - axios - .post("http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/user/join", userInfo) - .then((res) => { - console.log(res.data); - router("/login"); - }) - .catch((err) => { - console.log(err); - }); -}; +import axios from "axios"; +// import sha256 from "crypto-js/sha256"; + +export const onSignUp = (userInfo, router) => { + // let newUserInfo = { + // ...userInfo, + // // 비밀번호 암호화 로직 + // password: sha256(userInfo.password).toString(), + // }; + axios + .post("http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/user/join", userInfo) + .then((res) => { + console.log(res.data); + router("/login"); + }) + .catch((err) => { + console.log(err); + }); +}; diff --git a/src/component/AllFrameCpn/FrameList.jsx b/src/component/AllFrameCpn/FrameList.jsx index 25319bc..7f289c5 100644 --- a/src/component/AllFrameCpn/FrameList.jsx +++ b/src/component/AllFrameCpn/FrameList.jsx @@ -1,63 +1,72 @@ -import { useState, useEffect } from "react"; -import styles from "./FrameList.module.css"; -import useAxios from "../../apis/axiosWithToken"; -import { Link } from "react-router-dom"; -// import { getAllFrames } from "../../apis/getFrame"; -import { useAtom } from "jotai"; -import { accessTokenAtom } from "../../store/jotaiAtoms"; - -const FrameList = () => { - const [frames, setFrames] = useState([]); - const [accessToken, ] = useAtom(accessTokenAtom); - const axios = useAxios(); - - useEffect(() => { - // 액세스 토큰이 있을 때만 API 요청을 보내도록 조건 처리 - if (accessToken) { - console.log("Framelist ACT:", accessToken); // accessToken jotai에서 잘 불러오는지 확인 - // axios 요청 설정 - // const config = { - // headers: { - // Authorization: `Bearer ${accessToken}`, // 헤더에 accessToken을 추가 - // }, - // }; - // API 요청 보내기 - axios.get('/frame/list') // 인스턴스로 axios 요청 보내기 - .then((response) => setFrames(response.data)) - .catch((error) => console.error(error)); - } - }, [accessToken]); // useEffect가 실행되는 조건을 accessToken이 변경될 때로 설정 - - return ( -
- - - -
- {frames.length === null ? ( // frames 배열이 비어 있는 경우 -
-

새 프레임을 추가해주세요

-
- ) : ( - // frames 배열에 프레임이 있는 경우 - - )} -
-
- ); -}; - -export default FrameList; +import { useState, useEffect } from "react"; +import styles from "./FrameList.module.css"; +import useAxios from "../../apis/axiosWithToken"; +import { Link } from "react-router-dom"; +// import { getAllFrames } from "../../apis/getFrame"; +import { useAtom } from "jotai"; +import { accessTokenAtom } from "../../store/jotaiAtoms"; + +const FrameList = () => { + const [frames, setFrames] = useState([]); + const [accessToken] = useAtom(accessTokenAtom); + const axios = useAxios(); + + useEffect(() => { + // 액세스 토큰이 있을 때만 API 요청을 보내도록 조건 처리 + if (accessToken) { + console.log("Framelist ACT:", accessToken); // accessToken jotai에서 잘 불러오는지 확인 + const config = { + headers: { + Authorization: `Bearer ${accessToken}`, // 헤더에 accessToken을 추가 + }, + }; + axios + .get( + "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame/list", + config + ) + .then((res) => { + console.log(res.data); + // 성공적으로 데이터를 받아온 경우 + setFrames(res.data); // 받아온 데이터로 frames 상태 업데이트 + }) + .catch((err) => { + // 오류 처리 + console.error("API 요청 중 오류 발생:", err); + }); + } + }, [accessToken]); // useEffect가 실행되는 조건을 accessToken이 변경될 때로 설정 + + return ( +
+ + + +
+ {frames.length === 0 ? ( // frames 배열이 비어 있는 경우 +
+

새 프레임을 추가해주세요

+
+ ) : ( + // frames 배열에 프레임이 있는 경우 + + )} +
+
+ ); +}; + +export default FrameList; diff --git a/src/component/AllFrameCpn/FrameList.module.css b/src/component/AllFrameCpn/FrameList.module.css index a4917c2..6fb239b 100644 --- a/src/component/AllFrameCpn/FrameList.module.css +++ b/src/component/AllFrameCpn/FrameList.module.css @@ -1,69 +1,70 @@ -ul { - list-style-type: none; - margin: 0px; - padding: 0px; -} - -.FrameList { - width: 390px; - height: 760px; - background-color: #ffffff; - display: flex; - flex-direction: column; -} - -.FrameList button { - border: 1px solid var(--, #009eff); -} - -.newFrame { - width: 340px; - height: 50px; - margin-top: 20px; - color: #009eff; - background-color: #ffffff; - border-radius: 10px; - border-color: #009eff; -} - -.FrameScroll { - height: 619px; -} - -.InfoMsg { - height: 100%; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; -} - -.FrameUl { - height: 100%; - overflow-y: scroll; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - flex-wrap: wrap; /* 너비를 넘어가면 다음 줄로 넘어감 */ -} - -.FrameUl::-webkit-scrollbar { - display: none; -} - -.FrameItem { - width: calc(40% - 10px); - gap: 10px; - margin: 20px 10px; -} - -.FrameItem button { - background: #ffffff; - border: none; -} - -.FrameImage { - width: 100%; - height: auto; -} +ul { + list-style-type: none; + margin: 0px; + padding: 0px; +} + +.FrameList { + width: 390px; + height: 760px; + background-color: #ffffff; + display: flex; + flex-direction: column; +} + +.FrameList button { + border: 1px solid var(--, #009eff); +} + +.newFrame { + width: 340px; + height: 50px; + margin-top: 20px; + color: #009eff; + background-color: #ffffff; + border-radius: 10px; + border-color: #009eff; +} + +.FrameScroll { + height: 619px; +} + +.InfoMsg { + height: 100%; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.FrameUl { + height: 100%; + overflow-y: scroll; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + flex-wrap: wrap; /* 너비를 넘어가면 다음 줄로 넘어감 */ +} + +.FrameUl::-webkit-scrollbar { + display: none; +} + +.FrameItem { + width: calc(40% - 10px); + gap: 10px; + margin: 20px 10px 0px 10px; +} + +.FrameItem button { + background-color: #f7f7f7; + border: none; + height: auto; +} + +.FrameImage { + width: 60%; + height: auto; +} diff --git a/src/component/MakeFrameCpn/AddPhoto.jsx b/src/component/MakeFrameCpn/AddPhoto.jsx index 12cf300..7361f8c 100644 --- a/src/component/MakeFrameCpn/AddPhoto.jsx +++ b/src/component/MakeFrameCpn/AddPhoto.jsx @@ -1,43 +1,43 @@ -import React from "react"; -import addbutton from "../../img/addbutton.png"; -import styles from "./AddPhoto.module.css"; - -const AddPhoto = ({ handleUploadedImage }) => { - const fileInput = React.useRef(null); - - const handleButtonClick = () => { - fileInput.current.click(); - }; - - const handleChange = (e) => { - const selectedFile = e.target.files[0]; - - // FileReader를 사용하여 선택된 파일을 읽어 옴 - const reader = new FileReader(); - reader.onloadend = () => { - // 이미지 데이터를 MakeFrame 컴포넌트로 전달 - handleUploadedImage(reader.result); - }; - if (selectedFile) { - reader.readAsDataURL(selectedFile); - } - }; - - return ( -
-
- - -
-
- ); -}; - -export default AddPhoto; +import React from "react"; +import addbutton from "../../img/addbutton.png"; +import styles from "./AddPhoto.module.css"; + +const AddPhoto = ({ handleUploadedImage }) => { + const fileInput = React.useRef(null); + + const handleButtonClick = () => { + fileInput.current.click(); + }; + + const handleChange = (e) => { + const selectedFile = e.target.files[0]; + + // FileReader를 사용하여 선택된 파일을 읽어 옴 + const reader = new FileReader(); + reader.onloadend = () => { + // 이미지 데이터를 MakeFrame 컴포넌트로 전달 + handleUploadedImage(reader.result); + }; + if (selectedFile) { + reader.readAsDataURL(selectedFile); + } + }; + + return ( +
+
+ + +
+
+ ); +}; + +export default AddPhoto; diff --git a/src/component/MakeFrameCpn/AddPhoto.module.css b/src/component/MakeFrameCpn/AddPhoto.module.css index 3fb4bbe..859327d 100644 --- a/src/component/MakeFrameCpn/AddPhoto.module.css +++ b/src/component/MakeFrameCpn/AddPhoto.module.css @@ -1,41 +1,41 @@ -.Bottom { - width: 390px; - height: 204px; -} - -.ListView { - display: inline-flex; - height: 200px; - padding: 15px 0px 15px 18px; - flex-direction: row; - gap: 18px; -} - -.ListView button { - background: #ffffff; - outline: none; - border: none; - cursor: pointer; - border: none; -} - -.ListView button:visited { - border: none; - outline: none; -} - -.ListView button:hover { - border: none; - outline: none; -} - -.ListView button:active { - border: none; - outline: none; -} - -.addbutton { - display: flex; - justify-content: center; - align-items: center; -} +.Bottom { + width: 390px; + height: 204px; +} + +.ListView { + display: inline-flex; + height: 200px; + padding: 15px 0px 15px 18px; + flex-direction: row; + gap: 18px; +} + +.ListView button { + background: #ffffff; + outline: none; + border: none; + cursor: pointer; + border: none; +} + +.ListView button:visited { + border: none; + outline: none; +} + +.ListView button:hover { + border: none; + outline: none; +} + +.ListView button:active { + border: none; + outline: none; +} + +.addbutton { + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/component/MakeFrameCpn/Background.jsx b/src/component/MakeFrameCpn/Background.jsx index c8be919..48a7da8 100644 --- a/src/component/MakeFrameCpn/Background.jsx +++ b/src/component/MakeFrameCpn/Background.jsx @@ -1,46 +1,46 @@ -import color from "../../img/color.png"; -import colorpalette from "../../img/colorpalette.png"; -import frame_FFC700 from "../../assets/frame-FFC700.png"; -import frame_FFFDBA from "../../assets/frame-FFFDBA.png"; -import frame_FFDE7D from "../../assets/frame-FFDE7D.png"; -import frame_F69401 from "../../assets/frame-F69401.png"; -import frame_8BD3FF from "../../assets/frame-8BD3FF.png"; -import frame_0066FF from "../../assets/frame-0066FF.png"; -import frame_009EFF from "../../assets/frame-009EFF.png"; -import frame_F1FFAD from "../../assets/frame-F1FFAD.png"; -import styles from "./Background.module.css"; - -const Background = ({ changeFrameImage }) => { - const handleFrameButtonClick = (frameImage) => { - changeFrameImage(frameImage); // MakeFrame 컴포넌트에서 프레임 이미지 업데이트 - }; - - return ( -
-
- - -
-
-
- - - - -
-
- - - - -
-
-
- ); -}; - -export default Background; +import color from "../../img/color.png"; +import colorpalette from "../../img/colorpalette.png"; +import frame_FFC700 from "../../assets/frame-FFC700.png"; +import frame_FFFDBA from "../../assets/frame-FFFDBA.png"; +import frame_FFDE7D from "../../assets/frame-FFDE7D.png"; +import frame_F69401 from "../../assets/frame-F69401.png"; +import frame_8BD3FF from "../../assets/frame-8BD3FF.png"; +import frame_0066FF from "../../assets/frame-0066FF.png"; +import frame_009EFF from "../../assets/frame-009EFF.png"; +import frame_F1FFAD from "../../assets/frame-F1FFAD.png"; +import styles from "./Background.module.css"; + +const Background = ({ changeFrameImage }) => { + const handleFrameButtonClick = (frameImage) => { + changeFrameImage(frameImage); // MakeFrame 컴포넌트에서 프레임 이미지 업데이트 + }; + + return ( +
+
+ + +
+
+
+ + + + +
+
+ + + + +
+
+
+ ); +}; + +export default Background; diff --git a/src/component/MakeFrameCpn/Background.module.css b/src/component/MakeFrameCpn/Background.module.css index 23359dd..0bfe117 100644 --- a/src/component/MakeFrameCpn/Background.module.css +++ b/src/component/MakeFrameCpn/Background.module.css @@ -1,95 +1,95 @@ -.Bottom { - width: 390px; - height: 204px; -} - -.ListTop { - height: 40px; - padding: 10px; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - font-weight: 400; -} - -.ListTop button { - background-color: #ffffff; - border: none; -} - -.ListView { - width: 100%; - height: 120px; - padding: 5px 0px; - display: flex; - flex-direction: column; - justify-content: center; - gap: 20px; -} - -.FirstLine { - display: flex; - flex-direction: row; - justify-content: space-evenly; -} - -.FirstLine button { - width: 60px; - height: 50px; - border-radius: 10px; -} - -.FirstLine button:nth-child(1) { - background: #ffc700; -} - -.FirstLine button:nth-child(2) { - background: #fffdba; -} - -.FirstLine button:nth-child(3) { - background: #ffde7d; -} - -.FirstLine button:nth-child(4) { - background: #f69401; -} - -.SecondLine { - display: flex; - flex-direction: row; - justify-content: space-evenly; -} - -.SecondLine button { - width: 60px; - height: 50px; - border-radius: 10px; -} - -.SecondLine button:nth-child(1) { - background: #8bd3ff; -} - -.SecondLine button:nth-child(2) { - background: #0066ff; -} - -.SecondLine button:nth-child(3) { - background: #009eff; -} - -.SecondLine button:nth-child(4) { - background: #f1ffad; -} - -button { - outline: none; -} - -button:hover { - outline: none; - color: #009eff; - font-weight: 600; -} +.Bottom { + width: 390px; + height: 204px; +} + +.ListTop { + height: 40px; + padding: 10px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + font-weight: 400; +} + +.ListTop button { + background-color: #ffffff; + border: none; +} + +.ListView { + width: 100%; + height: 120px; + padding: 5px 0px; + display: flex; + flex-direction: column; + justify-content: center; + gap: 20px; +} + +.FirstLine { + display: flex; + flex-direction: row; + justify-content: space-evenly; +} + +.FirstLine button { + width: 60px; + height: 50px; + border-radius: 10px; +} + +.FirstLine button:nth-child(1) { + background: #ffc700; +} + +.FirstLine button:nth-child(2) { + background: #fffdba; +} + +.FirstLine button:nth-child(3) { + background: #ffde7d; +} + +.FirstLine button:nth-child(4) { + background: #f69401; +} + +.SecondLine { + display: flex; + flex-direction: row; + justify-content: space-evenly; +} + +.SecondLine button { + width: 60px; + height: 50px; + border-radius: 10px; +} + +.SecondLine button:nth-child(1) { + background: #8bd3ff; +} + +.SecondLine button:nth-child(2) { + background: #0066ff; +} + +.SecondLine button:nth-child(3) { + background: #009eff; +} + +.SecondLine button:nth-child(4) { + background: #f1ffad; +} + +button { + outline: none; +} + +button:hover { + outline: none; + color: #009eff; + font-weight: 600; +} diff --git a/src/component/MakeFrameCpn/Brush.jsx b/src/component/MakeFrameCpn/Brush.jsx index 68e3b2a..2d3ea88 100644 --- a/src/component/MakeFrameCpn/Brush.jsx +++ b/src/component/MakeFrameCpn/Brush.jsx @@ -1,80 +1,63 @@ -import React, { useState } from "react"; -import styles from "./Brush.module.css"; -import color from "../../img/color.png"; - -const Brush = () => { - // 초기 색상은 검정색으로 설정 - const [selectedColor, setSelectedColor] = useState("#000000"); - - const handleColorClick = (color) => { - setSelectedColor(color); - }; - - return ( -
-
- - - - - - - - - -
-
- ); -}; - -export default Brush; +import React, { useState, useEffect } from "react"; +import styles from "./Brush.module.css"; +import color from "../../img/color.png"; + +const Brush = ({ ctx, setCtx }) => { + const [lineColor, setLineColor] = useState("#000000"); + const [lineWidth, setLineWidth] = useState(5); + const [lineOpacity, setLineOpacity] = useState(0.1); + + useEffect(() => { + // 캔버스 context의 설정을 변경합니다. + if (ctx) { + ctx.strokeStyle = lineColor; + ctx.lineWidth = lineWidth; + ctx.globalAlpha = lineOpacity; + } + }, [ctx, lineColor, lineWidth, lineOpacity]); + + return ( +
+
+ + { + setLineColor(e.target.value); + }} + /> +
+
+
+ + { + setLineWidth(e.target.value); + }} + /> +
+
+ + { + setLineOpacity(e.target.value); + }} + /> +
+
+
+ ); +}; + +export default Brush; diff --git a/src/component/MakeFrameCpn/Brush.module.css b/src/component/MakeFrameCpn/Brush.module.css index 02f78a1..7ac5e86 100644 --- a/src/component/MakeFrameCpn/Brush.module.css +++ b/src/component/MakeFrameCpn/Brush.module.css @@ -1,22 +1,68 @@ -.Bottom { - width: 390px; - height: 204px; -} - -.Bottom button { - width: 25px; - height: 25px; - border-radius: 100%; - display: flex; - justify-content: center; - align-items: center; -} - -.ColorContainer { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding-top: 20px; - gap: 10px; -} +.Bottom { + width: 390px; + height: 204px; + display: flex; + flex-direction: column; +} + +.Bottom button { + width: 25px; + height: 25px; + + border-radius: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.ColorContainer { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding-top: 20px; + gap: 10px; +} + +.ColorContainer input { + background-color: white; +} + +.BrushContainer { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding-top: 10px; + gap: 10px; +} + +.BrushContainer input { + width: 100px; +} + +.brushwidth { + background: linear-gradient( + to right, + #ffe283 0%, + #ffe283 50%, + #ececec 50%, + #ececec 100% + ); + border-radius: 8px; + outline: none; + accent-color: #ffca1d; +} + +.brushopacity { + background: linear-gradient( + to right, + #ffe283 0%, + #ffe283 50%, + #ececec 50%, + #ececec 100% + ); + border-radius: 8px; + outline: none; + accent-color: #ffca1d; +} diff --git a/src/component/MakeFrameCpn/Sticker.jsx b/src/component/MakeFrameCpn/Sticker.jsx index 54ba356..2885b06 100644 --- a/src/component/MakeFrameCpn/Sticker.jsx +++ b/src/component/MakeFrameCpn/Sticker.jsx @@ -1,95 +1,95 @@ -import React, { useState, useEffect } from "react"; -import { useDrag } from "react-use-gesture"; -import styles from "./Sticker.module.css"; -import { useAtom } from "jotai"; -import { accessTokenAtom } from "../../store/jotaiAtoms"; -import axios from "axios"; - -const Sticker = ({ handleStickerSelect }) => { - const [stickers, setStickers] = useState([]); - const [stickerPos, setstickerPos] = useState({ x: 0, y: 0 }); - const [selectedTheme, setSelectedTheme] = useState(1); - const [selectedSticker, setSelectedSticker] = useState(null); - const [stickerSize, setStickerSize] = useState(100); // 초기 스티커 크기 - const [accessToken] = useAtom(accessTokenAtom); - - const themes = [1, 2, 3, 4, 5]; - - useEffect(() => { - // API 요청 시 accessToken을 헤더에 추가하여 요청 - const config = { - headers: { - Authorization: `Bearer ${accessToken}`, - }, - }; - fetchStickers(selectedTheme, config); // fetchStickers 함수에 추가된 config 객체 전달 - }, [selectedTheme, accessToken]); - - // 서버로부터 스티커 데이터를 가져오는 함수 - const fetchStickers = async (theme, config) => { - try { - const res = await axios.get( - `http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame/stickerList/${theme}`, - config - ); - const imageStickers = res.data.filter((url, index) => index !== 0); - console.log("이미지 URL 리스트:", imageStickers); - setStickers(imageStickers); // 서버로부터 받아온 스티커 데이터 설정 - } catch (err) { - console.error("Error fetching stickers:", err); - } - }; - - const handleThemeClick = (themeNumber) => { - setSelectedTheme(themeNumber); // 클릭된 테마 버튼의 테마 번호를 설정 - }; - - const handleStickerClick = (stickerInfo) => { - // 선택한 스티커 정보를 MakeFrame 컴포넌트로 전달 - handleStickerSelect(stickerInfo); - setSelectedSticker(stickerInfo); - }; - - const handleSizeChange = (event) => { - setStickerSize(event.target.value); // 스티커 크기 업데이트 - }; - - return ( -
-
- {themes.map((theme, index) => ( - - ))} -
-
- {stickers.map((sticker, index) => ( - sticker handleStickerClick(sticker)} - /> - ))} -
- {selectedSticker && ( -
- - 스티커 크기 조절 -
- )} -
- ); -}; - -export default Sticker; +import React, { useState, useEffect } from "react"; +import { useDrag } from "react-use-gesture"; +import styles from "./Sticker.module.css"; +import { useAtom } from "jotai"; +import { accessTokenAtom } from "../../store/jotaiAtoms"; +import axios from "axios"; + +const Sticker = ({ handleStickerSelect }) => { + const [stickers, setStickers] = useState([]); + const [stickerPos, setstickerPos] = useState({ x: 0, y: 0 }); + const [selectedTheme, setSelectedTheme] = useState(1); + const [selectedSticker, setSelectedSticker] = useState(null); + const [stickerSize, setStickerSize] = useState(100); // 초기 스티커 크기 + const [accessToken] = useAtom(accessTokenAtom); + + const themes = [1, 2, 3, 4, 5]; + + useEffect(() => { + // API 요청 시 accessToken을 헤더에 추가하여 요청 + const config = { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }; + fetchStickers(selectedTheme, config); // fetchStickers 함수에 추가된 config 객체 전달 + }, [selectedTheme, accessToken]); + + // 서버로부터 스티커 데이터를 가져오는 함수 + const fetchStickers = async (theme, config) => { + try { + const res = await axios.get( + `http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame/stickerList/${theme}`, + config + ); + const imageStickers = res.data.filter((url, index) => index !== 0); + console.log("이미지 URL 리스트:", imageStickers); + setStickers(imageStickers); // 서버로부터 받아온 스티커 데이터 설정 + } catch (err) { + console.error("Error fetching stickers:", err); + } + }; + + const handleThemeClick = (themeNumber) => { + setSelectedTheme(themeNumber); // 클릭된 테마 버튼의 테마 번호를 설정 + }; + + const handleStickerClick = (stickerInfo) => { + setSelectedSticker(stickerInfo); + // 선택한 스티커 정보를 MakeFrame 컴포넌트로 전달 + handleStickerSelect(stickerInfo); + }; + + function handleSizeChange(event) { + setStickerSize(event.target.value); // 스티커 크기 업데이트 + } + + return ( +
+
+ {themes.map((theme, index) => ( + + ))} +
+
+ {stickers.map((sticker, index) => ( + sticker handleStickerClick(sticker)} + /> + ))} +
+ {selectedSticker && ( +
+ + 스티커 크기 조절 +
+ )} +
+ ); +}; + +export default Sticker; diff --git a/src/component/MakeFrameCpn/Sticker.module.css b/src/component/MakeFrameCpn/Sticker.module.css index b0067e2..154b989 100644 --- a/src/component/MakeFrameCpn/Sticker.module.css +++ b/src/component/MakeFrameCpn/Sticker.module.css @@ -1,55 +1,56 @@ -.Bottom { - width: 390px; - height: 204px; -} - -.ListTop { - height: 40px; - padding: 14px 14px 14px 18px; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - font-size: 10px; - font-weight: 400; -} - -.ListTop button { - background-color: #ffffff; - border: none; -} - -.ListView { - display: flex; - overflow-x: scroll; - -webkit-overflow-scrolling: touch; - height: 80px; - padding: 15px 0px 15px 18px; - flex-direction: row; - gap: 18px; -} - -.ListView::-webkit-scrollbar { - width: 12px; /* 스크롤 바의 너비 */ - height: 12px; /* 스크롤 바의 높이 */ -} - -.ListView::-webkit-scrollbar-thumb { - background-color: #888; /* 스크롤 바 색상 */ - border-radius: 6px; /* 스크롤 바 모서리 둥글기 */ -} - -.ListView::-webkit-scrollbar-track { - background-color: #f5f5f5; /* 스크롤 바의 배경색 */ - border-radius: 6px; /* 스크롤 바 배경 모서리 둥글기 */ -} - -button { - outline: none; -} - -button:hover { - outline: none; - color: #009eff; - font-weight: 600; -} +.Bottom { + width: 390px; + height: 204px; +} + +.ListTop { + height: 40px; + padding: 14px 14px 14px 18px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + font-size: 10px; + font-weight: 400; +} + +.ListTop button { + background-color: #ffffff; + border: none; +} + +.ListView { + display: flex; + overflow-x: scroll; + -webkit-overflow-scrolling: touch; + height: 80px; + padding: 15px 0px 15px 18px; + flex-direction: row; + gap: 18px; +} + +.ListView::-webkit-scrollbar { + width: 12px; /* 스크롤 바의 너비 */ + height: 12px; /* 스크롤 바의 높이 */ + display: none; +} + +.ListView::-webkit-scrollbar-thumb { + background-color: #888; /* 스크롤 바 색상 */ + border-radius: 6px; /* 스크롤 바 모서리 둥글기 */ +} + +.ListView::-webkit-scrollbar-track { + background-color: #f5f5f5; /* 스크롤 바의 배경색 */ + border-radius: 6px; /* 스크롤 바 배경 모서리 둥글기 */ +} + +button { + outline: none; +} + +button:hover { + outline: none; + color: #009eff; + font-weight: 600; +} diff --git a/src/component/MakeFrameCpn/Template.jsx b/src/component/MakeFrameCpn/Template.jsx index 385228a..8a0cf6c 100644 --- a/src/component/MakeFrameCpn/Template.jsx +++ b/src/component/MakeFrameCpn/Template.jsx @@ -1,39 +1,39 @@ -import template0 from "../../assets/template-0.png"; -import template1 from "../../assets/template-1.png"; -import template2 from "../../assets/template-2.png"; -import template3 from "../../assets/template-3.png"; -import template4 from "../../assets/template-4.png"; -import styles from "./Template.module.css"; - -const Template = ({ changeFrameImage }) => { - const handleFrameButtonClick = (frameImage) => { - changeFrameImage(frameImage); // MakeFrame 컴포넌트에서 프레임 이미지 업데이트 - }; - - return ( -
-
- -
-
- - - - {/* */} - -
-
- ); -}; - -export default Template; +import template0 from "../../assets/template-0.png"; +import template1 from "../../assets/template-1.png"; +import template2 from "../../assets/template-2.png"; +import template3 from "../../assets/template-3.png"; +import template4 from "../../assets/template-4.png"; +import styles from "./Template.module.css"; + +const Template = ({ changeFrameImage }) => { + const handleFrameButtonClick = (frameImage) => { + changeFrameImage(frameImage); // MakeFrame 컴포넌트에서 프레임 이미지 업데이트 + }; + + return ( +
+
+ +
+
+ + + + {/* */} + +
+
+ ); +}; + +export default Template; diff --git a/src/component/MakeFrameCpn/Template.module.css b/src/component/MakeFrameCpn/Template.module.css index 93043c7..a720bf4 100644 --- a/src/component/MakeFrameCpn/Template.module.css +++ b/src/component/MakeFrameCpn/Template.module.css @@ -1,46 +1,46 @@ -.Bottom { - width: 390px; - height: 204px; -} - -.ListTop { - height: 40px; - padding: 14px 14px 14px 18px; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - font-size: 10px; - font-weight: 400; -} - -.ListTop button { - width: 100%; - background-color: #ffffff; - border: none; - display: flex; - justify-content: center; -} - -.ListView { - display: flex; - height: 100px; - padding: 0px 0px 0px 18px; - flex-direction: row; - gap: 6px; -} - -.ListView button { - background: #ffffff; - border: none; -} - -.ListView button img { - width: 72px; - height: 100px; - display: block; -} - -button { - outline: none; -} +.Bottom { + width: 390px; + height: 204px; +} + +.ListTop { + height: 40px; + padding: 14px 14px 14px 18px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + font-size: 10px; + font-weight: 400; +} + +.ListTop button { + width: 100%; + background-color: #ffffff; + border: none; + display: flex; + justify-content: center; +} + +.ListView { + display: flex; + height: 100px; + padding: 0px 0px 0px 18px; + flex-direction: row; + gap: 6px; +} + +.ListView button { + background: #ffffff; + border: none; +} + +.ListView button img { + width: 72px; + height: 100px; + display: block; +} + +button { + outline: none; +} diff --git a/src/index.css b/src/index.css index b5e5210..34b3260 100644 --- a/src/index.css +++ b/src/index.css @@ -1,25 +1,25 @@ -@font-face { - font-family: "SUIT Variable", sans-serif; - src: url(https://cdn.jsdelivr.net/gh/sunn-us/SUIT/fonts/variable/woff2/SUIT-Variable.css); -} - -:root { - width: 100vw; - height: calc(var(--vh, 1vh) * 100); - font-family: "SUIT Variable", -apple-system, BlinkMacSystemFont, Pretendard, - "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", - sans-serif; - font-weight: 400; - color: #1a1e27; - margin: 0; - overflow-x: hidden; - overflow-y: hidden; - display: flex; - align-items: center; - justify-content: center; -} - -button { - font-family: -apple-system, BlinkMacSystemFont, Pretendard, "Segoe UI", Roboto, - Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; -} +@font-face { + font-family: "SUIT Variable", sans-serif; + src: url(https://cdn.jsdelivr.net/gh/sunn-us/SUIT/fonts/variable/woff2/SUIT-Variable.css); +} + +:root { + width: 100vw; + height: calc(var(--vh, 1vh) * 100); + font-family: "SUIT Variable", -apple-system, BlinkMacSystemFont, Pretendard, + "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", + sans-serif; + font-weight: 400; + color: #1a1e27; + margin: 0; + overflow-x: hidden; + overflow-y: hidden; + display: flex; + align-items: center; + justify-content: center; +} + +button { + font-family: -apple-system, BlinkMacSystemFont, Pretendard, "Segoe UI", Roboto, + Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; +} diff --git a/src/main.jsx b/src/main.jsx index c70b84f..a05b9cf 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,16 +1,16 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import axios from "axios"; -import App from "./App.jsx"; -import "./index.css"; -// import { Provider } from 'jotai'; -// import { accessTokenAtom } from './store/jotaiAtoms.js'; - -ReactDOM.createRoot(document.getElementById("root")).render( - - - -) - -axios.defaults.baseURL = "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080"; +import React from "react"; +import ReactDOM from "react-dom/client"; +import axios from "axios"; +import App from "./App.jsx"; +import "./index.css"; +// import { Provider } from 'jotai'; +// import { accessTokenAtom } from './store/jotaiAtoms.js'; + +ReactDOM.createRoot(document.getElementById("root")).render( + + + +) + +axios.defaults.baseURL = "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080"; axios.defaults.withCredentials = true; \ No newline at end of file diff --git a/src/pages/Frame/ApplyFrame.jsx b/src/pages/Frame/ApplyFrame.jsx new file mode 100644 index 0000000..8127a23 --- /dev/null +++ b/src/pages/Frame/ApplyFrame.jsx @@ -0,0 +1,218 @@ +import axios from "axios"; +import React, { useState, useEffect } from "react"; +import styles from "../Frame/ApplyFrame.module.css"; +import edit from "../../img/edit.png"; +import trash from "../../img/trash.png"; +import photobook from "../../img/book.png"; +import frameline from "../../img/frame-line.png"; +import { Link, useLocation } from "react-router-dom"; +import { useAtom } from "jotai"; +import { accessTokenAtom } from "../../store/jotaiAtoms"; +import html2canvas from "html2canvas"; +import AddPhoto from "../../component/MakeFrameCpn/AddPhoto"; + +const ApplyFrame = () => { + const location = useLocation(); + console.log("", location); + const { selectedFrame } = location.state; + const [selectedButton, setSelectedButton] = useState("프레임 제작"); + const [accessToken] = useAtom(accessTokenAtom); + const [uploadedImage, setUploadedImage] = useState(null); + + useEffect(() => { + // uploadedImage 값이 변경될 때 로컬 스토리지에 이미지 데이터를 저장합니다. + if (uploadedImage) { + localStorage.setItem("uploadedImage", uploadedImage); + } + }, [uploadedImage]); + + useEffect(() => { + // uploadedImage 값이 변경될 때 로컬 스토리지에 이미지 데이터를 저장합니다. + if (uploadedImage) { + localStorage.setItem("uploadedImage", uploadedImage); + } + }, [uploadedImage]); + + const handleEditFrame = (frameUrl) => { + console.log("Edit Frame URL:", frameUrl); + + // 수정할 프레임의 URL과 accessToken을 이용하여 PUT 요청을 생성 + const editFrameRequest = { + url: `http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame`, + method: "PUT", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + data: { + url: frameUrl, // 수정할 프레임의 URL + // 여기에 수정할 데이터 추가 (예: 수정된 프레임의 새로운 URL 등) + }, + }; + + // Axios를 사용하여 PUT 요청 보내기 + axios(editFrameRequest) + .then((response) => { + // 수정 요청이 성공했을 때의 동작 + console.log("프레임 수정 요청 성공:", response.data); + // 필요에 따라 상태(state)를 업데이트하거나 다른 작업 수행 + }) + .catch((error) => { + // 수정 요청이 실패했을 때의 동작 + console.error("프레임 수정 요청 실패:", error); + // 오류 처리 혹은 다른 처리 로직 구현 + }); + }; + + const handleDeleteFrame = (frameUrl) => { + console.log("Delete Frame URL:", frameUrl); + + // 삭제할 프레임의 URL과 accessToken을 이용하여 DELETE 요청을 생성 + const deleteFrameRequest = { + url: `http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame`, + method: "DELETE", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + data: { + url: frameUrl, + }, + }; + + // Axios를 사용하여 DELETE 요청 보내기 + axios(deleteFrameRequest) + .then((response) => { + // 삭제 요청이 성공했을 때의 동작 + console.log("프레임 삭제 요청 성공:", response.data); + // 필요에 따라 상태(state)를 업데이트하거나 다른 작업 수행 + }) + .catch((error) => { + // 삭제 요청이 실패했을 때의 동작 + console.error("프레임 삭제 요청 실패:", error); + // 오류 처리 혹은 다른 처리 로직 구현 + }); + }; + + const handleUploadedImage = (event) => { + const file = event.target.files[0]; + const reader = new FileReader(); + + reader.onload = () => { + setUploadedImage(reader.result); + }; + + if (file) { + reader.readAsDataURL(file); + } + }; + + const handleSaveClick = () => { + // 액세스 토큰이 있을 때만 API 요청을 보내도록 조건 처리 + if (accessToken) { + const frameElement = document.querySelector("img"); + frameElement.src = selectedFrame; + + html2canvas(frameElement).then((canvas) => { + canvas.toBlob((blob) => { + const formData = new FormData(); + formData.append("photo", blob, "photo.png"); + + console.log(formData); + + // axios 요청 설정 + const config = { + headers: { + "Content-Type": "multipart/form-data", + Authorization: `Bearer ${accessToken}`, // 헤더에 accessToken을 추가 + }, + }; + + axios + .post( + "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/photo", + formData, + config + ) + .then((res) => { + console.log("프레임 적용한 사진 저장 API 응답:", res.data); + }) + .catch((err) => { + // 오류 처리 + console.error("API 요청 중 오류 발생:", err); + }); + }, "image/png"); + }); + } + }; + + return ( +
+
+
+ + +
+
+
+
+ selectedFrame + {uploadedImage && ( + uploadedImage + )} +
+
+
+
+ + +
+
+ + + + + + +
+
+
+
+ ); +}; + +export default ApplyFrame; diff --git a/src/pages/Frame/ApplyFrame.module.css b/src/pages/Frame/ApplyFrame.module.css new file mode 100644 index 0000000..e04bc4b --- /dev/null +++ b/src/pages/Frame/ApplyFrame.module.css @@ -0,0 +1,171 @@ +body { + margin: 0px; + padding: 0px; +} + +.ApplyFrame { + width: 390px; + height: calc(var(--vh, 1vh) * 100); + background: #ffffff; + display: flex; + flex-direction: column; + justify-content: center; + margin: 0; + text-decoration: none; +} + +.ApplyFramebox { + display: flex; + flex-direction: column; +} + +.Top { + height: 85px; + display: flex; + flex-direction: row; + justify-content: space-around; + align-items: center; + border-bottom: 2px solid #c9c9c9; +} + +.Top button { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.TextBtn { + width: 95px; + height: 24px; + background-color: #f7f8f8; + text-align: center; + font-size: 12px; + font-weight: 400; + border-radius: 19px; + border: none; +} + +.ImgBtn { + width: 24px; + height: 24px; + background-color: #ffffff; + border: none; +} + +.Middle { + width: 390px; + height: 479px; + display: inline-block; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: #f7f8f8; + position: relative; +} + +.MiddleTop { + width: 390px; + height: 49px; + background-color: #ffffff; +} + +.Frame { + position: relative; + width: 300px; + height: 430px; + object-fit: contain; + top: 0; + left: 50%; + transform: translateX(-50%); +} + +.Frame img { + width: 100%; + height: 100%; + display: block; + flex-direction: column; + justify-content: start; + align-items: center; + margin: 0 auto; + position: absolute; +} + +.SelectedFrame { + position: absolute; + z-index: 2; +} + +.UploadedImage { + position: absolute; + z-index: 1; +} + +.ButtonList { + width: 390px; + height: 210px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 20px; +} + +.addphoto { + width: 340px; + height: 50px; + border-radius: 10px; + border: 1px solid #009eff; + text-align: center; + font-size: 14px; + font-weight: 500; + background-color: #ffffff; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + position: relative; +} + +.savephoto { + width: 340px; + height: 50px; + border-radius: 10px; + border: 1px solid #009eff; + text-align: center; + font-size: 14px; + font-weight: 500; + background-color: #ffffff; +} + +.ListBottom { + width: 390px; + height: 70px; + background: #f7f8f8; + display: flex; + flex-direction: row; + justify-content: space-evenly; + align-items: center; + gap: 20px; +} + +.ListBottom button { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + font-size: 10px; + font-weight: 400; + border: none; + background-color: #f7f8f8; +} + +.ListBottom button img { + width: 24px; + height: 24px; +} + +.now { + text-decoration: none; +} diff --git a/src/pages/Frame/Frame.jsx b/src/pages/Frame/Frame.jsx index eaff064..b74409d 100644 --- a/src/pages/Frame/Frame.jsx +++ b/src/pages/Frame/Frame.jsx @@ -1,71 +1,80 @@ -import React, { useState } from "react"; -import { useDrag } from "react-use-gesture"; -import { useSpring, animated } from "react-spring"; -import map from "../../img/map.png"; -import frame from "../../img/frame-line.png"; -import book from "../../img/book.png"; -import person from "../../img/person.png"; -import framelist from "../../img/framelist.png"; -import styles from "./Frame.module.css"; -import Template from "../../component/MakeFrameCpn/Template"; -import FrameList from "../../component/AllFrameCpn/FrameList"; -import Photobook from "../Photobook/PhotoSelect"; -import { Link } from "react-router-dom"; - -const Frame = () => { - const [selectedButton, setSelectedButton] = useState("프레임 제작"); - // const [logoPos, setlogoPos] = useState({ x: 0, y: 0 }); - const logoPos = useSpring({ x: 0, y: 0 }); - const bindLogoPos = useDrag((params) => { - // setlogoPos({ - // x: params.offset[0], - // y: params.offset[1], - // }); - logoPos.x.set(params.offset[0]); - logoPos.y.set(params.offset[1]); - }); - - const handleButtonClick = (button) => { - setSelectedButton(button); - }; - - let middleContent; - - switch (selectedButton) { - case "프레임 제작": - middleContent = ; - break; - case "포토북": - middleContent = ; - break; - default: - middleContent = ; - break; - } - - return ( -
-
- 전체 프레임 - -
-
{middleContent}
-
-
- - -
-
-
- ); -}; - -export default Frame; +import React, { useState } from "react"; +import { useDrag } from "react-use-gesture"; +import { useSpring, animated } from "react-spring"; +import home from "../../img/home.png"; +import map from "../../img/map.png"; +import frame from "../../img/frame-line.png"; +import book from "../../img/book.png"; +import person from "../../img/person.png"; +import framelist from "../../img/framelist.png"; +import styles from "./Frame.module.css"; +import Template from "../../component/MakeFrameCpn/Template"; +import FrameList from "../../component/AllFrameCpn/FrameList"; +import Photobook from "../Photobook/PhotoSelect"; +import { Link } from "react-router-dom"; + +const Frame = () => { + const [selectedButton, setSelectedButton] = useState("프레임 제작"); + // const [logoPos, setlogoPos] = useState({ x: 0, y: 0 }); + const logoPos = useSpring({ x: 0, y: 0 }); + const bindLogoPos = useDrag((params) => { + // setlogoPos({ + // x: params.offset[0], + // y: params.offset[1], + // }); + logoPos.x.set(params.offset[0]); + logoPos.y.set(params.offset[1]); + }); + + const handleButtonClick = (button) => { + setSelectedButton(button); + }; + + let middleContent; + + switch (selectedButton) { + case "프레임 제작": + middleContent = ; + break; + case "포토북": + middleContent = ; + break; + default: + middleContent = ; + break; + } + + const topSpan = + selectedButton === "프레임 제작" ? "전체 프레임" : "전체 포토"; + + return ( +
+
+ + + + {topSpan} + +
+
{middleContent}
+
+
+ + +
+
+
+ ); +}; + +export default Frame; diff --git a/src/pages/Frame/Frame.module.css b/src/pages/Frame/Frame.module.css index 6f0871a..3e99cd2 100644 --- a/src/pages/Frame/Frame.module.css +++ b/src/pages/Frame/Frame.module.css @@ -1,117 +1,117 @@ -.Frame { - width: 390px; - height: calc(var(--vh, 1vh) * 100); - background: #ffffff; - display: flex; - flex-direction: column; - justify-content: center; - user-select: none; -} - -.Top { - height: 86px; - display: flex; - flex-direction: row; - justify-content: flex-start; - align-items: center; -} - -.Top span { - flex: 1; - text-align: center; - font-size: 18px; - font-weight: 600; - padding-left: 50px; -} - -.Top button { - width: 24px; - height: 24px; - background-color: #ffffff; - border: none; - padding-right: 45px; -} - -.mylistBtn { - width: 47px; - height: 47px; - font-size: 10px; - background-color: #ffffff; - border-radius: 30px; - margin-left: auto; - border: none; -} - -.Middle { - width: 390px; - height: 689px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - background-color: #ffffff; - gap: 13px; -} - -.Bottom { - width: 100%; - height: 70px; -} - -.ListTop { - height: 40px; - padding: 14px 14px 14px 18px; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - font-size: 10px; - font-weight: 400; -} - -.ListTop button { - background-color: #ffffff; -} - -.ListView { - display: inline-flex; - height: 160px; - padding: 15px 0px 15px 18px; - flex-direction: row; - gap: 18px; -} - -.ListView span { - width: 72px; - height: 130px; - border-radius: 10px; - background: #d9d9d9; -} - -.ListBottom { - width: 390px; - height: 70px; - background: #f7f8f8; - display: flex; - flex-direction: row; - justify-content: space-evenly; - align-items: center; - gap: 20px; -} - -.ListBottom button { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; - font-size: 10px; - font-weight: 400; - border: none; - background-color: #f7f8f8; -} - -.ListBottom button img { - width: 24px; - height: 24px; -} +.Frame { + width: 390px; + height: calc(var(--vh, 1vh) * 100); + background: #ffffff; + display: flex; + flex-direction: column; + justify-content: center; + user-select: none; +} + +.Top { + height: 86px; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; +} + +.Top span { + flex: 1; + text-align: center; + font-size: 18px; + font-weight: 600; + padding-left: 50px; +} + +.Top button { + width: 24px; + height: 24px; + background-color: #ffffff; + border: none; + padding-right: 45px; +} + +.mylistBtn { + width: 47px; + height: 47px; + font-size: 10px; + background-color: #ffffff; + border-radius: 30px; + margin-left: auto; + border: none; +} + +.Middle { + width: 390px; + height: 689px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: #ffffff; + gap: 13px; +} + +.Bottom { + width: 100%; + height: 70px; +} + +.ListTop { + height: 40px; + padding: 14px 14px 14px 18px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + font-size: 10px; + font-weight: 400; +} + +.ListTop button { + background-color: #ffffff; +} + +.ListView { + display: inline-flex; + height: 160px; + padding: 15px 0px 15px 18px; + flex-direction: row; + gap: 18px; +} + +.ListView span { + width: 72px; + height: 130px; + border-radius: 10px; + background: #d9d9d9; +} + +.ListBottom { + width: 390px; + height: 70px; + background: #f7f8f8; + display: flex; + flex-direction: row; + justify-content: space-evenly; + align-items: center; + gap: 20px; +} + +.ListBottom button { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + font-size: 10px; + font-weight: 400; + border: none; + background-color: #f7f8f8; +} + +.ListBottom button img { + width: 24px; + height: 24px; +} diff --git a/src/pages/Frame/MakeFrame.jsx b/src/pages/Frame/MakeFrame.jsx index 1584f80..af1c45d 100644 --- a/src/pages/Frame/MakeFrame.jsx +++ b/src/pages/Frame/MakeFrame.jsx @@ -1,350 +1,484 @@ -import React, { useState, useEffect } from "react"; -import { Link } from "react-router-dom"; -import { useSelector } from "react-redux"; -import home from "../../img/home.png"; -import save from "../../img/save.png"; -import template from "../../img/template.png"; -import sticker from "../../img/sticker.png"; -import background from "../../img/background.png"; -import brush from "../../img/brush.png"; -import addphoto from "../../img/addphoto.png"; -import left from "../../img/left.png"; -import right from "../../img/right.png"; -import framebase from "../../assets/framebase.png"; -import styles from "./MakeFrame.module.css"; -import Template from "../../component/MakeFrameCpn/Template"; -import Sticker from "../../component/MakeFrameCpn/Sticker"; -import Background from "../../component/MakeFrameCpn/Background"; -import Brush from "../../component/MakeFrameCpn/Brush"; -import AddPhoto from "../../component/MakeFrameCpn/AddPhoto"; -import html2canvas from "html2canvas"; -import axios from "axios"; -import { useAtom } from "jotai"; -import { accessTokenAtom } from "../../store/jotaiAtoms"; - -const BrushSizeSelector = ({ selectedBrushSize, setSelectedBrushSize }) => { - return ( -
- - - -
- ); -}; - -const MakeFrame = () => { - const [selectedButton, setSelectedButton] = useState("템플릿"); - const [isListHover, setIsListHover] = useState(false); - const [selectedBrushSize, setSelectedBrushSize] = useState("medium"); - const [selectedColor, setSelectedColor] = useState("#000000"); - const [uploadedImage, setUploadedImage] = useState(null); - const [stickerPositionsitions, setStickerPositionsitions] = useState([]); - const [frameImage, setFrameImage] = useState(framebase); - const [actions, setActions] = useState([]); - const [uploadedSticker, setUploadedSticker] = useState(null); - const [stickerSize, setStickerSize] = useState(100); - const [selectedSticker, setSelectedSticker] = useState(null); - const [accessToken] = useAtom(accessTokenAtom); - - const handleButtonClick = (button) => { - setSelectedButton(button); - if (button !== "브러쉬") { - // '브러쉬' 버튼이 아닌 경우 브러쉬 크기 설정을 초기화 - setSelectedBrushSize("medium"); - } - }; - - /*if (button === "브러쉬") { - setIsBrushSizeVisible(true); - } else { - setIsBrushSizeVisible(false); - }*/ - - const handleStickerSelect = (selectedSticker) => { - // Sticker 컴포넌트로부터 받은 스티커 정보로 중앙에 스티커 렌더링 - setUploadedSticker(selectedSticker); - setSelectedSticker(selectedSticker); - }; - - // Sticker에서 전달된 스티커 위치 정보를 받는 함수 - const handleStickerDrag = ({ index, x, y }) => { - const newStickerPositionsitions = [...stickerPositionsitions]; - newStickerPositionsitions[index] = { x, y }; - setStickerPositionsitions(newStickerPositionsitions); - }; - - // UploadedImage와 스티커들을 합성하여 보여주는 함수 - const renderFrame = () => { - const uploadedImageStyle = uploadedImage - ? { position: "absolute", top: 0, left: 0 } - : {}; - - return ( -
- framebase - {uploadedImage && ( - uploadedImage - )} - {stickerPositions.map((position, index) => ( - {`sticker_${index}`} - ))} -
- ); - }; - - const changeFrameImage = (newFrameImage) => { - setFrameImage(newFrameImage); - }; - - const handleSaveClick = () => { - // 액세스 토큰이 있을 때만 API 요청을 보내도록 조건 처리 - if (accessToken) { - // axios 요청 설정 - const config = { - headers: { - Authorization: `Bearer ${accessToken}`, // 헤더에 accessToken을 추가 - }, - }; - - const frameElement = document.querySelector(`.${styles.Frame}`); - html2canvas(frameElement).then((canvas) => { - const imageData = canvas.toDataURL("image/png"); - - axios - .post( - "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame", - { - image: imageData, - }, - config - ) - .then((res) => { - console.log("프레임 저장 API 응답:", res.data); - // 성공적으로 데이터를 받아온 경우 - // 받아온 데이터로 frames 상태 업데이트 - }) - .catch((err) => { - // 오류 처리 - console.error("API 요청 중 오류 발생:", err); - }); - }); - } - }; - - useEffect(() => { - // 액세스 토큰이 있을 때만 API 요청을 보내도록 조건 처리 - if (accessToken) { - // axios 요청 설정 - const config = { - headers: { - Authorization: `Bearer ${accessToken}`, // 헤더에 accessToken을 추가 - }, - }; - - const frameElement = document.querySelector(`.${styles.Frame}`); - html2canvas(frameElement).then((canvas) => { - const imageData = canvas.toDataURL("image/png"); - - axios - .post( - "http://ec2-3-35-208-177.ap-northeast-2.compute.amazonaws.com:8080/frame/save", - { - image: imageData, - }, - config - ) - .then((res) => { - console.log("프레임 저장 API 응답:", res.data); - // 성공적으로 데이터를 받아온 경우 - // 받아온 데이터로 frames 상태 업데이트 - }) - .catch((err) => { - // 오류 처리 - console.error("API 요청 중 오류 발생:", err); - }); - }); - } - }, [accessToken]); - - const handleUploadedImage = (imageData) => { - setUploadedImage(imageData); - console.log(uploadedImage); - }; - - let bottomContent; - - switch (selectedButton) { - case "템플릿": - bottomContent = ( -