From 5a0af6136b69c75ecbcb5886221d237dccdfbd42 Mon Sep 17 00:00:00 2001 From: chundang Date: Thu, 29 Aug 2024 18:34:03 +0900 Subject: [PATCH] =?UTF-8?q?feat:[#126]=20api=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FITple-Frontend/data/DeleteApi.jsx | 22 ++ FITple-Frontend/data/UpdateApi.jsx | 26 ++ .../components/DeletePopUp/DeletePopUp.jsx | 18 +- .../pages/ClothdetailPage/ClothdetailPage.jsx | 9 +- .../pages/ClothupdatePage/ClothupdatePage.jsx | 240 +++++++++++++----- 5 files changed, 250 insertions(+), 65 deletions(-) create mode 100644 FITple-Frontend/data/DeleteApi.jsx create mode 100644 FITple-Frontend/data/UpdateApi.jsx diff --git a/FITple-Frontend/data/DeleteApi.jsx b/FITple-Frontend/data/DeleteApi.jsx new file mode 100644 index 0000000..afe2970 --- /dev/null +++ b/FITple-Frontend/data/DeleteApi.jsx @@ -0,0 +1,22 @@ +// closetApi.js + +export const deleteCloth = async (clothId) => { + try { + const response = await fetch( + `http://localhost:3000/FITple/my/closet/${clothId}/modify`, + { + method: "DELETE", + credentials: "include", // 세션 쿠키 포함 + } + ); + + if (!response.ok) { + throw new Error("Failed to delete the cloth"); + } + + return response.json(); // 성공 시 응답 데이터를 반환 + } catch (error) { + console.error("Error deleting cloth:", error); + throw error; // 에러 발생 시 호출하는 곳에서 처리하도록 던짐 + } +}; diff --git a/FITple-Frontend/data/UpdateApi.jsx b/FITple-Frontend/data/UpdateApi.jsx new file mode 100644 index 0000000..a993aa1 --- /dev/null +++ b/FITple-Frontend/data/UpdateApi.jsx @@ -0,0 +1,26 @@ +const updateCloth = async (clothId, updatedData) => { + try { + const response = await fetch( + `http://localhost:3000/FITple/my/closet/${clothId}/modify`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + credentials: "include", // 쿠키 등의 인증 정보 포함 + body: JSON.stringify(updatedData), // 수정할 데이터 + } + ); + + if (!response.ok) { + throw new Error("Failed to update the cloth information"); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("Error updating cloth information:", error); + throw error; // 필요에 따라 에러 처리 + } +}; +export default updateCloth; diff --git a/FITple-Frontend/src/components/DeletePopUp/DeletePopUp.jsx b/FITple-Frontend/src/components/DeletePopUp/DeletePopUp.jsx index 4b68da8..f5be572 100644 --- a/FITple-Frontend/src/components/DeletePopUp/DeletePopUp.jsx +++ b/FITple-Frontend/src/components/DeletePopUp/DeletePopUp.jsx @@ -6,14 +6,26 @@ import { PopupButtonContainer, } from "./DeletePopUp.style"; import { useState } from "react"; - -const DeletePopUp = ({ onClose }) => { +import { useNavigate } from "react-router-dom"; +import { deleteCloth } from "../../../data/DeleteApi"; +const DeletePopUp = ({ clothId, onClose }) => { + console.log("Received clothId:", clothId); + const navigate = useNavigate(); const handlePopupback = () => { onClose(); }; const [popupdelete, setPopupdelete] = useState(false); - const handlePopupdelete = () => { + const handlePopupdelete = async () => { setPopupdelete(!popupdelete); + + try { + await deleteCloth(clothId); + alert("옷이 성공적으로 삭제되었습니다."); + navigate("/cloth"); + } catch (error) { + console.error("Error deleting cloth:", error); + alert("옷 삭제에 실패했습니다."); + } }; return ( diff --git a/FITple-Frontend/src/pages/ClothdetailPage/ClothdetailPage.jsx b/FITple-Frontend/src/pages/ClothdetailPage/ClothdetailPage.jsx index 6324159..e14e876 100644 --- a/FITple-Frontend/src/pages/ClothdetailPage/ClothdetailPage.jsx +++ b/FITple-Frontend/src/pages/ClothdetailPage/ClothdetailPage.jsx @@ -41,7 +41,6 @@ import CompareSearchPopUp from "../../components/CompareSearchPopUp/CompareSearc import CompareLoading from "../../components/CompareLoading/CompareLoading"; import CompareResult from "../../components/CompareResult/CompareResult"; import useAuthStore from "../../../data/store/userAuthStore"; // 토큰을 가져오기 위해 zustand의 store import - function ClothdetailPage() { const { clothId } = useParams(); // URL에서 clothId 가져오기 const [clothData, setClothData] = useState(null); // 가져온 데이터를 저장할 상태 @@ -102,7 +101,7 @@ function ClothdetailPage() { setIsEdit(!isEdit); }; - const handleDeleteCloth = () => { + const handleDeleteCloth = async () => { setisDeletePopupOpen(!isDeletePopupOpen); }; @@ -273,7 +272,10 @@ function ClothdetailPage() { {isEdit && ( - + 옷 정보 수정하기 @@ -297,6 +299,7 @@ function ClothdetailPage() { setisDeletePopupOpen(false)} + clothId={clothData.cloth_id} /> )} diff --git a/FITple-Frontend/src/pages/ClothupdatePage/ClothupdatePage.jsx b/FITple-Frontend/src/pages/ClothupdatePage/ClothupdatePage.jsx index 738b155..a3f3e15 100644 --- a/FITple-Frontend/src/pages/ClothupdatePage/ClothupdatePage.jsx +++ b/FITple-Frontend/src/pages/ClothupdatePage/ClothupdatePage.jsx @@ -1,3 +1,5 @@ +import { useState } from "react"; +import { useLocation, useParams, Link, useNavigate } from "react-router-dom"; import { BackIcon, SS, @@ -26,25 +28,72 @@ import { CurvedRectangle3, StyledButton, } from "./ClothupdatePage.style"; -import { useState } from "react"; -import { Link } from "react-router-dom"; +import updateCloth from "../../../data/UpdateApi"; + +// 카테고리와 핏 옵션을 상수로 관리 +const clothingCategories = [ + { value: 1, label: "아우터" }, + { value: 2, label: "상의" }, + { value: 3, label: "바지" }, + { value: 4, label: "스커트" }, + { value: 5, label: "원피스" }, + { value: 6, label: "신발" }, +]; + +const fitOptions = [ + { value: "레귤러", label: "레귤러" }, + { value: "오버", label: "오버" }, + { value: "세미오버", label: "세미오버" }, + { value: "슬림", label: "슬림" }, +]; const ClothupdatePage = () => { - //드롭다운 - const [isToggle, setIsToggle] = useState(false); - const [selectedValue, setSelectedValue] = useState("아우터"); - const handleToggle = () => { - setIsToggle(!isToggle); + const location = useLocation(); + const navigate = useNavigate(); + const { clothId } = useParams(); + + // detail 페이지에서 전달된 clothData를 state로 받아옴 + const initialClothData = location.state?.clothData || {}; + + const [clothData, setClothData] = useState(initialClothData); + const [isCategoryOpen, setIsCategoryOpen] = useState(false); + const [isFitOpen, setIsFitOpen] = useState(false); + const [rating, setRating] = useState(initialClothData.rating || 0); + + // 카테고리와 핏의 label을 찾기 위한 함수 + const getLabelByValue = (options, value) => { + const option = options.find((opt) => opt.value === value); + return option ? option.label : "선택"; + }; + + const handleCategorySelect = (value) => { + setClothData((prevData) => ({ + ...prevData, + category: value, + })); + setIsCategoryOpen(false); }; - const handleSelect = (value) => { - setSelectedValue(value); - setIsToggle(false); + + const handleFitSelect = (value) => { + setClothData((prevData) => ({ + ...prevData, + fit: value, + })); + setIsFitOpen(false); + }; + + const handleInputChange = (e) => { + const { name, value } = e.target; + setClothData((prevData) => ({ + ...prevData, + [name]: value, + })); }; - //별점 - const [rating, setRating] = useState(0); + const handleStarClick = (newRating) => { setRating(newRating); }; + const renderStars = () => { const stars = []; for (let i = 0; i < 5; i++) { @@ -60,6 +109,25 @@ const ClothupdatePage = () => { } return stars; }; + + const handleUpdate = async () => { + try { + const updatedData = { + ...clothData, + rating, + }; + + await updateCloth(clothId, updatedData); + + alert("옷 정보가 성공적으로 수정되었습니다."); + navigate(`/clothdetail/${clothId}`); + } catch (error) { + alert("옷 정보 수정에 실패했습니다. 다시 시도해주세요."); + } + + console.log(clothData); + }; + return (
@@ -67,7 +135,7 @@ const ClothupdatePage = () => { - + @@ -81,7 +149,11 @@ const ClothupdatePage = () => { 브랜드 - 나이키 + @@ -90,7 +162,11 @@ const ClothupdatePage = () => { - 에센셜 풀집 후디 + @@ -98,7 +174,11 @@ const ClothupdatePage = () => { 제품번호* - + @@ -106,59 +186,69 @@ const ClothupdatePage = () => { 분류* - {selectedValue} - < + + {getLabelByValue(clothingCategories, clothData.category)} + + setIsCategoryOpen(!isCategoryOpen)}> + < + - + - handleSelect("아우터")}> - 아우터 - - handleSelect("반소매 상의")}> - 반소매 상의 - - handleSelect("긴소매 상의")}> - 긴소매 상의 - - handleSelect("슬리브리스 상의")}> - 슬리브리스 상의 - - handleSelect("롱팬츠")}> - 롱팬츠 - - handleSelect("숏팬츠")}> - 숏팬츠 - - handleSelect("스커트")}> - 스커트 - - handleSelect("원피스")}> - 원피스 - - handleSelect("신발")}> - 신발 - + {clothingCategories.map((category) => ( + handleCategorySelect(category.value)} + > + {category.label} + + ))} 사이즈 - + - 세미 + + {getLabelByValue(fitOptions, clothData.fit)} + + setIsFitOpen(!isFitOpen)}> + < + + + + {fitOptions.map((fit) => ( + handleFitSelect(fit.value)} + > + {fit.label} + + ))} + + URL - - https:://adidas.co.kr/1245 + + {clothData.URL} @@ -172,7 +262,11 @@ const ClothupdatePage = () => { 메모 - 길이는 딱 맞고,팔이 조금 길다. + @@ -180,53 +274,81 @@ const ClothupdatePage = () => { 총장 - 40 + cm 어깨너비 - 71 + cm 가슴단면 - 73 + cm 암홀단면 - - + cm 소매단면 - - + cm 소매길이 - - + cm 밑단단면 - - + cm - 옷 정보 수정하기 + 옷 정보 수정하기