QPAT commited on
Commit
643cba5
·
1 Parent(s): fff2201

Fix some bug

Browse files
pom.xml CHANGED
@@ -35,6 +35,10 @@
35
  <groupId>org.springframework.boot</groupId>
36
  <artifactId>spring-boot-starter-data-jpa</artifactId>
37
  </dependency> -->
 
 
 
 
38
  <dependency>
39
  <groupId>org.springframework.boot</groupId>
40
  <artifactId>spring-boot-starter-mail</artifactId>
 
35
  <groupId>org.springframework.boot</groupId>
36
  <artifactId>spring-boot-starter-data-jpa</artifactId>
37
  </dependency> -->
38
+ <dependency>
39
+ <groupId>com.fasterxml.jackson.datatype</groupId>
40
+ <artifactId>jackson-datatype-jsr310</artifactId>
41
+ </dependency>
42
  <dependency>
43
  <groupId>org.springframework.boot</groupId>
44
  <artifactId>spring-boot-starter-mail</artifactId>
src/main/java/com/attendenceSystem/module/attendance/api/AttendanceApiController.java CHANGED
@@ -26,25 +26,25 @@ public class AttendanceApiController {
26
 
27
  private final AttendanceService attendanceService;
28
 
29
- @PostMapping("/check-in")
30
  public ResponseEntity<AttendanceResponse> checkIn() {
31
  AttendanceResponse resp = attendanceService.checkIn();
32
  return ResponseEntity.ok(resp);
33
  }
34
 
35
- @PostMapping("/check-out")
36
  public ResponseEntity<AttendanceResponse> checkOut() {
37
  AttendanceResponse resp = attendanceService.checkOut();
38
  return ResponseEntity.ok(resp);
39
  }
40
 
41
- @GetMapping("/history")
42
  public ResponseEntity<Page<AttendanceResponse>> getHistory(Pageable pageable) {
43
  Page<AttendanceResponse> page = attendanceService.getAttendanceHistory(pageable);
44
  return ResponseEntity.ok(page);
45
  }
46
 
47
- @PostMapping("/leave")
48
  public ResponseEntity<LeaveRequestResponse> createLeave(@RequestBody CreateLeaveRequest request) {
49
  LeaveRequestResponse resp = attendanceService.createLeaveRequest(request);
50
  return ResponseEntity.ok(resp);
@@ -56,7 +56,7 @@ public class AttendanceApiController {
56
  return ResponseEntity.ok(page);
57
  }
58
 
59
- @GetMapping("/leave/detail/{id}")
60
  public ResponseEntity<LeaveDetailResponse> getLeaveDetail(@PathVariable Long id) {
61
  LeaveDetailResponse detail = attendanceService.getLeaveDetail(id);
62
  return ResponseEntity.ok(detail);
 
26
 
27
  private final AttendanceService attendanceService;
28
 
29
+ @PostMapping(Routes.Attendance.CHECK_IN)
30
  public ResponseEntity<AttendanceResponse> checkIn() {
31
  AttendanceResponse resp = attendanceService.checkIn();
32
  return ResponseEntity.ok(resp);
33
  }
34
 
35
+ @PostMapping(Routes.Attendance.CHECK_OUT)
36
  public ResponseEntity<AttendanceResponse> checkOut() {
37
  AttendanceResponse resp = attendanceService.checkOut();
38
  return ResponseEntity.ok(resp);
39
  }
40
 
41
+ @GetMapping(Routes.Attendance.HISTORY)
42
  public ResponseEntity<Page<AttendanceResponse>> getHistory(Pageable pageable) {
43
  Page<AttendanceResponse> page = attendanceService.getAttendanceHistory(pageable);
44
  return ResponseEntity.ok(page);
45
  }
46
 
47
+ @PostMapping(Routes.Attendance.LEAVE)
48
  public ResponseEntity<LeaveRequestResponse> createLeave(@RequestBody CreateLeaveRequest request) {
49
  LeaveRequestResponse resp = attendanceService.createLeaveRequest(request);
50
  return ResponseEntity.ok(resp);
 
56
  return ResponseEntity.ok(page);
57
  }
58
 
59
+ @GetMapping(Routes.Attendance.LEAVE_DETAIL + "/{id}")
60
  public ResponseEntity<LeaveDetailResponse> getLeaveDetail(@PathVariable Long id) {
61
  LeaveDetailResponse detail = attendanceService.getLeaveDetail(id);
62
  return ResponseEntity.ok(detail);
src/main/java/com/attendenceSystem/module/attendance/api/AttendanceManagerApiController.java CHANGED
@@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
12
  import com.attendenceSystem.constant.Routes;
13
  import com.attendenceSystem.module.attendance.dto.response.AttendanceResponse;
14
  import com.attendenceSystem.module.attendance.dto.response.ManagerStatsResponse;
 
15
  import com.attendenceSystem.module.attendance.service.AttendanceService;
16
 
17
  import lombok.RequiredArgsConstructor;
@@ -32,7 +33,7 @@ public class AttendanceManagerApiController {
32
  com.attendenceSystem.module.attendance.entity.enums.AttendanceStatus attendanceStatus = null;
33
  if (status != null && !status.isEmpty()) {
34
  try {
35
- attendanceStatus = com.attendenceSystem.module.attendance.entity.enums.AttendanceStatus.valueOf(status);
36
  } catch (IllegalArgumentException e) {
37
  // Invalid status, ignore
38
  }
@@ -47,10 +48,10 @@ public class AttendanceManagerApiController {
47
  @RequestParam(required = false) LocalDate startDate,
48
  @RequestParam(required = false) LocalDate endDate,
49
  @RequestParam(required = false) String status) {
50
- com.attendenceSystem.module.attendance.entity.enums.AttendanceStatus attendanceStatus = null;
51
  if (status != null && !status.isEmpty()) {
52
  try {
53
- attendanceStatus = com.attendenceSystem.module.attendance.entity.enums.AttendanceStatus.valueOf(status);
54
  } catch (IllegalArgumentException e) {
55
  // Invalid status, ignore
56
  }
 
12
  import com.attendenceSystem.constant.Routes;
13
  import com.attendenceSystem.module.attendance.dto.response.AttendanceResponse;
14
  import com.attendenceSystem.module.attendance.dto.response.ManagerStatsResponse;
15
+ import com.attendenceSystem.module.attendance.entity.enums.AttendanceStatus;
16
  import com.attendenceSystem.module.attendance.service.AttendanceService;
17
 
18
  import lombok.RequiredArgsConstructor;
 
33
  com.attendenceSystem.module.attendance.entity.enums.AttendanceStatus attendanceStatus = null;
34
  if (status != null && !status.isEmpty()) {
35
  try {
36
+ attendanceStatus = AttendanceStatus.valueOf(status);
37
  } catch (IllegalArgumentException e) {
38
  // Invalid status, ignore
39
  }
 
48
  @RequestParam(required = false) LocalDate startDate,
49
  @RequestParam(required = false) LocalDate endDate,
50
  @RequestParam(required = false) String status) {
51
+ AttendanceStatus attendanceStatus = null;
52
  if (status != null && !status.isEmpty()) {
53
  try {
54
+ attendanceStatus = AttendanceStatus.valueOf(status);
55
  } catch (IllegalArgumentException e) {
56
  // Invalid status, ignore
57
  }
src/main/java/com/attendenceSystem/module/user/entity/enums/Department.java CHANGED
@@ -7,8 +7,8 @@ import lombok.RequiredArgsConstructor;
7
  @RequiredArgsConstructor
8
  public enum Department {
9
  DE213("DE213", "DE213-X7A9", "Phòng DE213"),
10
- DE212("DE212", "DE212-X7A9", "Phòng DE212"),
11
- DE211("DE211", "DE211-X7A9", "Phòng DE211");
12
 
13
  private final String roomCode;
14
  private final String joinCode;
 
7
  @RequiredArgsConstructor
8
  public enum Department {
9
  DE213("DE213", "DE213-X7A9", "Phòng DE213"),
10
+ DE212("DE212", "DE212-H3O4", "Phòng DE212"),
11
+ DE211("DE211", "DE211-FE2O3", "Phòng DE211");
12
 
13
  private final String roomCode;
14
  private final String joinCode;
src/main/resources/static/js/employee/room-code.js CHANGED
@@ -1,13 +1,12 @@
 
 
 
 
 
 
1
  const roomSelect = document.getElementById("roomSelect");
2
  const roomCode = document.getElementById("roomCode");
3
 
4
- const roomCodes = {
5
- DE211: "DE211-X7A9",
6
- DE212: "DE212-LP81",
7
- DE213: "DE213-KM32"
8
- };
9
-
10
  roomSelect.addEventListener("change", () => {
11
- roomCode.textContent =
12
- roomCodes[roomSelect.value] || "--------";
13
  });
 
1
+ // Lấy dữ liệu từ biến global đã được HTML (Thymeleaf) nạp sẵn
2
+ const roomCodes = window.serverRoomCodes || {};
3
+
4
+ console.log("Dữ liệu đồng bộ từ Backend:", roomCodes);
5
+
6
+ // Logic xử lý giao diện của FE giữ nguyên
7
  const roomSelect = document.getElementById("roomSelect");
8
  const roomCode = document.getElementById("roomCode");
9
 
 
 
 
 
 
 
10
  roomSelect.addEventListener("change", () => {
11
+ roomCode.textContent = roomCodes[roomSelect.value] || "--------";
 
12
  });
src/main/resources/templates/cms/absent/absent-list.html CHANGED
@@ -131,7 +131,7 @@
131
  </td>
132
 
133
 
134
- <!--
135
  <td>
136
  <div class="action-group">
137
 
@@ -148,7 +148,7 @@
148
  </form>
149
 
150
  </div>
151
- </td> -->
152
  </tr>
153
 
154
  </tbody>
 
131
  </td>
132
 
133
 
134
+
135
  <td>
136
  <div class="action-group">
137
 
 
148
  </form>
149
 
150
  </div>
151
+ </td>
152
  </tr>
153
 
154
  </tbody>
src/main/resources/templates/cms/account/employee-list.html CHANGED
@@ -51,7 +51,8 @@
51
 
52
  <select>
53
  <option>Tất cả phòng ban</option>
54
- <option th:each="dept : ${departments}" th:value="${dept.name()}" th:text="${dept.displayName}"></option>
 
55
  </select>
56
 
57
  <select>
@@ -98,7 +99,8 @@
98
 
99
  <div class="user">
100
 
101
- <div class="avatar" th:text="${#strings.substring(user.fullName(), 0, 1)}">H</div>
 
102
 
103
  <strong th:text="${user.fullName()}">Nguyễn Minh Hải</strong>
104
 
@@ -130,10 +132,12 @@
130
  Chi tiết
131
  </a>
132
 
133
- <form th:action="@{/manager/accounts/update/{id}(id=${user.id()})}" method="post" style="display:inline;">
 
134
  <select name="department" onchange="this.form.submit()">
135
  <option value="">Chuyển phòng</option>
136
- <option th:each="dept : ${departments}" th:value="${dept.name()}" th:text="${dept.displayName}"></option>
 
137
  </select>
138
  </form>
139
 
@@ -201,15 +205,23 @@
201
  </div>
202
  <button id="closePopup" class="close-btn">
203
  <i class="fas fa-times">Đóng</i>
204
-
205
  </button>
206
  </div>
207
 
208
  </div>
209
  </section>
210
- <script src="/js/employee/employee-popup.js"></script>
211
- <script src="/js/employee/room-code.js"></script>
212
- <script src="/js/employee/copy-code.js"></script>
 
 
 
 
 
 
 
 
213
  </body>
214
 
215
  </html>
 
51
 
52
  <select>
53
  <option>Tất cả phòng ban</option>
54
+ <option th:each="dept : ${departments}" th:value="${dept.name()}"
55
+ th:text="${dept.displayName}"></option>
56
  </select>
57
 
58
  <select>
 
99
 
100
  <div class="user">
101
 
102
+ <div class="avatar" th:text="${#strings.substring(user.fullName(), 0, 1)}">H
103
+ </div>
104
 
105
  <strong th:text="${user.fullName()}">Nguyễn Minh Hải</strong>
106
 
 
132
  Chi tiết
133
  </a>
134
 
135
+ <form th:action="@{/manager/accounts/update/{id}(id=${user.id()})}"
136
+ method="post" style="display:inline;">
137
  <select name="department" onchange="this.form.submit()">
138
  <option value="">Chuyển phòng</option>
139
+ <option th:each="dept : ${departments}" th:value="${dept.name()}"
140
+ th:text="${dept.displayName}"></option>
141
  </select>
142
  </form>
143
 
 
205
  </div>
206
  <button id="closePopup" class="close-btn">
207
  <i class="fas fa-times">Đóng</i>
208
+
209
  </button>
210
  </div>
211
 
212
  </div>
213
  </section>
214
+ <script th:inline="javascript">
215
+ // Tạo một biến global để cầu nối sang file JS tĩnh
216
+ window.serverRoomCodes = {};
217
+
218
+ /*[# th:each="dept : ${T(com.attendenceSystem.module.user.entity.enums.Department).values()}"]*/
219
+ window.serverRoomCodes[[${ dept.roomCode }]] = [[${ dept.joinCode }]];
220
+ /*[/]*/
221
+ </script>
222
+ <script th:src="@{/js/employee/employee-popup.js}"></script>
223
+ <script th:src="@{/js/employee/js/room-code.js}"></script>
224
+ <script th:src="@{/js/employee/copy-code.js}"></script>
225
  </body>
226
 
227
  </html>
src/main/resources/templates/cms/attendance/attendance-manual.html ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" xmlns:th="http://www.thymeleaf.org">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Document</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
src/main/resources/templates/cms/document/document-list.html CHANGED
@@ -128,7 +128,7 @@
128
  '<td>' + report.title + '</td>' +
129
  '<td>' + formattedDate + '</td>' +
130
  '<td>' + filesHtml + '</td>' +
131
- '<td>' + linkHtml + '</td>' +
132
 
133
  tableBody.appendChild(row);
134
  });
 
128
  '<td>' + report.title + '</td>' +
129
  '<td>' + formattedDate + '</td>' +
130
  '<td>' + filesHtml + '</td>' +
131
+ '<td>' + linkHtml + '</td>'
132
 
133
  tableBody.appendChild(row);
134
  });
src/main/resources/templates/cms/face-id/faceID-create.html CHANGED
@@ -40,19 +40,19 @@
40
 
41
  <!-- THÔNG TIN -->
42
  <div class="face-register-meta">
43
-
 
 
 
 
 
 
 
44
  <h3>Thông tin đăng ký</h3>
45
 
46
- <label for="roomCode">Mã phòng</label>
47
- <input type="text"
48
- id="roomCode"
49
- placeholder="Ví dụ: P101">
50
-
51
  <div class="face-sample-summary">
52
 
53
- <button id="faceSampleCount"
54
- class="face-sample-count-btn"
55
- type="button">
56
  0 / 5 mẫu
57
  </button>
58
 
@@ -73,21 +73,18 @@
73
  <div class="panel-header">
74
  <h3>Camera đăng ký</h3>
75
 
76
- <button id="faceRegisterToggleBtn"
77
- type="button">
78
  Bật camera
79
  </button>
80
  </div>
81
 
82
  <!-- MODE -->
83
  <div class="mode-tabs">
84
- <button class="active"
85
- type="button">
86
  Đăng ký mới
87
  </button>
88
 
89
- <button type="button"
90
- id="rescanBtn">
91
  Quét lại
92
  </button>
93
  </div>
@@ -112,14 +109,10 @@
112
  <!-- VIDEO -->
113
  <div class="video-wrap">
114
 
115
- <video id="video"
116
- autoplay
117
- playsinline
118
- muted>
119
  </video>
120
 
121
- <canvas id="captureCanvas"
122
- style="display:none;">
123
  </canvas>
124
 
125
  </div>
@@ -127,22 +120,18 @@
127
  <!-- ACTION -->
128
  <div class="action-row">
129
 
130
- <button type="button"
131
- id="captureFaceBtn">
132
  📷 Chụp mẫu
133
  </button>
134
 
135
- <button type="button"
136
- id="resetFaceScanBtn"
137
- class="secondary">
138
  Làm lại
139
  </button>
140
 
141
  </div>
142
 
143
  <!-- MESSAGE -->
144
- <div id="faceRegisterMessage"
145
- class="message">
146
  </div>
147
 
148
  </div>
@@ -279,7 +268,7 @@
279
  // Gửi ảnh lên server
280
  async function submitSamples() {
281
  const roomCode = document.getElementById('roomCode').value;
282
-
283
  try {
284
  const response = await fetch('/api/face-id/register', {
285
  method: 'POST',
 
40
 
41
  <!-- THÔNG TIN -->
42
  <div class="face-register-meta">
43
+ <h3>Chuyển phòng nhanh</h3>
44
+ <h4>Lưu ý: Khi đã chuyển phòng</h4>
45
+ <div>
46
+ <input type="text" id="roomCode" placeholder="Nhập mã phòng (VD: P101)">
47
+ <button id="btnSwitchRoom" type="button">
48
+ Chuyển phòng
49
+ </button>
50
+ </div>
51
  <h3>Thông tin đăng ký</h3>
52
 
 
 
 
 
 
53
  <div class="face-sample-summary">
54
 
55
+ <button id="faceSampleCount" class="face-sample-count-btn" type="button">
 
 
56
  0 / 5 mẫu
57
  </button>
58
 
 
73
  <div class="panel-header">
74
  <h3>Camera đăng ký</h3>
75
 
76
+ <button id="faceRegisterToggleBtn" type="button">
 
77
  Bật camera
78
  </button>
79
  </div>
80
 
81
  <!-- MODE -->
82
  <div class="mode-tabs">
83
+ <button class="active" type="button">
 
84
  Đăng ký mới
85
  </button>
86
 
87
+ <button type="button" id="rescanBtn">
 
88
  Quét lại
89
  </button>
90
  </div>
 
109
  <!-- VIDEO -->
110
  <div class="video-wrap">
111
 
112
+ <video id="video" autoplay playsinline muted>
 
 
 
113
  </video>
114
 
115
+ <canvas id="captureCanvas" style="display:none;">
 
116
  </canvas>
117
 
118
  </div>
 
120
  <!-- ACTION -->
121
  <div class="action-row">
122
 
123
+ <button type="button" id="captureFaceBtn">
 
124
  📷 Chụp mẫu
125
  </button>
126
 
127
+ <button type="button" id="resetFaceScanBtn" class="secondary">
 
 
128
  Làm lại
129
  </button>
130
 
131
  </div>
132
 
133
  <!-- MESSAGE -->
134
+ <div id="faceRegisterMessage" class="message">
 
135
  </div>
136
 
137
  </div>
 
268
  // Gửi ảnh lên server
269
  async function submitSamples() {
270
  const roomCode = document.getElementById('roomCode').value;
271
+
272
  try {
273
  const response = await fetch('/api/face-id/register', {
274
  method: 'POST',