Skip to content

Commit 605cef3

Browse files
authored
Merge pull request #82 from INU-Software-Design/feature/student-parent-page
fix:bug fix
2 parents d0a15fc + 2465428 commit 605cef3

5 files changed

Lines changed: 353 additions & 82 deletions

File tree

src/components/student-record/category/Attendance.test.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// __tests__/Attendance.test.tsx
2-
31
import { render, screen, waitFor, fireEvent } from "@testing-library/react";
42
import Attendance from "@/components/student-record/category/Attendance";
53
import axios from "axios";
@@ -20,7 +18,6 @@ jest.mock("@/store/selected-date-store", () => ({
2018

2119
describe("Attendance Component", () => {
2220
beforeEach(() => {
23-
// store mock 설정
2421
(useStudentFilterStore as unknown as jest.Mock).mockReturnValue({
2522
grade: 1,
2623
classNumber: 2,
@@ -40,8 +37,8 @@ describe("Attendance Component", () => {
4037
jest.clearAllMocks();
4138
});
4239

43-
it("출결 데이터를 불러오는 동안 로딩 메시지를 보여준다", async () => {
44-
(axios.get as jest.Mock).mockImplementation(() => new Promise(() => {})); // 무한 대기
40+
it("출결 데이터를 불러오는 동안 로딩 메시지를 보여준다", () => {
41+
(axios.get as jest.Mock).mockImplementation(() => new Promise(() => {}));
4542

4643
render(<Attendance />);
4744
expect(screen.getByText("출결 통계 데이터를 불러오는 중...")).toBeInTheDocument();
@@ -58,7 +55,6 @@ describe("Attendance Component", () => {
5855
});
5956

6057
it("출결 통계를 정상적으로 렌더링한다", async () => {
61-
// summary
6258
(axios.get as jest.Mock).mockImplementation((url: string) => {
6359
if (url.includes("/summary")) {
6460
return Promise.resolve({
@@ -88,11 +84,9 @@ describe("Attendance Component", () => {
8884
});
8985

9086
render(<Attendance />);
91-
await waitFor(() => {
92-
expect(screen.getByText("출석")).toBeInTheDocument();
93-
expect(screen.getByText("20")).toBeInTheDocument();
94-
expect(screen.getByDisplayValue("피드백 내용")).toBeInTheDocument();
95-
});
87+
expect(await screen.findByText("출석")).toBeInTheDocument();
88+
expect(screen.getByText("20")).toBeInTheDocument();
89+
expect(screen.getByDisplayValue("피드백 내용")).toBeInTheDocument();
9690
});
9791

9892
it("피드백이 없을 때 새 피드백을 저장한다 (POST)", async () => {
@@ -133,11 +127,15 @@ describe("Attendance Component", () => {
133127
});
134128

135129
render(<Attendance />);
136-
await waitFor(() => screen.getByText("저장"));
130+
131+
const editButton = await screen.findByText("수정");
132+
fireEvent.click(editButton);
137133

138134
const textarea = screen.getByRole("textbox");
139135
fireEvent.change(textarea, { target: { value: "새로운 피드백입니다." } });
140-
fireEvent.click(screen.getByText("저장"));
136+
137+
const saveButton = screen.getByText("저장");
138+
fireEvent.click(saveButton);
141139

142140
await waitFor(() => {
143141
expect(axios.post).toHaveBeenCalled();
@@ -177,11 +175,15 @@ describe("Attendance Component", () => {
177175
(axios.put as jest.Mock).mockResolvedValue({});
178176

179177
render(<Attendance />);
180-
await waitFor(() => screen.getByText("저장"));
178+
179+
const editButton = await screen.findByText("수정");
180+
fireEvent.click(editButton);
181181

182182
const textarea = screen.getByRole("textbox");
183183
fireEvent.change(textarea, { target: { value: "수정된 피드백" } });
184-
fireEvent.click(screen.getByText("저장"));
184+
185+
const saveButton = screen.getByText("저장");
186+
fireEvent.click(saveButton);
185187

186188
await waitFor(() => {
187189
expect(axios.put).toHaveBeenCalled();

src/components/student-record/category/Attendance.tsx

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export default function Attendance() {
2424
const [feedback, setFeedback] = useState("");
2525
const [feedbackId, setFeedbackId] = useState("");
2626
const [saveMessage, setSaveMessage] = useState("");
27+
const [isEditing, setIsEditing] = useState(false);
2728

2829
const token = localStorage.getItem("accessToken");
2930

@@ -62,9 +63,9 @@ export default function Attendance() {
6263
setFeedbackId(data.feedbackId);
6364
} catch (err) {
6465
console.error("출결 피드백 조회 에러:", err);
65-
setFeedback(""); // 피드백 초기화
66-
setFeedbackId(""); // 피드백 ID 초기화
67-
setSaveMessage(""); // ✅ 이전 저장 메시지 제거
66+
setFeedback("");
67+
setFeedbackId("");
68+
setSaveMessage("");
6869
}
6970
};
7071
getAttendancesFeedback();
@@ -99,22 +100,27 @@ export default function Attendance() {
99100
headers: { Authorization: `Bearer ${token}` },
100101
}
101102
);
102-
const data = res.data;
103-
console.log("put feedback:", data);
103+
console.log(res);
104104
setSaveMessage("피드백이 수정되었습니다.");
105105
} catch (err) {
106106
console.error("출결 피드백 수정 에러:", err);
107107
setSaveMessage("피드백 수정 중 오류가 발생했습니다.");
108108
}
109109
};
110110

111-
const handleSaveFeedback = () => {
112-
setSaveMessage(""); // 메시지 초기화
111+
const handleEditClick = () => {
112+
setIsEditing(true);
113+
setSaveMessage("");
114+
};
115+
116+
const handleSaveClick = () => {
117+
setSaveMessage("");
113118
if (feedbackId) {
114119
putAttendancesFeedback();
115120
} else {
116121
postAttendancesFeedback();
117122
}
123+
setIsEditing(false);
118124
};
119125

120126
const attendanceHeaders = [
@@ -157,10 +163,18 @@ export default function Attendance() {
157163

158164
<div className="flex flex-col mx-4 mt-4">
159165
<span className="mb-2 font-semibold">출결 피드백</span>
160-
<textarea className="border h-48 border-[#a9a9a9] rounded-md p-2 resize-none" value={feedback} onChange={(e) => setFeedback(e.target.value)} />
161-
<button className="mt-2 self-end bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" onClick={handleSaveFeedback}>
162-
저장
163-
</button>
166+
<textarea className="border h-48 border-[#a9a9a9] rounded-md p-2 resize-none" value={feedback} onChange={(e) => setFeedback(e.target.value)} disabled={!isEditing} />
167+
<div className="mt-2 self-end">
168+
{!isEditing ? (
169+
<button className="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600" onClick={handleEditClick}>
170+
수정
171+
</button>
172+
) : (
173+
<button className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" onClick={handleSaveClick}>
174+
저장
175+
</button>
176+
)}
177+
</div>
164178
{saveMessage && <p className="text-sm text-green-600 mt-1 self-end">{saveMessage}</p>}
165179
</div>
166180
</div>

0 commit comments

Comments
 (0)