From dcf7b4ff8a445ed704136e415dde6581a16a7a87 Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Sun, 11 May 2025 22:31:55 +0900 Subject: [PATCH 01/33] [Deploy] Run jar on EC2 --- .github/workflows/deploy.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f0b620f..2ef3e69 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -40,7 +40,14 @@ jobs: - name: Copy JAR to EC2 run: | scp -o StrictHostKeyChecking=no -i pirocheck.pem backend/pirocheck/build/libs/*.jar ubuntu@${{ secrets.EC2_HOST }}:/home/ubuntu/ + + - name: Run jar on EC2 + run: | + ssh -o StrictHostKeyChecking=no -i pirocheck.pem \ + ubuntu@${{ secrets.EC2_HOST }} \ + "fuser -k 8080/tcp || true && nohup java -jar pirocheck-0.0.1-SNAPSHOT.jar > log.txt 2>&1 &" + - name: Restart Spring Boot on EC2 run: | ssh -o StrictHostKeyChecking=no -i pirocheck.pem ubuntu@${{ secrets.EC2_HOST }} 'bash ~/restart.sh' @@ -106,4 +113,4 @@ jobs: AWS_S3_BUCKET: www.pirocheck.org AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - SOURCE_DIR: frontend/dist \ No newline at end of file + SOURCE_DIR: frontend/dist From a65944631427da6effadf53474df77db424018fc Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Sun, 11 May 2025 23:17:08 +0900 Subject: [PATCH 02/33] =?UTF-8?q?=EB=B3=B4=EC=A6=9D=EA=B8=88=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20withCredentials:=20true=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Deposit.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/Deposit.jsx b/frontend/src/Deposit.jsx index ce2198c..500de27 100644 --- a/frontend/src/Deposit.jsx +++ b/frontend/src/Deposit.jsx @@ -5,6 +5,7 @@ import { useEffect, useState } from "react"; const Deposit = () => { const [deposit, setDeposit] = useState(null); + useEffect(() => { const user = JSON.parse(localStorage.getItem("user")); const userId = user?.id; @@ -12,7 +13,9 @@ const Deposit = () => { if (!userId) return; axios - .get(`/api/deposit/${userId}`) + .get(`/api/deposit/${userId}`, { + withCredentials: true, // 세션 쿠키 포함 + }) .then((res) => setDeposit(res.data)) .catch((err) => { alert("보증금 정보를 불러오지 못했습니다."); From b9a2515429b7efacfe4d28a971af33cea5fed4d6 Mon Sep 17 00:00:00 2001 From: Imggaggu Date: Sun, 11 May 2025 23:18:39 +0900 Subject: [PATCH 03/33] [Fix] add credential true --- frontend/src/api/assignment.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/api/assignment.js b/frontend/src/api/assignment.js index 4102105..a576b62 100644 --- a/frontend/src/api/assignment.js +++ b/frontend/src/api/assignment.js @@ -1,5 +1,8 @@ import axios from "axios"; export const fetchAssignmentsByUser = async (userId) => { - const res = await axios.get(`/api/assignment/grouped/${userId}`); return res.data; + const res = await axios.get(`/api/assignment/grouped/${userId}`, { + withCredentials: true + }); + return res.data; }; From 15045de01380f7c3cc2e127992cbeb1e3412f0e8 Mon Sep 17 00:00:00 2001 From: NamKyeongMin Date: Sun, 11 May 2025 23:23:22 +0900 Subject: [PATCH 04/33] =?UTF-8?q?[add]:=20Attendance.jsx=20=EC=84=B8?= =?UTF-8?q?=EC=85=98=20=EA=B8=B0=EB=B0=98=20=EC=9D=B8=EC=A6=9D=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Attendance.jsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/frontend/src/Attendance.jsx b/frontend/src/Attendance.jsx index cff814f..1abe9db 100644 --- a/frontend/src/Attendance.jsx +++ b/frontend/src/Attendance.jsx @@ -90,6 +90,7 @@ const Attendance = () => { // 유저 전체 출석 데이터 불러오기 const res = await axios.get(`/api/attendance/user`, { params: { userId }, + withCredentials: true, // 세션 기반 인증 요청처리 }); const rawData = res.data.data; const weekly = processWeeklyAttendance(rawData); @@ -109,6 +110,7 @@ const Attendance = () => { const today = new Date().toISOString().split("T")[0]; // YYYY-MM-DD const res = await axios.get(`/api/attendance/user/date`, { params: { userId, date: today }, + withCredentials: true, // 세션 기반 인증 요청처리 }); const slots = res.data.data?.[0]?.slots || []; @@ -149,10 +151,16 @@ const Attendance = () => { if (!userId) return; // 유저가 입력한 출석 코드 서버에 전달(서버에서 출석코드 체크) - const res = await axios.post("/api/attendance/mark", { - userId, - code: attendanceCode[0], - }); + const res = await axios.post( + "/api/attendance/mark", + { + userId, + code: attendanceCode[0], + }, + { + withCredentials: true, // 세션 기반 인증 요청처리 + } + ); if (res.data.success) { alert("출석이 성공적으로 처리되었습니다!"); From ad78ca4646c86f7c478e83a5541259ea481a4921 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Sun, 11 May 2025 23:31:10 +0900 Subject: [PATCH 05/33] =?UTF-8?q?=EC=A0=84=EC=97=AD=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=84=B8=EC=85=98=EB=A7=8C=EB=A3=8C=EC=8B=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Deposit.jsx | 7 +++---- frontend/src/api/api.js | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 frontend/src/api/api.js diff --git a/frontend/src/Deposit.jsx b/frontend/src/Deposit.jsx index 500de27..3a84615 100644 --- a/frontend/src/Deposit.jsx +++ b/frontend/src/Deposit.jsx @@ -2,6 +2,7 @@ import Header from "./components/Header"; import styles from "./Deposit.module.css"; import axios from "axios"; import { useEffect, useState } from "react"; +import api from "./api/api"; const Deposit = () => { const [deposit, setDeposit] = useState(null); @@ -12,10 +13,8 @@ const Deposit = () => { if (!userId) return; - axios - .get(`/api/deposit/${userId}`, { - withCredentials: true, // 세션 쿠키 포함 - }) + api + .get(`/deposit/${userId}`) .then((res) => setDeposit(res.data)) .catch((err) => { alert("보증금 정보를 불러오지 못했습니다."); diff --git a/frontend/src/api/api.js b/frontend/src/api/api.js new file mode 100644 index 0000000..814c063 --- /dev/null +++ b/frontend/src/api/api.js @@ -0,0 +1,19 @@ +import axios from "axios"; + +const api = axios.create({ + baseURL: "/api", + withCredentials: true, +}); + +// 401 오류 시 로그인 페이지로 리다이렉트 +api.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 401) { + window.location.href = "/login"; + } + return Promise.reject(error); + } +); + +export default api; From e112d19e07e0e4f953446d6c44d437ba357c33c1 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Sun, 11 May 2025 23:41:42 +0900 Subject: [PATCH 06/33] =?UTF-8?q?fetch=20=EC=A0=88=EB=8C=80=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/api/user.js b/frontend/src/api/user.js index 3964bac..749dc0a 100644 --- a/frontend/src/api/user.js +++ b/frontend/src/api/user.js @@ -1,5 +1,5 @@ export const loginUser = async ({ name, password }) => { - const res = await fetch("/api/login", { + const res = await fetch("http://www.pirocheck.org/login/login", { method: "POST", headers: { "Content-Type": "application/json", From 70c865e34b6435132717c5594649fad1ea999548 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Sun, 11 May 2025 23:55:09 +0900 Subject: [PATCH 07/33] =?UTF-8?q?fetch=20usesr=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Attendance.jsx | 4 ++-- frontend/src/api/user.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/Attendance.jsx b/frontend/src/Attendance.jsx index 1abe9db..66c2da3 100644 --- a/frontend/src/Attendance.jsx +++ b/frontend/src/Attendance.jsx @@ -3,7 +3,7 @@ import Header from "./components/Header"; import InputBlock from "./components/InputBlock"; import AttendanceWeekInfo from "./components/AttendanceWeekInfo"; import styles from "./Attendance.module.css"; -import axios from "axios"; +import api from "./api/api"; const Attendance = () => { const [attendanceCode, setAttendanceCode] = useState([""]); @@ -88,7 +88,7 @@ const Attendance = () => { if (!userId) return; // 유저 전체 출석 데이터 불러오기 - const res = await axios.get(`/api/attendance/user`, { + const res = await api.get(`/attendance/user`, { params: { userId }, withCredentials: true, // 세션 기반 인증 요청처리 }); diff --git a/frontend/src/api/user.js b/frontend/src/api/user.js index 749dc0a..f91670c 100644 --- a/frontend/src/api/user.js +++ b/frontend/src/api/user.js @@ -1,5 +1,5 @@ export const loginUser = async ({ name, password }) => { - const res = await fetch("http://www.pirocheck.org/login/login", { + const res = await fetch("http://www.pirocheck.org/api/login", { method: "POST", headers: { "Content-Type": "application/json", From 5c15ca1ce4624f4fc8c474bb7886ba35a5a544b5 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Mon, 12 May 2025 00:07:36 +0900 Subject: [PATCH 08/33] =?UTF-8?q?=EC=84=B8=EC=85=98=EB=A7=8C=EB=A3=8C?= =?UTF-8?q?=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Assignment.jsx | 24 ++++++++++++------------ frontend/src/api/assignment.js | 6 ++---- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/frontend/src/Assignment.jsx b/frontend/src/Assignment.jsx index cff140f..f24604a 100644 --- a/frontend/src/Assignment.jsx +++ b/frontend/src/Assignment.jsx @@ -4,6 +4,7 @@ import Header from "./components/Header"; import AssignmentInfoBlock from "./components/AssignmentInfoBlock"; import styles from "./Assignment.module.css"; import { mapStatus } from "./utils/AssignmentStatus.js"; +import { fetchAssignmentsByUser } from "./api/assignment.js"; const Assignment = () => { const [weeks, setWeeks] = useState([]); @@ -16,18 +17,18 @@ const Assignment = () => { if (!userId) return; fetchAssignmentsByUser(userId) - .then((weekData) => { - const formatted = weekData.map((weekItem) => ({ - label: `${weekItem.week}주차 ${weekItem.title}`, - details: weekItem.days.map((dayItem) => ({ - day: dayItem.day, - subject: weekItem.title, - tasks: dayItem.details.map((task) => ({ - label: task.assignmentName, - status: mapStatus(task.status), + .then((weekData) => { + const formatted = weekData.map((weekItem) => ({ + label: `${weekItem.week}주차 ${weekItem.title}`, + details: weekItem.days.map((dayItem) => ({ + day: dayItem.day, + subject: weekItem.title, + tasks: dayItem.details.map((task) => ({ + label: task.assignmentName, + status: mapStatus(task.status), + })), })), - })), - })); + })); setWeeks(formatted); @@ -63,4 +64,3 @@ const Assignment = () => { }; export default Assignment; - diff --git a/frontend/src/api/assignment.js b/frontend/src/api/assignment.js index a576b62..cf1a11a 100644 --- a/frontend/src/api/assignment.js +++ b/frontend/src/api/assignment.js @@ -1,8 +1,6 @@ -import axios from "axios"; +import api from "./api"; export const fetchAssignmentsByUser = async (userId) => { - const res = await axios.get(`/api/assignment/grouped/${userId}`, { - withCredentials: true - }); + const res = await api.get(`/assignment/grouped/${userId}`); return res.data; }; From 64bad80a62ce1cfe4d2f7c2abd2d0205aa7abc89 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Mon, 12 May 2025 00:08:59 +0900 Subject: [PATCH 09/33] base url http://www.pirocheck.org/api --- frontend/src/api/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/api/api.js b/frontend/src/api/api.js index 814c063..4ecf00d 100644 --- a/frontend/src/api/api.js +++ b/frontend/src/api/api.js @@ -1,7 +1,7 @@ import axios from "axios"; const api = axios.create({ - baseURL: "/api", + baseURL: "http://www.pirocheck.org/api", withCredentials: true, }); From c94f3855d4ed245727df03e72463f2f9ef6bbf91 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Mon, 12 May 2025 00:29:28 +0900 Subject: [PATCH 10/33] =?UTF-8?q?attendance=20api=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Attendance.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/Attendance.jsx b/frontend/src/Attendance.jsx index 66c2da3..45f8f6b 100644 --- a/frontend/src/Attendance.jsx +++ b/frontend/src/Attendance.jsx @@ -108,7 +108,7 @@ const Attendance = () => { if (!userId) return; const today = new Date().toISOString().split("T")[0]; // YYYY-MM-DD - const res = await axios.get(`/api/attendance/user/date`, { + const res = await api.get(`/attendance/user/date`, { params: { userId, date: today }, withCredentials: true, // 세션 기반 인증 요청처리 }); @@ -151,8 +151,8 @@ const Attendance = () => { if (!userId) return; // 유저가 입력한 출석 코드 서버에 전달(서버에서 출석코드 체크) - const res = await axios.post( - "/api/attendance/mark", + const res = await api.post( + "/attendance/mark", { userId, code: attendanceCode[0], From 55f7d5260407c8055dd898e88ff7253c22ddb6ec Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Mon, 12 May 2025 11:19:11 +0900 Subject: [PATCH 11/33] Update deploy.yml --- .github/workflows/deploy.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2ef3e69..76e87ad 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -48,9 +48,9 @@ jobs: "fuser -k 8080/tcp || true && nohup java -jar pirocheck-0.0.1-SNAPSHOT.jar > log.txt 2>&1 &" - - name: Restart Spring Boot on EC2 - run: | - ssh -o StrictHostKeyChecking=no -i pirocheck.pem ubuntu@${{ secrets.EC2_HOST }} 'bash ~/restart.sh' + # - name: Restart Spring Boot on EC2 + # run: | + # ssh -o StrictHostKeyChecking=no -i pirocheck.pem ubuntu@${{ secrets.EC2_HOST }} 'bash ~/restart.sh' - name: Send Discord notification (Success) From c15dd048d081008151156bc136478a683f2ee120 Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Mon, 12 May 2025 12:12:33 +0900 Subject: [PATCH 12/33] Update deploy.yml --- .github/workflows/deploy.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 76e87ad..949c22b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,8 +45,9 @@ jobs: run: | ssh -o StrictHostKeyChecking=no -i pirocheck.pem \ ubuntu@${{ secrets.EC2_HOST }} \ - "fuser -k 8080/tcp || true && nohup java -jar pirocheck-0.0.1-SNAPSHOT.jar > log.txt 2>&1 &" - + "fuser -k 8080/tcp || true && \ + cd /home/ubuntu && \ + nohup java -jar pirocheck-0.0.1-SNAPSHOT.jar > log.txt 2>&1 &" # - name: Restart Spring Boot on EC2 # run: | From 3aa2521b47d116442ea40c40605d88849d23257d Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Mon, 12 May 2025 12:32:06 +0900 Subject: [PATCH 13/33] Update deploy.yml --- .github/workflows/deploy.yml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 949c22b..e969afb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,17 +41,10 @@ jobs: run: | scp -o StrictHostKeyChecking=no -i pirocheck.pem backend/pirocheck/build/libs/*.jar ubuntu@${{ secrets.EC2_HOST }}:/home/ubuntu/ - - name: Run jar on EC2 + + - name: Restart Spring Boot on EC2 run: | - ssh -o StrictHostKeyChecking=no -i pirocheck.pem \ - ubuntu@${{ secrets.EC2_HOST }} \ - "fuser -k 8080/tcp || true && \ - cd /home/ubuntu && \ - nohup java -jar pirocheck-0.0.1-SNAPSHOT.jar > log.txt 2>&1 &" - - # - name: Restart Spring Boot on EC2 - # run: | - # ssh -o StrictHostKeyChecking=no -i pirocheck.pem ubuntu@${{ secrets.EC2_HOST }} 'bash ~/restart.sh' + ssh -o StrictHostKeyChecking=no -i pirocheck.pem ubuntu@${{ secrets.EC2_HOST }} 'bash ~/restart.sh' - name: Send Discord notification (Success) From 7c562d906028f8504aa6aeaec501b6210479b023 Mon Sep 17 00:00:00 2001 From: Imggaggu Date: Mon, 12 May 2025 13:37:23 +0900 Subject: [PATCH 14/33] [Fix] baseurl for api --- frontend/src/api/api.js | 2 +- frontend/src/api/user.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/api/api.js b/frontend/src/api/api.js index 4ecf00d..8278d08 100644 --- a/frontend/src/api/api.js +++ b/frontend/src/api/api.js @@ -1,7 +1,7 @@ import axios from "axios"; const api = axios.create({ - baseURL: "http://www.pirocheck.org/api", + baseURL: "http://api.pirocheck.org/api", withCredentials: true, }); diff --git a/frontend/src/api/user.js b/frontend/src/api/user.js index f91670c..811264c 100644 --- a/frontend/src/api/user.js +++ b/frontend/src/api/user.js @@ -1,5 +1,5 @@ export const loginUser = async ({ name, password }) => { - const res = await fetch("http://www.pirocheck.org/api/login", { + const res = await fetch("http://api.pirocheck.org/api/login", { method: "POST", headers: { "Content-Type": "application/json", From ec1224cd69a849341c08cf6797f1d44960107d87 Mon Sep 17 00:00:00 2001 From: Imggaggu Date: Mon, 12 May 2025 13:49:47 +0900 Subject: [PATCH 15/33] [Fix]back-allowed origins url --- .../src/main/java/backend/pirocheck/config/WebConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index a6ae980..f67ed5b 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -10,7 +10,7 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 백엔드 API 요청에만 CORS 허용 - .allowedOrigins("http://pirocheck.org:3000") // 프론트 배포 URL + .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 .allowCredentials(true); // 세션 쿠키 주고받기 허용 } From 7a28b54274de2cc9591c0442fc3087c48346fe25 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Mon, 12 May 2025 13:56:26 +0900 Subject: [PATCH 16/33] =?UTF-8?q?[fix]=20WebConfig.java=203000=EB=B2=88=20?= =?UTF-8?q?=ED=8F=AC=ED=8A=B8=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=20api=20=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pirocheck/assignment/controller/AssignmentController.java | 2 +- .../src/main/java/backend/pirocheck/config/WebConfig.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 3552b44..0c1379f 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 @@ -10,7 +10,7 @@ import java.util.List; @RestController -@RequestMapping("/assignment") +@RequestMapping("/api/assignment") @RequiredArgsConstructor public class AssignmentController { diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index a6ae980..f67ed5b 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -10,7 +10,7 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 백엔드 API 요청에만 CORS 허용 - .allowedOrigins("http://pirocheck.org:3000") // 프론트 배포 URL + .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 .allowCredentials(true); // 세션 쿠키 주고받기 허용 } From c5886d75e3beb8a70406725b99472a955cedb9a5 Mon Sep 17 00:00:00 2001 From: Imggaggu Date: Mon, 12 May 2025 14:13:33 +0900 Subject: [PATCH 17/33] [Fix] baseurl for api --- frontend/src/api/api.js | 2 +- frontend/src/api/user.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/api/api.js b/frontend/src/api/api.js index 8278d08..9ba4ee2 100644 --- a/frontend/src/api/api.js +++ b/frontend/src/api/api.js @@ -1,7 +1,7 @@ import axios from "axios"; const api = axios.create({ - baseURL: "http://api.pirocheck.org/api", + baseURL: "http://api.pirocheck.org:8080/api", withCredentials: true, }); diff --git a/frontend/src/api/user.js b/frontend/src/api/user.js index 811264c..12e057a 100644 --- a/frontend/src/api/user.js +++ b/frontend/src/api/user.js @@ -1,5 +1,5 @@ export const loginUser = async ({ name, password }) => { - const res = await fetch("http://api.pirocheck.org/api/login", { + const res = await fetch("http://api.pirocheck.org:8080/api/login", { method: "POST", headers: { "Content-Type": "application/json", From a2b27cba453f3ff4b0109873f69b14fe43ffaed1 Mon Sep 17 00:00:00 2001 From: Imggaggu Date: Mon, 12 May 2025 14:27:24 +0900 Subject: [PATCH 18/33] =?UTF-8?q?[Chore]=20Generation/=20admin=20directory?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/{ => pages/admin}/Admin.jsx | 0 frontend/src/{ => pages/generation}/Assignment.jsx | 10 +++++----- .../src/{ => pages/generation}/Assignment.module.css | 0 frontend/src/{ => pages/generation}/Attendance.jsx | 8 ++++---- .../src/{ => pages/generation}/Attendance.module.css | 0 frontend/src/{ => pages/generation}/Deposit.jsx | 4 ++-- frontend/src/{ => pages/generation}/Deposit.module.css | 0 7 files changed, 11 insertions(+), 11 deletions(-) rename frontend/src/{ => pages/admin}/Admin.jsx (100%) rename frontend/src/{ => pages/generation}/Assignment.jsx (86%) rename frontend/src/{ => pages/generation}/Assignment.module.css (100%) rename frontend/src/{ => pages/generation}/Attendance.jsx (97%) rename frontend/src/{ => pages/generation}/Attendance.module.css (100%) rename frontend/src/{ => pages/generation}/Deposit.jsx (94%) rename frontend/src/{ => pages/generation}/Deposit.module.css (100%) diff --git a/frontend/src/Admin.jsx b/frontend/src/pages/admin/Admin.jsx similarity index 100% rename from frontend/src/Admin.jsx rename to frontend/src/pages/admin/Admin.jsx diff --git a/frontend/src/Assignment.jsx b/frontend/src/pages/generation/Assignment.jsx similarity index 86% rename from frontend/src/Assignment.jsx rename to frontend/src/pages/generation/Assignment.jsx index f24604a..1654cc6 100644 --- a/frontend/src/Assignment.jsx +++ b/frontend/src/pages/generation/Assignment.jsx @@ -1,10 +1,10 @@ import React, { useEffect, useState } from "react"; -import WeeklyListBlock from "./components/WeeklyListBlock"; -import Header from "./components/Header"; -import AssignmentInfoBlock from "./components/AssignmentInfoBlock"; +import WeeklyListBlock from "../components/WeeklyListBlock"; +import Header from "../components/Header"; +import AssignmentInfoBlock from "../components/AssignmentInfoBlock"; import styles from "./Assignment.module.css"; -import { mapStatus } from "./utils/AssignmentStatus.js"; -import { fetchAssignmentsByUser } from "./api/assignment.js"; +import { mapStatus } from "../utils/AssignmentStatus.js"; +import { fetchAssignmentsByUser } from "../api/assignment.js"; const Assignment = () => { const [weeks, setWeeks] = useState([]); diff --git a/frontend/src/Assignment.module.css b/frontend/src/pages/generation/Assignment.module.css similarity index 100% rename from frontend/src/Assignment.module.css rename to frontend/src/pages/generation/Assignment.module.css diff --git a/frontend/src/Attendance.jsx b/frontend/src/pages/generation/Attendance.jsx similarity index 97% rename from frontend/src/Attendance.jsx rename to frontend/src/pages/generation/Attendance.jsx index 0e72c16..3d95709 100644 --- a/frontend/src/Attendance.jsx +++ b/frontend/src/pages/generation/Attendance.jsx @@ -1,9 +1,9 @@ import { useEffect, useState } from "react"; -import Header from "./components/Header"; -import InputBlock from "./components/InputBlock"; -import AttendanceWeekInfo from "./components/AttendanceWeekInfo"; +import Header from "../components/Header"; +import InputBlock from "../components/InputBlock"; +import AttendanceWeekInfo from "../components/AttendanceWeekInfo"; import styles from "./Attendance.module.css"; -import api from "./api/api"; +import api from "../api/api"; const Attendance = () => { const [attendanceCode, setAttendanceCode] = useState([""]); diff --git a/frontend/src/Attendance.module.css b/frontend/src/pages/generation/Attendance.module.css similarity index 100% rename from frontend/src/Attendance.module.css rename to frontend/src/pages/generation/Attendance.module.css diff --git a/frontend/src/Deposit.jsx b/frontend/src/pages/generation/Deposit.jsx similarity index 94% rename from frontend/src/Deposit.jsx rename to frontend/src/pages/generation/Deposit.jsx index 3a84615..63d5621 100644 --- a/frontend/src/Deposit.jsx +++ b/frontend/src/pages/generation/Deposit.jsx @@ -1,8 +1,8 @@ -import Header from "./components/Header"; +import Header from "../components/Header"; import styles from "./Deposit.module.css"; import axios from "axios"; import { useEffect, useState } from "react"; -import api from "./api/api"; +import api from "../api/api"; const Deposit = () => { const [deposit, setDeposit] = useState(null); diff --git a/frontend/src/Deposit.module.css b/frontend/src/pages/generation/Deposit.module.css similarity index 100% rename from frontend/src/Deposit.module.css rename to frontend/src/pages/generation/Deposit.module.css From 5ecc609191eacc887016339c33094103f2a0dcae Mon Sep 17 00:00:00 2001 From: Imggaggu Date: Mon, 12 May 2025 14:31:13 +0900 Subject: [PATCH 19/33] =?UTF-8?q?[Chore]=20Generation/=20admin=20directory?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.jsx | 8 ++++---- frontend/src/pages/generation/Assignment.jsx | 10 +++++----- frontend/src/pages/generation/Attendance.jsx | 8 ++++---- frontend/src/pages/generation/Deposit.jsx | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index db217ff..50530e1 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -2,11 +2,11 @@ import React from "react"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import Login from "./Login"; import Home from "./Home"; -import Assignment from "./Assignment"; -import Deposit from "./Deposit"; +import Assignment from "./pages/generation/Assignment"; +import Deposit from "./pages/generation/Deposit"; import Intro from "./Intro"; -import Admin from "./Admin"; -import Attendance from "./Attendance"; +import Admin from "./pages/admin/Admin"; +import Attendance from "./pages/generation/Attendance"; function App() { return ( diff --git a/frontend/src/pages/generation/Assignment.jsx b/frontend/src/pages/generation/Assignment.jsx index 1654cc6..d1c0115 100644 --- a/frontend/src/pages/generation/Assignment.jsx +++ b/frontend/src/pages/generation/Assignment.jsx @@ -1,10 +1,10 @@ import React, { useEffect, useState } from "react"; -import WeeklyListBlock from "../components/WeeklyListBlock"; -import Header from "../components/Header"; -import AssignmentInfoBlock from "../components/AssignmentInfoBlock"; +import WeeklyListBlock from "../../components/WeeklyListBlock"; +import Header from "../../components/Header"; +import AssignmentInfoBlock from "../../components/AssignmentInfoBlock"; import styles from "./Assignment.module.css"; -import { mapStatus } from "../utils/AssignmentStatus.js"; -import { fetchAssignmentsByUser } from "../api/assignment.js"; +import { mapStatus } from "../../utils/AssignmentStatus.js"; +import { fetchAssignmentsByUser } from "../../api/assignment.js"; const Assignment = () => { const [weeks, setWeeks] = useState([]); diff --git a/frontend/src/pages/generation/Attendance.jsx b/frontend/src/pages/generation/Attendance.jsx index 3d95709..dce08b1 100644 --- a/frontend/src/pages/generation/Attendance.jsx +++ b/frontend/src/pages/generation/Attendance.jsx @@ -1,9 +1,9 @@ import { useEffect, useState } from "react"; -import Header from "../components/Header"; -import InputBlock from "../components/InputBlock"; -import AttendanceWeekInfo from "../components/AttendanceWeekInfo"; +import Header from "../../components/Header"; +import InputBlock from "../../components/InputBlock"; +import AttendanceWeekInfo from "../../components/AttendanceWeekInfo"; import styles from "./Attendance.module.css"; -import api from "../api/api"; +import api from "../../api/api"; const Attendance = () => { const [attendanceCode, setAttendanceCode] = useState([""]); diff --git a/frontend/src/pages/generation/Deposit.jsx b/frontend/src/pages/generation/Deposit.jsx index 63d5621..8b9c17b 100644 --- a/frontend/src/pages/generation/Deposit.jsx +++ b/frontend/src/pages/generation/Deposit.jsx @@ -1,8 +1,8 @@ -import Header from "../components/Header"; +import Header from "../../components/Header"; import styles from "./Deposit.module.css"; import axios from "axios"; import { useEffect, useState } from "react"; -import api from "../api/api"; +import api from "../../api/api"; const Deposit = () => { const [deposit, setDeposit] = useState(null); From 65672e18d619a4bdfb690b1493ad79a5aa3b996d Mon Sep 17 00:00:00 2001 From: Imggaggu Date: Mon, 12 May 2025 14:42:31 +0900 Subject: [PATCH 20/33] [Fix] Allow all headers for CORS --- .../src/main/java/backend/pirocheck/config/WebConfig.java | 1 + frontend/src/api/api.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index f67ed5b..0d16c22 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -13,5 +13,6 @@ public void addCorsMappings(CorsRegistry registry) { .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 .allowCredentials(true); // 세션 쿠키 주고받기 허용 + .allowedHeaders("*") } } diff --git a/frontend/src/api/api.js b/frontend/src/api/api.js index 9ba4ee2..2cd0305 100644 --- a/frontend/src/api/api.js +++ b/frontend/src/api/api.js @@ -1,7 +1,7 @@ import axios from "axios"; const api = axios.create({ - baseURL: "http://api.pirocheck.org:8080/api", + baseURL: "http://api.:8080/api", withCredentials: true, }); From 0907577aa4d9ca9b5d35f4c73183197b75fb70c5 Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Mon, 12 May 2025 14:47:40 +0900 Subject: [PATCH 21/33] Update WebConfig.java --- .../src/main/java/backend/pirocheck/config/WebConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index 0d16c22..910877b 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -13,6 +13,6 @@ public void addCorsMappings(CorsRegistry registry) { .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 .allowCredentials(true); // 세션 쿠키 주고받기 허용 - .allowedHeaders("*") + .allowedHeaders("*"); } } From 390252f18a04f44d57c1b36dd4789dfb863cc93a Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Mon, 12 May 2025 14:50:23 +0900 Subject: [PATCH 22/33] Update WebConfig.java --- .../src/main/java/backend/pirocheck/config/WebConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index 910877b..d75bc55 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -12,7 +12,8 @@ public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 백엔드 API 요청에만 CORS 허용 .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 - .allowCredentials(true); // 세션 쿠키 주고받기 허용 .allowedHeaders("*"); + .allowCredentials(true); // 세션 쿠키 주고받기 허용 + } } From 24099efd9f5136f391e7bd8d9d2fb5cc67fdb725 Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Mon, 12 May 2025 14:54:27 +0900 Subject: [PATCH 23/33] Update WebConfig.java --- .../src/main/java/backend/pirocheck/config/WebConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index 0d16c22..c9c63bf 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -12,7 +12,7 @@ public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 백엔드 API 요청에만 CORS 허용 .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 - .allowCredentials(true); // 세션 쿠키 주고받기 허용 - .allowedHeaders("*") + .allowCredentials(true) // 세션 쿠키 주고받기 허용 + .allowedHeaders("*"); } } From 67dfc6c802aead3a50f51c677bfaf8c5e660a8d6 Mon Sep 17 00:00:00 2001 From: Suhjung Park <145967352+Imggaggu@users.noreply.github.com> Date: Mon, 12 May 2025 14:55:46 +0900 Subject: [PATCH 24/33] Update WebConfig.java --- .../src/main/java/backend/pirocheck/config/WebConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index d75bc55..e8bff61 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -12,7 +12,7 @@ public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 백엔드 API 요청에만 CORS 허용 .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 - .allowedHeaders("*"); + .allowedHeaders("*") .allowCredentials(true); // 세션 쿠키 주고받기 허용 } From c4c2d97e0350dc95f7828f6ae429c85c99565dd2 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Mon, 12 May 2025 16:12:26 +0900 Subject: [PATCH 25/33] =?UTF-8?q?[fix]=20WebConfig.java=20Origin=20url=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/backend/pirocheck/config/WebConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index c9c63bf..f729c5c 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -10,8 +10,8 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 백엔드 API 요청에만 CORS 허용 - .allowedOrigins("http://pirocheck.org") // 프론트 배포 URL - .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드 + .allowedOrigins("http://www.pirocheck.org") // 프론트 배포 URL + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 허용할 HTTP 메서드 .allowCredentials(true) // 세션 쿠키 주고받기 허용 .allowedHeaders("*"); } From d2d37c9ad25837b50298c138df3f8604fe378d99 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Tue, 13 May 2025 12:17:49 +0900 Subject: [PATCH 26/33] =?UTF-8?q?admin=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.jsx | 6 ++++ frontend/src/pages/admin/Admin.jsx | 31 +++++++++++++++++-- frontend/src/pages/admin/AttendanceCode.jsx | 4 +++ frontend/src/pages/admin/ManageStudent.jsx | 4 +++ frontend/src/pages/admin/ManageTask.jsx | 4 +++ frontend/src/{ => pages/generation}/Home.jsx | 1 - .../{ => pages/generation}/Home.module.css | 0 7 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 frontend/src/pages/admin/AttendanceCode.jsx create mode 100644 frontend/src/pages/admin/ManageStudent.jsx create mode 100644 frontend/src/pages/admin/ManageTask.jsx rename frontend/src/{ => pages/generation}/Home.jsx (96%) rename frontend/src/{ => pages/generation}/Home.module.css (100%) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 50530e1..2d7135e 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -6,6 +6,9 @@ import Assignment from "./pages/generation/Assignment"; import Deposit from "./pages/generation/Deposit"; import Intro from "./Intro"; import Admin from "./pages/admin/Admin"; +import MagageStudent from "./pages/admin/MagageStudent"; +import MagageTask from "./pages/admin/MagageTask"; +import AttendanceCode from "./pages/admin/AttendanceCode"; import Attendance from "./pages/generation/Attendance"; function App() { @@ -19,6 +22,9 @@ function App() { } /> } /> } /> + } /> + } /> + } /> ); diff --git a/frontend/src/pages/admin/Admin.jsx b/frontend/src/pages/admin/Admin.jsx index 1eb01d0..2223673 100644 --- a/frontend/src/pages/admin/Admin.jsx +++ b/frontend/src/pages/admin/Admin.jsx @@ -1,9 +1,34 @@ +import { useNavigate } from "react-router-dom"; +import styles from "../generation/Home.module.css"; + const Admin = () => { + const navigate = useNavigate(); return ( -
-

Admin Page

-

This is the admin page.

+
+
+

PIROCHECK

+ + + + 로고 +
); }; + export default Admin; diff --git a/frontend/src/pages/admin/AttendanceCode.jsx b/frontend/src/pages/admin/AttendanceCode.jsx new file mode 100644 index 0000000..bd0987b --- /dev/null +++ b/frontend/src/pages/admin/AttendanceCode.jsx @@ -0,0 +1,4 @@ +const AttendanceCode = () => { + return

수강생 관리

; +}; +export default AttendanceCode; diff --git a/frontend/src/pages/admin/ManageStudent.jsx b/frontend/src/pages/admin/ManageStudent.jsx new file mode 100644 index 0000000..41f63e8 --- /dev/null +++ b/frontend/src/pages/admin/ManageStudent.jsx @@ -0,0 +1,4 @@ +const MagageStudent = () => { + return

수강생 관리

; +}; +export default MagageStudent; diff --git a/frontend/src/pages/admin/ManageTask.jsx b/frontend/src/pages/admin/ManageTask.jsx new file mode 100644 index 0000000..f0f4924 --- /dev/null +++ b/frontend/src/pages/admin/ManageTask.jsx @@ -0,0 +1,4 @@ +const MagageTask = () => { + return

수강생 관리

; +}; +export default MagageTask; diff --git a/frontend/src/Home.jsx b/frontend/src/pages/generation/Home.jsx similarity index 96% rename from frontend/src/Home.jsx rename to frontend/src/pages/generation/Home.jsx index f1fe4fa..df86a12 100644 --- a/frontend/src/Home.jsx +++ b/frontend/src/pages/generation/Home.jsx @@ -1,4 +1,3 @@ -import React from "react"; import { useNavigate } from "react-router-dom"; import styles from "./Home.module.css"; diff --git a/frontend/src/Home.module.css b/frontend/src/pages/generation/Home.module.css similarity index 100% rename from frontend/src/Home.module.css rename to frontend/src/pages/generation/Home.module.css From f6f6d1d14ef1f9746a0ef4b56d5abba3c62cbde3 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Tue, 13 May 2025 13:23:30 +0900 Subject: [PATCH 27/33] =?UTF-8?q?home=20=EA=B2=BD=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.jsx | 2 +- frontend/src/pages/admin/AttendanceCode.jsx | 2 +- frontend/src/pages/admin/ManageTask.jsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 2d7135e..e757361 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,7 +1,7 @@ import React from "react"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import Login from "./Login"; -import Home from "./Home"; +import Home from "./pages/admin/Home"; import Assignment from "./pages/generation/Assignment"; import Deposit from "./pages/generation/Deposit"; import Intro from "./Intro"; diff --git a/frontend/src/pages/admin/AttendanceCode.jsx b/frontend/src/pages/admin/AttendanceCode.jsx index bd0987b..d184e1d 100644 --- a/frontend/src/pages/admin/AttendanceCode.jsx +++ b/frontend/src/pages/admin/AttendanceCode.jsx @@ -1,4 +1,4 @@ const AttendanceCode = () => { - return

수강생 관리

; + return

출석코드 생성

; }; export default AttendanceCode; diff --git a/frontend/src/pages/admin/ManageTask.jsx b/frontend/src/pages/admin/ManageTask.jsx index f0f4924..7140e6e 100644 --- a/frontend/src/pages/admin/ManageTask.jsx +++ b/frontend/src/pages/admin/ManageTask.jsx @@ -1,4 +1,4 @@ const MagageTask = () => { - return

수강생 관리

; + return

과제 관리

; }; export default MagageTask; From 159f0ca7d138df31213f60251c7aac674e900efa Mon Sep 17 00:00:00 2001 From: seonjuuu Date: Wed, 14 May 2025 00:03:52 +0900 Subject: [PATCH 28/33] [feat] ManageStudents --- .../Controller/ManageStudentsController.java | 26 ++++++++++++++ .../response/ManageStudentsListResDto.java | 13 +++++++ .../service/ManageStudentsService.java | 35 +++++++++++++++++++ .../User/repository/UserRepository.java | 3 ++ 4 files changed, 77 insertions(+) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentsListResDto.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java new file mode 100644 index 0000000..3712f45 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java @@ -0,0 +1,26 @@ +package backend.pirocheck.ManageStudents.Controller; + +import backend.pirocheck.ManageStudents.dto.response.ManageStudentsListResDto; +import backend.pirocheck.ManageStudents.service.ManageStudentsService; +import backend.pirocheck.User.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api/admin/managestudent") +@RequiredArgsConstructor +public class ManageStudentsController { + + private final ManageStudentsService manageStudentsService; + + @GetMapping + public List getStudents(@RequestParam(required = false) String name) { + return manageStudentsService.searchStudents(name); + } + +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentsListResDto.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentsListResDto.java new file mode 100644 index 0000000..d5e028f --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentsListResDto.java @@ -0,0 +1,13 @@ +package backend.pirocheck.ManageStudents.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ManageStudentsListResDto { + + private Long id; + private String name; + +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java new file mode 100644 index 0000000..826d726 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java @@ -0,0 +1,35 @@ +package backend.pirocheck.ManageStudents.service; + +import backend.pirocheck.ManageStudents.dto.response.ManageStudentsListResDto; +import backend.pirocheck.User.entity.Role; +import backend.pirocheck.User.entity.User; +import backend.pirocheck.User.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class ManageStudentsService { + + private final UserRepository userRepository; + + public List searchStudents(String name) { + List users; + + if(name == null || name.isBlank()) { + // 검색어가 없으면 맴버 전체 조회 + users = userRepository.findByRole(Role.MEMBER); + } + else { + // 이름 검색 + users = userRepository.findByNameContainingAndRole(name, Role.MEMBER); + } + + return users.stream() + .map(user -> new ManageStudentsListResDto(user.getId(), user.getName())) + .collect(Collectors.toList()); + } +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/User/repository/UserRepository.java b/backend/pirocheck/src/main/java/backend/pirocheck/User/repository/UserRepository.java index 9f80d25..8859494 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/User/repository/UserRepository.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/User/repository/UserRepository.java @@ -12,4 +12,7 @@ public interface UserRepository extends JpaRepository { Optional findByName(String name); List findByRole(Role role); + + // 학생 이름으로 검색기능 + List findByNameContainingAndRole(String name, Role role); } From 707de406885e88a27c8658da6045155607705cf2 Mon Sep 17 00:00:00 2001 From: qkrxogmla Date: Wed, 14 May 2025 12:28:45 +0900 Subject: [PATCH 29/33] [fix]css --- frontend/src/App.jsx | 8 +-- frontend/src/pages/admin/Admin.jsx | 2 +- frontend/src/pages/admin/Admin.module.css | 50 +++++++++++++++++++ frontend/src/pages/generation/Home.module.css | 10 ++-- 4 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 frontend/src/pages/admin/Admin.module.css diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e757361..b11b9d0 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,13 +1,13 @@ import React from "react"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import Login from "./Login"; -import Home from "./pages/admin/Home"; +import Home from "./pages/generation/Home"; import Assignment from "./pages/generation/Assignment"; import Deposit from "./pages/generation/Deposit"; import Intro from "./Intro"; import Admin from "./pages/admin/Admin"; -import MagageStudent from "./pages/admin/MagageStudent"; -import MagageTask from "./pages/admin/MagageTask"; +import MagageStudent from "./pages/admin/ManageStudent.jsx"; +import ManageTask from "./pages/admin/ManageTask.jsx"; import AttendanceCode from "./pages/admin/AttendanceCode"; import Attendance from "./pages/generation/Attendance"; @@ -23,7 +23,7 @@ function App() { } /> } /> } /> - } /> + } /> } /> diff --git a/frontend/src/pages/admin/Admin.jsx b/frontend/src/pages/admin/Admin.jsx index 2223673..fa42daf 100644 --- a/frontend/src/pages/admin/Admin.jsx +++ b/frontend/src/pages/admin/Admin.jsx @@ -1,5 +1,5 @@ import { useNavigate } from "react-router-dom"; -import styles from "../generation/Home.module.css"; +import styles from "./Admin.module.css"; const Admin = () => { const navigate = useNavigate(); diff --git a/frontend/src/pages/admin/Admin.module.css b/frontend/src/pages/admin/Admin.module.css new file mode 100644 index 0000000..760d1d9 --- /dev/null +++ b/frontend/src/pages/admin/Admin.module.css @@ -0,0 +1,50 @@ +.home { + height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + overflow: hidden; + font-family: "Akira Expanded"; +} +.pirocheck { + margin-top: 84px; + font-size: 1.25rem; + margin-bottom: 103px; +} +.home_container { + background-color: var(--background-black); + color: var(--main-green); + font-family: "Cafe24Moyamoya-Regular-v1.0", sans-serif; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} +.button { + width: 309px; + height: 81px; + border-radius: 8px; + background-color: var(--border-gray); + color: var(--text-white); + font-family: "Akira Expanded"; + font-weight: 400; + font-size: 16px; + border: none; + padding: 29px 103px; + font-weight: bold; + margin-bottom: 26px; + z-index: 1; + display: flex; + justify-content: center; +} +.button p { + text-align: start; +} +.button:hover { + background-color: var(--card-toggle-green); + color: var(--text-white); +} +.home img { + position: relative; + opacity: 0.8; + bottom: 11%; + z-index: 0; +} diff --git a/frontend/src/pages/generation/Home.module.css b/frontend/src/pages/generation/Home.module.css index 9cdf1de..436f3ed 100644 --- a/frontend/src/pages/generation/Home.module.css +++ b/frontend/src/pages/generation/Home.module.css @@ -5,10 +5,10 @@ align-items: center; justify-content: flex-start; overflow: hidden; - font-family: 'Akira Expanded'; + font-family: "Akira Expanded"; } .pirocheck { - margin-top: 43px; + margin-top: 84px; font-size: 1.25rem; margin-bottom: 103px; } @@ -24,10 +24,10 @@ border-radius: 8px; background-color: var(--border-gray); color: var(--text-white); - font-family: 'Akira Expanded'; + font-family: "Akira Expanded"; font-weight: 400; font-size: 16px; - border: 1px var(--background-black) solid; + border: none; padding: 15px; font-weight: bold; margin-bottom: 26px; @@ -43,6 +43,6 @@ .home img { position: relative; opacity: 0.8; - top: -92px; + bottom: -2%; z-index: 0; } From 2add8f958165da833d0ffbd67820e2954f6b2c34 Mon Sep 17 00:00:00 2001 From: seonjuuu Date: Thu, 15 May 2025 02:58:43 +0900 Subject: [PATCH 30/33] [feat] ManageStudents_StudentDetail --- .../Controller/ManageStudentsController.java | 17 ++++---- .../dto/request/ShieldUpdateReqDto.java | 11 +++++ .../response/ManageStudentDetailResDto.java | 16 ++++++++ .../service/ManageStudentsService.java | 40 ++++++++++++++++++- .../exception/GlobalExceptionHandler.java | 8 ++++ 5 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/ShieldUpdateReqDto.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java index 3712f45..1ccf09e 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java @@ -1,13 +1,10 @@ package backend.pirocheck.ManageStudents.Controller; +import backend.pirocheck.ManageStudents.dto.response.ManageStudentDetailResDto; import backend.pirocheck.ManageStudents.dto.response.ManageStudentsListResDto; import backend.pirocheck.ManageStudents.service.ManageStudentsService; -import backend.pirocheck.User.repository.UserRepository; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -18,9 +15,15 @@ public class ManageStudentsController { private final ManageStudentsService manageStudentsService; - @GetMapping + // 수강생 리스트 조회 + @GetMapping("") public List getStudents(@RequestParam(required = false) String name) { - return manageStudentsService.searchStudents(name); + return manageStudentsService.searchMembers(name); } + // 수강생 상세 조회 + @GetMapping("/{studentId}") + public ManageStudentDetailResDto getStudentDetail(@PathVariable Long studentId) { + return manageStudentsService.getMemberDetail(studentId); + } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/ShieldUpdateReqDto.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/ShieldUpdateReqDto.java new file mode 100644 index 0000000..98418e1 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/ShieldUpdateReqDto.java @@ -0,0 +1,11 @@ +package backend.pirocheck.ManageStudents.dto.request; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ShieldUpdateReqDto { + private int shield; +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java new file mode 100644 index 0000000..d1eb325 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java @@ -0,0 +1,16 @@ +package backend.pirocheck.ManageStudents.dto.response; + +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +public class ManageStudentDetailResDto { + + private String name; + private int deposit; + private int shield; // 방어권 + private List assignmentTitles; // 과제 제목 리스트 +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java index 826d726..0fb2377 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java @@ -1,9 +1,14 @@ package backend.pirocheck.ManageStudents.service; +import backend.pirocheck.Deposit.entity.Deposit; +import backend.pirocheck.Deposit.repository.DepositRepository; +import backend.pirocheck.ManageStudents.dto.response.ManageStudentDetailResDto; import backend.pirocheck.ManageStudents.dto.response.ManageStudentsListResDto; import backend.pirocheck.User.entity.Role; import backend.pirocheck.User.entity.User; import backend.pirocheck.User.repository.UserRepository; +import backend.pirocheck.assignment.entity.Assignment; +import backend.pirocheck.assignment.repository.AssignmentRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,8 +20,11 @@ public class ManageStudentsService { private final UserRepository userRepository; + private final DepositRepository depositRepository; + private final AssignmentRepository assignmentRepository; - public List searchStudents(String name) { + // 수강생 조회 + public List searchMembers(String name) { List users; if(name == null || name.isBlank()) { @@ -32,4 +40,34 @@ public List searchStudents(String name) { .map(user -> new ManageStudentsListResDto(user.getId(), user.getName())) .collect(Collectors.toList()); } + + // 수강생 상세 조회 + public ManageStudentDetailResDto getMemberDetail(Long studentId) { + // User 조회 + User user = userRepository.findById(studentId) + .orElseThrow(() -> new RuntimeException("해당 맴버가 존재하지 않습니다.")); + + // deposit 조회 + Deposit deposit = depositRepository.findByUser(user); + if (deposit == null) { + throw new RuntimeException("해당 수강생의 보증금 정보가 없습니다."); + } + + // Assignment 리스트 조회 + List assignments = assignmentRepository.findByUserId(studentId); + + // 과제 제목만 리스트로 변환 + List assignmentTitles = assignments.stream() + .map(Assignment::getAssignmentName) + .toList(); + + // ManageStudentDetailResDto 조립 + return ManageStudentDetailResDto.builder() + .name(user.getName()) + .deposit(deposit.getAmount()) + .shield(deposit.getAscentDefence()) + .assignmentTitles(assignmentTitles) + .build(); + + } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/User/exception/GlobalExceptionHandler.java b/backend/pirocheck/src/main/java/backend/pirocheck/User/exception/GlobalExceptionHandler.java index 4fd3755..f26232f 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/User/exception/GlobalExceptionHandler.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/User/exception/GlobalExceptionHandler.java @@ -16,4 +16,12 @@ public ResponseEntity> handleInvalidLoginException(InvalidLoginEx .status(HttpStatus.UNAUTHORIZED) // 401 상태 코드 .body(ApiResponse.error(e.getMessage())); // 에러 메시지 전달 } + + // RuntimeException (유저관리 상세페이지) + @ExceptionHandler(RuntimeException.class) + public ResponseEntity> handleRuntimeException(RuntimeException ex) { + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) // 404 + .body(ApiResponse.error(ex.getMessage())); + } } From 5e5d952a469e09360cd77bb683bbf190e8b0516b Mon Sep 17 00:00:00 2001 From: seonjuuu Date: Thu, 15 May 2025 03:52:30 +0900 Subject: [PATCH 31/33] [feat] ManageStudents_updateShield --- .../pirocheck/Deposit/entity/Deposit.java | 6 ++---- .../Controller/ManageStudentsController.java | 8 ++++++++ .../service/ManageStudentsService.java | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java b/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java index 139e385..958e9b3 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java @@ -2,13 +2,11 @@ import backend.pirocheck.User.entity.User; import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; @Entity @Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java index 1ccf09e..b9fb79a 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java @@ -1,5 +1,6 @@ package backend.pirocheck.ManageStudents.Controller; +import backend.pirocheck.ManageStudents.dto.request.ShieldUpdateReqDto; import backend.pirocheck.ManageStudents.dto.response.ManageStudentDetailResDto; import backend.pirocheck.ManageStudents.dto.response.ManageStudentsListResDto; import backend.pirocheck.ManageStudents.service.ManageStudentsService; @@ -26,4 +27,11 @@ public List getStudents(@RequestParam(required = false public ManageStudentDetailResDto getStudentDetail(@PathVariable Long studentId) { return manageStudentsService.getMemberDetail(studentId); } + + // 방어권 업데이트 + @PatchMapping("/{studentId}/shield") + public void updateShield(@PathVariable Long studentId, @RequestBody ShieldUpdateReqDto req) { + manageStudentsService.updateShield(studentId, req.getShield()); + } + } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java index 0fb2377..4e4cb5a 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java @@ -68,6 +68,23 @@ public ManageStudentDetailResDto getMemberDetail(Long studentId) { .shield(deposit.getAscentDefence()) .assignmentTitles(assignmentTitles) .build(); + } + + // 방어권 업데이트 + public void updateShield(Long studentId, int shield) { + User user = userRepository.findById(studentId) + .orElseThrow(() -> new RuntimeException("해당 수강생의 보증금 정보가 없습니다.")); + Deposit deposit = depositRepository.findByUser(user); + + // 업데이트 + deposit.updateAmounts( + deposit.getDescentAssignment(), + deposit.getDescentAssignment(), + shield // 수정한 방어권 + ); + + // 저장 + depositRepository.save(deposit); } } From 82b109cb120fb033a79c89d1a8a89e65b1d1e3d4 Mon Sep 17 00:00:00 2001 From: seonjuuu Date: Thu, 15 May 2025 04:20:54 +0900 Subject: [PATCH 32/33] [fix] updateDefence --- .../java/backend/pirocheck/Deposit/entity/Deposit.java | 8 ++++++++ .../Controller/ManageStudentsController.java | 8 ++++---- ...hieldUpdateReqDto.java => DefenceUpdateReqDto.java} | 4 ++-- .../dto/response/ManageStudentDetailResDto.java | 2 +- .../ManageStudents/service/ManageStudentsService.java | 10 +++------- 5 files changed, 18 insertions(+), 14 deletions(-) rename backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/{ShieldUpdateReqDto.java => DefenceUpdateReqDto.java} (66%) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java b/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java index 958e9b3..a0431e6 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/entity/Deposit.java @@ -35,4 +35,12 @@ public void updateAmounts(int descentAssignment, int descentAttendance, int asce this.amount = Math.min(calculateAmount, 120000); // 12만원 넘어가지 않도록 } + // 방어권 업데이트 + public void updateDefence(int newAscentDefence) { + this.ascentDefence = newAscentDefence; + int calculateAmount = 120000 - this.descentAssignment - this.descentAttendance + newAscentDefence; + this.amount = Math.min(calculateAmount, 120000); + + } + } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java index b9fb79a..043b571 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/Controller/ManageStudentsController.java @@ -1,6 +1,6 @@ package backend.pirocheck.ManageStudents.Controller; -import backend.pirocheck.ManageStudents.dto.request.ShieldUpdateReqDto; +import backend.pirocheck.ManageStudents.dto.request.DefenceUpdateReqDto; import backend.pirocheck.ManageStudents.dto.response.ManageStudentDetailResDto; import backend.pirocheck.ManageStudents.dto.response.ManageStudentsListResDto; import backend.pirocheck.ManageStudents.service.ManageStudentsService; @@ -29,9 +29,9 @@ public ManageStudentDetailResDto getStudentDetail(@PathVariable Long studentId) } // 방어권 업데이트 - @PatchMapping("/{studentId}/shield") - public void updateShield(@PathVariable Long studentId, @RequestBody ShieldUpdateReqDto req) { - manageStudentsService.updateShield(studentId, req.getShield()); + @PatchMapping("/{studentId}/defence") + public void updateDefence(@PathVariable Long studentId, @RequestBody DefenceUpdateReqDto req) { + manageStudentsService.updateDefence(studentId, req.getDefence()); } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/ShieldUpdateReqDto.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/DefenceUpdateReqDto.java similarity index 66% rename from backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/ShieldUpdateReqDto.java rename to backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/DefenceUpdateReqDto.java index 98418e1..78e39f7 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/ShieldUpdateReqDto.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/request/DefenceUpdateReqDto.java @@ -6,6 +6,6 @@ @Getter @Setter -public class ShieldUpdateReqDto { - private int shield; +public class DefenceUpdateReqDto { + private int defence; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java index d1eb325..e5206fc 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/dto/response/ManageStudentDetailResDto.java @@ -11,6 +11,6 @@ public class ManageStudentDetailResDto { private String name; private int deposit; - private int shield; // 방어권 + private int defence; // 방어권 private List assignmentTitles; // 과제 제목 리스트 } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java index 4e4cb5a..e28c409 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java @@ -65,23 +65,19 @@ public ManageStudentDetailResDto getMemberDetail(Long studentId) { return ManageStudentDetailResDto.builder() .name(user.getName()) .deposit(deposit.getAmount()) - .shield(deposit.getAscentDefence()) + .defence(deposit.getAscentDefence()) .assignmentTitles(assignmentTitles) .build(); } // 방어권 업데이트 - public void updateShield(Long studentId, int shield) { + public void updateDefence(Long studentId, int defence) { User user = userRepository.findById(studentId) .orElseThrow(() -> new RuntimeException("해당 수강생의 보증금 정보가 없습니다.")); Deposit deposit = depositRepository.findByUser(user); // 업데이트 - deposit.updateAmounts( - deposit.getDescentAssignment(), - deposit.getDescentAssignment(), - shield // 수정한 방어권 - ); + deposit.updateDefence(defence); // 저장 depositRepository.save(deposit); From 8631e912f5d8c376882f7ad0fccf76fae07a2469 Mon Sep 17 00:00:00 2001 From: dietken1 Date: Fri, 16 May 2025 12:19:53 +0900 Subject: [PATCH 33/33] =?UTF-8?q?=EC=B6=9C=EC=84=9D=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=EB=A1=9C=EC=A7=81,=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=ED=98=95=EC=8B=9D=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?swagger=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AttendanceController.java | 97 +++++++++---------- .../dto/request/MarkAttendanceReq.java | 5 + .../dto/response/AttendanceCodeResponse.java | 9 ++ .../dto/response/AttendanceSlotRes.java | 6 +- .../dto/response/AttendanceStatusRes.java | 8 ++ .../Attendance/service/AttendanceService.java | 37 +++++-- .../src/main/resources/application.yml | 18 +++- 7 files changed, 118 insertions(+), 62 deletions(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AttendanceController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AttendanceController.java index 2401afb..103135c 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AttendanceController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AttendanceController.java @@ -2,93 +2,88 @@ import backend.pirocheck.Attendance.dto.request.MarkAttendanceReq; import backend.pirocheck.Attendance.dto.response.ApiResponse; -import backend.pirocheck.Attendance.dto.response.AttendanceCodeResponse; +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.entity.AttendanceCode; import backend.pirocheck.Attendance.service.AttendanceService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +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 @RequiredArgsConstructor @RequestMapping("/api/attendance") +@Tag(name = "출석관리", description = "학생용 출석 관련 API") public class AttendanceController { private final AttendanceService attendanceService; // 특정 유저의 출석 정보 + @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 = "사용자를 찾을 수 없음") + }) @GetMapping("/user") - public ApiResponse> getAttendanceByUserId(@RequestParam Long userId) { + public ApiResponse> getAttendanceByUserId( + @Parameter(description = "사용자 ID", required = true) + @RequestParam Long userId) { return ApiResponse.success(attendanceService.findByUserId(userId)); } // 특정 유저의 특정 일자 출석 정보 + @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 = "사용자 또는 날짜 정보를 찾을 수 없음") + }) @GetMapping("/user/date") public ApiResponse> getAttendanceByUserIdAndDate( + @Parameter(description = "사용자 ID", required = true) @RequestParam Long userId, + @Parameter(description = "조회할 날짜 (YYYY-MM-DD)", required = true) @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date ) { return ApiResponse.success(attendanceService.findByUserIdAndDate(userId, date)); } - // 출석체크 시작 - @PostMapping("/start") - public ApiResponse postAttendance() { - AttendanceCode code = attendanceService.generateCodeAndCreateAttendances(); - return ApiResponse.success(AttendanceCodeResponse.from(code)); - } - - // 현재 활성화된 출석코드 조회 - @GetMapping("/active-code") - public ApiResponse getActiveCode() { - Optional codeOpt = attendanceService.getActiveAttendanceCode(); - - if (codeOpt.isEmpty()) { - return ApiResponse.error("현재 활성화된 출석코드가 없습니다"); - } - - return ApiResponse.success(AttendanceCodeResponse.from(codeOpt.get())); - } - // 출석코드 비교 + @Operation(summary = "출석 체크", description = "출석 코드를 입력하여 출석을 체크합니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "출석 성공 또는 이미 출석 완료"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 출석 코드 또는 출석 체크 진행중이 아님") + }) @PostMapping("/mark") - public ApiResponse markAttendance(@RequestBody MarkAttendanceReq req) { - String result = attendanceService.markAttendance(req.getUserId(), req.getCode()); - - if (result.equals("출석이 성공적으로 처리되었습니다")) { - return ApiResponse.success(result, null); - } else { - return ApiResponse.error(result); - } - } - - // 출석체크 종료 (코드 직접 전달) - @PutMapping("/expire") - public ApiResponse expireAttendance(@RequestParam String code) { - String result = attendanceService.exprireAttendanceCode(code); + public ApiResponse markAttendance( + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "출석 체크 요청", required = true, + content = @Content(schema = @Schema(implementation = MarkAttendanceReq.class))) + @RequestBody MarkAttendanceReq req) { + AttendanceMarkResponse response = attendanceService.markAttendance(req.getUserId(), req.getCode()); - if (result.equals("출석 코드가 성공적으로 만료되었습니다")) { - return ApiResponse.success(result, null); - } else { - return ApiResponse.error(result); - } - } - - // 출석체크 종료 (가장 최근 활성화된 코드 자동 만료) - @PutMapping("/expire-latest") - public ApiResponse expireLatestAttendance() { - String result = attendanceService.expireLatestAttendanceCode(); + // statusCode가 SUCCESS 또는 ALREADY_MARKED인 경우 성공으로 처리 + boolean isSuccess = "SUCCESS".equals(response.getStatusCode()) || + "ALREADY_MARKED".equals(response.getStatusCode()); - if (result.equals("출석 코드가 성공적으로 만료되었습니다")) { - return ApiResponse.success(result, null); + if (isSuccess) { + return ApiResponse.success(response); } else { - return ApiResponse.error(result); + // 그 외의 경우 (NO_ACTIVE_SESSION, CODE_EXPIRED, ERROR)는 오류로 처리 + return ApiResponse.builder() + .success(false) + .message(response.getMessage()) + .data(response) + .build(); } } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/MarkAttendanceReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/MarkAttendanceReq.java index 779ead3..450728e 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/MarkAttendanceReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/request/MarkAttendanceReq.java @@ -1,9 +1,14 @@ package backend.pirocheck.Attendance.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; @Getter +@Schema(description = "출석 체크 요청") public class MarkAttendanceReq { + @Schema(description = "사용자 ID", example = "1") private Long userId; + + @Schema(description = "출석 코드", example = "1234") private String code; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceCodeResponse.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceCodeResponse.java index 4fe0b37..ca3dc4b 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceCodeResponse.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceCodeResponse.java @@ -1,6 +1,7 @@ package backend.pirocheck.Attendance.dto.response; import backend.pirocheck.Attendance.entity.AttendanceCode; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -12,10 +13,18 @@ @Builder @NoArgsConstructor @AllArgsConstructor +@Schema(description = "출석 코드 응답") public class AttendanceCodeResponse { + @Schema(description = "출석 코드", example = "1234") private String code; + + @Schema(description = "출석 날짜", example = "2025-06-24") private LocalDate date; + + @Schema(description = "출석 차시 (1, 2, 3)", example = "1") private int order; + + @Schema(description = "만료 여부", example = "false") private boolean isExpired; public static AttendanceCodeResponse from(AttendanceCode attendanceCode) { diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceSlotRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceSlotRes.java index aa1a5cc..8a804bd 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceSlotRes.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceSlotRes.java @@ -1,5 +1,6 @@ package backend.pirocheck.Attendance.dto.response; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -7,8 +8,11 @@ @Getter @Setter @AllArgsConstructor +@Schema(description = "출석 차시별 상태") public class AttendanceSlotRes { + @Schema(description = "출석 차시 (1, 2, 3)", example = "1") private int order; + + @Schema(description = "출석 여부", example = "true") private boolean status; - } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceStatusRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceStatusRes.java index 7a0cfa4..6716f8a 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceStatusRes.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceStatusRes.java @@ -1,5 +1,6 @@ package backend.pirocheck.Attendance.dto.response; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; @@ -8,7 +9,14 @@ @Getter @Setter +@Schema(description = "사용자 출석 상태") public class AttendanceStatusRes { + @Schema(description = "출석 날짜", example = "2025-06-24") private LocalDate date; + + @Schema(description = "주차", example = "1") + private int week; + + @Schema(description = "출석 차시별 상태 목록") private List slots; } 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 de65f49..ae2d5a8 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 @@ -3,6 +3,7 @@ import backend.pirocheck.User.entity.Role; import backend.pirocheck.User.entity.User; import backend.pirocheck.User.repository.UserRepository; +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.entity.Attendance; @@ -43,6 +44,11 @@ public AttendanceCode generateCodeAndCreateAttendances() { // 오늘 생성된 출석코드 개수 = 현재까지 생성된 차시 수 + 1 (MAX=3) int currentOrder = attendanceCodeRepository.countByDate(today) + 1; + + // 하루 최대 3회 출석 체크만 허용 + if (currentOrder > 3) { + throw new IllegalStateException("하루에 최대 3회까지만 출석 체크를 진행할 수 있습니다."); + } // 1. 출석 코드 생성 String code = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 10000)); @@ -119,25 +125,38 @@ public String exprireAttendanceCode(String code) { // 출석처리 함수 @Transactional - public String markAttendance(Long userId, String inputCode) { - // 1. 출석코드 일치 비교 - Optional validCodeOpt = attendanceCodeRepository.findByCodeAndDate(inputCode, LocalDate.now()); - + public AttendanceMarkResponse markAttendance(Long userId, String inputCode) { + // 오늘 날짜 + LocalDate today = LocalDate.now(); + + // 현재 활성화된 출석 코드가 있는지 확인 + List activeCodes = attendanceCodeRepository.findByDateAndIsExpiredFalse(today); + + // 활성화된 출석 코드가 없는 경우 + if (activeCodes.isEmpty()) { + return AttendanceMarkResponse.noActiveSession(); + } + + // 입력한 출석 코드와 일치하는 코드가 있는지 확인 + Optional validCodeOpt = attendanceCodeRepository.findByCodeAndDate(inputCode, today); + + // 입력한 출석 코드가 존재하지 않는 경우 if (validCodeOpt.isEmpty()) { - return "출석 코드가 존재하지 않습니다. 현재 출석 체크가 진행중이 아닙니다"; + return AttendanceMarkResponse.invalidCode(); } AttendanceCode code = validCodeOpt.get(); + // 입력한 출석 코드가 만료된 경우 if (code.isExpired()) { - return "출석 코드가 만료되었습니다"; + return AttendanceMarkResponse.codeExpired(); } // 2. 해당 유저의 출석 레코드 조회 Optional attendanceOpt = attendanceRepository.findByUserIdAndDateAndOrder(userId, code.getDate(), code.getOrder()); if (attendanceOpt.isEmpty()) { - return "출석 정보를 찾을 수 없습니다"; + return AttendanceMarkResponse.error("출석 정보를 찾을 수 없습니다"); } // 3. 출석 처리 @@ -145,13 +164,13 @@ public String markAttendance(Long userId, String inputCode) { // 이미 출석한 경우 if (attendance.isStatus()) { - return "이미 출석처리가 완료되었습니다"; + return AttendanceMarkResponse.alreadyMarked(); } attendance.setStatus(true); attendanceRepository.save(attendance); - return "출석이 성공적으로 처리되었습니다"; + return AttendanceMarkResponse.success(); } // 유저의 전체 출석 현황을 조회하는 함수 diff --git a/backend/pirocheck/src/main/resources/application.yml b/backend/pirocheck/src/main/resources/application.yml index b8b7096..bdef4aa 100644 --- a/backend/pirocheck/src/main/resources/application.yml +++ b/backend/pirocheck/src/main/resources/application.yml @@ -20,4 +20,20 @@ server: secure: false # HTTPS 전용 전송 (Https -> true로 바꿔야 함) same-site: Lax # CSRF 방지 timeout: 30m # 세션 타임아웃 30분 (30 minutes) - address: 0.0.0.0 \ No newline at end of file + address: 0.0.0.0 + +# Swagger 설정 +springdoc: + packages-to-scan: backend.pirocheck + default-consumes-media-type: application/json + default-produces-media-type: application/json + swagger-ui: + path: /swagger-ui.html + disable-swagger-default-url: true + display-request-duration: true + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /api-docs + cache: + disabled: true \ No newline at end of file