From 1e09fe39eb7c467fae8dfd5feb9d190a66ae302d Mon Sep 17 00:00:00 2001 From: "Oh, Sukyeong" Date: Fri, 27 Sep 2024 00:04:26 +0900 Subject: [PATCH] =?UTF-8?q?:lipstick:=20Design:=20=EC=83=81=EC=A0=90=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20UI=20=EC=88=98=EC=A0=95(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/pages/objects/Flooring.jsx | 40 +++- src/pages/objects/Furniture.jsx | 40 +++- src/pages/objects/Gift.jsx | 201 +++++++--------- src/pages/objects/LeftAccessory.jsx | 40 +++- src/pages/objects/LeftWall.jsx | 40 +++- src/pages/objects/RightAccessory.jsx | 88 ++++--- src/pages/objects/RightWall.jsx | 56 +++-- src/pages/objects/Rug.jsx | 40 +++- src/pages/objects/SideTable.jsx | 40 +++- src/pages/objects/Sofa.jsx | 40 +++- src/pages/objects/Toy.jsx | 40 +++- src/pages/objects/Wallpaper.jsx | 44 +++- src/pages/shop/Shop.jsx | 343 +++++++++++++++++++-------- 14 files changed, 719 insertions(+), 334 deletions(-) diff --git a/package.json b/package.json index 34ab262..73a07d0 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "moodfriend-app", "version": "0.1.0", "private": true, + "proxy": "https://kapi.kakao.com", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.6.0", "@fortawesome/free-brands-svg-icons": "^6.6.0", diff --git a/src/pages/objects/Flooring.jsx b/src/pages/objects/Flooring.jsx index 6d1f2d9..3f69dd7 100644 --- a/src/pages/objects/Flooring.jsx +++ b/src/pages/objects/Flooring.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/Furniture.jsx b/src/pages/objects/Furniture.jsx index 5d85bbc..9d9bd1a 100644 --- a/src/pages/objects/Furniture.jsx +++ b/src/pages/objects/Furniture.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/Gift.jsx b/src/pages/objects/Gift.jsx index 196e6f6..de433bd 100644 --- a/src/pages/objects/Gift.jsx +++ b/src/pages/objects/Gift.jsx @@ -7,80 +7,69 @@ import WhiteBackArrowIcon from "../../assets/icons/WhiteBackArrow.svg"; import AngryHoyaIcon from "../../assets/icons/AngryHoya.svg"; import ShopIcon from "../../assets/icons/Shop.svg"; import ObjCheckIcon from "../../assets/icons/ObjCheck.svg"; -import HeartObjIcon from "../../assets/icons/HeartObj.svg"; -import PinkHeartObjIcon from "../../assets/icons/PinkHeartObj.svg"; -import BlackHeartObjIcon from "../../assets/icons/BlackHeartObj.svg"; +import XIcon from "../../assets/icons/X.svg"; const Gift = () => { + const [isHeartVisible, setIsHeartVisible] = useState(true); const [objectNames, setObjectNames] = useState([]); - const [objectStatuses, setObjectStatuses] = useState([]); - const [selectedIndex, setSelectedIndex] = useState(null); - const [viewMode, setViewMode] = useState("owned"); // "owned" or "available" const [errorMessage, setErrorMessage] = useState(""); const navigate = useNavigate(); - const fetchObjectData = async (url) => { - const accessToken = localStorage.getItem("accessToken"); - if (accessToken) { - try { - const response = await axios.get(url, { - headers: { - Authorization: `Bearer ${accessToken}` + useEffect(() => { + const fetchUserData = async () => { + const accessToken = localStorage.getItem("accessToken"); + if (accessToken) { + try { + const response = await axios.get( + "https://moodfriend.site/api/v1/object/display", + { + headers: { + Authorization: `Bearer ${accessToken}` + } + } + ); + + // 응답 데이터 구조 확인 + console.log("API 응답 데이터:", response.data); + + // 응답 데이터에서 objectNames 추출 + const objectData = response.data.data; + if (objectData && objectData.length > 5) { + const names = objectData.map((obj) => obj.objectName); + setObjectNames(names); + + // 로컬스토리지에 저장 + localStorage.setItem("objectNames", JSON.stringify(names)); + } else { + console.error("data 배열에 오브제 정보가 없습니다."); + setErrorMessage("서버에서 오브제 정보를 가져오지 못했습니다."); } - }); - - console.log("API 응답 데이터:", response.data); - - const objectData = response.data.data; - if (objectData && objectData.length > 0) { - const names = objectData.map((obj) => obj.objectName || obj); - const statuses = objectData.map((obj) => obj.status || false); - setObjectNames(names); - setObjectStatuses(statuses); - - localStorage.setItem("objectNames", JSON.stringify(names)); - localStorage.setItem("objectStatuses", JSON.stringify(statuses)); - } else { - console.error("data 배열에 오브제 정보가 없습니다."); - setErrorMessage("서버에서 오브제 정보를 가져오지 못했습니다."); + } catch (error) { + console.error("사용자 정보 조회 실패:", error); + setErrorMessage("사용자 정보를 불러올 수 없습니다."); } - } catch (error) { - console.error("사용자 정보 조회 실패:", error); - setErrorMessage("사용자 정보를 불러올 수 없습니다."); + } else { + console.log("액세스 토큰이 없습니다."); } - } else { - console.log("액세스 토큰이 없습니다."); - } - }; + }; - useEffect(() => { - if (viewMode === "owned") { - fetchObjectData("https://moodfriend.site/api/v1/object/owned/display"); - } else if (viewMode === "available") { - fetchObjectData( - "https://moodfriend.site/api/v1/object/available/display" - ); - } - }, [viewMode]); + fetchUserData(); + }, []); const handleShopClick = () => { navigate("/shop"); }; const handleObjCheckClick = () => { - if (viewMode === "available") { - alert("상점에서 구매해주세요!"); - } else { - navigate("/object"); - } + navigate(-1); }; - const handleObjItemClick = (index) => { - const updatedStatuses = objectStatuses.map((_, i) => i === index); - setObjectStatuses(updatedStatuses); - localStorage.setItem("objectStatuses", JSON.stringify(updatedStatuses)); - setSelectedIndex(index); + const handleObjItemClick = () => { + if (isHeartVisible) { + setIsHeartVisible(false); + // 서버에 하트 오브제 상태 업데이트 요청을 보내는 부분 추가 가능 + } }; return ( @@ -93,20 +82,7 @@ const Gift = () => { - - {selectedIndex !== null && ( - - )} - + @@ -114,51 +90,22 @@ const Gift = () => { - setViewMode("owned")}> - 보유중 - - setViewMode("available")}> - 구매하기 - + 보유중 + 구매하기 - {objectNames.length > 0 ? ( + {objectNames.length > 5 ? ( objectNames.map((name, index) => ( - handleObjItemClick(index)} - style={{ - opacity: - (viewMode === "owned" && objectStatuses[index]) || - (viewMode === "available" && selectedIndex === index) - ? 1 - : 0.7 - }} - > - + + {name} )) ) : ( - 정보 없음 + )} @@ -228,7 +175,6 @@ const ObjCheckText = styled.span` font-size: 14px; font-weight: bold; margin-left: 45px; - cursor: pointer; `; const ObjCheckText2 = styled.span` @@ -236,7 +182,6 @@ const ObjCheckText2 = styled.span` font-size: 14px; font-weight: bold; margin-right: 65px; - cursor: pointer; `; const Background = styled.div` @@ -260,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -291,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` @@ -316,7 +287,7 @@ const ObjItem = styled.div` const ObjItemCheckImage = styled.img` width: 24px; height: 24px; - margin-bottom: 10px; + margin-top: 100px; `; const Shop = styled.div` @@ -329,7 +300,7 @@ const Shop = styled.div` display: flex; align-items: center; justify-content: center; - margin-top: 110px; + margin-top: 50px; margin-left: 250px; `; diff --git a/src/pages/objects/LeftAccessory.jsx b/src/pages/objects/LeftAccessory.jsx index b044068..f9b82ff 100644 --- a/src/pages/objects/LeftAccessory.jsx +++ b/src/pages/objects/LeftAccessory.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/LeftWall.jsx b/src/pages/objects/LeftWall.jsx index 443fedb..1c2e5c6 100644 --- a/src/pages/objects/LeftWall.jsx +++ b/src/pages/objects/LeftWall.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/RightAccessory.jsx b/src/pages/objects/RightAccessory.jsx index 45a9b58..341c418 100644 --- a/src/pages/objects/RightAccessory.jsx +++ b/src/pages/objects/RightAccessory.jsx @@ -7,10 +7,9 @@ import WhiteBackArrowIcon from "../../assets/icons/WhiteBackArrow.svg"; import AngryHoyaIcon from "../../assets/icons/AngryHoya.svg"; import ShopIcon from "../../assets/icons/Shop.svg"; import ObjCheckIcon from "../../assets/icons/ObjCheck.svg"; -import XIcon from "../../assets/icons/X.svg"; +import HeartIcon from "../../assets/icons/HeartObj.svg"; const RightAccessory = () => { - const [isHeartVisible, setIsHeartVisible] = useState(true); const [objectNames, setObjectNames] = useState([]); const [errorMessage, setErrorMessage] = useState(""); @@ -22,7 +21,7 @@ const RightAccessory = () => { if (accessToken) { try { const response = await axios.get( - "https://moodfriend.site/api/v1/object/display", + "https://moodfriend.site/api/v1/object/owned/display", { headers: { Authorization: `Bearer ${accessToken}` @@ -30,16 +29,13 @@ const RightAccessory = () => { } ); - // 응답 데이터 구조 확인 console.log("API 응답 데이터:", response.data); - // 응답 데이터에서 objectNames 추출 const objectData = response.data.data; - if (objectData && objectData.length > 5) { + if (objectData && objectData.length > 0) { const names = objectData.map((obj) => obj.objectName); setObjectNames(names); - // 로컬스토리지에 저장 localStorage.setItem("objectNames", JSON.stringify(names)); } else { console.error("data 배열에 오브제 정보가 없습니다."); @@ -65,13 +61,6 @@ const RightAccessory = () => { navigate(-1); }; - const handleObjItemClick = () => { - if (isHeartVisible) { - setIsHeartVisible(false); - // 서버에 하트 오브제 상태 업데이트 요청을 보내는 부분 추가 가능 - } - }; - return ( <> @@ -91,21 +80,20 @@ const RightAccessory = () => { 보유중 - 구매하기 - {objectNames.length > 5 ? ( + {objectNames.length > 0 ? ( objectNames.map((name, index) => ( - - + + {name} )) ) : ( - + 오브제 정보가 없습니다. )} @@ -205,19 +193,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,18 +240,27 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` - display: flex; - flex-wrap: wrap; - justify-content: center; - width: 100%; - gap: 20px; + display: grid; + grid-template-columns: repeat(3, 1fr); + width: 90%; + padding: 10px; `; const ObjItem = styled.div` @@ -255,7 +268,8 @@ const ObjItem = styled.div` display: flex; flex-direction: column; align-items: center; - margin: 10px; + + text-align: center; `; const ObjItemCheckImage = styled.img` @@ -310,4 +324,14 @@ const ObjCheckImage = styled.img` const Text = styled.span` font-size: 12px; + + @media (max-width: 360px) { + padding: 20px; + } +`; + +const HeartImage = styled.img` + width: 24px; + height: 24px; + margin-top: 5px; `; diff --git a/src/pages/objects/RightWall.jsx b/src/pages/objects/RightWall.jsx index 992ee9a..0256406 100644 --- a/src/pages/objects/RightWall.jsx +++ b/src/pages/objects/RightWall.jsx @@ -65,13 +65,6 @@ const RightWall = () => { navigate(-1); }; - const handleObjItemClick = () => { - if (isHeartVisible) { - setIsHeartVisible(false); - // 서버에 하트 오브제 상태 업데이트 요청을 보내는 부분 추가 가능 - } - }; - return ( <> @@ -98,14 +91,9 @@ const RightWall = () => { {objectNames.length > 5 ? ( - objectNames.map((name, index) => ( - - - {name} - - )) + objectNames.map((name, index) => {name}) ) : ( - + )} @@ -205,19 +193,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +240,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/Rug.jsx b/src/pages/objects/Rug.jsx index c0db5af..5228ac4 100644 --- a/src/pages/objects/Rug.jsx +++ b/src/pages/objects/Rug.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/SideTable.jsx b/src/pages/objects/SideTable.jsx index 980cdaf..42d84dc 100644 --- a/src/pages/objects/SideTable.jsx +++ b/src/pages/objects/SideTable.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/Sofa.jsx b/src/pages/objects/Sofa.jsx index f79a063..5d4fff6 100644 --- a/src/pages/objects/Sofa.jsx +++ b/src/pages/objects/Sofa.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/Toy.jsx b/src/pages/objects/Toy.jsx index edad32e..b6b975f 100644 --- a/src/pages/objects/Toy.jsx +++ b/src/pages/objects/Toy.jsx @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/objects/Wallpaper.jsx b/src/pages/objects/Wallpaper.jsx index 30a2f20..f72eca4 100644 --- a/src/pages/objects/Wallpaper.jsx +++ b/src/pages/objects/Wallpaper.jsx @@ -9,7 +9,7 @@ import ShopIcon from "../../assets/icons/Shop.svg"; import ObjCheckIcon from "../../assets/icons/ObjCheck.svg"; import XIcon from "../../assets/icons/X.svg"; -const Gift = () => { +const Wallpaper = () => { const [isHeartVisible, setIsHeartVisible] = useState(true); const [objectNames, setObjectNames] = useState([]); const [errorMessage, setErrorMessage] = useState(""); @@ -117,7 +117,7 @@ const Gift = () => { ); }; -export default Gift; +export default Wallpaper; // 스타일 컴포넌트 정의 const CenteredContainer = styled.div` @@ -205,19 +205,35 @@ const Floor = styled.div` position: absolute; bottom: 0; left: 0; - z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; const Circular = styled.img` - width: 120px; - height: 40px; border-radius: 50%; background-color: ${(props) => props.theme.color.greenColor}; display: flex; align-items: center; justify-content: center; position: absolute; - bottom: 75px; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } `; const FloorInterior = styled.div` @@ -236,10 +252,20 @@ const RightFloorObj = styled.img` `; const Character = styled.img` - width: 70px; - height: 80px; position: absolute; - bottom: 115px; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } `; const ObjItems = styled.div` diff --git a/src/pages/shop/Shop.jsx b/src/pages/shop/Shop.jsx index ec7109c..5007b09 100644 --- a/src/pages/shop/Shop.jsx +++ b/src/pages/shop/Shop.jsx @@ -2,91 +2,115 @@ import React, { useState, useEffect } from "react"; import axios from "axios"; import styled from "styled-components"; import { useNavigate } from "react-router-dom"; +import Menubar from "../../components/common/Menubar"; import WhiteBackArrowIcon from "../../assets/icons/WhiteBackArrow.svg"; +import AngryHoyaIcon from "../../assets/icons/AngryHoya.svg"; +import ShopIcon from "../../assets/icons/Shop.svg"; +import ObjCheckIcon from "../../assets/icons/ObjCheck.svg"; +import HeartIcon from "../../assets/icons/HeartObj.svg"; const Shop = () => { + const [objectNames, setObjectNames] = useState([]); + const [errorMessage, setErrorMessage] = useState(""); + const [visibleHeartIndex, setVisibleHeartIndex] = useState(null); + const [selectedProduct, setSelectedProduct] = useState(null); // 선택한 제품 상태 추가 + const navigate = useNavigate(); - const [objects, setObjects] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(""); useEffect(() => { - const fetchAvailableObjects = async () => { + const fetchUserData = async () => { const accessToken = localStorage.getItem("accessToken"); - - if (!accessToken) { - setError("로그인이 필요합니다."); - setIsLoading(false); - return; - } - - try { - const response = await axios.get( - "https://moodfriend.site/api/v1/object/available/display", - { - headers: { - Authorization: `Bearer ${accessToken}` + if (accessToken) { + try { + const response = await axios.get( + "https://moodfriend.site/api/v1/object/available/display", + { + headers: { + Authorization: `Bearer ${accessToken}` + } } - } - ); - const { success, data, message } = response.data; + ); - if (success) { - setObjects(data); // data가 이미 배열 형태임 - } else { - setError(message || "오브제 조회에 실패했습니다."); + const objectData = response.data.data; + if ( + objectData && + Array.isArray(objectData) && + objectData.length > 0 + ) { + setObjectNames(objectData); + localStorage.setItem("objectNames", JSON.stringify(objectData)); + } else { + setErrorMessage("서버에서 오브제 정보를 가져오지 못했습니다."); + } + } catch (error) { + setErrorMessage("사용자 정보를 불러올 수 없습니다."); } - } catch (error) { - console.error("API 요청 중 오류 발생:", error); - setError("서버 요청 중 오류가 발생했습니다."); - } finally { - setIsLoading(false); } }; - fetchAvailableObjects(); + fetchUserData(); }, []); - if (isLoading) { - return 로딩 중...; - } + const handleShopClick = () => { + navigate("/shop"); + }; + + const handleObjCheckClick = () => { + const userConfirmed = window.confirm("구매하시겠습니까?"); + if (userConfirmed) { + console.log("선택한 제품:", selectedProduct); + navigate("/payment", { state: { productName: selectedProduct } }); // 선택한 제품 이름 전달 + } + }; + + const toggleHeart = (index, name) => { + setVisibleHeartIndex((prevIndex) => (prevIndex === index ? null : index)); + setSelectedProduct(name); // 선택한 제품 이름 저장 + }; return ( <> + navigate(-1)} /> - 상점 + 오브제 - - 꾸미기 - navigate("/charge")}> - 충전하기 - - - - {error ? ( - {error} - ) : objects.length > 0 ? ( - objects.map((object, index) => ( - - - {object} {/* object는 문자열 */} - - navigate("/charge", { - state: { productName: object, price: 1000 } // 예시로 가격을 1000으로 설정 - }) - } - > - 구매하기 - - - - )) - ) : ( - 구매 가능한 오브제가 없습니다. + + + + + + + + + {visibleHeartIndex !== null && ( + )} - + + + + 구매하기 + + + + + + {objectNames.length > 0 ? ( + objectNames.map((name, index) => ( + toggleHeart(index, name)}> + + {name} + + )) + ) : ( + 오브제 정보가 없습니다. + )} + + + + 상점 + + ); }; @@ -94,6 +118,23 @@ const Shop = () => { export default Shop; // 스타일 컴포넌트 정의 +const CenteredContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + height: 50vh; + width: 100%; + position: relative; +`; + +const StyledHeartImage = styled.img` + position: absolute; + top: 30%; + left: 25%; + width: 24px; + height: 24px; +`; + const Box = styled.div` display: flex; align-items: center; @@ -116,76 +157,176 @@ const MyText = styled.span` color: #ffffff; `; +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: 40vh; + position: relative; + background-color: white; + padding: 20px; + overflow: hidden; +`; + const TopRow = styled.div` display: flex; justify-content: space-between; align-items: center; - margin: 20px; + width: 100%; + margin-bottom: 10px; `; const ObjCheckText = styled.span` color: black; font-size: 14px; font-weight: bold; - margin-left: 40px; + margin-left: 45px; `; -const ObjCheckText2 = styled.span` - color: black; - font-size: 14px; - font-weight: bold; - margin-right: 80px; - cursor: pointer; +const Background = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 80%; + padding-bottom: 80%; + background-color: ${(props) => props.theme.color.pinkColor}; + position: relative; `; -const ObjectList = styled.div` - margin: 20px; +const Floor = styled.div` + width: 100%; + height: 40%; + display: flex; + flex-direction: column; + align-items: center; + background-color: ${(props) => props.theme.color.lightPinkColor}; + position: absolute; + bottom: 0; + left: 0; + + @media (max-width: 430px) and (max-height: 932px) { + height: 35%; + } + + @media (max-width: 360px) and (max-height: 780px) { + height: 33%; + } `; -const ObjectItem = styled.div` +const Circular = styled.img` + border-radius: 50%; + background-color: ${(props) => props.theme.color.greenColor}; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + + @media (max-width: 430px) and (max-height: 932px) { + width: 120px; + height: 45px; + bottom: 80px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 110px; + height: 40px; + bottom: 60px; + } +`; + +const FloorInterior = styled.div` + display: flex; + align-items: center; + position: absolute; + bottom: 40px; + z-index: 3; +`; + +const Character = styled.img` + position: absolute; + z-index: 1; + + @media (max-width: 430px) and (max-height: 932px) { + width: 70px; + height: 80px; + bottom: 100px; + } + + @media (max-width: 360px) and (max-height: 780px) { + width: 60px; + height: 70px; + bottom: 80px; + } +`; + +const ObjItems = styled.div` + display: flex; + flex-wrap: wrap; + justify-content: space-around; width: 100%; - margin-bottom: 20px; + gap: 20px; `; -const ObjectBackground = styled.div` - background-color: #ffffff; - border-radius: 5px; - padding: 15px; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +const ObjItem = styled.div` + cursor: pointer; display: flex; flex-direction: column; align-items: center; + width: 30%; + text-align: center; + margin: 15px; `; -const ObjectName = styled.div` - font-size: 16px; - margin-bottom: 15px; +const HeartImage = styled.img` + width: 24px; + height: 24px; + margin-top: 5px; `; -const BuyButton = styled.button` - background-color: ${(props) => props.theme.color.primaryColor}; - color: #ffffff; - border: none; - padding: 10px 20px; - border-radius: 5px; +const Shop2 = styled.div` + position: relative; + width: 50px; + height: 50px; cursor: pointer; - font-size: 14px; + background: url(${ShopIcon}) no-repeat center center; + background-size: cover; + display: flex; + align-items: center; + justify-content: center; + margin-top: 50px; + margin-left: 250px; `; -const NoObjects = styled.div` - text-align: center; - font-size: 16px; - color: #666; +const ShopImage = styled.img` + width: 100%; + height: 100%; + opacity: 0; `; -const ErrorText = styled.div` +const ShopText = styled.span` + position: absolute; + color: white; + font-size: 12px; + font-weight: bold; + bottom: 14px; text-align: center; - font-size: 16px; - color: red; `; -const LoadingText = styled.div` - text-align: center; - font-size: 16px; - color: #666; +const ObjCheck = styled.div` + cursor: pointer; + background: url(${ObjCheckIcon}) no-repeat center center; + background-size: cover; + width: 24px; + height: 24px; +`; + +const ObjCheckImage = styled.img` + width: 100%; + height: 100%; +`; + +const Text = styled.span` + font-size: 12px; `;