Skip to content

Commit 13267ae

Browse files
committed
feat : 게시글 수정 관련 코드 작성
- 게시글 수정 버튼을 클릭하면, state의 mode를 변경하는 방식으로 설정.같은 /posting 경로에서 State를 create모드와 modify 모드로 분리. - 게시글 수정 시 postId를 기반으로 postData를 호출해오는 API 함수 getPostById 작성 -Posting.jsx 에서 게시글을 수정하는 useEffect작성 ref : #18
1 parent a7ade43 commit 13267ae

File tree

5 files changed

+117
-47
lines changed

5 files changed

+117
-47
lines changed

src/api/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
signupCEOAPI,
66
} from "./signupAPI";
77
import { loginAPI } from "./loginAPI";
8-
import{ postJobPosting, updateJobPosting } from "./postingAPI";
8+
import{ postJobPosting, updateJobPosting, getPostById } from "./postingAPI";
99
import { postListAPI, searchPostListAPI } from "./homeAPI";
1010

1111
export {
@@ -16,6 +16,7 @@ export {
1616
loginAPI, // 로그인 API
1717
postJobPosting, //모집글 작성 API
1818
updateJobPosting, //모집글 수정 API
19+
getPostById, // 모집글 수정시 postData 불러오기 API
1920
postListAPI, // 알바리스트 불러오기(홈) API
2021
searchPostListAPI, // 알바리스트 불러오기 (검색) API
2122
};

src/api/postingAPI.js

+22-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import axios from "axios";
12
import { privateAxios } from "../utils/customAxios";
23

34
/*---- 게시글 등록 ----*/
@@ -9,8 +10,7 @@ export const postJobPosting = async (accessToken, payload) => {
910
};
1011

1112
try {
12-
const result = await privateAxios(accessToken).patch("/api/v1/post", payload);
13-
13+
const result = await privateAxios(accessToken).post("/api/v1/post", payload); // POST로 변경
1414
if (result.status === 200) {
1515
response.isSuccess = true;
1616
response.message = result.data.message;
@@ -19,18 +19,17 @@ export const postJobPosting = async (accessToken, payload) => {
1919
} catch (err) {
2020
response.isSuccess = false;
2121
response.message = err.response?.data?.message || err.message;
22-
22+
2323
if (err.response?.status === 401) {
2424
alert("인증이 필요합니다. 다시 로그인해주세요.");
2525
}
26-
2726
}
2827

2928
return response;
3029
};
3130

32-
// /*---- 게시글 수정 ----*/
33-
export const updateJobPosting = async (accessToken, postId, postData) => {
31+
/*---- 게시글 수정 ----*/
32+
export const updateJobPosting = async (accessToken, postId, postData, userId) => {
3433
const response = {
3534
isSuccess: false,
3635
message: "",
@@ -39,11 +38,11 @@ export const updateJobPosting = async (accessToken, postId, postData) => {
3938

4039
try {
4140
const body = {
42-
postId,
41+
postId,
4342
userId,
4443
storeName: "", // 수정 불가
4544
workPlaceAddress: "", // 수정 불가
46-
postData, // 수정 가능한 postData만 포함
45+
postData,
4746
};
4847

4948
const result = await privateAxios(accessToken).patch(`/api/v1/post/${postId}`, body);
@@ -59,4 +58,19 @@ export const updateJobPosting = async (accessToken, postId, postData) => {
5958
}
6059

6160
return response;
61+
};
62+
63+
/*---- 게시글 데이터 호출 ----*/
64+
export const getPostById = async (postId, accessToken) => {
65+
try {
66+
const response = await axios.get(`http://43.203.223.82:8080/api/v1/post/${postId}`, {
67+
headers: {
68+
Authorization: `Bearer ${accessToken}`,
69+
},
70+
});
71+
return response.data;
72+
} catch (error) {
73+
console.error("Error fetching post data:", error);
74+
throw error;
75+
}
6276
};

src/components/ButtonsModal.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ const ButtonsModal = ({ isMode, setIsMode, postId }) => {
4545
//게시글 수정
4646
const modifyPosts = () => {
4747
if (confirm("해당 게시글을 수정하시겠습니까?")) {
48-
navigate(`/modify`, {
48+
navigate("/posting", {
4949
state: {
5050
postId: postId,
5151
mode: "modify", // 수정 모드 전달
5252
},
5353
});
5454
}
55-
};
55+
};
5656

5757
// 게시글 삭제
5858
const deletePosts = () => {

src/pages/recruitment/Posting.jsx

+62-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
import React, { useState } from "react";
1+
import React, { useState, useEffect } from "react";
22
import { PageContainer, ContentContainer, FixedButtonContainer } from "../../styles/posting/PostingStyles";
33
import { InputField, Tag, Toggle, WeekdayPicker, WorkTimePicker, PayPicker, AddressInput, PhotoUpload, DescriptionInput, PhoneInput, Button } from "../../components";
44
import "../../styles/posting/Posting.css";
55
import { POSTING_UPMU_TAG } from "../../constants";
6-
import { postJobPosting, updateJobPosting } from "../../api";
6+
import { postJobPosting, updateJobPosting, getPostById } from "../../api";
77
import { useNavigate, useLocation } from "react-router-dom";
88
import { useSelector } from "react-redux";
9-
import getAccessToken from "../../utils/getAccessToken"; // 일반 함수로 가져오기
9+
import getAccessToken from "../../utils/getAccessToken"; // 일반 함수로 가져와야 오류 안뜸!!
1010
import { createPayload } from "../../utils/posting/payloadHelper"; // 분리된 payload 생성 함수
1111
import { validateForm } from "../../utils/posting/validationHelper"; // 분리된 유효성 검증 함수
1212
import { parseAddress, convertDays } from "../../utils/posting/formatHelper"; // 분리된 주소 및 요일 변환 함수
1313

1414
const Posting = () => {
1515
const state = useSelector((state) => state);
1616
const accessToken = getAccessToken(state);
17+
const location = useLocation();
18+
const navigate = useNavigate();
19+
const userId = useSelector((state) => state.userInfo.userId);
20+
const { mode, postId } = location.state || { mode: "create", postId: null };
21+
1722
const [isOptionSelected, setIsOptionSelected] = useState(false);
1823
const [validStates, setValidStates] = useState({
1924
title: true,
@@ -36,12 +41,6 @@ const Posting = () => {
3641
workPeriod: "1개월 이상"
3742
});
3843

39-
const location = useLocation();
40-
const navigate = useNavigate();
41-
const mode = location.state?.mode || "create";
42-
const postId = location.state?.postId || null;
43-
const userId = useSelector((state) => state.userInfo.userId);
44-
4544
const handleChange = (key, value) => {
4645
setFormData((prev) => ({ ...prev, [key]: value }));
4746
};
@@ -59,6 +58,59 @@ const Posting = () => {
5958
handleChange("selectedOption", value);
6059
setIsOptionSelected(true);
6160
};
61+
// 게시글 수정 useEffect
62+
useEffect(() => {
63+
if (mode === "modify" && postId) {
64+
// 수정 모드에서 데이터 가져오기
65+
fetchPostData(postId);
66+
}
67+
}, [mode, postId]);
68+
69+
const fetchPostData = async (postId) => {
70+
try {
71+
const postData = await getPostById(postId, accessToken);
72+
populateFormData(postData); // 폼 데이터 초기화
73+
} catch (error) {
74+
alert("게시글 데이터를 불러오는 데 실패했습니다.");
75+
}
76+
};
77+
78+
const populateFormData = (postData) => {
79+
const {
80+
title,
81+
workType,
82+
pay,
83+
payType,
84+
workStartHour,
85+
workStartMinute,
86+
workEndHour,
87+
workEndTimeMinute,
88+
isNegotiable,
89+
applyNumber,
90+
workDays,
91+
content,
92+
doName,
93+
siName,
94+
detailName,
95+
} = postData.postData;
96+
97+
setFormData({
98+
...formData,
99+
title,
100+
workTags: [workType],
101+
workDays,
102+
workTime: {
103+
start: `${workStartHour}:${workStartMinute.toString().padStart(2, "0")}`,
104+
end: `${workEndHour}:${workEndTimeMinute.toString().padStart(2, "0")}`,
105+
},
106+
pay,
107+
payType,
108+
isNegotiable,
109+
applyNumber,
110+
description: content,
111+
workLocation: `${doName} ${siName} ${detailName}`, // 주소 결합
112+
});
113+
};
62114

63115
const handleSubmit = async () => {
64116
const allValid = Object.values(validStates).every((isValid) => isValid);
@@ -95,7 +147,7 @@ const Posting = () => {
95147
return (
96148
<PageContainer>
97149
<ContentContainer>
98-
<div className="header">어떤 알바를 구하고 계신가요?</div>
150+
<div className="header">{mode === "modify" ? "게시글 수정" : "어떤 알바를 구하고 계신가요?"}</div>
99151
<div className="toggle-section">
100152
<Toggle
101153
options={["업무 목적"]}

src/utils/posting/validationHelper.js

+29-26
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
// utils/validationHelper.js
22
export const validateForm = (payload, formData) => {
3-
const requiredFields = {
4-
"제목": payload.postData.title,
5-
"하는 일": payload.postData.workType,
6-
"일하는 기간": formData.workPeriod,
7-
"일하는 요일": formData.workDays,
8-
"일하는 시간": formData.workTime?.start && formData.workTime?.end,
9-
"급여": formData.pay,
10-
"일하는 장소": formData.workLocation,
11-
"업체명": payload.storeName,
12-
"연락처": payload.postData.applyNumber,
13-
};
14-
15-
for (const [label, value] of Object.entries(requiredFields)) {
16-
if (
17-
value === undefined ||
18-
value === null ||
19-
(typeof value === "string" && value.trim() === "") ||
20-
(Array.isArray(value) && value.length === 0) ||
21-
value === false
22-
) {
23-
alert(`${label}을(를) 입력해주세요.`);
24-
return false;
25-
}
26-
}
27-
return true;
28-
};
3+
const requiredFields = {
4+
"제목": payload.postData.title,
5+
"하는 일": payload.postData.workType,
6+
"일하는 기간": formData.workPeriod,
7+
"일하는 요일": formData.workDays,
8+
"일하는 시간": formData.workTime?.start && formData.workTime?.end,
9+
"급여": formData.pay,
10+
"일하는 장소": formData.workLocation,
11+
"업체명": payload.storeName,
12+
"연락처": payload.postData.applyNumber,
13+
};
14+
15+
const missingFields = Object.entries(requiredFields)
16+
.filter(([_, value]) =>
17+
value === undefined ||
18+
value === null ||
19+
(typeof value === "string" && value.trim() === "") ||
20+
(Array.isArray(value) && value.length === 0) ||
21+
value === false
22+
)
23+
.map(([label]) => label);
24+
25+
if (missingFields.length > 0) {
26+
alert(`다음 항목을 입력해주세요: ${missingFields.join(", ")}`);
27+
return false; // 유효성 검증 실패
28+
}
29+
30+
return true; // 유효성 검증 성공
31+
};

0 commit comments

Comments
 (0)