From cbe231196e44fbe72c64330d72c00ae7f6308f30 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Tue, 20 May 2025 17:53:28 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[fix]=20=EA=B3=BC=EC=A0=9C=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pirocheck/Assignment/service/AssignmentService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java index f1ef8ef..398e662 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java @@ -14,6 +14,7 @@ import backend.pirocheck.User.entity.User; import backend.pirocheck.User.repository.UserRepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -22,6 +23,7 @@ import java.util.Map; import java.util.stream.Collectors; +@Slf4j // 로그를 찍기위해 사용 @Service @Transactional @RequiredArgsConstructor @@ -118,7 +120,9 @@ public String updateAssignment(Long assignmentId, AssignmentUpdateReq req) { } // 과제 채점 결과 저장 - public AssignmentStatus createAssignmentItem(Long assignmentId, Long userId, AssignmentItemCreateReq req) { + public AssignmentStatus createAssignmentItem(Long userId, Long assignmentId, AssignmentItemCreateReq req) { + log.info("userId 요청 값: {}", userId); + User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("조회된 사용자가 없습니다.")); From a53a7221f36b1b55dc89a076db411732a83f19c7 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Tue, 20 May 2025 18:28:39 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[feat]=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=9C=20=EC=B1=84=EC=A0=90=20=EA=B2=B0=EA=B3=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AssignmentController.java | 8 +++++--- .../dto/request/AssignmentItemUpdateReq.java | 16 ++++++++++++++++ .../Assignment/entity/AssignmentItem.java | 6 ++++++ .../repository/AssignmentItemRepository.java | 5 +++++ .../Assignment/service/AssignmentService.java | 19 +++++++++++++++++++ 5 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemUpdateReq.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java index 2759f31..042c94d 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java @@ -2,6 +2,7 @@ import backend.pirocheck.Assignment.dto.request.AssignmentCreateReq; import backend.pirocheck.Assignment.dto.request.AssignmentItemCreateReq; +import backend.pirocheck.Assignment.dto.request.AssignmentItemUpdateReq; import backend.pirocheck.Assignment.dto.request.AssignmentUpdateReq; import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; import backend.pirocheck.Assignment.entity.AssignmentStatus; @@ -119,13 +120,14 @@ public AssignmentStatus submissionAssignment( } ) @PutMapping("/admin/users/{userId}/assignments/{assignmentId}/submission") - public String updateSubmission( + public AssignmentStatus updateSubmission( @Parameter(description = "사용자 ID", example = "1") @PathVariable Long userId, @Parameter(description = "과제 ID", example = "1") - @PathVariable Long assignmentId + @PathVariable Long assignmentId, + @RequestBody AssignmentItemUpdateReq req ) { - return null; + return assignmentService.updateAssignmentItem(userId, assignmentId, req); } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemUpdateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemUpdateReq.java new file mode 100644 index 0000000..b917d54 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemUpdateReq.java @@ -0,0 +1,16 @@ +package backend.pirocheck.Assignment.dto.request; + +import backend.pirocheck.Assignment.entity.AssignmentStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Pattern; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class AssignmentItemUpdateReq { + + @Pattern(regexp = "SUCCESS/INSUFFICIENT/FAILURE", message = "status는 SUCCESS, INSUFFICIENT 혹은 FAILURE 여야 합니다.") + @Schema(description = "과제 결과", example = "SUCCESS") + private AssignmentStatus status; +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java index 74719c7..6a9dddf 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java @@ -35,4 +35,10 @@ public static AssignmentItem create(User user, Assignment assignment, Assignment .submitted(submitted) .build(); } + + public void update(AssignmentStatus submitted) { + + this.submitted = submitted; + + } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java index 1a39eec..f07c351 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java @@ -1,5 +1,6 @@ package backend.pirocheck.Assignment.repository; +import backend.pirocheck.Assignment.entity.Assignment; import backend.pirocheck.Assignment.entity.AssignmentItem; import backend.pirocheck.Assignment.entity.AssignmentStatus; import backend.pirocheck.User.entity.User; @@ -7,6 +8,7 @@ import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @Repository public interface AssignmentItemRepository extends JpaRepository { @@ -17,4 +19,7 @@ public interface AssignmentItemRepository extends JpaRepository findByUserAndAssignment(User user, Assignment assignment); + // Optional 처리로 오류 발생 check + } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java index 398e662..e589e2c 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java @@ -2,6 +2,7 @@ import backend.pirocheck.Assignment.dto.request.AssignmentCreateReq; import backend.pirocheck.Assignment.dto.request.AssignmentItemCreateReq; +import backend.pirocheck.Assignment.dto.request.AssignmentItemUpdateReq; import backend.pirocheck.Assignment.dto.request.AssignmentUpdateReq; import backend.pirocheck.Assignment.dto.response.AssignmentDayRes; import backend.pirocheck.Assignment.dto.response.AssignmentDetailRes; @@ -139,4 +140,22 @@ public AssignmentStatus createAssignmentItem(Long userId, Long assignmentId, Ass return assignmentItem.getSubmitted(); } + + // 과제 채점 결과 수정 + public AssignmentStatus updateAssignmentItem(Long userId, Long assignmentId, AssignmentItemUpdateReq req) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("조회된 사용자가 없습니다.")); + + Assignment assignment = assignmentRepository.findById(assignmentId) + .orElseThrow(() -> new IllegalArgumentException("조회된 과제가 없습니다.")); + + AssignmentItem assignmentItem = assignmentItemRepository.findByUserAndAssignment(user, assignment) + .orElseThrow(() -> new IllegalArgumentException("해당 유저의 과제 채점 결과가 없습니다.")); + + assignmentItem.update(req.getStatus()); // 상태 업데이트 + + assignmentItemRepository.save(assignmentItem); // 상태 저장 + + return assignmentItem.getSubmitted(); + } } From f1f223ec4a874e6f36f189ffe795b658b347758c Mon Sep 17 00:00:00 2001 From: dietken1 Date: Tue, 20 May 2025 21:22:17 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AdminAttendanceController.java | 52 ++++++++++++++++++- .../request/UpdateAttendanceStatusReq.java | 20 +++++++ .../dto/response/UserAttendanceStatusRes.java | 34 ++++++++++++ .../repository/AttendanceRepository.java | 3 ++ .../Attendance/service/AttendanceService.java | 41 ++++++++++++++- 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/UpdateAttendanceStatusReq.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/UserAttendanceStatusRes.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java index f811f53..5b75a14 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java @@ -1,7 +1,9 @@ package backend.pirocheck.Attendance.controller; +import backend.pirocheck.Attendance.dto.request.UpdateAttendanceStatusReq; import backend.pirocheck.Attendance.dto.response.ApiResponse; import backend.pirocheck.Attendance.dto.response.AttendanceCodeResponse; +import backend.pirocheck.Attendance.dto.response.UserAttendanceStatusRes; import backend.pirocheck.Attendance.entity.AttendanceCode; import backend.pirocheck.Attendance.service.AttendanceService; import io.swagger.v3.oas.annotations.Operation; @@ -12,8 +14,11 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.*; +import java.time.LocalDate; +import java.util.List; import java.util.Optional; @RestController @@ -79,7 +84,7 @@ public ApiResponse getActiveCode() { public ApiResponse expireAttendance( @Parameter(description = "만료할 출석 코드", required = true) @RequestParam String code) { - String result = attendanceService.exprireAttendanceCode(code); + String result = attendanceService.expireAttendanceCode(code); if (result.equals("출석 코드가 성공적으로 만료되었습니다")) { return ApiResponse.success(result, null); @@ -104,4 +109,49 @@ public ApiResponse expireLatestAttendance() { return ApiResponse.error(result); } } + + // 출석 상태 변경 (관리자 전용) + @Operation(summary = "출석 상태 변경", description = "관리자가 특정 사용자의 출석 상태를 변경합니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "출석 상태 변경 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 요청"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "출석 기록을 찾을 수 없음") + }) + @PutMapping("/status") + public ApiResponse updateAttendanceStatus( + @io.swagger.v3.oas.annotations.parameters.RequestBody( + description = "출석 상태 변경 요청", + required = true, + content = @Content(schema = @Schema(implementation = UpdateAttendanceStatusReq.class)) + ) + @RequestBody UpdateAttendanceStatusReq req) { + + boolean result = attendanceService.updateAttendanceStatus( + req.getAttendanceId(), + req.isStatus() + ); + + if (result) { + return ApiResponse.success("출석 상태가 성공적으로 변경되었습니다", null); + } else { + return ApiResponse.error("출석 상태 변경에 실패했습니다. 출석 기록을 찾을 수 없습니다."); + } + } + + // 특정 날짜와 차수에 대한 모든 학생의 출석 현황 조회 + @Operation(summary = "특정 날짜와 차수의 출석 현황 조회", description = "특정 날짜와 차수에 대한 모든 학생의 출석 현황을 조회합니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "조회 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 요청") + }) + @GetMapping("/list") + public ApiResponse> getAllAttendanceByDateAndOrder( + @Parameter(description = "조회할 날짜 (YYYY-MM-DD)", required = true) + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, + @Parameter(description = "조회할 차수", required = true) + @RequestParam int order) { + + List attendances = attendanceService.findAllByDateAndOrder(date, order); + return ApiResponse.success(attendances); + } } \ No newline at end of file diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/UpdateAttendanceStatusReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/UpdateAttendanceStatusReq.java new file mode 100644 index 0000000..2c6973c --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/UpdateAttendanceStatusReq.java @@ -0,0 +1,20 @@ +package backend.pirocheck.Attendance.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Schema(description = "출석 상태 수정 요청") +public class UpdateAttendanceStatusReq { + @Schema(description = "출석 기록 ID", example = "1") + private Long attendanceId; + + @Schema(description = "변경할 출석 상태", example = "true") + private boolean status; +} \ No newline at end of file diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/UserAttendanceStatusRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/UserAttendanceStatusRes.java new file mode 100644 index 0000000..fcb624c --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/UserAttendanceStatusRes.java @@ -0,0 +1,34 @@ +package backend.pirocheck.Attendance.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(description = "사용자 출석 상태 응답") +public class UserAttendanceStatusRes { + @Schema(description = "출석 기록 ID", example = "1") + private Long attendanceId; + + @Schema(description = "사용자 ID", example = "1") + private Long userId; + + @Schema(description = "사용자 이름", example = "홍길동") + private String username; + + @Schema(description = "출석 날짜", example = "2023-10-20") + private LocalDate date; + + @Schema(description = "출석 차수", example = "1") + private int order; + + @Schema(description = "출석 상태", example = "true") + private boolean status; +} \ No newline at end of file diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/repository/AttendanceRepository.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/repository/AttendanceRepository.java index e06f6e9..783b90b 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/repository/AttendanceRepository.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/repository/AttendanceRepository.java @@ -17,4 +17,7 @@ public interface AttendanceRepository extends JpaRepository { // 출석 실패 int countByUserAndStatusFalse(User user); + + // 특정 날짜와 차수에 대한 모든 출석 기록 조회 + List findByDateAndOrder(LocalDate date, int order); } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/service/AttendanceService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/service/AttendanceService.java index ae2d5a8..4a1adb8 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/service/AttendanceService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/service/AttendanceService.java @@ -6,6 +6,7 @@ import backend.pirocheck.Attendance.dto.response.AttendanceMarkResponse; import backend.pirocheck.Attendance.dto.response.AttendanceSlotRes; import backend.pirocheck.Attendance.dto.response.AttendanceStatusRes; +import backend.pirocheck.Attendance.dto.response.UserAttendanceStatusRes; import backend.pirocheck.Attendance.entity.Attendance; import backend.pirocheck.Attendance.entity.AttendanceCode; import backend.pirocheck.Attendance.repository.AttendanceCodeRepository; @@ -104,7 +105,7 @@ public String expireLatestAttendanceCode() { // 출석코드 만료처리 함수 @Transactional - public String exprireAttendanceCode(String code) { + public String expireAttendanceCode(String code) { Optional codeOpt = attendanceCodeRepository.findByCodeAndDate(code, LocalDate.now()); if (codeOpt.isEmpty()) { @@ -208,4 +209,42 @@ public List findByUserIdAndDate(Long userId, LocalDate date) .sorted(Comparator.comparingInt(AttendanceSlotRes::getOrder)) .toList(); } + + // 관리자가 유저의 출석 상태를 변경하는 함수 + @Transactional + public boolean updateAttendanceStatus(Long attendanceId, boolean status) { + Optional attendanceOpt = attendanceRepository.findById(attendanceId); + + if (attendanceOpt.isEmpty()) { + return false; + } + + // 출석 상태 변경 + Attendance attendance = attendanceOpt.get(); + attendance.setStatus(status); + attendanceRepository.save(attendance); + return true; + } + + // 특정 날짜와 차수의 모든 학생 출석 현황 조회 + public List findAllByDateAndOrder(LocalDate date, int order) { + // 해당 날짜와 차수에 대한 모든 출석 기록 조회 + List attendances = attendanceRepository.findByDateAndOrder(date, order); + + // 사용자별로 DTO 변환 + return attendances.stream() + .map(attendance -> { + User user = attendance.getUser(); + return UserAttendanceStatusRes.builder() + .userId(user.getId()) + .username(user.getName()) + .date(attendance.getDate()) + .order(attendance.getOrder()) + .status(attendance.isStatus()) + .attendanceId(attendance.getId()) // 출석 기록 ID 추가 + .build(); + }) + .sorted(Comparator.comparing(UserAttendanceStatusRes::getUsername)) + .toList(); + } } From 861a5e449c830f763b3e23af158918f165d3b0a4 Mon Sep 17 00:00:00 2001 From: NamKyeongMin Date: Wed, 21 May 2025 11:28:55 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[fix]:=20ManageStudent.jsx=20css=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/admin/ManageStudent.module.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/pages/admin/ManageStudent.module.css b/frontend/src/pages/admin/ManageStudent.module.css index 931680a..3a900c7 100644 --- a/frontend/src/pages/admin/ManageStudent.module.css +++ b/frontend/src/pages/admin/ManageStudent.module.css @@ -25,6 +25,9 @@ text-align: left; font-size: 16px; width: 100%; + display: flex; + align-items: center; + justify-content: space-between; } .student_button:hover { border: 1px solid #39ff14; From 296161b61417980f9c8eb838523f1e211f8a2b9d Mon Sep 17 00:00:00 2001 From: NamKyeongMin Date: Wed, 21 May 2025 12:03:19 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[add]:=20DetailManageStudent.jsx=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C,=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.jsx | 9 ++++ frontend/src/api/students.js | 10 ++++ .../src/pages/admin/DetailManageStudent.jsx | 47 +++++++++++++++++++ .../admin/DetailManageStudent.module.css | 11 +++++ frontend/src/pages/admin/ManageStudent.jsx | 8 +++- 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 frontend/src/pages/admin/DetailManageStudent.jsx create mode 100644 frontend/src/pages/admin/DetailManageStudent.module.css diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 5d442d1..5bc8878 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -6,6 +6,7 @@ import Assignment from "./pages/generation/Assignment"; import Deposit from "./pages/generation/Deposit"; import Intro from "./Intro"; import Admin from "./pages/admin/Admin"; +import DetailManageStudent from "./pages/admin/DetailManageStudent.jsx"; import ManageStudent from "./pages/admin/ManageStudent.jsx"; import ManageTask from "./pages/admin/ManageTask.jsx"; import AttendanceCode from "./pages/admin/AttendanceCode"; @@ -68,6 +69,14 @@ function App() { } /> + + + + } + /> { }); return res.data; // [{ id: ..., name: ... }] }; + +export const getStudentDetail = async (studentId) => { + try { + const res = await api.get(`/admin/managestudent/${studentId}`); + return res.data; + } catch (error) { + console.error("학생 상세 정보 불러오기 실패:", error); + throw error; + } +}; diff --git a/frontend/src/pages/admin/DetailManageStudent.jsx b/frontend/src/pages/admin/DetailManageStudent.jsx new file mode 100644 index 0000000..f932ea9 --- /dev/null +++ b/frontend/src/pages/admin/DetailManageStudent.jsx @@ -0,0 +1,47 @@ +import { useParams } from "react-router-dom"; +import { useEffect, useState } from "react"; +import Header from "../../components/Header"; +import style from "./DetailManageStudent.module.css"; +import { getStudentDetail } from "../../api/students"; + +const DetailManageStudent = () => { + const { studentId } = useParams(); + const [student, setStudent] = useState(null); + + useEffect(() => { + const fetchStudent = async () => { + try { + const data = await getStudentDetail(studentId); + setStudent(data); + } catch (err) { + console.error("학생 상세 정보 불러오기 실패:", err); + } + }; + + fetchStudent(); + }, [studentId]); + + if (!student) return
loading...
; + + return ( +
+
+
+
+

{student.name}

+

잔여 보증금: {student.deposit}원

+

보증금 방어권: {student.defence}

+
+ +
+ {student.assignmentTitles.map((title, idx) => ( + + ))} +
+
+
+ ); +}; +export default DetailManageStudent; diff --git a/frontend/src/pages/admin/DetailManageStudent.module.css b/frontend/src/pages/admin/DetailManageStudent.module.css new file mode 100644 index 0000000..86fe69d --- /dev/null +++ b/frontend/src/pages/admin/DetailManageStudent.module.css @@ -0,0 +1,11 @@ +.managestudent_wrapper { + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; +} +.under_header { + display: flex; + flex-direction: column; + align-items: center; +} diff --git a/frontend/src/pages/admin/ManageStudent.jsx b/frontend/src/pages/admin/ManageStudent.jsx index 252175f..80a02e3 100644 --- a/frontend/src/pages/admin/ManageStudent.jsx +++ b/frontend/src/pages/admin/ManageStudent.jsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; import { getStudentsByName } from "../../api/students"; import Header from "../../components/Header"; import InputBlock from "../../components/InputBlock"; @@ -8,6 +9,7 @@ const ManageStudent = () => { const [studentName, setStudentName] = useState([""]); const [page, setPage] = useState(1); const [students, setStudents] = useState([]); // 서버 데이터 저장 + const navigate = useNavigate(); const studentsPerPage = 6; @@ -54,7 +56,11 @@ const ManageStudent = () => { />
{paginatedStudents.map((student, index) => ( - ))}