Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bafeed5
Merge pull request #141 from pirogramming/main
qkrxogmla May 21, 2025
8328505
[Fix]merge& adminassignment 연결
Imggaggu May 21, 2025
28df930
Merge pull request #143 from pirogramming/frontend_admin_sj
Imggaggu May 21, 2025
4177928
Merge pull request #144 from pirogramming/main
NamKyeongMin May 21, 2025
7d7fe68
[Fix] AdminStudentAssignment.jsx
Imggaggu May 21, 2025
24847b2
Merge pull request #146 from pirogramming/main
NamKyeongMin May 21, 2025
135faeb
Update vite.config.js
Imggaggu May 21, 2025
d1fb9ec
Update vite.config.js
Imggaggu May 21, 2025
5a7c2e0
Update assignment.js
Imggaggu May 21, 2025
bfc0996
Merge pull request #149 from pirogramming/main
qkrxogmla May 21, 2025
30b5a0f
[fix]: DetailManageStudent error fix
NamKyeongMin May 21, 2025
655bc4a
Merge pull request #150 from pirogramming/frontend_km
NamKyeongMin May 21, 2025
e12c0a9
Merge pull request #152 from pirogramming/main
qkrxogmla May 21, 2025
0357077
Merge pull request #153 from pirogramming/backend_sj
seonjuuu May 21, 2025
ba00de9
Merge pull request #155 from pirogramming/main
qkrxogmla May 21, 2025
73d5b14
[add]: detailstudentmanage - 출석관리 btn + 과제 btn
NamKyeongMin May 21, 2025
f8be044
Merge pull request #156 from pirogramming/frontend_km
NamKyeongMin May 21, 2025
5fc48e6
[fix]: Attendance.jsx api 수정
NamKyeongMin May 21, 2025
cf4c580
Merge pull request #157 from pirogramming/frontend_km
NamKyeongMin May 21, 2025
5d2ea51
Merge pull request #159 from pirogramming/backend_sj
seonjuuu May 21, 2025
04bd57a
[fix]: detailstudentmanage 출석/과제 버튼 로직 수정
NamKyeongMin May 21, 2025
a5c9d11
[add]: 버튼 조건부 렌더링 추가
NamKyeongMin May 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@

import backend.pirocheck.Deposit.dto.DepositResDto;
import backend.pirocheck.Deposit.service.DepositService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "보증금 관리", description = "수강생 보증금/차감/방어권 관련 API")
@RestController
@RequestMapping("/api/deposit")
@RequiredArgsConstructor
public class DepositController {

private final DepositService depositService;

@Operation(summary = "보증금 조회", description = "해당 유저의 현재 보증금, 차감 내역, 방어권 금액을 반환합니다.")
@GetMapping("/{userId}")
public DepositResDto getDeposit(@PathVariable Long userId) {
return depositService.getDeposit(userId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package backend.pirocheck.Deposit.dto;


import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -11,9 +12,16 @@
@NoArgsConstructor
@AllArgsConstructor
public class DepositResDto {
@Schema(description = "현재 보증금 잔액", example = "110000")
private int amount;

@Schema(description = "과제 차감 총액", example = "10000")
private int descentAssignment;

@Schema(description = "출석 차감 총액", example = "10000")
private int descentAttendance;

@Schema(description = "방어권 보상 총액", example = "10000")
private int ascentDefence;

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ public void updateAmounts(int descentAssignment, int descentAttendance, int asce
this.ascentDefence = ascentDefence;

int calculateAmount = 120000 - descentAssignment - descentAttendance + ascentDefence;
this.amount = Math.min(calculateAmount, 120000); // 12만원 넘어가지 않도록
this.amount = Math.max(0, Math.min(calculateAmount, 120000)); // 0 이상 12만원 이하
}

// 방어권 업데이트
public void updateDefence(int newAscentDefence) {
this.ascentDefence = newAscentDefence;
int calculateAmount = 120000 - this.descentAssignment - this.descentAttendance + newAscentDefence;
this.amount = Math.min(calculateAmount, 120000);
this.amount = Math.max(0, Math.min(calculateAmount, 120000)); // 0 이상 12만원 이하

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
import backend.pirocheck.ManageStudents.dto.response.ManageStudentDetailResDto;
import backend.pirocheck.ManageStudents.dto.response.ManageStudentsListResDto;
import backend.pirocheck.ManageStudents.service.ManageStudentsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "수강생 관리", description = "관리자가 수강생을 조회하고 방어권을 수정하는 API")
@RestController
@RequestMapping("/api/admin/managestudent")
@RequiredArgsConstructor
Expand All @@ -17,18 +20,21 @@ public class ManageStudentsController {
private final ManageStudentsService manageStudentsService;

// 수강생 리스트 조회
@Operation(summary = "수강생 리스트 조회", description = "이름에 따라 수강생 리스트를 검색합니다.")
@GetMapping("")
public List<ManageStudentsListResDto> getStudents(@RequestParam(required = false) String name) {
return manageStudentsService.searchMembers(name);
}

// 수강생 상세 조회
@Operation(summary = "수강생 상세 조회", description = "studentId로 해당 수강생의 보증금, 방어권, 과제 정보를 조회합니다.")
@GetMapping("/{studentId}")
public ManageStudentDetailResDto getStudentDetail(@PathVariable Long studentId) {
return manageStudentsService.getMemberDetail(studentId);
}

// 방어권 업데이트
@Operation(summary = "방어권 수정", description = "studentId에 해당하는 수강생의 보증금 방어권 금액을 수정합니다.")
@PatchMapping("/{studentId}/defence")
public void updateDefence(@PathVariable Long studentId, @RequestBody DefenceUpdateReqDto req) {
manageStudentsService.updateDefence(studentId, req.getDefence());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package backend.pirocheck.ManageStudents.dto.request;


import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class DefenceUpdateReqDto {

@Schema(description = "방어권 금액", example = "20000")
private int defence;

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package backend.pirocheck.ManageStudents.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;

Expand All @@ -9,8 +10,15 @@
@Builder
public class ManageStudentDetailResDto {

@Schema(description = "수강생 이름", example = "김피로")
private String name;

@Schema(description = "현재 보증금 잔액", example = "11000")
private int deposit;

@Schema(description = "방어권 금액", example = "10000")
private int defence; // 방어권

@Schema(description = "과제 제목 리스트", example = "[\"제로초 인강\", \"토스 클론\"]")
private List<String> assignmentTitles; // 과제 제목 리스트
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import backend.pirocheck.User.entity.Role;
import backend.pirocheck.User.entity.User;
import backend.pirocheck.User.repository.UserRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

Expand Down Expand Up @@ -41,6 +42,7 @@ public List<ManageStudentsListResDto> searchMembers(String name) {
}

// 수강생 상세 조회
@Transactional
public ManageStudentDetailResDto getMemberDetail(Long studentId) {
// User 조회
User user = userRepository.findById(studentId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@
import backend.pirocheck.User.entity.User;
import backend.pirocheck.User.repository.UserRepository;
import backend.pirocheck.User.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "유저 인증", description = "로그인 / 로그아웃 API")
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
Expand All @@ -22,8 +26,9 @@ public class UserController {
private final UserService userService;

// 로그인
@Operation(summary = "로그인", description = "사용자 이름과 비밀번호로 로그인하고 세션을 생성합니다.")
@PostMapping("/login")
public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request, HttpSession session) {
public ResponseEntity<LoginResponse> login(@RequestBody @Valid LoginRequest request, HttpSession session) {
User user = userService.login(request.getName(), request.getPassword());

//세션에 로그인 정보 저장
Expand All @@ -34,6 +39,7 @@ public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request, Ht
}

// 로그아웃
@Operation(summary = "로그아웃", description = "세션을 종료하여 로그아웃합니다.")
@PostMapping("/logout")
public ResponseEntity<Void> logout(HttpSession session) {
session.invalidate(); // 세션 종료 (메모리에서 삭제)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package backend.pirocheck.User.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class LoginRequest {

@Schema(description = "사용자 이름", example = "김피로")
@NotBlank(message = "이름을 입력해주세요.")
private String name;

@Schema(description = "비밀번호", example = "qwer1234!")
@NotBlank(message = "비밀번호를 입력해주세요.")
private String password;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@


import backend.pirocheck.User.entity.User;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

@Getter
public class LoginResponse {

@Schema(description = "유저 고유 ID", example = "1")
private Long id;

@Schema(description = "유저 이름", example = "김피로")
private String name;

@Schema(description = "유저 권한", example = "MEMBER")
private String role;

public LoginResponse(User user) {
Expand Down
24 changes: 8 additions & 16 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,16 @@ import ManageTask from "./pages/admin/ManageTask.jsx";
import AttendanceCode from "./pages/admin/AttendanceCode";
import Attendance from "./pages/generation/Attendance";
import AdminStudentAttendance from "./pages/admin/AdminStudentAttendance";
<<<<<<< HEAD
import AdminStudentAssignment from "./pages/admin/AdminStudentAssignment.jsx";
=======
import RequireAuth from "./components/RequireAuth";
import RequireAdmin from "./components/RequireAdmin";

>>>>>>> 08242a5045ea08b68c40b107cc871f8b3c3446eb
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Intro />} />
<Route path="/login" element={<Login />} />
<<<<<<< HEAD
<Route path="/home" element={<Home />} />
<Route path="/assignment" element={<Assignment />} />
<Route path="/attendance" element={<Attendance />} />
<Route path="/deposit" element={<Deposit />} />
<Route path="/admin" element={<Admin />} />
<Route path="/magagestudent" element={<MagageStudent />} />
<Route path="/magagetask" element={<ManageTask />} />
<Route path="/attendancecode" element={<AttendanceCode />} />
<Route path="/admin/attendance/:studentId" element={<AdminStudentAttendance />} />
<Route path="/admin/managestudent/:studentId" element={<AdminStudentAssignment />} />
=======
<Route
path="/home"
element={
Expand Down Expand Up @@ -117,7 +102,14 @@ function App() {
</RequireAdmin>
}
/>
>>>>>>> 08242a5045ea08b68c40b107cc871f8b3c3446eb
<Route
path="/admin/assignment/:studentId"
element={
<RequireAdmin>
<AdminStudentAssignment />
</RequireAdmin>
}
/>
</Routes>
</BrowserRouter>
);
Expand Down
19 changes: 17 additions & 2 deletions frontend/src/api/assignment.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,25 @@ export const fetchAssignmentsByUser = async (userId) => {
*/
export const fetchAssignmentsByUser = async (userId) => {
try {
const res = await api.get(`/api/assignment/${userId}`);
const res = await api.get(`/assignment/${userId}`);
return res.data; // 백엔드가 반환하는 JSON 그대로
} catch (err) {
console.error("과제 데이터 불러오기 실패:", err);
throw err;
}
};
};


export const submitAssignmentStatus = async (userId, assignmentId, status) => {
return api.post(`/admin/users/${userId}/assignments/${assignmentId}/submission`, {
assignmentId,
userId,
status,
});
};

export const updateAssignmentStatus = async (userId, assignmentId, status) => {
return api.put(`/admin/users/${userId}/assignments/${assignmentId}/submission`, {
status,
});
};
27 changes: 24 additions & 3 deletions frontend/src/pages/admin/AdminStudentAssignment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import WeeklyOpenBlock from "../../components/WeeklyOpenBlock";
import AssignmentInfoBlock from "../../components/AssignmentInfoBlock";
import api from "../../api/api";
import styles from "./AdminStudentAssignment.module.css";
import { submitAssignmentStatus, updateAssignmentStatus } from "../../api/assignment";

const AdminStudentAssignment = () => {
const { studentId, week } = useParams();
Expand All @@ -14,7 +15,7 @@ const AdminStudentAssignment = () => {
const [selectedWeekLabel, setSelectedWeekLabel] = useState(null);

useEffect(() => {
api.get(`/admin/users/${studentId}`).then((res) => {
api.get(`/admin/users/${userId}`).then((res) => {
setStudentInfo(res.data.data);
});

Expand Down Expand Up @@ -62,13 +63,33 @@ const AdminStudentAssignment = () => {
task.modified = true;
setWeeks(updated);
};

/*
const handleSave = async (taskId, status) => {
await api.put("/admin/assignment/status", {
assignmentId: taskId,
status,
});
};
*/
const handleSave = async (taskId, status) => {
const userId = parseInt(studentId); // 문자열일 수 있으니 숫자로 변환

try {
// PUT 요청 시도 (기존 과제 수정)
await updateAssignmentStatus(userId, taskId, status);
alert("과제 상태가 수정되었습니다.");
} catch (err) {
console.warn("PUT 실패, POST 시도");
try {
// 없으면 POST 요청 (새 과제 등록)
await submitAssignmentStatus(userId, taskId, status);
alert("과제 상태가 등록되었습니다.");
} catch (err) {
alert("상태 저장 실패");
console.error(err);
}
}
};

return (
<div className={styles.container}>
Expand Down Expand Up @@ -122,4 +143,4 @@ const AdminStudentAssignment = () => {
);
};

export default AdminStudentAssignment;
export default AdminStudentAssignment;
Loading