diff --git a/src/api/my/deletePC.js b/src/api/my/deletePC.js new file mode 100644 index 0000000000000000000000000000000000000000..09ee7e2a685ae7e584ee95e8eeedfcb148e3f006 --- /dev/null +++ b/src/api/my/deletePC.js @@ -0,0 +1,23 @@ +import axios from '../axios'; + +const deletePC = async (pcId) => { + try { + const response = await axios.delete(`/my/pc/${pcId}`); + return response.data; + } catch (error) { + if (error.response?.status === 401) { + const unauthorizedError = new Error("인증되지 않은 요청입니다"); + unauthorizedError.response = { + data: { + message: "인증되지 않은 요청입니다", + statusCode: 401, + data: {} + } + }; + throw unauthorizedError; + } + throw error; + } +}; + +export default deletePC; \ No newline at end of file diff --git a/src/mocks/handlers.js b/src/mocks/handlers.js index a5dae3a0b5ca5752c77c7580b76fb92bafefe8dc..ea4debda5bb16c810ffe4c264dbb67a43270c879 100644 --- a/src/mocks/handlers.js +++ b/src/mocks/handlers.js @@ -404,7 +404,7 @@ export const handlers = [ http.post(`${api}/auth/verify/email`, async ({ request }) => { const { email } = await request.json(); return HttpResponse.json({ - message: "인증번호가 해당 이메일로 발송되었습니다.", + message: "인증번호가 해당 이메일로 발송��었습니다.", statusCode: 200, data: { verificationCode: "123456" // 실제로는 이메일로 발송됨 @@ -518,6 +518,27 @@ export const handlers = [ } }); }), + + // PC 삭제 + http.delete(`${api}/my/pc/:pcId`, async ({ request, params }) => { + const authHeader = request.headers.get('Authorization'); + if (!authHeader) { + return HttpResponse.json({ + message: "인증되지 않은 요청입니다", + statusCode: 401, + data: {} + }, { status: 401 }); + } + + return HttpResponse.json({ + message: "PC가 성공적으로 삭제되었습니다", + statusCode: 200, + data: { + id: params.pcId, + deletedAt: new Date().toISOString() + } + }); + }), ]; // 부품 조회 함수 diff --git a/src/pages/MyCombinationPage/MyCombinationPage.css b/src/pages/MyCombinationPage/MyCombinationPage.css index ffc38c5b709ea2c1e777a3fb9bda10c813944f94..3fa221b6e78a4a4d427415e491d1d73b13c64a2c 100644 --- a/src/pages/MyCombinationPage/MyCombinationPage.css +++ b/src/pages/MyCombinationPage/MyCombinationPage.css @@ -274,3 +274,36 @@ margin-right: 1rem; } } + +.pc-item-buttons { + display: flex; + gap: 8px; +} + +.edit-button, +.delete-button { + padding: 4px 12px; + font-size: 13px; + background-color: var(--primary-color); + border: 1px solid var(--primary-color); + border-radius: 8px; + color: white; + cursor: pointer; + transition: all 0.3s ease; +} + +.edit-button:hover, +.delete-button:hover { + background-color: var(--primary-color); + box-shadow: 0 0 0 3px var(--primary-light); + transform: translateY(-1px); +} + +.edit-button:disabled, +.delete-button:disabled { + background-color: var(--primary-light); + border-color: var(--primary-light); + cursor: not-allowed; + transform: none; + box-shadow: none; +} diff --git a/src/pages/MyCombinationPage/MyCombinationPage.jsx b/src/pages/MyCombinationPage/MyCombinationPage.jsx index 8078e365081870f12f5a99e91f4cb71ca1008c05..066e674cdd61d90c9affdddefe1cf2de519fb1d3 100644 --- a/src/pages/MyCombinationPage/MyCombinationPage.jsx +++ b/src/pages/MyCombinationPage/MyCombinationPage.jsx @@ -5,6 +5,7 @@ import { useNavigate } from "react-router-dom"; import './MyCombinationPage.css'; import PartItem from "@/components/PartItem"; import updatePCName from "@/api/my/updatePCName"; +import deletePC from "@/api/my/deletePC"; const CertifiedCombination = () => { const [pcs, setPcs] = useState([]); @@ -16,6 +17,7 @@ const CertifiedCombination = () => { const [editingName, setEditingName] = useState(""); const navigate = useNavigate(); const [isPartsLoading, setIsPartsLoading] = useState(false); + const [isDeleting, setIsDeleting] = useState(false); useEffect(() => { const fetchPCs = async () => { @@ -107,6 +109,28 @@ const CertifiedCombination = () => { setEditingName(e.target.value); }; + const handleDeleteClick = async (pcId, e) => { + e.stopPropagation(); + + if (!window.confirm('정말로 이 PC를 삭제하시겠습니까?')) { + return; + } + + setIsDeleting(true); + try { + await deletePC(pcId); + setPcs(pcs.filter(pc => pc.id !== pcId)); + if (selectedPc?.id === pcId) { + setSelectedPc(pcs.find(pc => pc.id !== pcId) || null); + } + } catch (error) { + console.error("PC 삭제 중 오류 발생:", error); + alert("PC 삭제 중 오류가 발생했습니다"); + } finally { + setIsDeleting(false); + } + }; + return ( <div className="layout"> <aside className="sidebar"> @@ -152,15 +176,24 @@ const CertifiedCombination = () => { ) : ( <div className="pc-item-content" onClick={() => handlePcClick(pc.id)}> <span>{pc.name}</span> - <button - className="edit-button" - onClick={(e) => { - e.stopPropagation(); - handleEditClick(pc); - }} - > - 수정 - </button> + <div className="pc-item-buttons"> + <button + className="edit-button" + onClick={(e) => { + e.stopPropagation(); + handleEditClick(pc); + }} + > + 수정 + </button> + <button + className="delete-button" + onClick={(e) => handleDeleteClick(pc.id, e)} + disabled={isDeleting} + > + {isDeleting ? '삭제 중...' : '삭제'} + </button> + </div> </div> )} </li>