Compare commits
merge into: yoganandhank:main
yoganandhank:main
yoganandhank:master
pull from: yoganandhank:master
yoganandhank:main
yoganandhank:master
1 Commits
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
7e3561a146 |
first commit
|
8 months ago |
82 changed files with 3513 additions and 7550 deletions
-
6pom.xml
-
6src/main/java/com/gcc/flagpoles_services/FlagpolesApplication.java
-
12src/main/java/com/gcc/flagpoles_services/configuration/AppConfig.java
-
23src/main/java/com/gcc/flagpoles_services/configuration/DataSourceConfig.java
-
2src/main/java/com/gcc/flagpoles_services/configuration/JacksonConfiguration.java
-
25src/main/java/com/gcc/flagpoles_services/configuration/SecurityConfig.java
-
2src/main/java/com/gcc/flagpoles_services/configuration/ThymeleafConfig.java
-
16src/main/java/com/gcc/flagpoles_services/configuration/WebMvcConfig.java
-
42src/main/java/com/gcc/flagpoles_services/controller/APIController.java
-
30src/main/java/com/gcc/flagpoles_services/controller/AdminController.java
-
4src/main/java/com/gcc/flagpoles_services/controller/CustomErrorController.java
-
2src/main/java/com/gcc/flagpoles_services/controller/DateTimeUtil.java
-
6src/main/java/com/gcc/flagpoles_services/controller/FileController.java
-
6src/main/java/com/gcc/flagpoles_services/controller/MainController.java
-
36src/main/java/com/gcc/flagpoles_services/controller/MenuController.java
-
6src/main/java/com/gcc/flagpoles_services/controller/login.java
-
2src/main/java/com/gcc/flagpoles_services/entity/AppModuleAccessEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/AppModuleEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/AppUserEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/AppUserGroupEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/MenuItemAccessEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/MenuItemEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/SubMenuItemAccessEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/SubMenuItemEntity.java
-
2src/main/java/com/gcc/flagpoles_services/entity/UserActivityLog.java
-
2src/main/java/com/gcc/flagpoles_services/entity/UserInfoEntity.java
-
425src/main/java/com/gcc/flagpoles_services/flagpoles/controller/FlagPoleApiController.java
-
53src/main/java/com/gcc/flagpoles_services/flagpoles/controller/MainController.java
-
248src/main/java/com/gcc/flagpoles_services/flagpoles/service/FlagpoleSMSService.java
-
1356src/main/java/com/gcc/flagpoles_services/flagpoles/service/RdoService.java
-
41src/main/java/com/gcc/flagpoles_services/flagpoles/util/MessageUtility.java
-
36src/main/java/com/gcc/flagpoles_services/interceptor/AppInterceptor.java
-
2src/main/java/com/gcc/flagpoles_services/modeldata/ErrorResponse.java
-
4src/main/java/com/gcc/flagpoles_services/repository/AppModuleAccessRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/AppModuleRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/AppUserGroupRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/AppUserRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/MenuItemAccessRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/MenuItemRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/SubMenuItemAccessRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/SubMenuItemRepository.java
-
4src/main/java/com/gcc/flagpoles_services/repository/UserActivityLogRepository.java
-
2src/main/java/com/gcc/flagpoles_services/repository/UserInfoRepository.java
-
2src/main/java/com/gcc/flagpoles_services/service/Base64Util.java
-
2src/main/java/com/gcc/flagpoles_services/service/CustomUserDetails.java
-
6src/main/java/com/gcc/flagpoles_services/service/CustomUserDetailsService.java
-
2src/main/java/com/gcc/flagpoles_services/service/LoginUserInfo.java
-
6src/main/java/com/gcc/flagpoles_services/service/UserActivityService.java
-
6src/main/java/com/gcc/flagpoles_services/service/UserActivityTimelineService.java
-
163src/main/java/com/gcc/swm_services/swm/controller/AdminController.java
-
35src/main/java/com/gcc/swm_services/swm/controller/DropDownApiController.java
-
71src/main/java/com/gcc/swm_services/swm/controller/MainController.java
-
145src/main/java/com/gcc/swm_services/swm/controller/SwmAdminApiController.java
-
202src/main/java/com/gcc/swm_services/swm/controller/SwmApiController.java
-
510src/main/java/com/gcc/swm_services/swm/service/AddDetailsService.java
-
37src/main/java/com/gcc/swm_services/swm/service/DropDownService.java
-
2src/main/resources/application-dev.properties
-
4src/main/resources/application-prod.properties
-
4src/main/resources/application.properties
-
98src/main/resources/templates/error-403.html
-
2src/main/resources/templates/fragments/modules/base/footer.html
-
2src/main/resources/templates/fragments/modules/base/head.html
-
4src/main/resources/templates/fragments/modules/base/header.html
-
2src/main/resources/templates/fragments/modules/base/login-head.html
-
2src/main/resources/templates/fragments/modules/base/script.html
-
6src/main/resources/templates/index.html
-
6src/main/resources/templates/login.html
-
4src/main/resources/templates/modules/admin/user-group-access.html
-
2src/main/resources/templates/modules/admin/user-list.html
-
480src/main/resources/templates/modules/flagpole/approvedandrejectedlist.html
-
930src/main/resources/templates/modules/flagpole/requestlist.html
-
754src/main/resources/templates/modules/swm/biogas.html
-
416src/main/resources/templates/modules/swm/cdwaste.html
-
764src/main/resources/templates/modules/swm/eachreport.html
-
447src/main/resources/templates/modules/swm/gwtcwaste.html
-
421src/main/resources/templates/modules/swm/incinerator.html
-
428src/main/resources/templates/modules/swm/mcc.html
-
424src/main/resources/templates/modules/swm/mrf.html
-
418src/main/resources/templates/modules/swm/plastingbaling.html
-
944src/main/resources/templates/modules/swm/reports.html
-
442src/main/resources/templates/modules/swm/requestlist.html
-
419src/main/resources/templates/modules/swm/windrow.html
@ -1,13 +1,13 @@ |
|||||
package com.gcc.swm_services; |
|
||||
|
package com.gcc.flagpoles_services; |
||||
|
|
||||
import org.springframework.boot.SpringApplication; |
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
|
||||
@SpringBootApplication |
@SpringBootApplication |
||||
public class SwmApplication { |
|
||||
|
public class FlagpolesApplication { |
||||
|
|
||||
public static void main(String[] args) { |
public static void main(String[] args) { |
||||
SpringApplication.run(SwmApplication.class, args); |
|
||||
|
SpringApplication.run(FlagpolesApplication.class, args); |
||||
} |
} |
||||
|
|
||||
} |
} |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.configuration; |
|
||||
|
package com.gcc.flagpoles_services.configuration; |
||||
|
|
||||
import org.springframework.context.annotation.Bean; |
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
import org.springframework.context.annotation.Configuration; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.configuration; |
|
||||
|
package com.gcc.flagpoles_services.configuration; |
||||
|
|
||||
import org.springframework.context.annotation.Bean; |
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
import org.springframework.context.annotation.Configuration; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.controller; |
|
||||
|
package com.gcc.flagpoles_services.controller; |
||||
|
|
||||
import org.springframework.stereotype.Service; |
import org.springframework.stereotype.Service; |
||||
import java.time.LocalDateTime; |
import java.time.LocalDateTime; |
||||
@ -1,12 +1,12 @@ |
|||||
package com.gcc.swm_services.controller; |
|
||||
|
package com.gcc.flagpoles_services.controller; |
||||
|
|
||||
import org.springframework.stereotype.Controller; |
import org.springframework.stereotype.Controller; |
||||
import org.springframework.ui.Model; |
import org.springframework.ui.Model; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
|
||||
@RequestMapping("/swm") |
|
||||
@Controller("swmLoginController") |
|
||||
|
@RequestMapping("/flagpoles") |
||||
|
@Controller("flagpolesLoginController") |
||||
public class login { |
public class login { |
||||
|
|
||||
@GetMapping("/login") |
@GetMapping("/login") |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import java.time.LocalDateTime; |
import java.time.LocalDateTime; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.entity; |
|
||||
|
package com.gcc.flagpoles_services.entity; |
||||
|
|
||||
import javax.persistence.Column; |
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
import javax.persistence.Entity; |
||||
@ -0,0 +1,425 @@ |
|||||
|
package com.gcc.flagpoles_services.flagpoles.controller; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.http.HttpStatus; |
||||
|
import org.springframework.http.ResponseEntity; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||
|
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.client.RestTemplate; |
||||
|
|
||||
|
import com.gcc.flagpoles_services.configuration.AppConfig; |
||||
|
import com.gcc.flagpoles_services.flagpoles.service.FlagpoleSMSService; |
||||
|
import com.gcc.flagpoles_services.flagpoles.service.RdoService; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/flagpoles/api/flagpoleregistration") |
||||
|
public class FlagPoleApiController { |
||||
|
|
||||
|
@Autowired |
||||
|
private RdoService rdoService; |
||||
|
|
||||
|
@Autowired |
||||
|
private FlagpoleSMSService flagpoleSMSService; |
||||
|
|
||||
|
private final RestTemplate restTemplate; |
||||
|
private final AppConfig appConfig; |
||||
|
|
||||
|
@Autowired |
||||
|
public FlagPoleApiController(RestTemplate restTemplate, AppConfig appConfig) { |
||||
|
this.restTemplate = restTemplate; |
||||
|
this.appConfig = appConfig; |
||||
|
} |
||||
|
|
||||
|
// new |
||||
|
// @GetMapping("/getAllDetails") |
||||
|
// public ResponseEntity<?> getAllRequestDetails( |
||||
|
// @RequestParam String userLogin, |
||||
|
// @RequestParam(required = false) String startDate, |
||||
|
// @RequestParam(required = false) String endDate) { |
||||
|
|
||||
|
// try { |
||||
|
// List<Map<String, Object>> result = |
||||
|
// rdoService.getAllRequestDetailsByUserLogin( |
||||
|
// userLogin, startDate, endDate); |
||||
|
|
||||
|
// // 🔥 Attach HISTORY per refid |
||||
|
// for (Map<String, Object> record : result) { |
||||
|
// String refid = (String) record.get("refid"); |
||||
|
|
||||
|
// // List<Map<String, Object>> history = |
||||
|
// // rdoService.getRequestHistoryByRefId(refid); |
||||
|
// List<Map<String, Object>> history = |
||||
|
// rdoService.getOfficerFeedbackHistoryByRefId(refid, |
||||
|
// userLogin); |
||||
|
|
||||
|
// record.put("history", history); |
||||
|
// } |
||||
|
|
||||
|
// return ResponseEntity.ok( |
||||
|
// Map.of( |
||||
|
// "status", "success", |
||||
|
// "count", result.size(), |
||||
|
// "data", result)); |
||||
|
|
||||
|
// } catch (Exception e) { |
||||
|
// e.printStackTrace(); |
||||
|
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
// .body(Map.of( |
||||
|
// "status", "error", |
||||
|
// "message", "Failed to fetch data", |
||||
|
// "error", e.getMessage())); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
// @GetMapping("/getAllDetails") |
||||
|
// public ResponseEntity<?> getAllRequestDetails( |
||||
|
// @RequestParam String gccUserId, |
||||
|
// @RequestParam(required = false) String startDate, |
||||
|
// @RequestParam(required = false) String endDate) { |
||||
|
|
||||
|
// try { |
||||
|
|
||||
|
// // 🔥 Resolve username ONCE (backend trust) |
||||
|
// String username = rdoService.getUsernameByUserId(gccUserId); |
||||
|
// if (username == null) { |
||||
|
// throw new RuntimeException("Invalid gccUserId : " + gccUserId); |
||||
|
// } |
||||
|
|
||||
|
// List<Map<String, Object>> result = |
||||
|
// rdoService.getAllRequestDetailsByUserLogin( |
||||
|
// gccUserId, startDate, endDate); |
||||
|
|
||||
|
// // 🔥 Attach HISTORY per refid (dept-wise) |
||||
|
// for (Map<String, Object> record : result) { |
||||
|
// String refid = (String) record.get("refid"); |
||||
|
|
||||
|
// List<Map<String, Object>> history = |
||||
|
// rdoService.getOfficerFeedbackHistoryByRefId( |
||||
|
// refid, username); |
||||
|
|
||||
|
// record.put("history", history); |
||||
|
// } |
||||
|
|
||||
|
// return ResponseEntity.ok( |
||||
|
// Map.of( |
||||
|
// "status", "success", |
||||
|
// "count", result.size(), |
||||
|
// "data", result)); |
||||
|
|
||||
|
// } catch (Exception e) { |
||||
|
// e.printStackTrace(); |
||||
|
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
// .body(Map.of( |
||||
|
// "status", "error", |
||||
|
// "message", "Failed to fetch data", |
||||
|
// "error", e.getMessage())); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
@GetMapping("/getAllDetails") |
||||
|
public ResponseEntity<?> getAllRequestDetails( |
||||
|
@RequestParam String gccUserId, |
||||
|
@RequestParam(required = false) String startDate, |
||||
|
@RequestParam(required = false) String endDate) { |
||||
|
|
||||
|
try { |
||||
|
|
||||
|
/* 🔥 Normalize input (username OR id → gccuserid) */ |
||||
|
gccUserId = rdoService.resolveGccUserId(gccUserId); |
||||
|
|
||||
|
List<Map<String, Object>> result = rdoService.getAllRequestDetailsByUserLogin(gccUserId, |
||||
|
startDate, endDate); |
||||
|
|
||||
|
/* 🔥 Attach HISTORY per refid */ |
||||
|
for (Map<String, Object> record : result) { |
||||
|
|
||||
|
String refid = (String) record.get("refid"); |
||||
|
|
||||
|
List<Map<String, Object>> history = rdoService.getOfficerFeedbackHistoryByRefId(refid, |
||||
|
gccUserId); |
||||
|
|
||||
|
record.put("history", history); |
||||
|
} |
||||
|
|
||||
|
return ResponseEntity.ok( |
||||
|
Map.of( |
||||
|
"status", "success", |
||||
|
"count", result.size(), |
||||
|
"data", result)); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
.body(Map.of( |
||||
|
"status", "error", |
||||
|
"message", "Failed to fetch data", |
||||
|
"error", e.getMessage())); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// old |
||||
|
// @PostMapping("/rdo/updateDecision") |
||||
|
// public ResponseEntity<?> updateRdoDecision( |
||||
|
// @RequestParam String refid, |
||||
|
// @RequestParam String status, |
||||
|
// @RequestParam String remarks, |
||||
|
// @RequestParam String approvedBy) { |
||||
|
|
||||
|
// int count = rdoService.updateRdoDecision(refid, status, remarks, approvedBy); |
||||
|
|
||||
|
// if (count > 0) { |
||||
|
// return ResponseEntity.ok(Map.of( |
||||
|
// "status", "SUCCESS", |
||||
|
// "message", "Decision updated successfully")); |
||||
|
// } else { |
||||
|
// return ResponseEntity.badRequest().body(Map.of( |
||||
|
// "status", "FAILED", |
||||
|
// "message", "Unable to update decision")); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
// @PostMapping("/rdo/updateDecision") |
||||
|
// public ResponseEntity<?> updateRdoDecision( |
||||
|
// @RequestParam String refid, |
||||
|
// @RequestParam String status, |
||||
|
// @RequestParam String remarks, |
||||
|
// @RequestParam String gccUserId) { |
||||
|
|
||||
|
// try { |
||||
|
|
||||
|
// /* 🔥 Normalize username OR id → gccuserid */ |
||||
|
// gccUserId = rdoService.resolveGccUserId(gccUserId); |
||||
|
|
||||
|
// int count = rdoService.updateRdoDecision( |
||||
|
// refid, status, remarks, gccUserId); |
||||
|
|
||||
|
// if (count > 0) { |
||||
|
// return ResponseEntity.ok(Map.of( |
||||
|
// "status", "SUCCESS", |
||||
|
// "message", "Decision updated successfully")); |
||||
|
// } else { |
||||
|
// return ResponseEntity.badRequest().body(Map.of( |
||||
|
// "status", "FAILED", |
||||
|
// "message", "Unable to update decision")); |
||||
|
// } |
||||
|
|
||||
|
// } catch (Exception e) { |
||||
|
// e.printStackTrace(); |
||||
|
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
// .body(Map.of( |
||||
|
// "status", "ERROR", |
||||
|
// "message", e.getMessage())); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
@PostMapping("/officer/updateDecision") |
||||
|
public ResponseEntity<?> updateOfficerDecision( |
||||
|
@RequestParam String refid, |
||||
|
@RequestParam String status, |
||||
|
@RequestParam String remarks, |
||||
|
@RequestParam String gccUserId, |
||||
|
@RequestParam String username) { |
||||
|
|
||||
|
try { |
||||
|
|
||||
|
/* 🔥 Normalize username OR id → gccuserid */ |
||||
|
gccUserId = rdoService.resolveGccUserId(gccUserId); |
||||
|
|
||||
|
int count = rdoService.updateOfficerDecision( |
||||
|
refid, |
||||
|
status, |
||||
|
remarks, |
||||
|
gccUserId, |
||||
|
username); |
||||
|
|
||||
|
if (count > 0) { |
||||
|
return ResponseEntity.ok(Map.of( |
||||
|
"status", "SUCCESS", |
||||
|
"message", "Decision updated successfully")); |
||||
|
} else { |
||||
|
return ResponseEntity.badRequest().body(Map.of( |
||||
|
"status", "FAILED", |
||||
|
"message", "Unable to update decision")); |
||||
|
} |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
.body(Map.of( |
||||
|
"status", "ERROR", |
||||
|
"message", e.getMessage())); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// old |
||||
|
// @GetMapping("/getApprovedAndRejectedDetails") |
||||
|
// public ResponseEntity<?> getApprovedRequestDetails( |
||||
|
// @RequestParam String userLogin, |
||||
|
// @RequestParam(required = false) String startDate, |
||||
|
// @RequestParam(required = false) String endDate, |
||||
|
// @RequestParam(required = false) String status) { |
||||
|
|
||||
|
// try { |
||||
|
// List<Map<String, Object>> result = |
||||
|
// rdoService.getRdoApprovedRequestDetailsByUserLogin( |
||||
|
// userLogin, startDate, endDate, status); |
||||
|
|
||||
|
// return ResponseEntity.ok( |
||||
|
// Map.of( |
||||
|
// "status", "success", |
||||
|
// "count", result.size(), |
||||
|
// "data", result)); |
||||
|
|
||||
|
// } catch (Exception e) { |
||||
|
// e.printStackTrace(); |
||||
|
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
// .body( |
||||
|
// Map.of( |
||||
|
// "status", "error", |
||||
|
// "message", "Failed to fetch data", |
||||
|
// "error", e.getMessage())); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
// new |
||||
|
// @GetMapping("/getApprovedAndRejectedDetails") |
||||
|
// public ResponseEntity<?> getApprovedRequestDetails( |
||||
|
// @RequestParam String userLogin, |
||||
|
// @RequestParam(required = false) String startDate, |
||||
|
// @RequestParam(required = false) String endDate, |
||||
|
// @RequestParam(required = false) String status) { |
||||
|
|
||||
|
// try { |
||||
|
// List<Map<String, Object>> result = |
||||
|
// rdoService.getRdoApprovedRequestDetailsByUserLogin( |
||||
|
// userLogin, startDate, endDate, status); |
||||
|
|
||||
|
// // 🔥 Attach HISTORY per refid |
||||
|
// for (Map<String, Object> record : result) { |
||||
|
// String refid = (String) record.get("refid"); |
||||
|
|
||||
|
// List<Map<String, Object>> history = |
||||
|
// rdoService.getRequestHistoryByRefId(refid); |
||||
|
|
||||
|
// record.put("history", history); |
||||
|
// } |
||||
|
|
||||
|
// return ResponseEntity.ok( |
||||
|
// Map.of( |
||||
|
// "status", "success", |
||||
|
// "count", result.size(), |
||||
|
// "data", result)); |
||||
|
|
||||
|
// } catch (Exception e) { |
||||
|
// e.printStackTrace(); |
||||
|
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
// .body(Map.of( |
||||
|
// "status", "error", |
||||
|
// "message", "Failed to fetch data", |
||||
|
// "error", e.getMessage())); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
// @GetMapping("/getApprovedAndRejectedDetails") |
||||
|
// public ResponseEntity<?> getApprovedRequestDetails( |
||||
|
// @RequestParam String userLogin, |
||||
|
// @RequestParam(required = false) String startDate, |
||||
|
// @RequestParam(required = false) String endDate) { |
||||
|
|
||||
|
// try { |
||||
|
// List<Map<String, Object>> result = |
||||
|
// rdoService.getRdoApprovedRequestDetailsByUserLogin( |
||||
|
// userLogin, startDate, endDate, null); |
||||
|
|
||||
|
// for (Map<String, Object> record : result) { |
||||
|
// String refid = (String) record.get("refid"); |
||||
|
|
||||
|
// // 🔥 NEW: officer feedback history |
||||
|
// List<Map<String, Object>> history = |
||||
|
// rdoService.getOfficerFeedbackHistoryByRefId(refid, |
||||
|
// userLogin); |
||||
|
|
||||
|
// record.put("history", history); |
||||
|
// } |
||||
|
|
||||
|
// return ResponseEntity.ok(Map.of( |
||||
|
// "status", "success", |
||||
|
// "count", result.size(), |
||||
|
// "data", result)); |
||||
|
|
||||
|
// } catch (Exception e) { |
||||
|
// e.printStackTrace(); |
||||
|
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
// .body(Map.of( |
||||
|
// "status", "error", |
||||
|
// "message", "Failed to fetch data", |
||||
|
// "error", e.getMessage())); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
@GetMapping("/getApprovedAndRejectedDetails") |
||||
|
public ResponseEntity<?> getApprovedRequestDetails( |
||||
|
@RequestParam String gccUserId, |
||||
|
@RequestParam(required = false) String startDate, |
||||
|
@RequestParam(required = false) String endDate) { |
||||
|
|
||||
|
try { |
||||
|
|
||||
|
/* 🔥 Normalize username OR id → gccuserid */ |
||||
|
gccUserId = rdoService.resolveGccUserId(gccUserId); |
||||
|
|
||||
|
/* 🔥 Fetch approved & rejected records */ |
||||
|
List<Map<String, Object>> result = rdoService.getRdoApprovedRequestDetailsByUserLogin( |
||||
|
gccUserId, startDate, endDate, null); |
||||
|
|
||||
|
/* 🔥 Attach officer feedback history per refid */ |
||||
|
for (Map<String, Object> record : result) { |
||||
|
|
||||
|
String refid = (String) record.get("refid"); |
||||
|
|
||||
|
List<Map<String, Object>> history = rdoService.getOfficerFeedbackHistoryByRefId(refid, |
||||
|
gccUserId); |
||||
|
|
||||
|
record.put("history", history); |
||||
|
} |
||||
|
|
||||
|
return ResponseEntity.ok(Map.of( |
||||
|
"status", "success", |
||||
|
"count", result.size(), |
||||
|
"data", result)); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
.body(Map.of( |
||||
|
"status", "error", |
||||
|
"message", "Failed to fetch approved/rejected data", |
||||
|
"error", e.getMessage())); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/sendApprovedMessage") |
||||
|
public String sendApprovedMessage(@RequestParam String mobileNo, |
||||
|
@RequestParam String refid) { |
||||
|
|
||||
|
return flagpoleSMSService.userrequestApprovedsms(mobileNo, refid); |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/sendRejectMessage") |
||||
|
public String sendRejectMessage(@RequestParam String mobileNo, @RequestParam String refid) { |
||||
|
return flagpoleSMSService.userrequestRejectedsms(mobileNo, refid); |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/sendUnauthorizedMessage") |
||||
|
public String sendUnauthorizedMessage(@RequestParam String mobileNo, @RequestParam String location, |
||||
|
@RequestParam String fineAmount, @RequestParam String refid) { |
||||
|
return flagpoleSMSService.unauthorizedFlagPoleSms(mobileNo, location, fineAmount, refid); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
package com.gcc.flagpoles_services.flagpoles.controller; |
||||
|
|
||||
|
import org.springframework.stereotype.Controller; |
||||
|
import org.springframework.ui.Model; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
|
||||
|
import com.gcc.flagpoles_services.service.LoginUserInfo; |
||||
|
|
||||
|
@RequestMapping("/flagpoles/list") |
||||
|
@Controller("flagpolesController") |
||||
|
public class MainController { |
||||
|
|
||||
|
@GetMapping("/requestlist") |
||||
|
public String home(Model model) { |
||||
|
|
||||
|
String LoginUserId = LoginUserInfo.getLoginUserId(); |
||||
|
model.addAttribute("LoginUserId", LoginUserId); |
||||
|
|
||||
|
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
||||
|
model.addAttribute("officer_name", officer_name); |
||||
|
|
||||
|
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
||||
|
model.addAttribute("UserRole", UserRole); |
||||
|
|
||||
|
return "modules/flagpole/requestlist"; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/approvedandrejectedlist") |
||||
|
public String batches(Model model) { |
||||
|
String LoginUserId = LoginUserInfo.getLoginUserId(); |
||||
|
model.addAttribute("LoginUserId", LoginUserId); |
||||
|
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
||||
|
model.addAttribute("officer_name", officer_name); |
||||
|
|
||||
|
String UserRole = LoginUserInfo.getUserRole(); |
||||
|
model.addAttribute("UserRole", UserRole); |
||||
|
return "modules/flagpole/approvedandrejectedlist"; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/reports") |
||||
|
public String dataentry(Model model) { |
||||
|
String LoginUserId = LoginUserInfo.getLoginUserId(); |
||||
|
model.addAttribute("LoginUserId", LoginUserId); |
||||
|
|
||||
|
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
||||
|
model.addAttribute("officer_name", officer_name); |
||||
|
|
||||
|
String UserRole = LoginUserInfo.getUserRole(); |
||||
|
model.addAttribute("UserRole", UserRole); |
||||
|
return "modules/flagpole/reports"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,248 @@ |
|||||
|
package com.gcc.flagpoles_services.flagpoles.service; |
||||
|
|
||||
|
import java.io.BufferedReader; |
||||
|
import java.io.InputStreamReader; |
||||
|
import java.net.HttpURLConnection; |
||||
|
import java.net.URL; |
||||
|
import java.net.URLEncoder; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import com.gcc.flagpoles_services.configuration.AppConfig; |
||||
|
import com.gcc.flagpoles_services.flagpoles.util.MessageUtility; |
||||
|
|
||||
|
@Service |
||||
|
public class FlagpoleSMSService { |
||||
|
|
||||
|
@Autowired |
||||
|
private AppConfig appConfig; |
||||
|
|
||||
|
@Autowired |
||||
|
private MessageUtility messageUtility; |
||||
|
|
||||
|
private final String key = "pfTEYN6H"; |
||||
|
|
||||
|
public String sendBookingSuccesssms(String mobileNo, String requestId) { |
||||
|
|
||||
|
String message = "Your Flag Pole permission request has been submitted successfully. " |
||||
|
+ "Request ID: " + requestId |
||||
|
+ ". You will be notified once the status is updated. By GCC"; |
||||
|
|
||||
|
// Encode message and fix colon issue (gateway not decoding %3A) |
||||
|
String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8) |
||||
|
.replace("%3A", ":"); |
||||
|
|
||||
|
String urlString = appConfig.getOtpUrl() |
||||
|
+ "from=GCCCRP" |
||||
|
+ "&key=" + key |
||||
|
+ "&sender=GCCCRP" |
||||
|
+ "&to=" + mobileNo |
||||
|
+ "&body=" + encodedMsg |
||||
|
+ "&entityid=1401572690000011081" |
||||
|
+ "&templateid=1407176959297472163"; |
||||
|
|
||||
|
System.out.println("SMS URL:- " + urlString); |
||||
|
|
||||
|
String response = messageUtility.sendSMS(urlString); |
||||
|
System.out.println("SMS RESPONSE:- " + response); |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
public String userrequestApprovedsms(String mobileNo, String requestId) { |
||||
|
|
||||
|
String message = "Your Flag Pole permission request has been approved. " |
||||
|
+ "Request ID: " + requestId |
||||
|
+ ". Please proceed as per the permitted guidelines. By GCC"; |
||||
|
|
||||
|
// Encode message and fix colon issue (gateway not decoding %3A) |
||||
|
String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8) |
||||
|
.replace("%3A", ":"); |
||||
|
|
||||
|
String urlString = appConfig.getOtpUrl() |
||||
|
+ "from=GCCCRP" |
||||
|
+ "&key=" + key |
||||
|
+ "&sender=GCCCRP" |
||||
|
+ "&to=" + mobileNo |
||||
|
+ "&body=" + encodedMsg |
||||
|
+ "&entityid=1401572690000011081" |
||||
|
+ "&templateid=1407176959304753543"; |
||||
|
|
||||
|
System.out.println("SMS URL:- " + urlString); |
||||
|
|
||||
|
String response = messageUtility.sendSMS(urlString); |
||||
|
System.out.println("SMS RESPONSE:- " + response); |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
// public String userrequestRejectedsms(String mobileNo, String requestId) { |
||||
|
|
||||
|
// String message = "Your Flag Pole permission request has been rejected. " |
||||
|
// + "Request ID: " + requestId + ". " |
||||
|
// + "Review the details in the portal |
||||
|
// https://gccservices.in/flagpolesregistration/status\n" |
||||
|
// + "By GCC"; |
||||
|
|
||||
|
// // ONLY encode. Do NOT replace %3A |
||||
|
// String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8); |
||||
|
|
||||
|
// String urlString = appConfig.getOtpUrl() |
||||
|
// + "from=GCCCRP" |
||||
|
// + "&key=" + key |
||||
|
// + "&sender=GCCCRP" |
||||
|
// + "&to=" + mobileNo |
||||
|
// + "&body=" + encodedMsg |
||||
|
// + "&entityid=1401572690000011081" |
||||
|
// + "&templateid=1407176959315374790"; |
||||
|
|
||||
|
// System.out.println("SMS URL:- " + urlString); |
||||
|
|
||||
|
// String response = messageUtility.sendSMS(urlString); |
||||
|
// System.out.println("SMS RESPONSE:- " + response); |
||||
|
|
||||
|
// return response; |
||||
|
// } |
||||
|
|
||||
|
public String userrequestRejectedsms(String mobileNo, String requestId) { |
||||
|
|
||||
|
try { |
||||
|
|
||||
|
String url = "https://gccservices.in/flagpolesregistration/status"; |
||||
|
|
||||
|
String message = "Your Flag Pole permission request has been rejected. Request ID: " + requestId |
||||
|
+ ". Review the details in the portal " + url + "\r\nBy GCC"; |
||||
|
|
||||
|
String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8); |
||||
|
|
||||
|
String urlString = appConfig.getOtpUrl() |
||||
|
+ "from=GCCCRP" |
||||
|
+ "&key=" + key |
||||
|
+ "&sender=GCCCRP" |
||||
|
+ "&to=" + mobileNo |
||||
|
+ "&body=" + encodedMsg |
||||
|
+ "&entityid=1401572690000011081" |
||||
|
+ "&templateid=1407176959315374790"; |
||||
|
|
||||
|
System.out.println("FINAL SMS URL:- " + urlString); |
||||
|
|
||||
|
URL apiUrl = new URL(urlString); |
||||
|
HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection(); |
||||
|
conn.setRequestMethod("GET"); |
||||
|
conn.setConnectTimeout(15000); |
||||
|
conn.setReadTimeout(15000); |
||||
|
|
||||
|
BufferedReader in = new BufferedReader( |
||||
|
new InputStreamReader(conn.getInputStream())); |
||||
|
String inputLine; |
||||
|
StringBuilder content = new StringBuilder(); |
||||
|
|
||||
|
while ((inputLine = in.readLine()) != null) { |
||||
|
content.append(inputLine); |
||||
|
} |
||||
|
|
||||
|
in.close(); |
||||
|
conn.disconnect(); |
||||
|
|
||||
|
System.out.println("DIRECT SMS RESPONSE:- " + content.toString()); |
||||
|
|
||||
|
return content.toString(); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return "FAILED"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// public String unauthorizedFlagPoleSms(String mobileNo, |
||||
|
// String location, |
||||
|
// String fineAmount, |
||||
|
// String requestId) { |
||||
|
|
||||
|
// String message = "An unauthorized flag pole installation was found at " + |
||||
|
// location + ". " |
||||
|
// + "Fine amount: Rs. " + fineAmount |
||||
|
// + " to be paid at |
||||
|
// https://gccservices.in/flagpolesregistration/paymentform?requestId=" |
||||
|
// + requestId + " to avoid further action.\n" |
||||
|
// + "By GCC"; |
||||
|
|
||||
|
// // Encode full message |
||||
|
// String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8); |
||||
|
|
||||
|
// String urlString = appConfig.getOtpUrl() |
||||
|
// + "from=GCCCRP" |
||||
|
// + "&key=" + key |
||||
|
// + "&sender=GCCCRP" |
||||
|
// + "&to=" + mobileNo |
||||
|
// + "&body=" + encodedMsg |
||||
|
// + "&entityid=1401572690000011081" |
||||
|
// + "&templateid=1407176959335259899"; // replace with actual template id |
||||
|
|
||||
|
// System.out.println("SMS URL:- " + urlString); |
||||
|
|
||||
|
// String response = messageUtility.sendSMS(urlString); |
||||
|
// System.out.println("SMS RESPONSE:- " + response); |
||||
|
|
||||
|
// return response; |
||||
|
// } |
||||
|
|
||||
|
public String unauthorizedFlagPoleSms(String mobileNo, |
||||
|
String location, |
||||
|
String fineAmount, |
||||
|
String requestId) { |
||||
|
|
||||
|
try { |
||||
|
|
||||
|
String paymentUrl = "https://gccservices.in/flagpolesregistration/paymentform?requestId=" |
||||
|
+ requestId; |
||||
|
|
||||
|
String message = "An unauthorized flag pole installation was found at " + location + ". " |
||||
|
+ "Fine amount: Rs. " + fineAmount |
||||
|
+ " to be paid at " + paymentUrl |
||||
|
+ " to avoid further action.\r\n" |
||||
|
+ "By GCC"; |
||||
|
|
||||
|
String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8); |
||||
|
|
||||
|
String urlString = appConfig.getOtpUrl() |
||||
|
+ "from=GCCCRP" |
||||
|
+ "&key=" + key |
||||
|
+ "&sender=GCCCRP" |
||||
|
+ "&to=" + mobileNo |
||||
|
+ "&body=" + encodedMsg |
||||
|
+ "&entityid=1401572690000011081" |
||||
|
+ "&templateid=1407176959335259899"; |
||||
|
|
||||
|
System.out.println("FINAL SMS URL:- " + urlString); |
||||
|
|
||||
|
URL apiUrl = new URL(urlString); |
||||
|
HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection(); |
||||
|
conn.setRequestMethod("GET"); |
||||
|
conn.setConnectTimeout(15000); |
||||
|
conn.setReadTimeout(15000); |
||||
|
|
||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); |
||||
|
String inputLine; |
||||
|
StringBuilder content = new StringBuilder(); |
||||
|
|
||||
|
while ((inputLine = in.readLine()) != null) { |
||||
|
content.append(inputLine); |
||||
|
} |
||||
|
|
||||
|
in.close(); |
||||
|
conn.disconnect(); |
||||
|
|
||||
|
System.out.println("DIRECT SMS RESPONSE:- " + content.toString()); |
||||
|
|
||||
|
return content.toString(); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return "FAILED"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
1356
src/main/java/com/gcc/flagpoles_services/flagpoles/service/RdoService.java
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,41 @@ |
|||||
|
package com.gcc.flagpoles_services.flagpoles.util; |
||||
|
|
||||
|
import java.net.HttpURLConnection; |
||||
|
import java.net.URL; |
||||
|
|
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.web.client.RestTemplate; |
||||
|
|
||||
|
@Service |
||||
|
public class MessageUtility { |
||||
|
|
||||
|
public String sendMsg(String msgUrl) { |
||||
|
System.out.println("Whatsapp URL :-" + msgUrl); |
||||
|
|
||||
|
String response = ""; |
||||
|
try { |
||||
|
HttpURLConnection connection = null; |
||||
|
|
||||
|
URL url = new URL(msgUrl); |
||||
|
connection = (HttpURLConnection) url.openConnection(); |
||||
|
connection.setRequestMethod("GET"); |
||||
|
|
||||
|
int responseCode = connection.getResponseCode(); |
||||
|
response = responseCode + ""; |
||||
|
System.out.println("Response Code: " + responseCode); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
public String sendSMS(String SMS_Url) { |
||||
|
// System.out.println("SMS URL:- " + SMS_Url); |
||||
|
RestTemplate restTemplate = new RestTemplate(); |
||||
|
String response = restTemplate.getForObject(SMS_Url, String.class); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.modeldata; |
|
||||
|
package com.gcc.flagpoles_services.modeldata; |
||||
|
|
||||
public class ErrorResponse { |
public class ErrorResponse { |
||||
|
|
||||
@ -1,10 +1,10 @@ |
|||||
package com.gcc.swm_services.repository; |
|
||||
|
package com.gcc.flagpoles_services.repository; |
||||
|
|
||||
import org.springframework.data.jpa.repository.JpaRepository; |
import org.springframework.data.jpa.repository.JpaRepository; |
||||
import org.springframework.data.jpa.repository.Query; |
import org.springframework.data.jpa.repository.Query; |
||||
import org.springframework.stereotype.Repository; |
import org.springframework.stereotype.Repository; |
||||
|
|
||||
import com.gcc.swm_services.entity.AppUserGroupEntity; |
|
||||
|
import com.gcc.flagpoles_services.entity.AppUserGroupEntity; |
||||
|
|
||||
import javax.transaction.Transactional; |
import javax.transaction.Transactional; |
||||
|
|
||||
@ -1,11 +1,11 @@ |
|||||
package com.gcc.swm_services.repository; |
|
||||
|
package com.gcc.flagpoles_services.repository; |
||||
|
|
||||
import java.util.List; |
import java.util.List; |
||||
|
|
||||
import org.springframework.data.jpa.repository.JpaRepository; |
import org.springframework.data.jpa.repository.JpaRepository; |
||||
import org.springframework.stereotype.Repository; |
import org.springframework.stereotype.Repository; |
||||
|
|
||||
import com.gcc.swm_services.entity.UserActivityLog; |
|
||||
|
import com.gcc.flagpoles_services.entity.UserActivityLog; |
||||
|
|
||||
import javax.transaction.Transactional; |
import javax.transaction.Transactional; |
||||
|
|
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.repository; |
|
||||
|
package com.gcc.flagpoles_services.repository; |
||||
|
|
||||
import org.springframework.data.jpa.repository.Query; |
import org.springframework.data.jpa.repository.Query; |
||||
import org.springframework.stereotype.Repository; |
import org.springframework.stereotype.Repository; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.service; |
|
||||
|
package com.gcc.flagpoles_services.service; |
||||
|
|
||||
import java.util.Base64; |
import java.util.Base64; |
||||
|
|
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.service; |
|
||||
|
package com.gcc.flagpoles_services.service; |
||||
|
|
||||
import org.springframework.security.core.GrantedAuthority; |
import org.springframework.security.core.GrantedAuthority; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
import org.springframework.security.core.userdetails.UserDetails; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.gcc.swm_services.service; |
|
||||
|
package com.gcc.flagpoles_services.service; |
||||
|
|
||||
import java.time.LocalDate; |
import java.time.LocalDate; |
||||
import java.time.temporal.ChronoUnit; |
import java.time.temporal.ChronoUnit; |
||||
@ -1,10 +1,10 @@ |
|||||
package com.gcc.swm_services.service; |
|
||||
|
package com.gcc.flagpoles_services.service; |
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
import org.springframework.stereotype.Service; |
||||
|
|
||||
import com.gcc.swm_services.entity.UserActivityLog; |
|
||||
import com.gcc.swm_services.repository.UserActivityLogRepository; |
|
||||
|
import com.gcc.flagpoles_services.entity.UserActivityLog; |
||||
|
import com.gcc.flagpoles_services.repository.UserActivityLogRepository; |
||||
|
|
||||
import java.time.LocalDateTime; |
import java.time.LocalDateTime; |
||||
|
|
||||
@ -1,10 +1,10 @@ |
|||||
package com.gcc.swm_services.service; |
|
||||
|
package com.gcc.flagpoles_services.service; |
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
import org.springframework.stereotype.Service; |
||||
|
|
||||
import com.gcc.swm_services.entity.UserActivityLog; |
|
||||
import com.gcc.swm_services.repository.UserActivityLogRepository; |
|
||||
|
import com.gcc.flagpoles_services.entity.UserActivityLog; |
||||
|
import com.gcc.flagpoles_services.repository.UserActivityLogRepository; |
||||
|
|
||||
import java.util.List; |
import java.util.List; |
||||
|
|
||||
@ -1,163 +0,0 @@ |
|||||
package com.gcc.swm_services.swm.controller; |
|
||||
|
|
||||
import org.springframework.stereotype.Controller; |
|
||||
import org.springframework.ui.Model; |
|
||||
import org.springframework.web.bind.annotation.GetMapping; |
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
|
||||
|
|
||||
import com.gcc.swm_services.service.LoginUserInfo; |
|
||||
|
|
||||
@Controller("AdminswmController") |
|
||||
@RequestMapping("/swm/adminfacilities") |
|
||||
public class AdminController { |
|
||||
@GetMapping("/mcc") |
|
||||
public String mcc(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 1; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/mcc"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/windrow") |
|
||||
public String windrow(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 2; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/windrow"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/biocng") |
|
||||
public String biocng(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 3; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/biocng"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/biogas") |
|
||||
public String biogas(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 4; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/biogas"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/gwtcwaste") |
|
||||
public String gwtcwaste(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 5; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/gwtcwaste"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/mrf") |
|
||||
public String mrf(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 6; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/mrf"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/incinerator") |
|
||||
public String incinerator(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 7; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/incinerator"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/plastingbaling") |
|
||||
public String plastingbaling(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
int facilityTypeId = 8; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
return "modules/swm/plastingbaling"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/cdwaste") |
|
||||
public String cdwaste(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 9; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/cdwaste"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/reports") |
|
||||
public String reports(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
int facilityTypeId = 9; // Plastic Baling Centre |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
return "modules/swm/reports"; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,35 +0,0 @@ |
|||||
package com.gcc.swm_services.swm.controller; |
|
||||
|
|
||||
import java.util.Collections; |
|
||||
import java.util.List; |
|
||||
|
|
||||
import java.util.Map; |
|
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.http.HttpStatus; |
|
||||
import org.springframework.http.ResponseEntity; |
|
||||
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 com.gcc.swm_services.swm.service.DropDownService; |
|
||||
|
|
||||
@RestController |
|
||||
@RequestMapping("/swm/api/dropdown") |
|
||||
public class DropDownApiController { |
|
||||
|
|
||||
@Autowired |
|
||||
private DropDownService dropDownService; |
|
||||
|
|
||||
@GetMapping("/getfacilitiestypelist") |
|
||||
public List<Map<String, Object>> getFacilitiesTypeList() { |
|
||||
return dropDownService.getFacilitiesTypeList(); |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/getzoneslist") |
|
||||
public List<Map<String, Object>> getZonesList() { |
|
||||
return dropDownService.getZonesList(); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,71 +0,0 @@ |
|||||
package com.gcc.swm_services.swm.controller; |
|
||||
|
|
||||
import javax.servlet.http.HttpSession; |
|
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.stereotype.Controller; |
|
||||
import org.springframework.ui.Model; |
|
||||
import org.springframework.web.bind.annotation.GetMapping; |
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
|
||||
|
|
||||
import com.gcc.swm_services.service.LoginUserInfo; |
|
||||
import com.gcc.swm_services.swm.service.AddDetailsService; |
|
||||
|
|
||||
@Controller("swmController") |
|
||||
@RequestMapping("/swm/facilities") |
|
||||
public class MainController { |
|
||||
|
|
||||
@Autowired |
|
||||
private AddDetailsService addDetailsService; |
|
||||
|
|
||||
@GetMapping("/adddetails") |
|
||||
public String home(Model model, HttpSession session) { |
|
||||
|
|
||||
String loginUserId = LoginUserInfo.getLoginUserId(); // String |
|
||||
String officerName = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
String userRole = LoginUserInfo.getUserRole(); |
|
||||
|
|
||||
// store in session |
|
||||
session.setAttribute("gcc_user_id", loginUserId); |
|
||||
session.setAttribute("username", officerName); |
|
||||
|
|
||||
// 🔑 derive facility type |
|
||||
int gccUserId = Integer.parseInt(loginUserId); |
|
||||
int dpid = addDetailsService.getDpidByGccUserId(gccUserId); |
|
||||
|
|
||||
// DIRECT MAPPING (as fixed earlier) |
|
||||
int facilityTypeId = dpid; |
|
||||
|
|
||||
// 🔑 THIS WAS MISSING |
|
||||
boolean isTwoWeightFacility = (facilityTypeId == 5); |
|
||||
boolean isWeightTypeFacility = (facilityTypeId == 5 || facilityTypeId == 9); |
|
||||
|
|
||||
// add to model |
|
||||
model.addAttribute("LoginUserId", loginUserId); |
|
||||
model.addAttribute("officer_name", officerName); |
|
||||
model.addAttribute("UserRole", userRole); |
|
||||
model.addAttribute("facilityTypeId", facilityTypeId); |
|
||||
model.addAttribute("isTwoWeightFacility", isTwoWeightFacility); |
|
||||
model.addAttribute("isWeightTypeFacility", isWeightTypeFacility); |
|
||||
|
|
||||
return "modules/swm/requestlist"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/approvelist") |
|
||||
public String batches() { |
|
||||
return "modules/swm/approvelist"; |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/reports") |
|
||||
public String dataentry(Model model) { |
|
||||
String LoginUserId = LoginUserInfo.getLoginUserId(); |
|
||||
model.addAttribute("LoginUserId", LoginUserId); |
|
||||
|
|
||||
String officer_name = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
model.addAttribute("officer_name", officer_name); |
|
||||
|
|
||||
String UserRole = LoginUserInfo.getUserRole(); // rdo_north / rdo_central |
|
||||
model.addAttribute("UserRole", UserRole); |
|
||||
return "modules/swm/eachreport"; |
|
||||
} |
|
||||
} |
|
||||
@ -1,145 +0,0 @@ |
|||||
package com.gcc.swm_services.swm.controller; |
|
||||
|
|
||||
import java.time.LocalDate; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.format.annotation.DateTimeFormat; |
|
||||
import org.springframework.http.HttpStatus; |
|
||||
import org.springframework.http.ResponseEntity; |
|
||||
import org.springframework.web.bind.annotation.GetMapping; |
|
||||
import org.springframework.web.bind.annotation.PostMapping; |
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
|
||||
import org.springframework.web.bind.annotation.RequestParam; |
|
||||
import org.springframework.web.bind.annotation.RestController; |
|
||||
|
|
||||
import com.gcc.swm_services.service.LoginUserInfo; |
|
||||
import com.gcc.swm_services.swm.service.AddDetailsService; |
|
||||
|
|
||||
@RestController |
|
||||
@RequestMapping("/swm/api/admin") |
|
||||
public class SwmAdminApiController { |
|
||||
|
|
||||
@Autowired |
|
||||
private AddDetailsService addDetailsService; |
|
||||
|
|
||||
@PostMapping("/addfacility") |
|
||||
public ResponseEntity<?> addFacilityForAdmin( |
|
||||
|
|
||||
@RequestParam int facilityTypeId, |
|
||||
@RequestParam int zoneId, |
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate reqDate, |
|
||||
@RequestParam Double weight, |
|
||||
@RequestParam(required = false) Double weight1, |
|
||||
@RequestParam(required = false) String weightType, |
|
||||
@RequestParam String createdBy) { |
|
||||
|
|
||||
try { |
|
||||
// 🔴 Validation |
|
||||
if (facilityTypeId < 1 || facilityTypeId > 9) { |
|
||||
throw new IllegalArgumentException("Invalid facility type"); |
|
||||
} |
|
||||
|
|
||||
if (zoneId <= 0) { |
|
||||
throw new IllegalArgumentException("Invalid zone"); |
|
||||
} |
|
||||
|
|
||||
if (reqDate == null) { |
|
||||
throw new IllegalArgumentException("Request date is required"); |
|
||||
} |
|
||||
|
|
||||
if (weight == null) { |
|
||||
throw new IllegalArgumentException("Weight is required"); |
|
||||
} |
|
||||
|
|
||||
if (facilityTypeId == 5) { |
|
||||
if (weight < 0) { |
|
||||
throw new IllegalArgumentException("Weight cannot be negative"); |
|
||||
} |
|
||||
} else { |
|
||||
if (weight <= 0) { |
|
||||
throw new IllegalArgumentException("Weight must be greater than zero"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 🔴 Facility type 5 → TWO weights + weightType |
|
||||
if (facilityTypeId == 5) { |
|
||||
if (weight1 == null) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Second weight is required for GW & TC Waste facility"); |
|
||||
} |
|
||||
if (weightType == null || weightType.isBlank()) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Weight type (KDG / PDG) is required"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (facilityTypeId == 9) { |
|
||||
|
|
||||
if (weightType == null || weightType.isBlank()) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Weight type (KDG / PDG) is required"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 🔐 Admin username for audit |
|
||||
// String createdBy = LoginUserInfo.getCurrentUserDetails().getUsername(); |
|
||||
|
|
||||
// 🔵 SAVE |
|
||||
addDetailsService.addFacility( |
|
||||
facilityTypeId, |
|
||||
zoneId, |
|
||||
reqDate, |
|
||||
createdBy, |
|
||||
weight, |
|
||||
weight1, |
|
||||
weightType); |
|
||||
|
|
||||
return ResponseEntity.ok( |
|
||||
Map.of("status", "SUCCESS", "message", "Added successfully")); |
|
||||
|
|
||||
} catch (IllegalArgumentException ex) { |
|
||||
return ResponseEntity.badRequest().body( |
|
||||
Map.of("status", "ERROR", "message", ex.getMessage())); |
|
||||
} catch (Exception ex) { |
|
||||
ex.printStackTrace(); |
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body( |
|
||||
Map.of("status", "ERROR", "message", "Internal server error")); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/reports") |
|
||||
public ResponseEntity<?> getZoneTargetPercentage( |
|
||||
@RequestParam String fromDate, |
|
||||
@RequestParam String toDate) { |
|
||||
|
|
||||
if (fromDate == null || toDate == null || |
|
||||
fromDate.isBlank() || toDate.isBlank()) { |
|
||||
|
|
||||
return ResponseEntity.badRequest().body( |
|
||||
Map.of("status", "ERROR", "message", "Date range is required")); |
|
||||
} |
|
||||
|
|
||||
return ResponseEntity.ok( |
|
||||
Map.of( |
|
||||
"status", "SUCCESS", |
|
||||
"data", addDetailsService.getZoneTargetPercentage(fromDate, toDate))); |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/singledayreports") |
|
||||
public ResponseEntity<?> getZoneTargetPercentagePerDay( |
|
||||
@RequestParam String Date) { |
|
||||
|
|
||||
if (Date == null || Date.isBlank()) { |
|
||||
|
|
||||
return ResponseEntity.badRequest().body( |
|
||||
Map.of("status", "ERROR", "message", "Date range is required")); |
|
||||
} |
|
||||
|
|
||||
return ResponseEntity.ok( |
|
||||
Map.of( |
|
||||
"status", "SUCCESS", |
|
||||
"data", addDetailsService.getZoneTargetPercentageForOneDay(Date))); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,202 +0,0 @@ |
|||||
package com.gcc.swm_services.swm.controller; |
|
||||
|
|
||||
import java.time.LocalDate; |
|
||||
import java.util.List; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
import javax.servlet.http.HttpSession; |
|
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.format.annotation.DateTimeFormat; |
|
||||
import org.springframework.http.HttpStatus; |
|
||||
import org.springframework.http.ResponseEntity; |
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken; |
|
||||
import org.springframework.security.core.Authentication; |
|
||||
import org.springframework.security.core.context.SecurityContextHolder; |
|
||||
import org.springframework.web.bind.annotation.GetMapping; |
|
||||
import org.springframework.web.bind.annotation.PostMapping; |
|
||||
import org.springframework.web.bind.annotation.RequestMapping; |
|
||||
import org.springframework.web.bind.annotation.RequestParam; |
|
||||
import org.springframework.web.bind.annotation.RestController; |
|
||||
|
|
||||
import com.gcc.swm_services.service.LoginUserInfo; |
|
||||
import com.gcc.swm_services.swm.service.AddDetailsService; |
|
||||
|
|
||||
@RestController |
|
||||
@RequestMapping("/swm/api/facilities") |
|
||||
public class SwmApiController { |
|
||||
|
|
||||
@Autowired |
|
||||
private AddDetailsService addDetailsService; |
|
||||
|
|
||||
// @PostMapping("/addfacility") |
|
||||
// public ResponseEntity<?> addFacility( |
|
||||
|
|
||||
// @RequestParam int zoneId, |
|
||||
// @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate |
|
||||
// reqDate, |
|
||||
// @RequestParam Double weight, |
|
||||
// @RequestParam(required = false) Double weight1, |
|
||||
// HttpSession session) { |
|
||||
|
|
||||
// try { |
|
||||
// // 🔴 Validation |
|
||||
// if (zoneId <= 0) { |
|
||||
// throw new IllegalArgumentException("Invalid zone"); |
|
||||
// } |
|
||||
|
|
||||
// if (reqDate == null) { |
|
||||
// throw new IllegalArgumentException("Request date is required"); |
|
||||
// } |
|
||||
|
|
||||
// if (weight == null || weight <= 0) { |
|
||||
// throw new IllegalArgumentException("Weight must be greater than zero"); |
|
||||
// } |
|
||||
|
|
||||
// // 🔐 GET LOGIN DATA FROM SESSION (CORRECT WAY) |
|
||||
// Object gccUserIdObj = session.getAttribute("gcc_user_id"); |
|
||||
// Object usernameObj = session.getAttribute("username"); |
|
||||
|
|
||||
// if (gccUserIdObj == null || usernameObj == null) { |
|
||||
// throw new IllegalStateException("User session expired. Please login again."); |
|
||||
// } |
|
||||
|
|
||||
// int gccUserId = Integer.parseInt(gccUserIdObj.toString()); |
|
||||
// String username = usernameObj.toString(); |
|
||||
|
|
||||
// // 🔐 DB MAPPING |
|
||||
// int dpid = addDetailsService.getDpidByGccUserId(gccUserId); |
|
||||
// int facilityTypeId = addDetailsService.getFacilityTypeIdByDpid(dpid); |
|
||||
|
|
||||
// if (facilityTypeId == 5 && (weight1 == null || weight1 <= 0)) { |
|
||||
// throw new IllegalArgumentException( |
|
||||
// "Second weight is required for GW & TC Waste facility"); |
|
||||
// } |
|
||||
|
|
||||
// addDetailsService.addFacility( |
|
||||
// facilityTypeId, |
|
||||
// zoneId, |
|
||||
// reqDate, |
|
||||
// username, |
|
||||
// weight, |
|
||||
// weight1); |
|
||||
|
|
||||
// return ResponseEntity.ok( |
|
||||
// Map.of("status", "SUCCESS", "message", "Facility added successfully")); |
|
||||
|
|
||||
// } catch (IllegalArgumentException | IllegalStateException ex) { |
|
||||
// return ResponseEntity.badRequest().body( |
|
||||
// Map.of("status", "ERROR", "message", ex.getMessage())); |
|
||||
// } catch (Exception ex) { |
|
||||
// ex.printStackTrace(); |
|
||||
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body( |
|
||||
// Map.of("status", "ERROR", "message", "Internal server error")); |
|
||||
// } |
|
||||
// } |
|
||||
|
|
||||
@PostMapping("/addfacility") |
|
||||
public ResponseEntity<?> addFacility( |
|
||||
@RequestParam int zoneId, |
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate reqDate, |
|
||||
@RequestParam Double weight, |
|
||||
@RequestParam(required = false) Double weight1, |
|
||||
@RequestParam(required = false) String weightType, // ✅ ADDED |
|
||||
HttpSession session) { |
|
||||
|
|
||||
try { |
|
||||
|
|
||||
// 🔐 Session values |
|
||||
Object gccUserIdObj = session.getAttribute("gcc_user_id"); |
|
||||
Object usernameObj = session.getAttribute("username"); |
|
||||
int gccUserId = Integer.parseInt(gccUserIdObj.toString()); |
|
||||
String username = usernameObj.toString(); |
|
||||
|
|
||||
// 🔐 gcc_user_id → dpid → facilityTypeId |
|
||||
int dpid = addDetailsService.getDpidByGccUserId(gccUserId); |
|
||||
int facilityTypeId = dpid; |
|
||||
// 🔴 Validation |
|
||||
if (zoneId <= 0) { |
|
||||
throw new IllegalArgumentException("Invalid zone"); |
|
||||
} |
|
||||
|
|
||||
if (reqDate == null) { |
|
||||
throw new IllegalArgumentException("Request date is required"); |
|
||||
} |
|
||||
|
|
||||
if (weight == null) { |
|
||||
throw new IllegalArgumentException("Weight is required"); |
|
||||
} |
|
||||
|
|
||||
if (facilityTypeId == 5) { |
|
||||
if (weight < 0) { |
|
||||
throw new IllegalArgumentException("Weight cannot be negative"); |
|
||||
} |
|
||||
} else { |
|
||||
if (weight <= 0) { |
|
||||
throw new IllegalArgumentException("Weight must be greater than zero"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (gccUserIdObj == null || usernameObj == null) { |
|
||||
throw new IllegalStateException("User session expired. Please login again."); |
|
||||
} |
|
||||
|
|
||||
// 🔴 Facility type 5 → TWO weights + weightType |
|
||||
if (facilityTypeId == 5) { |
|
||||
if (weight1 == null) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Second weight is required for GW & TC Waste facility"); |
|
||||
} |
|
||||
if (weightType == null || weightType.isBlank()) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Location (KDG / PDG) is required"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (facilityTypeId == 9) { |
|
||||
|
|
||||
if (weightType == null || weightType.isBlank()) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Location (KDG / PDG) is required"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 🔵 SAVE |
|
||||
addDetailsService.addFacility( |
|
||||
facilityTypeId, |
|
||||
zoneId, |
|
||||
reqDate, |
|
||||
username, |
|
||||
weight, |
|
||||
weight1, |
|
||||
weightType // ✅ PASSED |
|
||||
); |
|
||||
|
|
||||
return ResponseEntity.ok( |
|
||||
Map.of("status", "SUCCESS", "message", "Added successfully")); |
|
||||
|
|
||||
} catch (IllegalArgumentException | IllegalStateException ex) { |
|
||||
return ResponseEntity.badRequest().body( |
|
||||
Map.of("status", "ERROR", "message", ex.getMessage())); |
|
||||
} catch (Exception ex) { |
|
||||
ex.printStackTrace(); |
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body( |
|
||||
Map.of("status", "ERROR", "message", "Internal server error")); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/reports") |
|
||||
public ResponseEntity<?> getZoneWiseByLogin( |
|
||||
@RequestParam String username, |
|
||||
@RequestParam String fromDate, |
|
||||
@RequestParam String toDate) { |
|
||||
|
|
||||
List<Map<String, Object>> data = addDetailsService.getZoneWiseFacilityByLogin( |
|
||||
username, fromDate, toDate); |
|
||||
|
|
||||
return ResponseEntity.ok(Map.of( |
|
||||
"status", "SUCCESS", |
|
||||
"data", data)); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,510 +0,0 @@ |
|||||
package com.gcc.swm_services.swm.service; |
|
||||
|
|
||||
import java.sql.Timestamp; |
|
||||
import java.time.LocalDate; |
|
||||
import java.util.List; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
import javax.sql.DataSource; |
|
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.beans.factory.annotation.Qualifier; |
|
||||
import org.springframework.jdbc.core.JdbcTemplate; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
@Service |
|
||||
public class AddDetailsService { |
|
||||
|
|
||||
@Autowired |
|
||||
private JdbcTemplate jdbcTemplate; |
|
||||
|
|
||||
@Autowired |
|
||||
public void setDataSourcemysql(@Qualifier("mysqlSwmDataSource") DataSource dataSource) { |
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource); |
|
||||
} |
|
||||
|
|
||||
// // ---------------- SAVE ---------------- |
|
||||
// public void addFacility( |
|
||||
// int facilityTypeId, |
|
||||
// int zoneId, |
|
||||
// LocalDate reqDate, |
|
||||
// String createdBy, |
|
||||
// Double weight, |
|
||||
// Double weight1) { |
|
||||
|
|
||||
// String sql = """ |
|
||||
// INSERT INTO facilities_weight_details |
|
||||
// (ft_id, zone_id, req_date, cby, weight, weight_1) |
|
||||
// VALUES (?, ?, ?, ?, ?, ?) |
|
||||
// """; |
|
||||
|
|
||||
// Timestamp reqTimestamp = Timestamp.valueOf(reqDate.atStartOfDay()); |
|
||||
|
|
||||
// Double dbWeight1 = (facilityTypeId == 5) ? weight1 : null; |
|
||||
|
|
||||
// jdbcTemplate.update( |
|
||||
// sql, |
|
||||
// facilityTypeId, |
|
||||
// zoneId, |
|
||||
// reqTimestamp, |
|
||||
// createdBy, |
|
||||
// weight, |
|
||||
// dbWeight1); |
|
||||
// } |
|
||||
|
|
||||
// public void addFacility( |
|
||||
// int facilityTypeId, |
|
||||
// int zoneId, |
|
||||
// LocalDate reqDate, |
|
||||
// String createdBy, |
|
||||
// Double weight, |
|
||||
// Double weight1, |
|
||||
// String weightType) { |
|
||||
|
|
||||
// String sql = """ |
|
||||
// INSERT INTO facilities_weight_details |
|
||||
// (ft_id, zone_id, req_date, cby, weight, weight_1, weight_type) |
|
||||
// VALUES (?, ?, ?, ?, ?, ?, ?) |
|
||||
// """; |
|
||||
|
|
||||
// Timestamp reqTimestamp = Timestamp.valueOf(reqDate.atStartOfDay()); |
|
||||
|
|
||||
// Double dbWeight1 = (facilityTypeId == 5) ? weight1 : null; |
|
||||
// // ✅ weight_type allowed for GW & TC (5) AND PBC / C&D (9) |
|
||||
// String dbWeightType = (facilityTypeId == 5 || facilityTypeId == 9) |
|
||||
// ? weightType |
|
||||
// : null; |
|
||||
|
|
||||
// jdbcTemplate.update( |
|
||||
// sql, |
|
||||
// facilityTypeId, |
|
||||
// zoneId, |
|
||||
// reqTimestamp, |
|
||||
// createdBy, |
|
||||
// weight, |
|
||||
// dbWeight1, |
|
||||
// dbWeightType); |
|
||||
// } |
|
||||
|
|
||||
private Integer getExistingRecordId( |
|
||||
int facilityTypeId, |
|
||||
int zoneId, |
|
||||
LocalDate reqDate) { |
|
||||
|
|
||||
String sql = """ |
|
||||
SELECT fid |
|
||||
FROM facilities_weight_details |
|
||||
WHERE ft_id = ? |
|
||||
AND zone_id = ? |
|
||||
AND DATE(req_date) = ? |
|
||||
AND is_delete = 0 |
|
||||
LIMIT 1 |
|
||||
"""; |
|
||||
|
|
||||
List<Integer> ids = jdbcTemplate.query( |
|
||||
sql, |
|
||||
ps -> { |
|
||||
ps.setInt(1, facilityTypeId); |
|
||||
ps.setInt(2, zoneId); |
|
||||
ps.setDate(3, java.sql.Date.valueOf(reqDate)); |
|
||||
}, |
|
||||
(rs, rowNum) -> rs.getInt("fid")); |
|
||||
|
|
||||
return ids.isEmpty() ? null : ids.get(0); |
|
||||
} |
|
||||
|
|
||||
public void addFacility( |
|
||||
int facilityTypeId, |
|
||||
int zoneId, |
|
||||
LocalDate reqDate, |
|
||||
String officerName, |
|
||||
Double weight, |
|
||||
Double weight1, |
|
||||
String weightType) { |
|
||||
|
|
||||
Timestamp reqTimestamp = Timestamp.valueOf(reqDate.atStartOfDay()); |
|
||||
|
|
||||
Double dbWeight1 = (facilityTypeId == 5) ? weight1 : null; |
|
||||
String dbWeightType = (facilityTypeId == 5 || facilityTypeId == 9) |
|
||||
? weightType |
|
||||
: null; |
|
||||
|
|
||||
Integer existingId = getExistingRecordId( |
|
||||
facilityTypeId, zoneId, reqDate); |
|
||||
|
|
||||
if (existingId == null) { |
|
||||
// 🟢 INSERT |
|
||||
String insertSql = """ |
|
||||
INSERT INTO facilities_weight_details |
|
||||
(ft_id, zone_id, req_date, weight, weight_1, weight_type, |
|
||||
cby, cdate, is_active, is_delete) |
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), 1, 0) |
|
||||
"""; |
|
||||
|
|
||||
jdbcTemplate.update( |
|
||||
insertSql, |
|
||||
facilityTypeId, |
|
||||
zoneId, |
|
||||
reqTimestamp, |
|
||||
weight, |
|
||||
dbWeight1, |
|
||||
dbWeightType, |
|
||||
officerName); |
|
||||
|
|
||||
} else { |
|
||||
// 🔵 UPDATE |
|
||||
String updateSql = """ |
|
||||
UPDATE facilities_weight_details |
|
||||
SET weight = ?, |
|
||||
weight_1 = ?, |
|
||||
weight_type = ?, |
|
||||
updated_by = ?, |
|
||||
updated_date = NOW() |
|
||||
WHERE fid = ? |
|
||||
"""; |
|
||||
|
|
||||
jdbcTemplate.update( |
|
||||
updateSql, |
|
||||
weight, |
|
||||
dbWeight1, |
|
||||
dbWeightType, |
|
||||
officerName, |
|
||||
existingId); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// ---------------- DPID ---------------- |
|
||||
public int getDpidByGccUserId(int gccUserId) { |
|
||||
|
|
||||
String sql = """ |
|
||||
SELECT dpid |
|
||||
FROM department_login |
|
||||
WHERE gcc_user_id = ? |
|
||||
AND is_active = 1 |
|
||||
AND is_delete = 0 |
|
||||
"""; |
|
||||
|
|
||||
List<Integer> list = jdbcTemplate.queryForList(sql, Integer.class, gccUserId); |
|
||||
|
|
||||
if (list.isEmpty()) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Department not mapped for user id: " + gccUserId); |
|
||||
} |
|
||||
|
|
||||
return list.get(0); |
|
||||
} |
|
||||
|
|
||||
// ---------------- FACILITY TYPE ---------------- |
|
||||
public int getFacilityTypeIdByDpid(int dpid) { |
|
||||
|
|
||||
String sql = """ |
|
||||
SELECT ft.ft_id |
|
||||
FROM department_login dl |
|
||||
JOIN facilities_type ft |
|
||||
ON LOWER(REPLACE(REPLACE(dl.department_name,'swm_',''),'_',' ')) |
|
||||
LIKE CONCAT('%', LOWER(ft.facilities_name), '%') |
|
||||
WHERE dl.dpid = ? |
|
||||
AND dl.is_active = 1 |
|
||||
AND dl.is_delete = 0 |
|
||||
AND ft.is_active = 1 |
|
||||
AND ft.is_delete = 0 |
|
||||
"""; |
|
||||
|
|
||||
List<Integer> list = jdbcTemplate.queryForList(sql, Integer.class, dpid); |
|
||||
|
|
||||
if (list.isEmpty()) { |
|
||||
throw new IllegalArgumentException( |
|
||||
"Facility type not mapped for department id: " + dpid); |
|
||||
} |
|
||||
|
|
||||
return list.get(0); |
|
||||
} |
|
||||
|
|
||||
public List<Map<String, Object>> getZoneTargetPercentage( |
|
||||
String fromDate, String toDate) { |
|
||||
|
|
||||
String sql = """ |
|
||||
SELECT |
|
||||
t.zone, |
|
||||
t.facility, |
|
||||
t.target, |
|
||||
COALESCE(a.achieved, 0) AS achieved, |
|
||||
ROUND( |
|
||||
CASE |
|
||||
WHEN t.target = 0 AND COALESCE(a.achieved, 0) > 0 THEN 100 |
|
||||
WHEN t.target = 0 THEN 0 |
|
||||
ELSE LEAST((COALESCE(a.achieved, 0) / t.target) * 100, 100) |
|
||||
END, |
|
||||
2 |
|
||||
) AS percentage |
|
||||
FROM ( |
|
||||
SELECT zone, 1 AS ft_id, 'MCC' AS facility, mcc AS target |
|
||||
FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
|
|
||||
UNION ALL |
|
||||
SELECT zone, 2, 'Windrow', windrow FROM zonewise_target |
|
||||
WHERE is_active = 1 AND is_delete = 0 |
|
||||
|
|
||||
UNION ALL |
|
||||
SELECT zone, 3, 'Bio-CNG', bio_cng FROM zonewise_target |
|
||||
WHERE is_active = 1 AND is_delete = 0 |
|
||||
|
|
||||
UNION ALL |
|
||||
SELECT zone, 4, 'Bio-GAS', bio_gas FROM zonewise_target |
|
||||
WHERE is_active = 1 AND is_delete = 0 |
|
||||
|
|
||||
UNION ALL |
|
||||
SELECT zone, 5, 'GW & TC Waste', gw_tc_waste FROM zonewise_target |
|
||||
WHERE is_active = 1 AND is_delete = 0 |
|
||||
|
|
||||
UNION ALL |
|
||||
SELECT zone, 6, 'MRF OR RRC', mrf_mrr FROM zonewise_target |
|
||||
WHERE is_active = 1 AND is_delete = 0 |
|
||||
|
|
||||
UNION ALL |
|
||||
SELECT zone, 7, 'Incinerator', incinerator FROM zonewise_target |
|
||||
WHERE is_active = 1 AND is_delete = 0 |
|
||||
|
|
||||
UNION ALL |
|
||||
SELECT zone, 8, 'Plasting Baling Centre', plasting_baling_centre |
|
||||
FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
) t |
|
||||
LEFT JOIN ( |
|
||||
SELECT |
|
||||
fwd.zone_id AS zone, |
|
||||
fwd.ft_id, |
|
||||
SUM( |
|
||||
CASE |
|
||||
WHEN fwd.ft_id = 5 |
|
||||
THEN COALESCE(fwd.weight, 0) |
|
||||
+ COALESCE(fwd.weight_1, 0) |
|
||||
ELSE |
|
||||
COALESCE(fwd.weight, 0) |
|
||||
END |
|
||||
) AS achieved |
|
||||
FROM facilities_weight_details fwd |
|
||||
WHERE fwd.is_active = 1 |
|
||||
AND fwd.is_delete = 0 |
|
||||
AND DATE(fwd.req_date) BETWEEN ? AND ? |
|
||||
GROUP BY fwd.zone_id, fwd.ft_id |
|
||||
) a |
|
||||
ON a.zone = t.zone |
|
||||
AND a.ft_id = t.ft_id |
|
||||
ORDER BY t.zone, t.facility |
|
||||
"""; |
|
||||
|
|
||||
return jdbcTemplate.queryForList(sql, fromDate, toDate); |
|
||||
} |
|
||||
|
|
||||
public List<Map<String, Object>> getZoneTargetPercentageForOneDay(String date) { |
|
||||
String sql = """ |
|
||||
SELECT |
|
||||
t.zone, |
|
||||
t.facility, |
|
||||
t.target, |
|
||||
COALESCE(a.achieved, 0) AS achieved, |
|
||||
ROUND( |
|
||||
CASE |
|
||||
WHEN t.target = 0 AND COALESCE(a.achieved, 0) > 0 THEN 100 |
|
||||
WHEN t.target = 0 THEN 0 |
|
||||
ELSE LEAST((COALESCE(a.achieved, 0) / t.target) * 100, 100) |
|
||||
END, |
|
||||
2 |
|
||||
) AS percentage |
|
||||
FROM ( |
|
||||
SELECT zone, 1 AS ft_id, 'MCC' AS facility, mcc AS target FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
UNION ALL SELECT zone, 2, 'Windrow', windrow FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
UNION ALL SELECT zone, 3, 'Bio-CNG', bio_cng FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
UNION ALL SELECT zone, 4, 'Bio-GAS', bio_gas FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
UNION ALL SELECT zone, 5, 'GW & TC Waste', gw_tc_waste FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
UNION ALL SELECT zone, 6, 'MRF OR RRC', mrf_mrr FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
UNION ALL SELECT zone, 7, 'Incinerator', incinerator FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
UNION ALL SELECT zone, 8, 'Plasting Baling Centre', plasting_baling_centre FROM zonewise_target WHERE is_active = 1 AND is_delete = 0 |
|
||||
) t |
|
||||
LEFT JOIN ( |
|
||||
SELECT |
|
||||
fwd.zone_id AS zone, |
|
||||
fwd.ft_id, |
|
||||
SUM( |
|
||||
CASE |
|
||||
WHEN fwd.ft_id = 5 |
|
||||
THEN COALESCE(fwd.weight, 0) + COALESCE(fwd.weight_1, 0) |
|
||||
ELSE COALESCE(fwd.weight, 0) |
|
||||
END |
|
||||
) AS achieved |
|
||||
FROM facilities_weight_details fwd |
|
||||
WHERE fwd.is_active = 1 |
|
||||
AND fwd.is_delete = 0 |
|
||||
AND DATE(fwd.req_date) = ? -- **single‑date filter** |
|
||||
GROUP BY fwd.zone_id, fwd.ft_id |
|
||||
) a |
|
||||
ON a.zone = t.zone |
|
||||
AND a.ft_id = t.ft_id |
|
||||
ORDER BY t.zone, t.facility |
|
||||
"""; |
|
||||
// Only one parameter (the date) is bound now. |
|
||||
return jdbcTemplate.queryForList(sql, date); |
|
||||
} |
|
||||
|
|
||||
// public List<Map<String, Object>> getZoneWiseFacilityByLogin( |
|
||||
// String username, |
|
||||
// String fromDate, |
|
||||
// String toDate) { |
|
||||
|
|
||||
// String sql = """ |
|
||||
// SELECT |
|
||||
// t.zone, |
|
||||
// t.facility, |
|
||||
// t.target, |
|
||||
// COALESCE(a.achieved, 0) AS achieved, |
|
||||
// ROUND( |
|
||||
// CASE |
|
||||
// WHEN t.target = 0 AND COALESCE(a.achieved, 0) > 0 THEN 100 |
|
||||
// WHEN t.target = 0 AND COALESCE(a.achieved, 0) = 0 THEN 0 |
|
||||
// ELSE LEAST((COALESCE(a.achieved, 0) / t.target) * 100, 100) |
|
||||
// END, 2 |
|
||||
// ) AS percentage |
|
||||
// FROM ( |
|
||||
// /* 🔹 TARGET – ONLY FACILITY FROM LOGIN */ |
|
||||
// SELECT |
|
||||
// zt.zone, |
|
||||
// ft.facilities_name AS facility, |
|
||||
// CASE ft.ft_id |
|
||||
// WHEN 1 THEN zt.mcc |
|
||||
// WHEN 2 THEN zt.windrow |
|
||||
// WHEN 3 THEN zt.bio_cng |
|
||||
// WHEN 4 THEN zt.bio_gas |
|
||||
// WHEN 5 THEN zt.gw_tc_waste |
|
||||
// WHEN 6 THEN zt.mrf_mrr |
|
||||
// WHEN 7 THEN zt.incinerator |
|
||||
// WHEN 8 THEN zt.plasting_baling_centre |
|
||||
// ELSE 0 |
|
||||
// END AS target |
|
||||
|
|
||||
// FROM department_login dl |
|
||||
// JOIN facilities_type ft ON ft.ft_id = dl.dpid |
|
||||
// JOIN zonewise_target zt ON zt.is_active = 1 AND zt.is_delete = 0 |
|
||||
// WHERE dl.user_name = ? |
|
||||
// ) t |
|
||||
// LEFT JOIN ( |
|
||||
// /* 🔹 ACHIEVED – SAME FT_ID + LOGIN */ |
|
||||
// SELECT |
|
||||
// fwd.zone_id AS zone, |
|
||||
// ft.facilities_name AS facility, |
|
||||
// SUM(COALESCE(fwd.weight, 0) + COALESCE(fwd.weight_1, 0)) AS achieved |
|
||||
// FROM facilities_weight_details fwd |
|
||||
// JOIN facilities_type ft ON ft.ft_id = fwd.ft_id |
|
||||
// WHERE fwd.is_active = 1 |
|
||||
// AND fwd.is_delete = 0 |
|
||||
// AND fwd.cby = ? |
|
||||
// AND DATE(fwd.req_date) BETWEEN ? AND ? |
|
||||
// GROUP BY fwd.zone_id, ft.facilities_name |
|
||||
// ) a |
|
||||
// ON a.zone = t.zone AND a.facility = t.facility |
|
||||
// ORDER BY t.zone |
|
||||
// """; |
|
||||
|
|
||||
// return jdbcTemplate.queryForList( |
|
||||
// sql, |
|
||||
// username, |
|
||||
// username, |
|
||||
// fromDate, |
|
||||
// toDate); |
|
||||
// } |
|
||||
|
|
||||
private String normalizeDate(String date) { |
|
||||
|
|
||||
if (date == null || date.isBlank()) { |
|
||||
return date; |
|
||||
} |
|
||||
|
|
||||
// If browser format yyyy-MM-dd → convert to dd-MM-yyyy |
|
||||
if (date.matches("\\d{4}-\\d{2}-\\d{2}")) { |
|
||||
String[] p = date.split("-"); |
|
||||
return p[2] + "-" + p[1] + "-" + p[0]; |
|
||||
} |
|
||||
|
|
||||
// Already dd-MM-yyyy |
|
||||
return date; |
|
||||
} |
|
||||
|
|
||||
public List<Map<String, Object>> getZoneWiseFacilityByLogin( |
|
||||
String username, |
|
||||
String fromDate, |
|
||||
String toDate) { |
|
||||
|
|
||||
// 🔥 Normalize date format (supports yyyy-MM-dd and dd-MM-yyyy) |
|
||||
fromDate = normalizeDate(fromDate); |
|
||||
toDate = normalizeDate(toDate); |
|
||||
|
|
||||
String sql = """ |
|
||||
SELECT |
|
||||
t.zone, |
|
||||
t.facility, |
|
||||
t.target, |
|
||||
COALESCE(a.achieved, 0) AS achieved, |
|
||||
ROUND( |
|
||||
CASE |
|
||||
WHEN t.target = 0 AND COALESCE(a.achieved, 0) > 0 THEN 100 |
|
||||
WHEN t.target = 0 AND COALESCE(a.achieved, 0) = 0 THEN 0 |
|
||||
ELSE LEAST((COALESCE(a.achieved, 0) / t.target) * 100, 100) |
|
||||
END, 2 |
|
||||
) AS percentage |
|
||||
FROM ( |
|
||||
/* TARGET */ |
|
||||
SELECT |
|
||||
zt.zone, |
|
||||
ft.ft_id, |
|
||||
ft.facilities_name AS facility, |
|
||||
CASE ft.ft_id |
|
||||
WHEN 1 THEN zt.mcc |
|
||||
WHEN 2 THEN zt.windrow |
|
||||
WHEN 3 THEN zt.bio_cng |
|
||||
WHEN 4 THEN zt.bio_gas |
|
||||
WHEN 5 THEN zt.gw_tc_waste |
|
||||
WHEN 6 THEN zt.mrf_mrr |
|
||||
WHEN 7 THEN zt.incinerator |
|
||||
WHEN 8 THEN zt.plasting_baling_centre |
|
||||
ELSE 0 |
|
||||
END AS target |
|
||||
FROM department_login dl |
|
||||
JOIN facilities_type ft ON ft.ft_id = dl.dpid |
|
||||
JOIN zonewise_target zt |
|
||||
ON zt.is_active = 1 |
|
||||
AND zt.is_delete = 0 |
|
||||
WHERE TRIM(dl.user_name) = ? |
|
||||
) t |
|
||||
LEFT JOIN ( |
|
||||
/* ACHIEVED */ |
|
||||
SELECT |
|
||||
fwd.zone_id AS zone, |
|
||||
fwd.ft_id, |
|
||||
SUM(COALESCE(fwd.weight, 0) + COALESCE(fwd.weight_1, 0)) AS achieved |
|
||||
FROM facilities_weight_details fwd |
|
||||
WHERE fwd.is_active = 1 |
|
||||
AND fwd.is_delete = 0 |
|
||||
AND TRIM(fwd.cby) = ? |
|
||||
AND fwd.req_date >= STR_TO_DATE(CONCAT(?, ' 00:00:00'), '%d-%m-%Y %H:%i:%s') |
|
||||
AND fwd.req_date <= STR_TO_DATE(CONCAT(?, ' 23:59:59'), '%d-%m-%Y %H:%i:%s') |
|
||||
AND fwd.ft_id = ( |
|
||||
SELECT dpid |
|
||||
FROM department_login |
|
||||
WHERE TRIM(user_name) = ? |
|
||||
) |
|
||||
GROUP BY fwd.zone_id, fwd.ft_id |
|
||||
) a |
|
||||
ON a.zone = t.zone |
|
||||
AND a.ft_id = t.ft_id |
|
||||
ORDER BY t.zone |
|
||||
"""; |
|
||||
|
|
||||
return jdbcTemplate.queryForList( |
|
||||
sql, |
|
||||
username, |
|
||||
username, |
|
||||
fromDate, |
|
||||
toDate, |
|
||||
username); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,37 +0,0 @@ |
|||||
package com.gcc.swm_services.swm.service; |
|
||||
|
|
||||
import java.util.List; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
import javax.sql.DataSource; |
|
||||
|
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.beans.factory.annotation.Qualifier; |
|
||||
import org.springframework.jdbc.core.JdbcTemplate; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
import org.springframework.web.client.RestTemplate; |
|
||||
|
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
|
||||
|
|
||||
@Service |
|
||||
public class DropDownService { |
|
||||
|
|
||||
@Autowired |
|
||||
private JdbcTemplate jdbcTemplate; |
|
||||
|
|
||||
@Autowired |
|
||||
public void setDataSourcemysql(@Qualifier("mysqlSwmDataSource") DataSource dataSource) { |
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource); |
|
||||
} |
|
||||
|
|
||||
public List<Map<String, Object>> getFacilitiesTypeList() { |
|
||||
String sql = " SELECT * FROM facilities_type where is_active = '1' and is_delete ='0' "; |
|
||||
return jdbcTemplate.queryForList(sql); |
|
||||
} |
|
||||
|
|
||||
public List<Map<String, Object>> getZonesList() { |
|
||||
String sql = " SELECT * FROM zones where is_active = '1' and is_delete ='0' "; |
|
||||
return jdbcTemplate.queryForList(sql); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,5 +1,5 @@ |
|||||
assets.base-url=/assets/ |
assets.base-url=/assets/ |
||||
|
|
||||
fileBaseUrl=http://localhost:8060 |
|
||||
|
fileBaseUrl=http://localhost:8061 |
||||
|
|
||||
#fileBaseUrl = D:/Projects/Election_Project/election_v1/gcc_election_uploads |
#fileBaseUrl = D:/Projects/Election_Project/election_v1/gcc_election_uploads |
||||
@ -1,3 +1,3 @@ |
|||||
assets.base-url=/swm/assets/ |
|
||||
|
assets.base-url=/flagpoles/assets/ |
||||
|
|
||||
fileBaseUrl=https://gccservices.in/files |
|
||||
|
fileBaseUrl=https://gccservices.in/flagpoles |
||||
@ -1,57 +1,63 @@ |
|||||
<!DOCTYPE html> |
<!DOCTYPE html> |
||||
<html lang="en" dir=""> |
<html lang="en" dir=""> |
||||
<html xmlns:th="http://www.thymeleaf.org"> |
<html xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
||||
<body> |
|
||||
<!--[if lt IE 8]> |
|
||||
|
|
||||
|
<body> |
||||
|
<!--[if lt IE 8]> |
||||
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> |
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> |
||||
<![endif]--> |
<![endif]--> |
||||
|
|
||||
<div class="auth-wrapper"> |
|
||||
<div class="container-fluid h-100"> |
|
||||
<div class="row flex-row h-100 bg-white"> |
|
||||
<div class="col-xl-6 col-lg-6 col-md-5 p-0 d-md-block d-lg-block d-sm-none d-none"> |
|
||||
<div class="lavalite-bg authentication-form mx-auto text-center"> |
|
||||
<div class="logo-centered" style="padding-top: 30px;"></div> |
|
||||
<img src="images/403.png" width="90%"/> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-xl-6 col-lg-6 col-md-7 my-auto p-0"> |
|
||||
<div class="authentication-form mx-auto text-center"> |
|
||||
<div class="logo-centered"> |
|
||||
<a href="/"><img src="images/logo.png" alt="Greater Chennai Corporation" class="header-brand-img" width="100%"></a> |
|
||||
</div> |
|
||||
<h3>Greater Chennai Corporation</h3> |
|
||||
<!-- Content --> |
|
||||
<div class="flex-grow-1 d-flex align-items-center p-5 bg-body-light"> |
|
||||
<div class="w-100"> |
|
||||
<p class="text-danger fs-4 fw-bold text-uppercase mb-2" th:utext="${errorStatus}"> |
|
||||
403 Error |
|
||||
</p> |
|
||||
<h1 class="fw-bold mb-2" th:utext="${errorError}"> |
|
||||
403 - Access Denied |
|
||||
</h1> |
|
||||
<p class="fs-4 fw-medium text-muted mb-5" th:utext="${errorMessage}"> |
|
||||
Oops, You don`t have permission to access this page. |
|
||||
</p> |
|
||||
<a class="btn btn-lg btn-alt-danger" href="#403" onclick="return goBack();"> |
|
||||
<i class="fa fa-arrow-left opacity-50 me-1"></i> Back |
|
||||
</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- END Content --> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
<div class="auth-wrapper"> |
||||
|
<div class="container-fluid h-100"> |
||||
|
<div class="row flex-row h-100 bg-white"> |
||||
|
<div class="col-xl-6 col-lg-6 col-md-5 p-0 d-md-block d-lg-block d-sm-none d-none"> |
||||
|
<div class="lavalite-bg authentication-form mx-auto text-center"> |
||||
|
<div class="logo-centered" style="padding-top: 30px;"></div> |
||||
|
<img src="images/403.png" width="90%" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-xl-6 col-lg-6 col-md-7 my-auto p-0"> |
||||
|
<div class="authentication-form mx-auto text-center"> |
||||
|
<div class="logo-centered"> |
||||
|
<a href="/"><img src="images/logo.png" alt="Greater Chennai Corporation" class="header-brand-img" |
||||
|
width="100%"></a> |
||||
</div> |
</div> |
||||
|
<h3>Greater Chennai Corporation |
||||
|
Flagpoles Officer Login |
||||
|
</h3> |
||||
|
<!-- Content --> |
||||
|
<div class="flex-grow-1 d-flex align-items-center p-5 bg-body-light"> |
||||
|
<div class="w-100"> |
||||
|
<p class="text-danger fs-4 fw-bold text-uppercase mb-2" th:utext="${errorStatus}"> |
||||
|
403 Error |
||||
|
</p> |
||||
|
<h1 class="fw-bold mb-2" th:utext="${errorError}"> |
||||
|
403 - Access Denied |
||||
|
</h1> |
||||
|
<p class="fs-4 fw-medium text-muted mb-5" th:utext="${errorMessage}"> |
||||
|
Oops, You don`t have permission to access this page. |
||||
|
</p> |
||||
|
<a class="btn btn-lg btn-alt-danger" href="#403" onclick="return goBack();"> |
||||
|
<i class="fa fa-arrow-left opacity-50 me-1"></i> Back |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END Content --> |
||||
|
</div> |
||||
</div> |
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
||||
|
<script> |
||||
|
function goBack() { |
||||
|
history.go(-1); // This will go back one step in the browser's history |
||||
|
return false; // Prevent the default link behavior |
||||
|
} |
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script> |
|
||||
function goBack() { |
|
||||
history.go(-1); // This will go back one step in the browser's history |
|
||||
return false; // Prevent the default link behavior |
|
||||
} |
|
||||
</script> |
|
||||
</body> |
|
||||
</html> |
</html> |
||||
@ -1,5 +1,5 @@ |
|||||
<footer class="footer"> |
<footer class="footer"> |
||||
<form id="logout-form" th:action="@{/swm/logout}" method="post" style="display: none;"></form> |
|
||||
|
<form id="logout-form" th:action="@{/flagpoles/logout}" method="post" style="display: none;"></form> |
||||
<div class="w-100 clearfix text-center"> |
<div class="w-100 clearfix text-center"> |
||||
<span class="text-center">Copyright © Greater Chennai Corporation | All rights reserved</span> |
<span class="text-center">Copyright © Greater Chennai Corporation | All rights reserved</span> |
||||
<!-- <span class="float-none float-sm-right mt-1 mt-sm-0 text-center">Coded By BonTon Softwares Pvt Ltd</span> --> |
<!-- <span class="float-none float-sm-right mt-1 mt-sm-0 text-center">Coded By BonTon Softwares Pvt Ltd</span> --> |
||||
|
|||||
@ -0,0 +1,930 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
||||
|
|
||||
|
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
||||
|
<style> |
||||
|
.width1 { |
||||
|
width: 120px; |
||||
|
} |
||||
|
|
||||
|
.width2 { |
||||
|
width: 150px; |
||||
|
} |
||||
|
|
||||
|
.modal-label { |
||||
|
font-weight: 600; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.modal-value { |
||||
|
color: #444; |
||||
|
} |
||||
|
|
||||
|
.modal-section-title { |
||||
|
font-size: 1.2rem; |
||||
|
font-weight: bold; |
||||
|
margin-top: 20px; |
||||
|
margin-bottom: 10px; |
||||
|
border-bottom: 2px solid #dee2e6; |
||||
|
padding-bottom: 5px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.modal-title-big { |
||||
|
font-size: 20px; |
||||
|
font-weight: 700; |
||||
|
} |
||||
|
|
||||
|
.modal-subtext { |
||||
|
color: #b4c5d3; |
||||
|
font-size: 13px; |
||||
|
} |
||||
|
|
||||
|
.card-section { |
||||
|
background: white; |
||||
|
border-radius: 10px; |
||||
|
padding: 20px; |
||||
|
margin-bottom: 25px; |
||||
|
border: 1px solid #eee; |
||||
|
} |
||||
|
|
||||
|
.section-title { |
||||
|
font-weight: 700; |
||||
|
color: #333; |
||||
|
margin-bottom: 15px; |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
.label-text { |
||||
|
font-size: 13px; |
||||
|
color: #6c757d; |
||||
|
} |
||||
|
|
||||
|
.value-text { |
||||
|
font-size: 15px; |
||||
|
font-weight: 600; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.info-block { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.badge-status { |
||||
|
background: #ffd9b3; |
||||
|
color: #a65c00; |
||||
|
padding: 6px 10px; |
||||
|
border-radius: 5px; |
||||
|
font-size: 13px; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.btn-big { |
||||
|
padding: 12px 25px; |
||||
|
border-radius: 8px; |
||||
|
width: 200px; |
||||
|
} |
||||
|
|
||||
|
.rdo-box { |
||||
|
border: 1px solid #eee; |
||||
|
border-radius: 10px; |
||||
|
padding: 20px; |
||||
|
} |
||||
|
</style> |
||||
|
|
||||
|
<body> |
||||
|
|
||||
|
<div class="wrapper"> |
||||
|
<!-- header top menu Start --> |
||||
|
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
||||
|
<!-- header top menu end --> |
||||
|
<div class="page-wrap"> |
||||
|
<!--=============== Left Menu side Start ================--> |
||||
|
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
||||
|
<!--=============== Left side End ================--> |
||||
|
<div class="main-content"> |
||||
|
<div class="container-fluid"> |
||||
|
<div class="page-header"> |
||||
|
<div class="row align-items-end"> |
||||
|
<div class="col-lg-6"> |
||||
|
<div class="page-header-title"> |
||||
|
<i class="fa fa-list-alt bg-blue"></i> |
||||
|
<div class="d-inline"> |
||||
|
<h5>Request List</h5> |
||||
|
<span>Flag Pole Request List</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-6"> |
||||
|
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
||||
|
<ol class="breadcrumb"> |
||||
|
<li class="breadcrumb-item"> |
||||
|
<a href="/flagpoles/index"><i class="ik ik-home"></i></a> |
||||
|
</li> |
||||
|
<li class="breadcrumb-item" aria-current="page">Flag Pole Request List</li> |
||||
|
<li class="breadcrumb-item active" aria-current="page">Request List</li> |
||||
|
</ol> |
||||
|
</nav> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="row mt-4"> |
||||
|
|
||||
|
<div class="col-md-12"> |
||||
|
<div class="card"> |
||||
|
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
||||
|
<h3 class="mb-0">Temporary Flag Poles - Request List : <span |
||||
|
th:text="${officer_name}"></span></h3> |
||||
|
<input type="hidden" id="userName" th:value="${officer_name}"> |
||||
|
<input type="hidden" id="loginuserid" th:value="${LoginUserId}"> |
||||
|
</div> |
||||
|
|
||||
|
<div class="row mt-3 ml-2"> |
||||
|
<div class="col-md-3"> |
||||
|
<label for="startDate" class="form-label" style="font-size: medium;">From |
||||
|
Date:</label> |
||||
|
<input type="date" id="startDate" class="form-control" placeholder="Start Date"> |
||||
|
</div> |
||||
|
<div class="col-md-3"> |
||||
|
<label for="endDate" class="form-label" style="font-size: medium;">To |
||||
|
Date:</label> |
||||
|
<input type="date" id="endDate" class="form-control" placeholder="End Date"> |
||||
|
</div> |
||||
|
<div class="col-md-3" style="margin-top: 30px;"> |
||||
|
<button id="searchBtn" class="btn btn-primary">Search</button> |
||||
|
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card-body"> |
||||
|
<div> |
||||
|
<div class="row mt-2"> |
||||
|
|
||||
|
|
||||
|
<div class="col-xl-3 col-md-3 col-sm-12"> |
||||
|
<div class="card card-box p-4"> |
||||
|
<h6 class="text-facebook mb-20 mt-2 text-center fw-bold"><b>Total |
||||
|
Request</b> |
||||
|
</h6> |
||||
|
<h4 class="text-twitter fw-700 text-center" id="totalrequest"> |
||||
|
</h4> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-xl-3 col-md-3 col-sm-12"> |
||||
|
<div class="card card-box p-4"> |
||||
|
<h6 class="text-facebook mb-20 mt-2 text-center"><b>Pending Decision |
||||
|
</b></h6> |
||||
|
<h4 class="text-twitter fw-700 text-center" id="pendingdecision"> |
||||
|
</h4> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-xl-3 col-md-3 col-sm-12" style="display: none;"> |
||||
|
<div class="card card-box p-4"> |
||||
|
<h6 class="text-facebook mb-20 mt-2 text-center"><b>Approved</b> |
||||
|
</h6> |
||||
|
<h4 class="text-twitter fw-700 text-center" id="approved"></h4> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-xl-3 col-md-3 col-sm-12" style="display: none;"> |
||||
|
<div class="card card-box p-4"> |
||||
|
<h6 class="text-facebook mb-20 mt-2 text-center"><b>Rejected</b> |
||||
|
</h6> |
||||
|
<h4 class="text-twitter fw-700 text-center" id="rejected"></h4> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<table id="QaqcDatatable" |
||||
|
class="table table-striped table-bordered table-hover dataTable" |
||||
|
role="grid"> |
||||
|
<thead class="thead-dark"> |
||||
|
<tr role="row"> |
||||
|
<th class="text-center">S.No</th> |
||||
|
<th class="text-center no-sort">Applicant Name</th> |
||||
|
<th class="text-center">RequestId</th> |
||||
|
<th class="text-center">Zone/Ward</th> |
||||
|
<th class="text-center">Event Type</th> |
||||
|
<th class="text-center">Event Date</th> |
||||
|
<th class="text-center">Total Cost</th> |
||||
|
<th class="text-center">Status</th> |
||||
|
<th class="text-center">Action</th> |
||||
|
|
||||
|
</tr> |
||||
|
|
||||
|
</thead> |
||||
|
<tbody> |
||||
|
|
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
<div id="pageLoader" |
||||
|
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
||||
|
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
||||
|
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
||||
|
<span class="sr-only">Loading...</span> |
||||
|
</div> |
||||
|
<!-- Add the 'Please wait' text below the spinner --> |
||||
|
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
||||
|
|
||||
|
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Details Modal --> |
||||
|
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
||||
|
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
||||
|
<div class="modal-content"> |
||||
|
|
||||
|
<div class="modal-header" style="background:#2f3e54; color:white;"> |
||||
|
<div> |
||||
|
<h4 class="modal-title-big" id="modalTitle"></h4> |
||||
|
<div id="modalSubTitle" class="modal-subtext"></div> |
||||
|
</div> |
||||
|
|
||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
||||
|
aria-hidden="true">×</span></button> |
||||
|
</div> |
||||
|
|
||||
|
<div class="modal-body"> |
||||
|
|
||||
|
<div id="modalContent"></div> |
||||
|
|
||||
|
<div class="text-center mt-4"> |
||||
|
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
||||
|
style="background:#2f3e54;">Close</button> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div class="modal fade" id="imagePreviewModal" tabindex="-1"> |
||||
|
<div class="modal-dialog modal-dialog-centered modal-lg"> |
||||
|
<div class="modal-content"> |
||||
|
<div class="modal-header"> |
||||
|
<h5 class="modal-title">Document Preview</h5> |
||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button> |
||||
|
</div> |
||||
|
<div class="modal-body text-center"> |
||||
|
<img id="previewImage" class="img-fluid"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
||||
|
<script type="text/javascript"> |
||||
|
|
||||
|
|
||||
|
let table; |
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
loadTable(); |
||||
|
|
||||
|
$("#searchBtn").on("click", loadTable); |
||||
|
|
||||
|
$("#resetBtn").on("click", function () { |
||||
|
$("#startDate").val(""); |
||||
|
$("#endDate").val(""); |
||||
|
loadTable(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
$(document).on("click", ".zoom-img", function () { |
||||
|
|
||||
|
const src = $(this).data("src"); |
||||
|
|
||||
|
$("#previewImage").attr("src", src); |
||||
|
|
||||
|
$("#imagePreviewModal").modal("show"); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
// function loadTable() { |
||||
|
|
||||
|
// let officer_name = $("#userName").val(); |
||||
|
// let startDate = $("#startDate").val(); |
||||
|
// let endDate = $("#endDate").val(); |
||||
|
|
||||
|
// if ($.fn.DataTable.isDataTable('#QaqcDatatable')) { |
||||
|
// $('#QaqcDatatable').DataTable().clear().destroy(); |
||||
|
// } |
||||
|
|
||||
|
// table = $('#QaqcDatatable').DataTable({ |
||||
|
// processing: true, |
||||
|
// responsive: true, |
||||
|
// scrollY: '50vh', |
||||
|
// dom: 'Bfrtip', // 🔥 ENABLE BUTTONS |
||||
|
|
||||
|
// ajax: { |
||||
|
// url: "/gcc/api/flagpoleregistration/getAllDetails", |
||||
|
// type: "GET", |
||||
|
// data: { |
||||
|
// userLogin: officer_name, |
||||
|
// startDate: startDate, |
||||
|
// endDate: endDate |
||||
|
// }, |
||||
|
// dataSrc: function (json) { |
||||
|
|
||||
|
// const data = json.data || []; |
||||
|
|
||||
|
// // 🔹 Dashboard counts |
||||
|
// let pending = 0, approved = 0, rejected = 0; |
||||
|
|
||||
|
// data.forEach(r => { |
||||
|
// if (!r.rdo_status) pending++; |
||||
|
// else if (r.rdo_status === 'APPROVED') approved++; |
||||
|
// else if (r.rdo_status === 'REJECTED') rejected++; |
||||
|
// }); |
||||
|
|
||||
|
// $("#totalrequest").text(data.length); |
||||
|
// $("#pendingdecision").text(pending); |
||||
|
// $("#approved").text(approved); |
||||
|
// $("#rejected").text(rejected); |
||||
|
|
||||
|
// return data; // ✅ already unique per refid |
||||
|
// } |
||||
|
// }, |
||||
|
|
||||
|
// columns: [ |
||||
|
// { |
||||
|
// data: null, |
||||
|
// className: "text-center", |
||||
|
// render: (d, t, r, m) => m.row + 1 |
||||
|
// }, |
||||
|
// { |
||||
|
// data: "applicant_name", |
||||
|
// className: "text-center" |
||||
|
// }, |
||||
|
// { |
||||
|
// data: "refid", |
||||
|
// className: "text-center" |
||||
|
// }, |
||||
|
// { |
||||
|
// data: null, |
||||
|
// className: "text-center", |
||||
|
// render: row => { |
||||
|
// if (!row.streets || row.streets.length === 0) return "-"; |
||||
|
// return `${row.streets[0].zone} / ${row.streets[0].ward}`; |
||||
|
// } |
||||
|
// }, |
||||
|
// { |
||||
|
// data: "event_name", |
||||
|
// className: "text-center" |
||||
|
// }, |
||||
|
// { |
||||
|
// data: "event_date", |
||||
|
// className: "text-center", |
||||
|
// render: d => new Date(d).toLocaleDateString("en-GB") |
||||
|
// }, |
||||
|
// { |
||||
|
// data: "total_cost", |
||||
|
// className: "text-center", |
||||
|
// render: d => d.toLocaleString("en-GB") |
||||
|
// }, |
||||
|
// { |
||||
|
// data: "rdo_status", |
||||
|
// className: "text-center", |
||||
|
// render: d => { |
||||
|
// if (!d) |
||||
|
// return `<span class="badge bg-warning text-dark">Pending</span>`; |
||||
|
// if (d === 'APPROVED') |
||||
|
// return `<span class="badge bg-success">Approved</span>`; |
||||
|
// return `<span class="badge bg-danger">Rejected</span>`; |
||||
|
// } |
||||
|
// }, |
||||
|
// { |
||||
|
// data: null, |
||||
|
// className: "text-center", |
||||
|
// render: row => |
||||
|
// `<button class="btn btn-primary btn-sm viewBtn" |
||||
|
// data-refid="${row.refid}"> |
||||
|
// View |
||||
|
// </button>` |
||||
|
// } |
||||
|
// ] |
||||
|
// }); |
||||
|
// } |
||||
|
|
||||
|
|
||||
|
|
||||
|
function loadTable() { |
||||
|
|
||||
|
let gccUserId = $("#loginuserid").val(); |
||||
|
let startDate = $("#startDate").val(); |
||||
|
let endDate = $("#endDate").val(); |
||||
|
|
||||
|
console.log("gccuserid:" + gccUserId); |
||||
|
|
||||
|
if ($.fn.DataTable.isDataTable('#QaqcDatatable')) { |
||||
|
$('#QaqcDatatable').DataTable().clear().destroy(); |
||||
|
} |
||||
|
|
||||
|
table = $('#QaqcDatatable').DataTable({ |
||||
|
processing: true, |
||||
|
responsive: true, |
||||
|
scrollY: '50vh', |
||||
|
dom: 'Bfrtip', |
||||
|
|
||||
|
ajax: { |
||||
|
url: "/flagpoles/api/flagpoleregistration/getAllDetails", |
||||
|
type: "GET", |
||||
|
data: { |
||||
|
gccUserId: gccUserId, |
||||
|
startDate: startDate, |
||||
|
endDate: endDate |
||||
|
}, |
||||
|
dataSrc: function (json) { |
||||
|
|
||||
|
const data = json.data || []; |
||||
|
|
||||
|
let pending = 0, approved = 0, rejected = 0; |
||||
|
|
||||
|
// data.forEach(r => { |
||||
|
// if (!r.rdo_status) pending++; |
||||
|
// else if (r.rdo_status === 'APPROVED') approved++; |
||||
|
// else if (r.rdo_status === 'REJECTED') rejected++; |
||||
|
// }); |
||||
|
|
||||
|
data.forEach(r => { |
||||
|
|
||||
|
const status = r.final_status; |
||||
|
|
||||
|
if (!status) pending++; |
||||
|
else if (status === 'APPROVED') approved++; |
||||
|
else if (status === 'REJECTED') rejected++; |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
$("#totalrequest").text(data.length); |
||||
|
$("#pendingdecision").text(pending); |
||||
|
$("#approved").text(approved); |
||||
|
$("#rejected").text(rejected); |
||||
|
|
||||
|
return data; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
columns: [ |
||||
|
{ data: null, render: (d, t, r, m) => m.row + 1, className: "text-center" }, |
||||
|
{ data: "applicant_name", className: "text-center" }, |
||||
|
{ data: "refid", className: "text-center" }, |
||||
|
{ |
||||
|
data: null, |
||||
|
className: "text-center", |
||||
|
render: r => |
||||
|
r.streets?.length |
||||
|
? `${r.streets[0].zone} / ${r.streets[0].ward}` |
||||
|
: "-" |
||||
|
}, |
||||
|
{ data: "event_name", className: "text-center" }, |
||||
|
{ |
||||
|
data: "event_date", |
||||
|
className: "text-center", |
||||
|
render: d => new Date(d).toLocaleDateString("en-GB") |
||||
|
}, |
||||
|
{ |
||||
|
data: "total_cost", |
||||
|
className: "text-center", |
||||
|
render: d => d.toLocaleString("en-GB") |
||||
|
}, |
||||
|
// { |
||||
|
// data: "rdo_status", |
||||
|
// className: "text-center", |
||||
|
// render: d => |
||||
|
// !d |
||||
|
// ? `<span class="badge bg-warning text-dark">Pending</span>` |
||||
|
// : d === 'APPROVED' |
||||
|
// ? `<span class="badge bg-success">Approved</span>` |
||||
|
// : `<span class="badge bg-danger">Rejected</span>` |
||||
|
// }, |
||||
|
{ |
||||
|
data: null, |
||||
|
className: "text-center", |
||||
|
render: r => { |
||||
|
|
||||
|
const status = r.final_status; |
||||
|
|
||||
|
if (!status) |
||||
|
return `<span class="badge bg-warning text-dark">Pending</span>`; |
||||
|
else if (status === 'APPROVED') |
||||
|
return `<span class="badge bg-success">Approved</span>`; |
||||
|
else |
||||
|
return `<span class="badge bg-danger">Rejected</span>`; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
data: null, |
||||
|
className: "text-center", |
||||
|
render: r => |
||||
|
`<button class="btn btn-primary btn-sm viewBtn" |
||||
|
data-refid="${r.refid}"> |
||||
|
View |
||||
|
</button>` |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
// 🔹 View button action |
||||
|
|
||||
|
// Destroy previous instance if exists |
||||
|
if ($.fn.DataTable.isDataTable('#QaqcDatatable')) { |
||||
|
$('#QaqcDatatable').DataTable().clear().destroy(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
// $('#QaqcDatatable').on("click", ".viewBtn", function () { |
||||
|
|
||||
|
// // 🔹 Get full row data from DataTable |
||||
|
// const record = table.row($(this).closest('tr')).data(); |
||||
|
|
||||
|
// if (!record) { |
||||
|
// alert("No details found"); |
||||
|
// return; |
||||
|
// } |
||||
|
|
||||
|
// populateModal(record); |
||||
|
// $("#detailsModal").modal("show"); |
||||
|
// }); |
||||
|
|
||||
|
$('#QaqcDatatable').on("click", ".viewBtn", function () { |
||||
|
|
||||
|
let tr = $(this).closest('tr'); |
||||
|
|
||||
|
// ✅ Handle responsive child rows (mobile view) |
||||
|
if (tr.hasClass('child')) { |
||||
|
tr = tr.prev(); |
||||
|
} |
||||
|
|
||||
|
// 🔹 Get full row data from DataTable |
||||
|
const record = table.row(tr).data(); |
||||
|
|
||||
|
if (!record) { |
||||
|
alert("No details found"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
populateModal(record); |
||||
|
$("#detailsModal").modal("show"); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
function populateModal(record) { |
||||
|
|
||||
|
// HEADER |
||||
|
$("#modalTitle").html(`Application Details - ${record.applicant_name}`); |
||||
|
$("#modalSubTitle").html( |
||||
|
`Ref ID: ${record.refid} - ${record.streets.length} Streets` |
||||
|
); |
||||
|
|
||||
|
$("#detailsModal").data("refid", record.refid); |
||||
|
|
||||
|
// 🔹 Streets |
||||
|
let streetHtml = ""; |
||||
|
|
||||
|
record.streets.forEach((s, i) => { |
||||
|
streetHtml += ` |
||||
|
<div class="card-section"> |
||||
|
<div class="section-title">Street ${i + 1}</div> |
||||
|
|
||||
|
<div class="row mb-2"> |
||||
|
<div class="col-md-4"> |
||||
|
<div class="label-text">Street Name</div> |
||||
|
<div class="value-text">${s.street_name}</div> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<div class="label-text">Zone</div> |
||||
|
<div class="value-text">${s.zone}</div> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<div class="label-text">Ward</div> |
||||
|
<div class="value-text">${s.ward}</div> |
||||
|
</div> |
||||
|
<div class="col-md-4"> |
||||
|
<div class="label-text">No. of Poles</div> |
||||
|
<div class="value-text">${s.no_of_poles}</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
<div class="label-text">Height</div> |
||||
|
<div class="value-text">${s.height}</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
<div class="label-text">Flag Material</div> |
||||
|
<div class="value-text">${s.flag_material}</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-4"> |
||||
|
<div class="label-text">Pole Material</div> |
||||
|
<div class="value-text">${s.pole_material}</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div>`; |
||||
|
}); |
||||
|
|
||||
|
let historyHtml = ""; |
||||
|
|
||||
|
if (record.history && record.history.length > 0) { |
||||
|
|
||||
|
historyHtml += ` |
||||
|
<div class="card-section"> |
||||
|
<div class="section-title">Application History</div> |
||||
|
`; |
||||
|
|
||||
|
record.history.forEach((h, index) => { |
||||
|
historyHtml += ` |
||||
|
<div class="row mb-2 border-bottom pb-2"> |
||||
|
<div class="col-md-3"> |
||||
|
<div class="label-text">Action Date</div> |
||||
|
<div class="value-text">${h.action_date}</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-md-3"> |
||||
|
<div class="label-text">Department</div> |
||||
|
<div class="value-text">${h.department_name}</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div class="col-md-3"> |
||||
|
<div class="label-text">Status</div> |
||||
|
<div class="value-text">${h.status}</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
${h.remarks ? ` |
||||
|
<div class="col-md-3"> |
||||
|
<div class="label-text">Remarks</div> |
||||
|
<div class="value-text">${h.remarks}</div> |
||||
|
</div>` : ""} |
||||
|
</div> |
||||
|
`; |
||||
|
}); |
||||
|
|
||||
|
historyHtml += `</div>`; |
||||
|
} |
||||
|
|
||||
|
let decisionHtml = ""; |
||||
|
|
||||
|
// 🔹 Show decision buttons ONLY if pending |
||||
|
if (!record.final_status) { |
||||
|
decisionHtml = ` |
||||
|
<div class="rdo-box"> |
||||
|
<div class="section-title">Department Decision</div> |
||||
|
|
||||
|
<textarea id="rdoRemarks" class="form-control mb-3" |
||||
|
rows="4" placeholder="Enter remarks..."></textarea> |
||||
|
|
||||
|
<div class="d-flex justify-content-between"> |
||||
|
<button class="btn btn-success btn-big" |
||||
|
onclick="submitOfficerDecision('APPROVED')">Approve</button> |
||||
|
|
||||
|
<button class="btn btn-danger btn-big" |
||||
|
onclick="submitOfficerDecision('REJECTED')">Reject</button> |
||||
|
</div> |
||||
|
</div>`; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
let html = ` |
||||
|
<div class="card-section"> |
||||
|
<div class="section-title">Applicant Information</div> |
||||
|
|
||||
|
<div class="row mb-2"> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Applicant Name</div> |
||||
|
<div class="value-text">${record.applicant_name}</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Mobile Number</div> |
||||
|
<div class="value-text">${record.mobile_number}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="row mb-2"> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Event Type</div> |
||||
|
<div class="value-text">${record.event_name}</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Event Date</div> |
||||
|
<div class="value-text"> |
||||
|
${new Date(record.event_date).toLocaleDateString("en-GB")} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Address</div> |
||||
|
<div class="value-text"> |
||||
|
${record.applicant_address} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Total Cost</div> |
||||
|
<div class="value-text"> |
||||
|
${record.total_cost.toLocaleString("en-GB")} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">No. of Days</div> |
||||
|
<div class="value-text">${record.no_of_days}</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Event Description</div> |
||||
|
<div class="value-text">${record.event_desc}</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<div class="row mb-2"> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="label-text">Applied Date</div> |
||||
|
<div class="value-text">${record.cdate}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
${streetHtml} |
||||
|
${historyHtml} |
||||
|
${decisionHtml} |
||||
|
|
||||
|
`; |
||||
|
|
||||
|
|
||||
|
|
||||
|
$("#modalContent").html(html); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
// function submitRdoDecision(status) { |
||||
|
|
||||
|
// let remarks = ($("#rdoRemarks").val() || "").trim(); |
||||
|
// let refid = $("#detailsModal").data("refid"); |
||||
|
// let gccUserId = $("#loginuserid").val(); // 🔥 ONLY THIS |
||||
|
|
||||
|
// //let approvedBy = $("#userName").val(); // 🔥 FROM HIDDEN INPUT |
||||
|
|
||||
|
// if (!remarks) { |
||||
|
// Swal.fire({ |
||||
|
// icon: 'warning', |
||||
|
// title: 'Remarks Required', |
||||
|
// text: 'Please enter remarks before submitting' |
||||
|
// }); |
||||
|
// return; |
||||
|
// } |
||||
|
|
||||
|
// Swal.fire({ |
||||
|
// title: `Are you sure?`, |
||||
|
// text: `You want to ${status.toLowerCase()} this request`, |
||||
|
// icon: status === 'APPROVED' ? 'success' : 'error', |
||||
|
// showCancelButton: true, |
||||
|
// confirmButtonColor: status === 'APPROVED' ? '#28a745' : '#dc3545', |
||||
|
// cancelButtonColor: '#6c757d', |
||||
|
// confirmButtonText: `Yes, ${status}` |
||||
|
// }).then((result) => { |
||||
|
|
||||
|
// if (!result.isConfirmed) return; |
||||
|
|
||||
|
// $.ajax({ |
||||
|
// url: "/gcc/api/flagpoleregistration/rdo/updateDecision", |
||||
|
// type: "POST", |
||||
|
// data: { |
||||
|
// refid: refid, |
||||
|
// status: status, |
||||
|
// remarks: remarks, |
||||
|
// gccUserId: gccUserId |
||||
|
// //approvedBy: approvedBy // 🔥 PASS TO BACKEND |
||||
|
// }, |
||||
|
// success: function (res) { |
||||
|
|
||||
|
// Swal.fire({ |
||||
|
// icon: 'success', |
||||
|
// title: status === 'APPROVED' ? 'Approved!' : 'Rejected!', |
||||
|
// text: res.message || `Request has been ${status.toLowerCase()}`, |
||||
|
// timer: 2000, |
||||
|
// showConfirmButton: false |
||||
|
// }); |
||||
|
|
||||
|
// $("#detailsModal").modal("hide"); |
||||
|
// $("#QaqcDatatable").DataTable().ajax.reload(null, false); |
||||
|
// }, |
||||
|
// error: function () { |
||||
|
// Swal.fire({ |
||||
|
// icon: 'error', |
||||
|
// title: 'Error', |
||||
|
// text: 'Failed to update decision' |
||||
|
// }); |
||||
|
// } |
||||
|
// }); |
||||
|
// }); |
||||
|
// } |
||||
|
|
||||
|
function submitOfficerDecision(status) { |
||||
|
|
||||
|
let remarks = ($("#rdoRemarks").val() || "").trim(); |
||||
|
let refid = $("#detailsModal").data("refid"); |
||||
|
|
||||
|
let gccUserId = $("#loginuserid").val(); // login user id |
||||
|
let username = $("#userName").val(); // display username |
||||
|
|
||||
|
if (!remarks) { |
||||
|
Swal.fire({ |
||||
|
icon: 'warning', |
||||
|
title: 'Remarks Required', |
||||
|
text: 'Please enter remarks before submitting' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
Swal.fire({ |
||||
|
title: `Are you sure?`, |
||||
|
text: `You want to ${status.toLowerCase()} this request`, |
||||
|
icon: status === 'APPROVED' ? 'success' : 'error', |
||||
|
showCancelButton: true, |
||||
|
confirmButtonColor: status === 'APPROVED' ? '#28a745' : '#dc3545', |
||||
|
cancelButtonColor: '#6c757d', |
||||
|
confirmButtonText: `Yes, ${status}` |
||||
|
}).then((result) => { |
||||
|
|
||||
|
if (!result.isConfirmed) return; |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: "/flagpoles/api/flagpoleregistration/officer/updateDecision", |
||||
|
type: "POST", |
||||
|
data: { |
||||
|
refid: refid, |
||||
|
status: status, |
||||
|
remarks: remarks, |
||||
|
gccUserId: gccUserId, |
||||
|
username: username // ✅ NEW |
||||
|
}, |
||||
|
success: function (res) { |
||||
|
|
||||
|
Swal.fire({ |
||||
|
icon: 'success', |
||||
|
title: status === 'APPROVED' ? 'Approved!' : 'Rejected!', |
||||
|
text: res.message || `Request has been ${status.toLowerCase()}`, |
||||
|
timer: 2000, |
||||
|
showConfirmButton: false |
||||
|
}); |
||||
|
|
||||
|
$("#detailsModal").modal("hide"); |
||||
|
$("#QaqcDatatable").DataTable().ajax.reload(null, false); |
||||
|
}, |
||||
|
error: function () { |
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: 'Failed to update decision' |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -1,754 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:attr="data-two-weight=${isTwoWeightFacility}"> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD Biogas Facilities Add Details List</h5> |
|
||||
<span>Biogas Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD Biogas Facilities Add |
|
||||
Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Biogas Add Details</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWM Biogas Add Details : <span th:text="${officer_name}"></span> |
|
||||
</h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select zones</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight:(in MT)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1">Enter Weight:</label><span class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
|
|
||||
// If today is Saturday (6) → today |
|
||||
// Else → go back to previous Saturday |
|
||||
const diffToLastSaturday = (day >= 6) |
|
||||
? day - 6 |
|
||||
: day + 1; |
|
||||
|
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
|
|
||||
// Friday = 5 |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = (d) => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
const minDate = formatDate(lastSaturday); |
|
||||
const maxDate = formatDate(thisFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
APPLY LIMITS |
|
||||
============================= */ |
|
||||
$("#date") |
|
||||
.attr("min", minDate) |
|
||||
.attr("max", maxDate) |
|
||||
.val(formatDate(today)); |
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, // backend will ignore if not needed |
|
||||
createdBy: createdBy |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
function loadTable() { |
|
||||
|
|
||||
let officer_name = $("#userName").val(); |
|
||||
let startDate = $("#startDate").val(); |
|
||||
let endDate = $("#endDate").val(); |
|
||||
|
|
||||
if ($.fn.DataTable.isDataTable('#QaqcDatatable')) { |
|
||||
$('#QaqcDatatable').DataTable().clear().destroy(); |
|
||||
} |
|
||||
|
|
||||
table = $('#QaqcDatatable').DataTable({ |
|
||||
processing: true, |
|
||||
responsive: true, |
|
||||
scrollY: '50vh', |
|
||||
dom: 'Bfrtip', // 🔥 ENABLE BUTTONS |
|
||||
|
|
||||
ajax: { |
|
||||
//url: "/gcc/api/flagpoleregistration/getAllDetails", |
|
||||
type: "GET", |
|
||||
data: { |
|
||||
userLogin: officer_name, |
|
||||
startDate: startDate, |
|
||||
endDate: endDate |
|
||||
}, |
|
||||
dataSrc: function (json) { |
|
||||
|
|
||||
const data = json.data || []; |
|
||||
|
|
||||
// 🔹 Dashboard counts |
|
||||
let pending = 0, approved = 0, rejected = 0; |
|
||||
|
|
||||
data.forEach(r => { |
|
||||
if (!r.rdo_status) pending++; |
|
||||
else if (r.rdo_status === 'APPROVED') approved++; |
|
||||
else if (r.rdo_status === 'REJECTED') rejected++; |
|
||||
}); |
|
||||
|
|
||||
$("#totalrequest").text(data.length); |
|
||||
$("#pendingdecision").text(pending); |
|
||||
$("#approved").text(approved); |
|
||||
$("#rejected").text(rejected); |
|
||||
|
|
||||
return data; // ✅ already unique per refid |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
columns: [ |
|
||||
{ |
|
||||
data: null, |
|
||||
className: "text-center", |
|
||||
render: (d, t, r, m) => m.row + 1 |
|
||||
}, |
|
||||
{ |
|
||||
data: "applicant_name", |
|
||||
className: "text-center" |
|
||||
}, |
|
||||
{ |
|
||||
data: "refid", |
|
||||
className: "text-center" |
|
||||
}, |
|
||||
{ |
|
||||
data: null, |
|
||||
className: "text-center", |
|
||||
render: row => { |
|
||||
if (!row.streets || row.streets.length === 0) return "-"; |
|
||||
return `${row.streets[0].zone} / ${row.streets[0].ward}`; |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
data: "event_name", |
|
||||
className: "text-center" |
|
||||
}, |
|
||||
{ |
|
||||
data: "event_date", |
|
||||
className: "text-center", |
|
||||
render: d => new Date(d).toLocaleDateString("en-GB") |
|
||||
}, |
|
||||
{ |
|
||||
data: "total_cost", |
|
||||
className: "text-center", |
|
||||
render: d => d.toLocaleString("en-GB") |
|
||||
}, |
|
||||
{ |
|
||||
data: "rdo_status", |
|
||||
className: "text-center", |
|
||||
render: d => { |
|
||||
if (!d) |
|
||||
return `<span class="badge bg-warning text-dark">Pending</span>`; |
|
||||
if (d === 'APPROVED') |
|
||||
return `<span class="badge bg-success">Approved</span>`; |
|
||||
return `<span class="badge bg-danger">Rejected</span>`; |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
data: null, |
|
||||
className: "text-center", |
|
||||
render: row => |
|
||||
`<button class="btn btn-primary btn-sm viewBtn" |
|
||||
data-refid="${row.refid}"> |
|
||||
View |
|
||||
</button>` |
|
||||
} |
|
||||
] |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 🔹 View button action |
|
||||
|
|
||||
// Destroy previous instance if exists |
|
||||
if ($.fn.DataTable.isDataTable('#QaqcDatatable')) { |
|
||||
$('#QaqcDatatable').DataTable().clear().destroy(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
$('#QaqcDatatable').on("click", ".viewBtn", function () { |
|
||||
|
|
||||
// 🔹 Get full row data from DataTable |
|
||||
const record = table.row($(this).closest('tr')).data(); |
|
||||
|
|
||||
if (!record) { |
|
||||
alert("No details found"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
populateModal(record); |
|
||||
$("#detailsModal").modal("show"); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
function populateModal(record) { |
|
||||
|
|
||||
// HEADER |
|
||||
$("#modalTitle").html(`Application Details - ${record.applicant_name}`); |
|
||||
$("#modalSubTitle").html( |
|
||||
`Ref ID: ${record.refid} - ${record.streets.length} Streets` |
|
||||
); |
|
||||
|
|
||||
$("#detailsModal").data("refid", record.refid); |
|
||||
|
|
||||
// 🔹 Streets |
|
||||
let streetHtml = ""; |
|
||||
|
|
||||
record.streets.forEach((s, i) => { |
|
||||
streetHtml += ` |
|
||||
<div class="card-section"> |
|
||||
<div class="section-title">Street ${i + 1}</div> |
|
||||
|
|
||||
<div class="row mb-2"> |
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">Street Name</div> |
|
||||
<div class="value-text">${s.street_name}</div> |
|
||||
</div> |
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">Zone</div> |
|
||||
<div class="value-text">${s.zone}</div> |
|
||||
</div> |
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">Ward</div> |
|
||||
<div class="value-text">${s.ward}</div> |
|
||||
</div> |
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">No. of Poles</div> |
|
||||
<div class="value-text">${s.no_of_poles}</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">Height</div> |
|
||||
<div class="value-text">${s.height}</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">Flag Material</div> |
|
||||
<div class="value-text">${s.flag_material}</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">Pole Material</div> |
|
||||
<div class="value-text">${s.pole_material}</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div>`; |
|
||||
}); |
|
||||
|
|
||||
let historyHtml = ""; |
|
||||
|
|
||||
if (record.history && record.history.length > 0) { |
|
||||
|
|
||||
historyHtml += ` |
|
||||
<div class="card-section"> |
|
||||
<div class="section-title">Application History</div> |
|
||||
`; |
|
||||
|
|
||||
record.history.forEach((h, index) => { |
|
||||
historyHtml += ` |
|
||||
<div class="row mb-2 border-bottom pb-2"> |
|
||||
<div class="col-md-4"> |
|
||||
<div class="label-text">Action Date</div> |
|
||||
<div class="value-text">${h.action_date}</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<div class="label-text">Department</div> |
|
||||
<div class="value-text">${h.department_name}</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
<div class="col-md-2"> |
|
||||
<div class="label-text">Status</div> |
|
||||
<div class="value-text">${h.status}</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<div class="col-md-2"> |
|
||||
<div class="label-text">RDO Status</div> |
|
||||
<div class="value-text"> |
|
||||
${record.rdo_status || "-"} |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
${h.remarks ? ` |
|
||||
<div class="col-md-12 mt-1"> |
|
||||
<div class="label-text">Remarks</div> |
|
||||
<div class="value-text">${h.remarks}</div> |
|
||||
</div>` : ""} |
|
||||
</div> |
|
||||
`; |
|
||||
}); |
|
||||
|
|
||||
historyHtml += `</div>`; |
|
||||
} |
|
||||
|
|
||||
let decisionHtml = ""; |
|
||||
|
|
||||
// 🔹 Show decision buttons ONLY if pending |
|
||||
if (!record.rdo_status) { |
|
||||
decisionHtml = ` |
|
||||
<div class="rdo-box"> |
|
||||
<div class="section-title">Department Decision</div> |
|
||||
|
|
||||
<textarea id="rdoRemarks" class="form-control mb-3" |
|
||||
rows="4" placeholder="Enter remarks..."></textarea> |
|
||||
|
|
||||
<div class="d-flex justify-content-between"> |
|
||||
<button class="btn btn-success btn-big" |
|
||||
onclick="submitRdoDecision('APPROVED')">Approve</button> |
|
||||
|
|
||||
<button class="btn btn-danger btn-big" |
|
||||
onclick="submitRdoDecision('REJECTED')">Reject</button> |
|
||||
</div> |
|
||||
</div>`; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
let html = ` |
|
||||
<div class="card-section"> |
|
||||
<div class="section-title">Applicant Information</div> |
|
||||
|
|
||||
<div class="row mb-2"> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Applicant Name</div> |
|
||||
<div class="value-text">${record.applicant_name}</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Mobile Number</div> |
|
||||
<div class="value-text">${record.mobile_number}</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mb-2"> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Event Type</div> |
|
||||
<div class="value-text">${record.event_name}</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Event Date</div> |
|
||||
<div class="value-text"> |
|
||||
${new Date(record.event_date).toLocaleDateString("en-GB")} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Address</div> |
|
||||
<div class="value-text"> |
|
||||
${record.applicant_address} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Total Cost</div> |
|
||||
<div class="value-text"> |
|
||||
${record.total_cost.toLocaleString("en-GB")} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">No. of Days</div> |
|
||||
<div class="value-text">${record.no_of_days}</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Event Description</div> |
|
||||
<div class="value-text">${record.event_desc}</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
<div class="row mb-2"> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="label-text">Applied Date</div> |
|
||||
<div class="value-text">${record.cdate}</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
${streetHtml} |
|
||||
${historyHtml} |
|
||||
${decisionHtml} |
|
||||
|
|
||||
`; |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#modalContent").html(html); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,416 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:attr="data-two-weight=${isTwoWeightFacility}"> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD CDWaste Facilities Add Details List</h5> |
|
||||
<span> CDWaste Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD CDWaste Facilities Add |
|
||||
Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">CDWaste Add Details</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWD CDWaste Add Details : <span th:text="${officer_name}"></span> |
|
||||
</h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label><span class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select days</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight:(in MT)</label><span class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1">Enter Weight (TC)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" id="weightTypeDiv"> |
|
||||
<label class="form-label">Location<span class="text-danger">*</span></label> |
|
||||
<select id="facilitytype" class="form-control"> |
|
||||
<option value="">Select</option> |
|
||||
<option value="KDG">KDG</option> |
|
||||
<option value="PDG">PDG</option> |
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
const diffToLastSaturday = (day >= 6) ? day - 6 : day + 1; |
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = d => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
$("#date") |
|
||||
.attr("min", formatDate(lastSaturday)) |
|
||||
.attr("max", formatDate(thisFriday)) |
|
||||
.val(formatDate(today)) |
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const weightType = $("#facilitytype").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, |
|
||||
weightType: weightType, |
|
||||
createdBy: createdBy // backend will ignore if not needed |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,764 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD Facilities Reports</h5> |
|
||||
<span>Reports</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD Facilities Reports</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Reports</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
<div class="col-md-12"> |
|
||||
<div class="card shadow-sm"> |
|
||||
|
|
||||
<!-- CARD HEADER --> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWD Facilities Reports : <span th:text="${officer_name}"></span> |
|
||||
</h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<!-- FILTER SECTION --> |
|
||||
<div class="card-body pb-0"> |
|
||||
<div class="row align-items-end g-3 mb-3"> |
|
||||
<div class="col-md-3"> |
|
||||
<label class="form-label">From Date</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="fromDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<label class="form-label">To Date</label><span class="text-danger">*</span> |
|
||||
<input type="date" id="toDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<button id="searchBtn" class="btn btn-primary w-100"> |
|
||||
Search |
|
||||
</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- TABLE SECTION --> |
|
||||
<div class="card-body pt-0"> |
|
||||
<div class="table-responsive"> |
|
||||
|
|
||||
<!-- Logged-in username --> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
|
|
||||
<table id="QaqcDatatable" |
|
||||
class="table table-striped table-bordered table-hover dataTable" |
|
||||
width="100%"> |
|
||||
|
|
||||
<thead class="thead-dark"> |
|
||||
<!-- MAIN GROUP HEADERS --> |
|
||||
<tr class="text-center"> |
|
||||
<th rowspan="2">S.No</th> |
|
||||
<th rowspan="2">Zone</th> |
|
||||
|
|
||||
<th colspan="3" class="grp-mcc">MCC</th> |
|
||||
<th colspan="3" class="grp-windrow">Windrow</th> |
|
||||
<th colspan="3" class="grp-biocng">Bio-CNG</th> |
|
||||
<th colspan="3" class="grp-biogas">Bio-GAS</th> |
|
||||
<th colspan="3" class="grp-incinerator">Incinerator</th> |
|
||||
<th colspan="3" class="grp-baling">Plasting Baling Centre</th> |
|
||||
<th colspan="3" class="grp-gwtc">GW & TC Waste</th> |
|
||||
<th colspan="3" class="grp-cd">C&D Waste Processing Centre</th> |
|
||||
|
|
||||
</tr> |
|
||||
|
|
||||
<!-- SUB HEADERS --> |
|
||||
<tr class="text-center"> |
|
||||
<th class="mcc">Target</th> |
|
||||
<th class="mcc">Achieved</th> |
|
||||
<th class="mcc">%</th> |
|
||||
<th class="windrow">Target</th> |
|
||||
<th class="windrow">Achieved</th> |
|
||||
<th class="windrow">%</th> |
|
||||
<th class="biocng">Target</th> |
|
||||
<th class="biocng">Achieved</th> |
|
||||
<th class="biocng">%</th> |
|
||||
<th class="biogas">Target</th> |
|
||||
<th class="biogas">Achieved</th> |
|
||||
<th class="biogas">%</th> |
|
||||
<th class="gwtc">Target</th> |
|
||||
<th class="gwtc">Achieved</th> |
|
||||
<th class="gwtc">%</th> |
|
||||
<th class="incinerator">Target</th> |
|
||||
<th class="incinerator">Achieved</th> |
|
||||
<th class="incinerator">%</th> |
|
||||
<th class="baling">Target</th> |
|
||||
<th class="baling">Achieved</th> |
|
||||
<th class="baling">%</th> |
|
||||
|
|
||||
|
|
||||
<th class="cd">Target</th> |
|
||||
<th class="cd">Achieved</th> |
|
||||
<th class="cd">%</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tfoot> |
|
||||
<tr class="fw-bold text-center"> |
|
||||
<th colspan="2">TOTAL</th> |
|
||||
|
|
||||
<!-- MCC --> |
|
||||
<th class="mcc"></th> |
|
||||
<th class="mcc"></th> |
|
||||
<th class="mcc"></th> |
|
||||
|
|
||||
<!-- Windrow --> |
|
||||
<th class="windrow"></th> |
|
||||
<th class="windrow"></th> |
|
||||
<th class="windrow"></th> |
|
||||
|
|
||||
<!-- Bio-CNG --> |
|
||||
<th class="biocng"></th> |
|
||||
<th class="biocng"></th> |
|
||||
<th class="biocng"></th> |
|
||||
|
|
||||
<!-- Bio-GAS --> |
|
||||
<th class="biogas"></th> |
|
||||
<th class="biogas"></th> |
|
||||
<th class="biogas"></th> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<!-- Incinerator --> |
|
||||
<th class="incinerator"></th> |
|
||||
<th class="incinerator"></th> |
|
||||
<th class="incinerator"></th> |
|
||||
|
|
||||
<!-- Baling --> |
|
||||
<th class="baling"></th> |
|
||||
<th class="baling"></th> |
|
||||
<th class="baling"></th> |
|
||||
|
|
||||
<th class="gwtc"></th> |
|
||||
<th class="gwtc"></th> |
|
||||
<th class="gwtc"></th> |
|
||||
|
|
||||
|
|
||||
<!-- C&D --> |
|
||||
<th class="cd"></th> |
|
||||
<th class="cd"></th> |
|
||||
<th class="cd"></th> |
|
||||
</tr> |
|
||||
</tfoot> |
|
||||
|
|
||||
|
|
||||
<tbody></tbody> |
|
||||
</table> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
let table; |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
table = $('#QaqcDatatable').DataTable({ |
|
||||
data: [], |
|
||||
ordering: false, |
|
||||
searching: true, |
|
||||
info: true, |
|
||||
paging: true, |
|
||||
pageLength: 15, // ✅ show 15 rows |
|
||||
lengthMenu: [15, 25, 50, 100], // ✅ optional dropdown |
|
||||
scrollX: true, |
|
||||
responsive: false, |
|
||||
dom: 'Bftip', |
|
||||
|
|
||||
buttons: [ |
|
||||
{ |
|
||||
extend: 'excelHtml5', |
|
||||
text: 'Excel', |
|
||||
title: 'Gcc Swm Report' |
|
||||
}, |
|
||||
{ |
|
||||
extend: 'pdfHtml5', |
|
||||
orientation: 'landscape', |
|
||||
pageSize: 'A3', |
|
||||
title: 'Gcc Swm Report' |
|
||||
}, |
|
||||
{ |
|
||||
extend: 'csvHtml5', |
|
||||
text: 'CSV' |
|
||||
} |
|
||||
], |
|
||||
|
|
||||
// columns: [ |
|
||||
// { data: "sno", defaultContent: "" }, |
|
||||
// { data: "zone", defaultContent: "" }, |
|
||||
|
|
||||
// { data: "MCC_target", defaultContent: 0 }, |
|
||||
// { data: "MCC_achieved", defaultContent: 0 }, |
|
||||
// { data: "MCC_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
// { data: "Windrow_target", defaultContent: 0 }, |
|
||||
// { data: "Windrow_achieved", defaultContent: 0 }, |
|
||||
// { data: "Windrow_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
// { data: "Bio-CNG_target", defaultContent: 0 }, |
|
||||
// { data: "Bio-CNG_achieved", defaultContent: 0 }, |
|
||||
// { data: "Bio-CNG_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
// { data: "Bio-GAS_target", defaultContent: 0 }, |
|
||||
// { data: "Bio-GAS_achieved", defaultContent: 0 }, |
|
||||
// { data: "Bio-GAS_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
|
|
||||
|
|
||||
// { data: "Incinerator_target", defaultContent: 0 }, |
|
||||
// { data: "Incinerator_achieved", defaultContent: 0 }, |
|
||||
// { data: "Incinerator_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
// { data: "Plasting Baling Centre_target", defaultContent: 0 }, |
|
||||
// { data: "Plasting Baling Centre_achieved", defaultContent: 0 }, |
|
||||
// { data: "Plasting Baling Centre_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
// { data: "GWTC_target", defaultContent: 0 }, |
|
||||
// { data: "GWTC_achieved", defaultContent: 0 }, |
|
||||
// { data: "GWTC_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
|
|
||||
// { data: "CD_target", defaultContent: 0 }, |
|
||||
// { data: "CD_achieved", defaultContent: 0 }, |
|
||||
// { data: "CD_percentage", defaultContent: "0%" } |
|
||||
|
|
||||
|
|
||||
|
|
||||
// ], |
|
||||
columns: [ |
|
||||
{ data: "sno" }, |
|
||||
{ data: "zone" }, |
|
||||
|
|
||||
{ data: "mcc_target", defaultContent: 0 }, |
|
||||
{ data: "mcc_achieved", defaultContent: 0 }, |
|
||||
{ data: "mcc_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
{ data: "windrow_target", defaultContent: 0 }, |
|
||||
{ data: "windrow_achieved", defaultContent: 0 }, |
|
||||
{ data: "windrow_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
{ data: "biocng_target", defaultContent: 0 }, |
|
||||
{ data: "biocng_achieved", defaultContent: 0 }, |
|
||||
{ data: "biocng_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
{ data: "biogas_target", defaultContent: 0 }, |
|
||||
{ data: "biogas_achieved", defaultContent: 0 }, |
|
||||
{ data: "biogas_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
|
|
||||
{ data: "incinerator_target", defaultContent: 0 }, |
|
||||
{ data: "incinerator_achieved", defaultContent: 0 }, |
|
||||
{ data: "incinerator_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
{ data: "baling_target", defaultContent: 0 }, |
|
||||
{ data: "baling_achieved", defaultContent: 0 }, |
|
||||
{ data: "baling_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
{ data: "gwtc_target", defaultContent: 0 }, |
|
||||
{ data: "gwtc_achieved", defaultContent: 0 }, |
|
||||
{ data: "gwtc_percentage", defaultContent: "0%" }, |
|
||||
|
|
||||
|
|
||||
{ data: "cd_target", defaultContent: 0 }, |
|
||||
{ data: "cd_achieved", defaultContent: 0 }, |
|
||||
{ data: "cd_percentage", defaultContent: "0%" } |
|
||||
], |
|
||||
|
|
||||
|
|
||||
/* ================= FOOTER TOTAL ================= */ |
|
||||
footerCallback: function () { |
|
||||
|
|
||||
const api = this.api(); |
|
||||
|
|
||||
function sum(colIdx) { |
|
||||
return api |
|
||||
.column(colIdx, { page: 'current' }) |
|
||||
.data() |
|
||||
.reduce((a, b) => { |
|
||||
const x = parseFloat(a) || 0; |
|
||||
const y = parseFloat(String(b).replace('%', '')) || 0; |
|
||||
return x + y; |
|
||||
}, 0) |
|
||||
.toFixed(2); |
|
||||
} |
|
||||
|
|
||||
const targetAchievedCols = [ |
|
||||
2, 3, // MCC |
|
||||
5, 6, // Windrow |
|
||||
8, 9, // Bio-CNG |
|
||||
11, 12, // Bio-GAS |
|
||||
14, 15, // Incinerator |
|
||||
17, 18, // Baling |
|
||||
20, 21, // gwtc |
|
||||
23, 24 // C&D |
|
||||
]; |
|
||||
|
|
||||
targetAchievedCols.forEach(idx => { |
|
||||
if (api.column(idx).visible()) { |
|
||||
$(api.column(idx).footer()).html(sum(idx)); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
// 🔥 Hide/Show facility columns based on username |
|
||||
applyFacilityVisibility(); |
|
||||
|
|
||||
$("#searchBtn").on("click", loadLoginWiseReport); |
|
||||
}); |
|
||||
|
|
||||
function normalizeFacilityName(facility) { |
|
||||
const map = { |
|
||||
// MCC |
|
||||
"MCC": "mcc", |
|
||||
|
|
||||
// Windrow |
|
||||
"Windrow": "windrow", |
|
||||
|
|
||||
// Bio-CNG |
|
||||
"Bio-CNG": "biocng", |
|
||||
|
|
||||
// Bio-GAS |
|
||||
"Bio-GAS": "biogas", |
|
||||
|
|
||||
// Incinerator |
|
||||
"Incinerator": "incinerator", |
|
||||
|
|
||||
// Baling |
|
||||
"Plasting Baling Centre": "baling", |
|
||||
"Plastic Baling Centre": "baling", |
|
||||
|
|
||||
// 🔥 GW & TC (THIS IS THE FIX) |
|
||||
"GW & TC Waste": "gwtc", |
|
||||
"GW & TC Waste Processing Centre": "gwtc", |
|
||||
"GW TC Waste": "gwtc", |
|
||||
|
|
||||
// C&D |
|
||||
"C&D Waste Processing Centre": "cd", |
|
||||
"C & D Waste Processing Centre": "cd", |
|
||||
"C&D Waste": "cd", |
|
||||
"SWM C&D": "cd" |
|
||||
}; |
|
||||
|
|
||||
return map[facility] || facility.toLowerCase().replace(/[^a-z]/g, ""); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
// function applyFacilityVisibility() { |
|
||||
|
|
||||
// const username = $("#userName").val().toLowerCase(); |
|
||||
|
|
||||
// // hide all facility columns |
|
||||
// table.columns([...Array(26).keys()].slice(2)).visible(false); |
|
||||
|
|
||||
|
|
||||
// // hide all headers |
|
||||
// $('.grp-mcc,.grp-windrow,.grp-biocng,.grp-biogas,.grp-incinerator,.grp-baling,.grp-gwtc,.grp-cd').hide(); |
|
||||
// $('.mcc,.windrow,.biocng,.biogas,.incinerator,.baling,.gwtc,.cd').hide(); |
|
||||
|
|
||||
// const map = { |
|
||||
// "mcc": { cols: [2, 3, 4], cls: "mcc", grp: "grp-mcc" }, |
|
||||
// "windrow": { cols: [5, 6, 7], cls: "windrow", grp: "grp-windrow" }, |
|
||||
// "biocng": { cols: [8, 9, 10], cls: "biocng", grp: "grp-biocng" }, |
|
||||
// "biogas": { cols: [11, 12, 13], cls: "biogas", grp: "grp-biogas" }, |
|
||||
// "incinerator": { cols: [14, 15, 16], cls: "incinerator", grp: "grp-incinerator" }, |
|
||||
// "baling": { cols: [17, 18, 19], cls: "baling", grp: "grp-baling" }, |
|
||||
// // ✅ ADD THIS (CRITICAL FIX) |
|
||||
// "pbc": { cols: [17, 18, 19], cls: "baling", grp: "grp-baling" }, |
|
||||
|
|
||||
// // ✅ GW & TC |
|
||||
// "gw": { cols: [20, 21, 22], cls: "gwtc", grp: "grp-gwtc" }, |
|
||||
// "tc": { cols: [20, 21, 22], cls: "gwtc", grp: "grp-gwtc" }, |
|
||||
// "gwtc": { cols: [20, 21, 22], cls: "gwtc", grp: "grp-gwtc" }, |
|
||||
// // ✅ C&D |
|
||||
// "cd": { cols: [23, 24, 25], cls: "cd", grp: "grp-cd" }, |
|
||||
// "c&d": { cols: [23, 24, 25], cls: "cd", grp: "grp-cd" } |
|
||||
// }; |
|
||||
|
|
||||
// Object.keys(map).forEach(key => { |
|
||||
// if (username.includes(key)) { |
|
||||
// table.columns(map[key].cols).visible(true); |
|
||||
// $('.' + map[key].cls).show(); |
|
||||
// $('.' + map[key].grp).show(); |
|
||||
// } |
|
||||
// }); |
|
||||
|
|
||||
// table.columns.adjust().draw(false); |
|
||||
// } |
|
||||
|
|
||||
function applyFacilityVisibility() { |
|
||||
|
|
||||
const username = $("#userName").val().toLowerCase(); |
|
||||
|
|
||||
// hide all columns except S.No & Zone |
|
||||
table.columns().visible(false); |
|
||||
table.columns([0, 1]).visible(true); |
|
||||
|
|
||||
// hide all headers |
|
||||
$('.grp-mcc,.grp-windrow,.grp-biocng,.grp-biogas,.grp-incinerator,.grp-baling,.grp-gwtc,.grp-cd').hide(); |
|
||||
$('.mcc,.windrow,.biocng,.biogas,.incinerator,.baling,.gwtc,.cd').hide(); |
|
||||
|
|
||||
const map = { |
|
||||
"mcc": { cols: [2, 3, 4], cls: "mcc", grp: "grp-mcc" }, |
|
||||
"windrow": { cols: [5, 6, 7], cls: "windrow", grp: "grp-windrow" }, |
|
||||
|
|
||||
// 🔥 FIX: support bio_cng login |
|
||||
"bio_cng": { cols: [8, 9, 10], cls: "biocng", grp: "grp-biocng" }, |
|
||||
"biocng": { cols: [8, 9, 10], cls: "biocng", grp: "grp-biocng" }, |
|
||||
|
|
||||
"bio_gas": { cols: [11, 12, 13], cls: "biogas", grp: "grp-biogas" }, |
|
||||
"biogas": { cols: [11, 12, 13], cls: "biogas", grp: "grp-biogas" }, |
|
||||
"incinerator": { cols: [14, 15, 16], cls: "incinerator", grp: "grp-incinerator" }, |
|
||||
|
|
||||
"baling": { cols: [17, 18, 19], cls: "baling", grp: "grp-baling" }, |
|
||||
"pbc": { cols: [17, 18, 19], cls: "baling", grp: "grp-baling" }, |
|
||||
|
|
||||
"gwtc_waste": { cols: [20, 21, 22], cls: "gwtc", grp: "grp-gwtc" }, |
|
||||
"gw": { cols: [20, 21, 22], cls: "gwtc", grp: "grp-gwtc" }, |
|
||||
"tc": { cols: [20, 21, 22], cls: "gwtc", grp: "grp-gwtc" }, |
|
||||
|
|
||||
"cd": { cols: [23, 24, 25], cls: "cd", grp: "grp-cd" }, |
|
||||
"c&d": { cols: [23, 24, 25], cls: "cd", grp: "grp-cd" } |
|
||||
}; |
|
||||
|
|
||||
Object.keys(map).forEach(key => { |
|
||||
if (username.includes(key)) { |
|
||||
table.columns(map[key].cols).visible(true); |
|
||||
$('.' + map[key].cls).show(); |
|
||||
$('.' + map[key].grp).show(); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
table.columns.adjust().draw(false); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// function renderZoneTable(data) { |
|
||||
|
|
||||
// const zoneMap = {}; |
|
||||
|
|
||||
// data.forEach(row => { |
|
||||
// const zone = row.zone; |
|
||||
// const facility = row.facility; // MCC / Windrow / etc |
|
||||
|
|
||||
// if (!zoneMap[zone]) { |
|
||||
// zoneMap[zone] = { |
|
||||
// zone: zone |
|
||||
// }; |
|
||||
// } |
|
||||
|
|
||||
// // Target |
|
||||
// zoneMap[zone][facility + "_target"] = |
|
||||
// row.target !== null ? row.target : 0; |
|
||||
|
|
||||
// // Achieved |
|
||||
// zoneMap[zone][facility + "_achieved"] = |
|
||||
// row.achieved !== null ? row.achieved : 0; |
|
||||
|
|
||||
// // Percentage |
|
||||
// zoneMap[zone][facility + "_percentage"] = |
|
||||
// row.percentage !== null ? row.percentage + "%" : "0%"; |
|
||||
// }); |
|
||||
|
|
||||
// let i = 1; |
|
||||
// const tableData = Object.values(zoneMap).map(row => ({ |
|
||||
// sno: i++, |
|
||||
// ...row |
|
||||
// })); |
|
||||
|
|
||||
// table.clear().rows.add(tableData).draw(); |
|
||||
// } |
|
||||
|
|
||||
// function renderZoneTable(data) { |
|
||||
|
|
||||
// const zoneMap = {}; |
|
||||
|
|
||||
// data.forEach(row => { |
|
||||
// const zone = row.zone; |
|
||||
// const facility = normalizeFacilityName(row.facility); |
|
||||
|
|
||||
// if (!zoneMap[zone]) { |
|
||||
// zoneMap[zone] = { zone }; |
|
||||
// } |
|
||||
|
|
||||
// zoneMap[zone][facility + "_target"] = row.target ?? 0; |
|
||||
// zoneMap[zone][facility + "_achieved"] = row.achieved ?? 0; |
|
||||
// zoneMap[zone][facility + "_percentage"] = |
|
||||
// row.percentage != null ? row.percentage + "%" : "0%"; |
|
||||
// }); |
|
||||
|
|
||||
// let i = 1; |
|
||||
// const tableData = Object.values(zoneMap).map(r => ({ |
|
||||
// sno: i++, |
|
||||
// ...r |
|
||||
// })); |
|
||||
|
|
||||
// table.clear().rows.add(tableData).draw(); |
|
||||
// } |
|
||||
|
|
||||
function renderZoneTable(data) { |
|
||||
|
|
||||
const zoneMap = {}; |
|
||||
|
|
||||
data.forEach(row => { |
|
||||
const zone = row.zone; |
|
||||
const facilityKey = normalizeFacilityName(row.facility); |
|
||||
|
|
||||
if (!zoneMap[zone]) { |
|
||||
zoneMap[zone] = { zone }; |
|
||||
} |
|
||||
|
|
||||
zoneMap[zone][facilityKey + "_target"] = row.target ?? 0; |
|
||||
zoneMap[zone][facilityKey + "_achieved"] = row.achieved ?? 0; |
|
||||
zoneMap[zone][facilityKey + "_percentage"] = |
|
||||
row.percentage != null ? row.percentage + "%" : "0%"; |
|
||||
}); |
|
||||
|
|
||||
let i = 1; |
|
||||
const tableData = Object.values(zoneMap).map(r => ({ |
|
||||
sno: i++, |
|
||||
...r |
|
||||
})); |
|
||||
|
|
||||
table.clear().rows.add(tableData).draw(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
function loadLoginWiseReport() { |
|
||||
|
|
||||
const fromDate = $("#fromDate").val(); |
|
||||
const toDate = $("#toDate").val(); |
|
||||
const username = $("#userName").val(); |
|
||||
|
|
||||
if (!fromDate || !toDate) { |
|
||||
Swal.fire("Validation", "Select both dates", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/facilities/reports", |
|
||||
type: "GET", |
|
||||
data: { |
|
||||
username: username, |
|
||||
fromDate: fromDate, |
|
||||
toDate: toDate |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Loading...", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (res) { |
|
||||
console.log(res); |
|
||||
Swal.close(); |
|
||||
renderZoneTable(res.data); |
|
||||
}, |
|
||||
error: function () { |
|
||||
Swal.fire("Error", "Failed to load report", "error"); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,447 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD GW&TC Waste Facilities Add Details List</h5> |
|
||||
<span>GW&TC Waste Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD GW&TC Waste Facilities Add |
|
||||
Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">GW&TC Waste Add Details |
|
||||
</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWD GW&TC Waste Add Details : <span |
|
||||
th:text="${officer_name}"></span></h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select zones</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight for Garden |
|
||||
Waste:(in MT)</label><span class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="weight1" class="form-label">Enter Weight Tender Coconut:(in |
|
||||
MT)</label><span class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<div class="col-md-3" id="weightTypeDiv"> |
|
||||
<label class="form-label">Location<span class="text-danger">*</span></label> |
|
||||
<select id="facilitytype" class="form-control"> |
|
||||
<option value="">Select</option> |
|
||||
<option value="KDG">KDG</option> |
|
||||
<option value="PDG">PDG</option> |
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
|
|
||||
// If today is Saturday (6) → today |
|
||||
// Else → go back to previous Saturday |
|
||||
const diffToLastSaturday = (day >= 6) |
|
||||
? day - 6 |
|
||||
: day + 1; |
|
||||
|
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
|
|
||||
// Friday = 5 |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = (d) => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
const minDate = formatDate(lastSaturday); |
|
||||
const maxDate = formatDate(thisFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
APPLY LIMITS |
|
||||
============================= */ |
|
||||
$("#date") |
|
||||
.attr("min", minDate) |
|
||||
.attr("max", maxDate) |
|
||||
.val(formatDate(today)); |
|
||||
|
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
|
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
|
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
const weightType = $("#facilitytype").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight == "") { |
|
||||
Swal.fire("Validation Error", "Weight is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
// if (!weight || weight <= 0) { |
|
||||
// Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
// return; |
|
||||
// } |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, |
|
||||
weightType: weightType, |
|
||||
createdBy: createdBy // backend will ignore if not needed |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,421 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:attr="data-two-weight=${isTwoWeightFacility}"> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD Incinerator Facilities Add Details List</h5> |
|
||||
<span>Incinerator Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD Incinerator Facilities Add |
|
||||
Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Incinerator Add Details |
|
||||
</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWD Incinerator Add Details : <span |
|
||||
th:text="${officer_name}"></span></h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select days</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight:(in MT)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1">Enter Weight (TC)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
|
|
||||
// If today is Saturday (6) → today |
|
||||
// Else → go back to previous Saturday |
|
||||
const diffToLastSaturday = (day >= 6) |
|
||||
? day - 6 |
|
||||
: day + 1; |
|
||||
|
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
|
|
||||
// Friday = 5 |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = (d) => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
const minDate = formatDate(lastSaturday); |
|
||||
const maxDate = formatDate(thisFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
APPLY LIMITS |
|
||||
============================= */ |
|
||||
$("#date") |
|
||||
.attr("min", minDate) |
|
||||
.attr("max", maxDate) |
|
||||
.val(formatDate(today)); |
|
||||
|
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, |
|
||||
createdBy: createdBy // backend will ignore if not needed |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,428 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:attr="data-two-weight=${isTwoWeightFacility}"> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD MCC Facilities Add Details List</h5> |
|
||||
<span> MCC Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD MCC Facilities Add Details |
|
||||
List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">MCC Add Details</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWM MCC Add Details : <span th:text="${officer_name}"></span></h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<!-- <div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label> |
|
||||
<input type="date" id="date" class="form-control" readonly> |
|
||||
</div> --> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" style="font-size: medium;"> |
|
||||
Date: |
|
||||
</label><span class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select zones</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight:(in MT)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1">Enter Weight (TC)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
|
|
||||
// If today is Saturday (6) → today |
|
||||
// Else → go back to previous Saturday |
|
||||
const diffToLastSaturday = (day >= 6) |
|
||||
? day - 6 |
|
||||
: day + 1; |
|
||||
|
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
|
|
||||
// Friday = 5 |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = (d) => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
const minDate = formatDate(lastSaturday); |
|
||||
const maxDate = formatDate(thisFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
APPLY LIMITS |
|
||||
============================= */ |
|
||||
$("#date") |
|
||||
.attr("min", minDate) |
|
||||
.attr("max", maxDate) |
|
||||
.val(formatDate(today)); |
|
||||
|
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, |
|
||||
createdBy: createdBy // backend will ignore if not needed |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,424 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:attr="data-two-weight=${isTwoWeightFacility}"> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD MRF OR RRC Facilities Add Details List</h5> |
|
||||
<span> MRF OR RRC Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD MRF OR RRC Facilities Add |
|
||||
Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">MRF OR RRC Add Details |
|
||||
</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWD MRF OR RRC Add Details : <span |
|
||||
th:text="${officer_name}"></span></h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select days</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight:(in MT)</label> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1">Enter Weight (TC)</label> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
|
|
||||
// If today is Saturday (6) → today |
|
||||
// Else → go back to previous Saturday |
|
||||
const diffToLastSaturday = (day >= 6) |
|
||||
? day - 6 |
|
||||
: day + 1; |
|
||||
|
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
|
|
||||
// Friday = 5 |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = (d) => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
const minDate = formatDate(lastSaturday); |
|
||||
const maxDate = formatDate(thisFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
APPLY LIMITS |
|
||||
============================= */ |
|
||||
$("#date") |
|
||||
.attr("min", minDate) |
|
||||
.attr("max", maxDate) |
|
||||
.val(formatDate(today)); |
|
||||
|
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, |
|
||||
createdBy: createdBy // backend will ignore if not needed |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,418 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:attr="data-two-weight=${isTwoWeightFacility}"> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD Plasting Baling Facilities Add Details List</h5> |
|
||||
<span>Plasting Baling Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD Plasting Baling Facilities |
|
||||
Add Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Plasting Baling Add |
|
||||
Details</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWD Plasting Baling Add Details : <span |
|
||||
th:text="${officer_name}"></span></h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select days</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight:(in MT)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1">Enter Weight (TC)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
|
|
||||
// If today is Saturday (6) → today |
|
||||
// Else → go back to previous Saturday |
|
||||
const diffToLastSaturday = (day >= 6) |
|
||||
? day - 6 |
|
||||
: day + 1; |
|
||||
|
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
|
|
||||
// Friday = 5 |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = (d) => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
const minDate = formatDate(lastSaturday); |
|
||||
const maxDate = formatDate(thisFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
APPLY LIMITS |
|
||||
============================= */ |
|
||||
$("#date") |
|
||||
.attr("min", minDate) |
|
||||
.attr("max", maxDate) |
|
||||
.val(formatDate(today)); |
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, |
|
||||
createdBy: createdBy // backend will ignore if not needed |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,944 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD Facilities Reports</h5> |
|
||||
<span>Reports</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD Facilities Reports</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Reports</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
<div class="col-md-12"> |
|
||||
<div class="card shadow-sm"> |
|
||||
|
|
||||
<!-- CARD HEADER --> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWD Facilities Reports : <span th:text="${officer_name}"></span> |
|
||||
</h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<!-- FILTER SECTION --> |
|
||||
<!-- <div class="card-body pb-0"> |
|
||||
<div class="row align-items-end g-3 mb-3"> |
|
||||
<div class="col-md-3"> |
|
||||
<label class="form-label">From Date</label> |
|
||||
<input type="date" id="fromDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<label class="form-label">To Date</label> |
|
||||
<input type="date" id="toDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<label class="form-label">date</label> |
|
||||
<input type="date" id="singleDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<label class="form-label">Report type</label> |
|
||||
<select> |
|
||||
< </select> |
|
||||
<option></option> |
|
||||
<input type="date" id="singleDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
<button id="searchBtn" class="btn btn-primary w-100"> |
|
||||
Search |
|
||||
</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> --> |
|
||||
|
|
||||
<div class="card-body pb-0"> |
|
||||
<div class="row align-items-end g-3 mb-3"> |
|
||||
|
|
||||
<!-- From Date --> |
|
||||
<div class="col-md-3 d-none" id="fromDateDiv"> |
|
||||
<label class="form-label">From Date</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="fromDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<!-- To Date --> |
|
||||
<div class="col-md-3 d-none" id="toDateDiv"> |
|
||||
<label class="form-label">To Date</label><span class="text-danger">*</span> |
|
||||
<input type="date" id="toDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Single Date --> |
|
||||
<div class="col-md-3 d-none" id="singleDateDiv"> |
|
||||
<label class="form-label">Date</label> <span class="text-danger">*</span> |
|
||||
</label> |
|
||||
<input type="date" id="singleDate" class="form-control"> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Report Type --> |
|
||||
<div class="col-md-3"> |
|
||||
<label class="form-label">Report Type</label> <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> |
|
||||
<select id="reportType" class="form-control"> |
|
||||
<option value="">Select</option> |
|
||||
<option value="DAY">Day Wise</option> |
|
||||
<option value="MONTH">Month Wise/Date Range</option> |
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Search --> |
|
||||
<div class="col-md-3"> |
|
||||
<button id="searchBtn" class="btn btn-primary w-100"> |
|
||||
Search |
|
||||
</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<!-- TABLE SECTION --> |
|
||||
<div class="card-body pt-0"> |
|
||||
<div class="table-responsive"> |
|
||||
<!-- <table id="QaqcDatatable" |
|
||||
class="table table-striped table-bordered table-hover dataTable" |
|
||||
role="grid"> |
|
||||
<thead class="thead-dark"> |
|
||||
<tr role="row"> |
|
||||
<th class="text-center">S.No</th> |
|
||||
<th class="text-center no-sort">Zone Name</th> |
|
||||
<th class="text-center no-sort">MCC (%)</th> |
|
||||
<th class="text-center no-sort">Windrow (%)</th> |
|
||||
<th class="text-center no-sort">BioCng (%)</th> |
|
||||
<th class="text-center no-sort">Horticulture (%)</th> |
|
||||
<th class="text-center no-sort">Incinerator (%)</th> |
|
||||
<th class="text-center no-sort">Baling center (%)</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tbody> </tbody> |
|
||||
</table> --> |
|
||||
|
|
||||
<table id="QaqcDatatable" |
|
||||
class="table table-striped table-bordered table-hover dataTable" |
|
||||
width="100%"> |
|
||||
|
|
||||
<thead class="thead-dark"> |
|
||||
<!-- ROW 1 : MAIN GROUP HEADERS --> |
|
||||
<!-- <tr class="text-center"> |
|
||||
<th colspan="23" class="text-center">Average month wise report</th> |
|
||||
</tr> --> |
|
||||
<tr class="text-center"> |
|
||||
|
|
||||
<th rowspan="2">S.No</th> |
|
||||
<th rowspan="2">Zone</th> |
|
||||
|
|
||||
<th colspan="3">MCC</th> |
|
||||
<th colspan="3">Windrow</th> |
|
||||
<th colspan="3">Bio-CNG</th> |
|
||||
<th colspan="3">Bio-GAS</th> |
|
||||
<th colspan="3">Horticulture</th> |
|
||||
<th colspan="3">Incinerator</th> |
|
||||
<th colspan="3">Plasting Baling Centre</th> |
|
||||
</tr> |
|
||||
|
|
||||
<!-- ROW 2 : SUB HEADERS --> |
|
||||
<tr class="text-center"> |
|
||||
<th>Target</th> |
|
||||
<th>Achieved</th> |
|
||||
<th>%</th> |
|
||||
|
|
||||
<th>Target</th> |
|
||||
<th>Achieved</th> |
|
||||
<th>%</th> |
|
||||
|
|
||||
<th>Target</th> |
|
||||
<th>Achieved</th> |
|
||||
<th>%</th> |
|
||||
|
|
||||
<th>Target</th> |
|
||||
<th>Achieved</th> |
|
||||
<th>%</th> |
|
||||
|
|
||||
<th>Target</th> |
|
||||
<th>Achieved</th> |
|
||||
<th>%</th> |
|
||||
|
|
||||
<th>Target</th> |
|
||||
<th>Achieved</th> |
|
||||
<th>%</th> |
|
||||
|
|
||||
<th>Target</th> |
|
||||
<th>Achieved</th> |
|
||||
<th>%</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tfoot> |
|
||||
<tr class="text-center fw-bold"> |
|
||||
<th colspan="2">TOTAL</th> |
|
||||
|
|
||||
<th></th> |
|
||||
<th></th> |
|
||||
<th></th> <!-- MCC --> |
|
||||
<th></th> |
|
||||
<th></th> |
|
||||
<th></th> <!-- Windrow --> |
|
||||
<th></th> |
|
||||
<th></th> |
|
||||
<th></th> <!-- Bio-CNG --> |
|
||||
<th></th> |
|
||||
<th></th> |
|
||||
<th></th> <!-- Bio-GAS --> |
|
||||
<th></th> |
|
||||
<th></th> |
|
||||
<th></th> <!-- Horticulture / GW&TC --> |
|
||||
<th></th> |
|
||||
<th></th> |
|
||||
<th></th> <!-- Incinerator --> |
|
||||
<th></th> |
|
||||
<th></th> |
|
||||
<th></th> <!-- Plastic Baling --> |
|
||||
</tr> |
|
||||
</tfoot> |
|
||||
|
|
||||
|
|
||||
<tbody></tbody> |
|
||||
</table> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
|
|
||||
|
|
||||
let table; |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
table = $('#QaqcDatatable').DataTable({ |
|
||||
data: [], |
|
||||
ordering: false, |
|
||||
searching: true, |
|
||||
info: true, |
|
||||
paging: true, |
|
||||
pageLength: 15, // show 15 rows |
|
||||
lengthMenu: [15, 25, 50, 100], // optional dropdown |
|
||||
scrollX: true, |
|
||||
responsive: false, |
|
||||
dom: 'Bftip', |
|
||||
|
|
||||
buttons: [ |
|
||||
|
|
||||
/* ===================== EXCEL (SIMPLE & SAFE) ===================== */ |
|
||||
{ |
|
||||
extend: 'excelHtml5', |
|
||||
text: 'Excel', |
|
||||
title: 'Gcc Swm Report', |
|
||||
filename: 'Gcc Swm Report', |
|
||||
exportOptions: { |
|
||||
format: { |
|
||||
header: function (data, columnIdx) { |
|
||||
|
|
||||
const headers = [ |
|
||||
'S.No', |
|
||||
'Zone', |
|
||||
|
|
||||
'MCC Target', |
|
||||
'MCC Achieved', |
|
||||
'MCC %', |
|
||||
|
|
||||
'Windrow Target', |
|
||||
'Windrow Achieved', |
|
||||
'Windrow %', |
|
||||
|
|
||||
'Bio-CNG Target', |
|
||||
'Bio-CNG Achieved', |
|
||||
'Bio-CNG %', |
|
||||
|
|
||||
'Bio-GAS Target', |
|
||||
'Bio-GAS Achieved', |
|
||||
'Bio-GAS %', |
|
||||
|
|
||||
'Incinerator Target', |
|
||||
'Incinerator Achieved', |
|
||||
'Incinerator %', |
|
||||
|
|
||||
'GW & TC Waste Target', |
|
||||
'GW & TC Waste Achieved', |
|
||||
'GW & TC Waste %', |
|
||||
|
|
||||
'Plasting Baling Centre Target', |
|
||||
'Plasting Baling Centre Achieved', |
|
||||
'Plasting Baling Centre %' |
|
||||
]; |
|
||||
|
|
||||
return headers[columnIdx]; |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
customize: function (xlsx) { |
|
||||
|
|
||||
const sheet = xlsx.xl.worksheets['sheet1.xml']; |
|
||||
const api = $('#QaqcDatatable').DataTable(); |
|
||||
|
|
||||
// Helper to get footer text safely |
|
||||
function footerVal(colIdx) { |
|
||||
const footer = api.column(colIdx).footer(); |
|
||||
return footer ? footer.innerText.trim() : '0'; |
|
||||
} |
|
||||
|
|
||||
// Build TOTAL row (MUST match column order) |
|
||||
const totalRow = [ |
|
||||
'TOTAL', '', |
|
||||
|
|
||||
footerVal(2), footerVal(3), footerVal(4), |
|
||||
footerVal(5), footerVal(6), footerVal(7), |
|
||||
footerVal(8), footerVal(9), footerVal(10), |
|
||||
footerVal(11), footerVal(12), footerVal(13), |
|
||||
footerVal(14), footerVal(15), footerVal(16), |
|
||||
footerVal(17), footerVal(18), footerVal(19), |
|
||||
footerVal(20), footerVal(21), footerVal(22) |
|
||||
]; |
|
||||
|
|
||||
// Convert TOTAL row to Excel XML |
|
||||
let rowXml = '<row>'; |
|
||||
totalRow.forEach(val => { |
|
||||
rowXml += `<c t="inlineStr"><is><t>${val}</t></is></c>`; |
|
||||
}); |
|
||||
rowXml += '</row>'; |
|
||||
|
|
||||
// Append TOTAL row at the end of sheet |
|
||||
const sheetData = sheet.getElementsByTagName('sheetData')[0]; |
|
||||
sheetData.innerHTML += rowXml; |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
|
|
||||
|
|
||||
/* ===================== PDF ===================== */ |
|
||||
{ |
|
||||
extend: 'pdfHtml5', |
|
||||
orientation: 'landscape', |
|
||||
pageSize: 'A3', |
|
||||
title: 'Gcc Swm Report' |
|
||||
}, |
|
||||
|
|
||||
/* ===================== CSV ===================== */ |
|
||||
{ |
|
||||
extend: 'csvHtml5', |
|
||||
text: 'CSV', |
|
||||
title: '' |
|
||||
} |
|
||||
], |
|
||||
|
|
||||
columns: [ |
|
||||
{ data: "sno" }, |
|
||||
{ data: "zone" }, |
|
||||
|
|
||||
{ data: "MCC_target" }, |
|
||||
{ data: "MCC_achieved" }, |
|
||||
{ data: "MCC_percentage" }, |
|
||||
|
|
||||
{ data: "Windrow_target" }, |
|
||||
{ data: "Windrow_achieved" }, |
|
||||
{ data: "Windrow_percentage" }, |
|
||||
|
|
||||
{ data: "Bio-CNG_target" }, |
|
||||
{ data: "Bio-CNG_achieved" }, |
|
||||
{ data: "Bio-CNG_percentage" }, |
|
||||
|
|
||||
{ data: "Bio-GAS_target" }, |
|
||||
{ data: "Bio-GAS_achieved" }, |
|
||||
{ data: "Bio-GAS_percentage" }, |
|
||||
|
|
||||
{ data: "Incinerator_target" }, |
|
||||
{ data: "Incinerator_achieved" }, |
|
||||
{ data: "Incinerator_percentage" }, |
|
||||
|
|
||||
{ data: "GW & TC Waste_target" }, |
|
||||
{ data: "GW & TC Waste_achieved" }, |
|
||||
{ data: "GW & TC Waste_percentage" }, |
|
||||
|
|
||||
{ data: "Plasting Baling Centre_target" }, |
|
||||
{ data: "Plasting Baling Centre_achieved" }, |
|
||||
{ data: "Plasting Baling Centre_percentage" } |
|
||||
], |
|
||||
|
|
||||
footerCallback: function () { |
|
||||
|
|
||||
const api = this.api(); |
|
||||
|
|
||||
// Sum helper |
|
||||
function sum(colIdx) { |
|
||||
return api |
|
||||
.column(colIdx, { page: 'current' }) |
|
||||
.data() |
|
||||
.reduce((a, b) => { |
|
||||
const x = parseFloat(a) || 0; |
|
||||
const y = parseFloat(b) || 0; |
|
||||
return x + y; |
|
||||
}, 0); |
|
||||
} |
|
||||
|
|
||||
// Facility-wise column mapping |
|
||||
const facilities = [ |
|
||||
{ target: 2, achieved: 3, percent: 4 }, // MCC |
|
||||
{ target: 5, achieved: 6, percent: 7 }, // Windrow |
|
||||
{ target: 8, achieved: 9, percent: 10 }, // Bio-CNG |
|
||||
{ target: 11, achieved: 12, percent: 13 },// Bio-GAS |
|
||||
{ target: 14, achieved: 15, percent: 16 },// GW & TC Waste |
|
||||
{ target: 17, achieved: 18, percent: 19 },// Incinerator |
|
||||
{ target: 20, achieved: 21, percent: 22 } // Plastic Baling Centre |
|
||||
]; |
|
||||
|
|
||||
facilities.forEach(f => { |
|
||||
|
|
||||
const totalTarget = sum(f.target); |
|
||||
const totalAchieved = sum(f.achieved); |
|
||||
|
|
||||
// Write totals |
|
||||
$(api.column(f.target).footer()).html(totalTarget.toFixed(2)); |
|
||||
$(api.column(f.achieved).footer()).html(totalAchieved.toFixed(2)); |
|
||||
|
|
||||
// Percentage calculation |
|
||||
let percent = 0; |
|
||||
if (totalTarget > 0) { |
|
||||
percent = (totalAchieved / totalTarget) * 100; |
|
||||
} |
|
||||
|
|
||||
$(api.column(f.percent).footer()).html(percent.toFixed(2) + '%'); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
}); |
|
||||
|
|
||||
$("#searchBtn").on("click", loadReport); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$("#reportType").on("change", function () { |
|
||||
|
|
||||
const type = $(this).val(); |
|
||||
|
|
||||
// Hide all first |
|
||||
$("#singleDateDiv").addClass("d-none"); |
|
||||
$("#fromDateDiv, #toDateDiv").addClass("d-none"); |
|
||||
|
|
||||
// Clear values |
|
||||
$("#singleDate, #fromDate, #toDate").val(""); |
|
||||
|
|
||||
if (type === "DAY") { |
|
||||
// Day wise → show single date |
|
||||
$("#singleDateDiv").removeClass("d-none"); |
|
||||
} |
|
||||
else if (type === "MONTH") { |
|
||||
// Month wise → show from & to date |
|
||||
$("#fromDateDiv, #toDateDiv").removeClass("d-none"); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
// function loadReport() { |
|
||||
|
|
||||
// const fromDate = $("#fromDate").val(); |
|
||||
// const toDate = $("#toDate").val(); |
|
||||
|
|
||||
// if (!fromDate || !toDate) { |
|
||||
// Swal.fire("Validation Error", "Please select both dates", "warning"); |
|
||||
// return; |
|
||||
// } |
|
||||
|
|
||||
// $.ajax({ |
|
||||
// url: "/swm/api/admin/reports", |
|
||||
// type: "GET", |
|
||||
// data: { fromDate, toDate }, |
|
||||
// beforeSend: function () { |
|
||||
// Swal.fire({ |
|
||||
// title: "Loading...", |
|
||||
// allowOutsideClick: false, |
|
||||
// didOpen: () => Swal.showLoading() |
|
||||
// }); |
|
||||
// }, |
|
||||
// success: function (res) { |
|
||||
// Swal.close(); |
|
||||
// renderZoneTable(res.data); |
|
||||
// }, |
|
||||
// error: function () { |
|
||||
// Swal.fire("Error", "Failed to load report", "error"); |
|
||||
// } |
|
||||
// }); |
|
||||
// } |
|
||||
|
|
||||
function getDateDiffInDays(fromDate, toDate) { |
|
||||
const start = new Date(fromDate); |
|
||||
const end = new Date(toDate); |
|
||||
|
|
||||
// +1 because inclusive (01 to 10 = 10 days) |
|
||||
return Math.floor((end - start) / (1000 * 60 * 60 * 24)) + 1; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// function renderZoneTableMonthWise(data, fromDate, toDate) { |
|
||||
|
|
||||
// const zoneMap = {}; |
|
||||
// const dayCount = getDateDiffInDays(fromDate, toDate); |
|
||||
|
|
||||
// data.forEach(row => { |
|
||||
|
|
||||
// const z = row.zone; |
|
||||
// const f = row.facility; |
|
||||
|
|
||||
// if (!zoneMap[z]) { |
|
||||
// zoneMap[z] = { zone: z }; |
|
||||
// } |
|
||||
|
|
||||
// const dailyTarget = Number(row.target || 0); |
|
||||
// const totalAchieved = Number(row.achieved || 0); |
|
||||
|
|
||||
// // Overall target for selected date range |
|
||||
// const overallTarget = dailyTarget * dayCount; |
|
||||
|
|
||||
// // Raw percentage |
|
||||
// let percent = 0; |
|
||||
// if (overallTarget > 0) { |
|
||||
// percent = (totalAchieved / overallTarget) * 100; |
|
||||
// } |
|
||||
|
|
||||
// // ✅ CAP percentage to max 100 |
|
||||
// percent = Math.min(percent, 100); |
|
||||
|
|
||||
// // Store values (2 decimal places) |
|
||||
// zoneMap[z][f + "_target"] = overallTarget.toFixed(2); |
|
||||
// zoneMap[z][f + "_achieved"] = totalAchieved.toFixed(2); |
|
||||
// zoneMap[z][f + "_percentage"] = percent.toFixed(2) + "%"; |
|
||||
// }); |
|
||||
|
|
||||
// let i = 1; |
|
||||
// const tableData = Object.values(zoneMap).map(r => ({ |
|
||||
// sno: i++, |
|
||||
// ...r |
|
||||
// })); |
|
||||
|
|
||||
// table.clear().rows.add(tableData).draw(); |
|
||||
// } |
|
||||
|
|
||||
function renderZoneTableMonthWise(data, fromDate, toDate) { |
|
||||
|
|
||||
const zoneMap = {}; |
|
||||
const dayCount = getDateDiffInDays(fromDate, toDate); |
|
||||
|
|
||||
data.forEach(row => { |
|
||||
|
|
||||
const z = row.zone; |
|
||||
const f = row.facility; |
|
||||
|
|
||||
if (!zoneMap[z]) { |
|
||||
zoneMap[z] = { zone: z }; |
|
||||
} |
|
||||
|
|
||||
const dailyTarget = Number(row.target || 0); |
|
||||
const perDayAchieved = Number(row.achieved || 0); |
|
||||
|
|
||||
// 🔹 INTERNAL TOTALS (as per your explanation) |
|
||||
const totalTarget = dailyTarget * dayCount; |
|
||||
const totalAchieved = perDayAchieved * dayCount; |
|
||||
|
|
||||
// 🔹 AVERAGES SHOWN IN TABLE |
|
||||
const avgTarget = |
|
||||
dayCount > 0 ? (totalTarget / dayCount) : 0; |
|
||||
|
|
||||
const avgAchieved = |
|
||||
dayCount > 0 ? (totalAchieved / dayCount) : 0; |
|
||||
|
|
||||
// 🔹 PERCENTAGE (based on averages) |
|
||||
let percent = 0; |
|
||||
if (avgTarget > 0) { |
|
||||
percent = (avgAchieved / avgTarget) * 100; |
|
||||
} |
|
||||
|
|
||||
// 🔹 Cap at 100% |
|
||||
percent = Math.min(percent, 100); |
|
||||
|
|
||||
// 🔹 Store values (2 decimals) |
|
||||
zoneMap[z][f + "_target"] = avgTarget.toFixed(2); |
|
||||
zoneMap[z][f + "_achieved"] = avgAchieved.toFixed(2); |
|
||||
zoneMap[z][f + "_percentage"] = percent.toFixed(2) + "%"; |
|
||||
}); |
|
||||
|
|
||||
let i = 1; |
|
||||
const tableData = Object.values(zoneMap).map(r => ({ |
|
||||
sno: i++, |
|
||||
...r |
|
||||
})); |
|
||||
|
|
||||
table.clear().rows.add(tableData).draw(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
function loadReport() { |
|
||||
|
|
||||
const reportType = $("#reportType").val(); |
|
||||
|
|
||||
if (!reportType) { |
|
||||
Swal.fire("Validation Error", "Please select Report Type", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
let url = ""; |
|
||||
let data = {}; |
|
||||
|
|
||||
// ================= DAY WISE ================= |
|
||||
if (reportType === "DAY") { |
|
||||
|
|
||||
const singleDate = $("#singleDate").val(); |
|
||||
|
|
||||
if (!singleDate) { |
|
||||
Swal.fire("Validation Error", "Please select Date", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
url = "/swm/api/admin/singledayreports"; |
|
||||
data = { Date: singleDate }; |
|
||||
|
|
||||
} |
|
||||
// ================= MONTH / DATE RANGE ================= |
|
||||
else if (reportType === "MONTH") { |
|
||||
|
|
||||
const fromDate = $("#fromDate").val(); |
|
||||
const toDate = $("#toDate").val(); |
|
||||
|
|
||||
if (!fromDate || !toDate) { |
|
||||
Swal.fire("Validation Error", "Please select From & To Date", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
url = "/swm/api/admin/reports"; |
|
||||
data = { fromDate, toDate }; |
|
||||
} |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: url, |
|
||||
type: "GET", |
|
||||
data: data, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Loading...", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (res) { |
|
||||
|
|
||||
Swal.close(); |
|
||||
|
|
||||
// ✅ SEPARATE RENDERING BASED ON REPORT TYPE |
|
||||
if (reportType === "MONTH") { |
|
||||
renderZoneTableMonthWise( |
|
||||
res.data, |
|
||||
$("#fromDate").val(), |
|
||||
$("#toDate").val() |
|
||||
); |
|
||||
} else { |
|
||||
renderZoneTable(res.data); // DAY wise (existing) |
|
||||
} |
|
||||
}, |
|
||||
error: function () { |
|
||||
Swal.fire("Error", "Failed to load report", "error"); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
function renderZoneTable(data) { |
|
||||
|
|
||||
const zoneMap = {}; |
|
||||
|
|
||||
data.forEach(row => { |
|
||||
const z = row.zone; |
|
||||
const f = row.facility; |
|
||||
|
|
||||
if (!zoneMap[z]) zoneMap[z] = { zone: z }; |
|
||||
|
|
||||
zoneMap[z][f + "_target"] = row.target ?? 0; |
|
||||
zoneMap[z][f + "_achieved"] = row.achieved ?? 0; |
|
||||
zoneMap[z][f + "_percentage"] = |
|
||||
row.percentage != null ? row.percentage + "%" : "0%"; |
|
||||
}); |
|
||||
|
|
||||
let i = 1; |
|
||||
const tableData = Object.values(zoneMap).map(r => ({ |
|
||||
sno: i++, |
|
||||
...r |
|
||||
})); |
|
||||
|
|
||||
table.clear().rows.add(tableData).draw(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// function renderZoneTable(data) { |
|
||||
|
|
||||
// const zoneMap = {}; |
|
||||
|
|
||||
// data.forEach(row => { |
|
||||
|
|
||||
// const z = row.zone; |
|
||||
// const f = row.facility; |
|
||||
|
|
||||
// if (!zoneMap[z]) { |
|
||||
// zoneMap[z] = { zone: z }; |
|
||||
// } |
|
||||
|
|
||||
// // Create facility bucket |
|
||||
// if (!zoneMap[z][f]) { |
|
||||
// zoneMap[z][f] = { |
|
||||
// dailyTarget: 0, |
|
||||
// totalAchieved: 0, |
|
||||
// dayCount: 0 |
|
||||
// }; |
|
||||
// } |
|
||||
|
|
||||
// const fac = zoneMap[z][f]; |
|
||||
|
|
||||
// // DAILY target from API |
|
||||
// fac.dailyTarget = Number(row.target || 0); |
|
||||
|
|
||||
// // EACH ROW = ONE DAY |
|
||||
// fac.dayCount += 1; |
|
||||
|
|
||||
// // SUM achieved |
|
||||
// fac.totalAchieved += Number(row.achieved || 0); |
|
||||
// }); |
|
||||
|
|
||||
// let i = 1; |
|
||||
// const tableData = []; |
|
||||
|
|
||||
// Object.values(zoneMap).forEach(z => { |
|
||||
|
|
||||
// const row = { |
|
||||
// sno: i++, |
|
||||
// zone: z.zone |
|
||||
// }; |
|
||||
|
|
||||
// Object.keys(z).forEach(f => { |
|
||||
|
|
||||
// if (f === "zone") return; |
|
||||
|
|
||||
// const fac = z[f]; |
|
||||
|
|
||||
// // ✅ MONTH TARGET = daily target × no of days |
|
||||
// const totalTarget = fac.dailyTarget * fac.dayCount; |
|
||||
|
|
||||
// const percent = |
|
||||
// totalTarget > 0 |
|
||||
// ? ((fac.totalAchieved / totalTarget) * 100).toFixed(2) |
|
||||
// : "0.00"; |
|
||||
|
|
||||
// row[f + "_target"] = totalTarget.toFixed(2); |
|
||||
// row[f + "_achieved"] = fac.totalAchieved.toFixed(2); |
|
||||
// row[f + "_percentage"] = percent + "%"; |
|
||||
// }); |
|
||||
|
|
||||
// tableData.push(row); |
|
||||
// }); |
|
||||
|
|
||||
// table.clear().rows.add(tableData).draw(); |
|
||||
// } |
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,442 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:data-two-weight="${isTwoWeightFacility}" th:data-weight-type="${isWeightTypeFacility}"> |
|
||||
|
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD Facilities Add Details List</h5> |
|
||||
<span>Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD Facilities Add Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Add Details</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWM Add Details : <span th:text="${officer_name}"></span></h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> |
|
||||
<select id="zones" class="form-control"> |
|
||||
<option value="">Select days</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight(in MT):</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1" class="form-label">Enter Weight(Tender |
|
||||
Coconut):</label><span class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" id="facilityTypeDiv" style="display:none;"> |
|
||||
<label for="facilitytype" class="form-label"> |
|
||||
Location <span class="text-danger">*</span> |
|
||||
</label> |
|
||||
<select id="facilitytype" class="form-control"> |
|
||||
<option value="">Select location</option> |
|
||||
<option value="KDG">KDG</option> |
|
||||
<option value="PDG">PDG</option> |
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
const isWeightTypeFacility = |
|
||||
$("body").data("weight-type") === true || |
|
||||
$("body").data("weight-type") === "true"; |
|
||||
// GW & TC + PBC / C&D → show KDG / PDG |
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
$("#weightTypeDiv").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weightTypeDiv").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
$("#facilitytype").val(""); |
|
||||
} |
|
||||
|
|
||||
if (isWeightTypeFacility) { |
|
||||
$("#facilityTypeDiv").show(); |
|
||||
} else { |
|
||||
$("#facilityTypeDiv").hide(); |
|
||||
$("#facilitytype").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
//$(document).ready(function () { |
|
||||
// const today = new Date().toISOString().split('T')[0]; |
|
||||
//$("#date").val(today); |
|
||||
//}); |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const yyyyMmDd = today.toISOString().split('T')[0]; |
|
||||
|
|
||||
const yesterday = new Date(); |
|
||||
yesterday.setDate(today.getDate() - 1); |
|
||||
const yyyMmDdYesterday = yesterday.toISOString().split('T')[0]; |
|
||||
|
|
||||
const $date = $("#date"); |
|
||||
|
|
||||
// set default date |
|
||||
$date.val(yyyyMmDd); |
|
||||
|
|
||||
// allow only yesterday and today |
|
||||
$date.attr("min", yyyMmDdYesterday); |
|
||||
$date.attr("max", yyyyMmDd); |
|
||||
|
|
||||
// 🚫 block manual typing & paste |
|
||||
$date.on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const weightType = $("#facilitytype").val(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (weight == null || weight == "") { |
|
||||
Swal.fire("Validation Error", "Weight is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (facilityTypeId == 5) { |
|
||||
if (weight < 0) { |
|
||||
Swal.fire("Validation Error", "Weight cannot be negative", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
} else { |
|
||||
if (weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/facilities/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, // backend will ignore if not needed |
|
||||
weightType: weightType |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -1,419 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|
||||
|
|
||||
<head th:replace="~{fragments/modules/base/head :: head}"></head> |
|
||||
<style> |
|
||||
.width1 { |
|
||||
width: 120px; |
|
||||
} |
|
||||
|
|
||||
.width2 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
|
|
||||
.modal-label { |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.modal-value { |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.modal-section-title { |
|
||||
font-size: 1.2rem; |
|
||||
font-weight: bold; |
|
||||
margin-top: 20px; |
|
||||
margin-bottom: 10px; |
|
||||
border-bottom: 2px solid #dee2e6; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.modal-title-big { |
|
||||
font-size: 20px; |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
|
|
||||
.modal-subtext { |
|
||||
color: #b4c5d3; |
|
||||
font-size: 13px; |
|
||||
} |
|
||||
|
|
||||
.card-section { |
|
||||
background: white; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 25px; |
|
||||
border: 1px solid #eee; |
|
||||
} |
|
||||
|
|
||||
.section-title { |
|
||||
font-weight: 700; |
|
||||
color: #333; |
|
||||
margin-bottom: 15px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.label-text { |
|
||||
font-size: 13px; |
|
||||
color: #6c757d; |
|
||||
} |
|
||||
|
|
||||
.value-text { |
|
||||
font-size: 15px; |
|
||||
font-weight: 600; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
.info-block { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.badge-status { |
|
||||
background: #ffd9b3; |
|
||||
color: #a65c00; |
|
||||
padding: 6px 10px; |
|
||||
border-radius: 5px; |
|
||||
font-size: 13px; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.btn-big { |
|
||||
padding: 12px 25px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
} |
|
||||
|
|
||||
.rdo-box { |
|
||||
border: 1px solid #eee; |
|
||||
border-radius: 10px; |
|
||||
padding: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
<body th:attr="data-two-weight=${isTwoWeightFacility}"> |
|
||||
|
|
||||
<div class="wrapper"> |
|
||||
<!-- header top menu Start --> |
|
||||
<header th:replace="~{fragments/modules/base/header :: header}"></header> |
|
||||
<!-- header top menu end --> |
|
||||
<div class="page-wrap"> |
|
||||
<!--=============== Left Menu side Start ================--> |
|
||||
<div th:replace="~{fragments/modules/base/menu :: menu}"></div> |
|
||||
<!--=============== Left side End ================--> |
|
||||
<div class="main-content"> |
|
||||
<div class="container-fluid"> |
|
||||
<div class="page-header"> |
|
||||
<div class="row align-items-end"> |
|
||||
<div class="col-lg-6"> |
|
||||
<div class="page-header-title"> |
|
||||
<i class="fa fa-list-alt bg-blue"></i> |
|
||||
<div class="d-inline"> |
|
||||
<h5>SWD Windrow Facilities Add Details List</h5> |
|
||||
<span>Windrow Add Details</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-lg-6"> |
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb"> |
|
||||
<ol class="breadcrumb"> |
|
||||
<li class="breadcrumb-item"> |
|
||||
<a href="/swm/index"><i class="ik ik-home"></i></a> |
|
||||
</li> |
|
||||
<li class="breadcrumb-item" aria-current="page">SWD Windrow Facilities Add |
|
||||
Details List |
|
||||
</li> |
|
||||
<li class="breadcrumb-item active" aria-current="page">Windrow Add Details</li> |
|
||||
</ol> |
|
||||
</nav> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row mt-4"> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<div class="card"> |
|
||||
<div class="card-header d-flex justify-content-between align-items-center fw-bold"> |
|
||||
<h3 class="mb-0"> SWM Windrow Add Details : <span th:text="${officer_name}"></span> |
|
||||
</h3> |
|
||||
<input type="hidden" id="userName" th:value="${officer_name}"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-body"> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="date" class="form-label" |
|
||||
style="font-size: medium;">Date:</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="date" id="date" class="form-control"> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<label for="zones" class="form-label">Zones <span |
|
||||
class="text-danger">*</span> |
|
||||
</label> <select id="zones" class="form-control"> |
|
||||
<option value="">Select zones</option> |
|
||||
|
|
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3"> |
|
||||
|
|
||||
<label for="weight" class="form-label">Enter Weight:(in MT)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight"> |
|
||||
</div> |
|
||||
|
|
||||
<input type="hidden" id="facilityTypeId" th:value="${facilityTypeId}"> |
|
||||
|
|
||||
<!-- SECOND WEIGHT (TC) --> |
|
||||
<div class="col-md-3" id="weight2Div" style="display:none;"> |
|
||||
<label for="weight1">Enter Weight (TC)</label><span |
|
||||
class="text-danger">*</span> |
|
||||
<input type="number" class="form-control" id="weight1"> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-3" style="margin-top: 30px;"> |
|
||||
<button id="submitBtn" class="btn btn-primary">Submit</button> |
|
||||
<button id="resetBtn" class="btn btn-secondary">Reset</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="pageLoader" |
|
||||
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;"> |
|
||||
<div style="position: relative; top: 50%; transform: translateY(-50%);"> |
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> |
|
||||
<span class="sr-only">Loading...</span> |
|
||||
</div> |
|
||||
<!-- Add the 'Please wait' text below the spinner --> |
|
||||
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> |
|
||||
|
|
||||
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Details Modal --> |
|
||||
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable"> |
|
||||
<div class="modal-content"> |
|
||||
|
|
||||
<div class="modal-header" style="background:#2f3e54; color:white;"> |
|
||||
<div> |
|
||||
<h4 class="modal-title-big" id="modalTitle"></h4> |
|
||||
<div id="modalSubTitle" class="modal-subtext"></div> |
|
||||
</div> |
|
||||
|
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span |
|
||||
aria-hidden="true">×</span></button> |
|
||||
</div> |
|
||||
|
|
||||
<div class="modal-body"> |
|
||||
|
|
||||
<div id="modalContent"></div> |
|
||||
|
|
||||
<div class="text-center mt-4"> |
|
||||
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal" |
|
||||
style="background:#2f3e54;">Close</button> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
<script th:replace="~{fragments/modules/base/script :: script}"></script> |
|
||||
<script type="text/javascript"> |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
const today = new Date(); |
|
||||
const day = today.getDay(); // 0=Sun, 1=Mon, ..., 6=Sat |
|
||||
|
|
||||
/* ============================= |
|
||||
LAST SATURDAY |
|
||||
============================= */ |
|
||||
const lastSaturday = new Date(today); |
|
||||
|
|
||||
// If today is Saturday (6) → today |
|
||||
// Else → go back to previous Saturday |
|
||||
const diffToLastSaturday = (day >= 6) |
|
||||
? day - 6 |
|
||||
: day + 1; |
|
||||
|
|
||||
lastSaturday.setDate(today.getDate() - diffToLastSaturday); |
|
||||
|
|
||||
/* ============================= |
|
||||
THIS WEEK FRIDAY |
|
||||
============================= */ |
|
||||
const thisFriday = new Date(today); |
|
||||
|
|
||||
// Friday = 5 |
|
||||
const diffToFriday = (5 - day + 7) % 7; |
|
||||
thisFriday.setDate(today.getDate() + diffToFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
FORMAT YYYY-MM-DD |
|
||||
============================= */ |
|
||||
const formatDate = (d) => d.toISOString().split("T")[0]; |
|
||||
|
|
||||
const minDate = formatDate(lastSaturday); |
|
||||
const maxDate = formatDate(thisFriday); |
|
||||
|
|
||||
/* ============================= |
|
||||
APPLY LIMITS |
|
||||
============================= */ |
|
||||
$("#date") |
|
||||
.attr("min", minDate) |
|
||||
.attr("max", maxDate) |
|
||||
.val(formatDate(today)); |
|
||||
// 🔒 BLOCK MANUAL TYPING (BUT ALLOW CALENDAR) |
|
||||
$("#date").on("keydown paste", function (e) { |
|
||||
e.preventDefault(); |
|
||||
}); |
|
||||
}); |
|
||||
$(document).ready(function () { |
|
||||
const isTwoWeightFacility = |
|
||||
$("body").data("two-weight") === true || |
|
||||
$("body").data("two-weight") === "true"; |
|
||||
|
|
||||
console.log($("body").data("two-weight")); |
|
||||
|
|
||||
|
|
||||
if (isTwoWeightFacility) { |
|
||||
$("#weight2Div").show(); |
|
||||
} else { |
|
||||
$("#weight2Div").hide(); |
|
||||
$("#weight1").val(""); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
const today = new Date().toISOString().split('T')[0]; |
|
||||
$("#date").val(today); |
|
||||
}); |
|
||||
|
|
||||
$("#resetBtn").on("click", function () { |
|
||||
location.reload(); |
|
||||
}); |
|
||||
|
|
||||
// Load zones when page loads |
|
||||
$(document).ready(function () { |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/dropdown/getzoneslist", |
|
||||
type: "GET", |
|
||||
dataType: "json", |
|
||||
success: function (data) { |
|
||||
|
|
||||
let zoneDropdown = $("#zones"); |
|
||||
zoneDropdown.empty(); |
|
||||
zoneDropdown.append("<option value=''>Select Zone</option>"); |
|
||||
|
|
||||
$.each(data, function (index, item) { |
|
||||
zoneDropdown.append( |
|
||||
`<option value="${item.id}">${item.zone_name}</option>` |
|
||||
); |
|
||||
}); |
|
||||
}, |
|
||||
error: function (xhr, status, error) { |
|
||||
console.error("Error fetching zones:", error); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
$("#submitBtn").on("click", function (e) { |
|
||||
e.preventDefault(); |
|
||||
|
|
||||
const facilityTypeId = $("#facilityTypeId").val(); // ✅ dynamic |
|
||||
const zoneId = $("#zones").val(); |
|
||||
const reqDate = $("#date").val(); |
|
||||
const weight = $("#weight").val(); |
|
||||
const weight1 = $("#weight1").val(); |
|
||||
const createdBy = $("#userName").val(); |
|
||||
|
|
||||
// 🔴 Client-side validations |
|
||||
if (!zoneId) { |
|
||||
Swal.fire("Validation Error", "Please select zone", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!reqDate) { |
|
||||
Swal.fire("Validation Error", "Date is required", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (!weight || weight <= 0) { |
|
||||
Swal.fire("Validation Error", "Weight must be greater than zero", "warning"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// ⚠️ Note: |
|
||||
// Facility type 5 validation is done in BACKEND |
|
||||
// because facilityTypeId is derived after login |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: "/swm/api/admin/addfacility", |
|
||||
type: "POST", |
|
||||
data: { |
|
||||
facilityTypeId: facilityTypeId, |
|
||||
zoneId: zoneId, |
|
||||
reqDate: reqDate, |
|
||||
weight: weight, |
|
||||
weight1: weight1, |
|
||||
createdBy: createdBy // backend will ignore if not needed |
|
||||
}, |
|
||||
beforeSend: function () { |
|
||||
Swal.fire({ |
|
||||
title: "Saving...", |
|
||||
text: "Please wait", |
|
||||
allowOutsideClick: false, |
|
||||
didOpen: () => Swal.showLoading() |
|
||||
}); |
|
||||
}, |
|
||||
success: function (response) { |
|
||||
Swal.fire("Success", response.message, "success"); |
|
||||
|
|
||||
// Reset fields |
|
||||
$("#weight").val(""); |
|
||||
$("#weight1").val(""); |
|
||||
}, |
|
||||
error: function (xhr) { |
|
||||
let msg = "Something went wrong"; |
|
||||
|
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) { |
|
||||
msg = xhr.responseJSON.message; |
|
||||
} |
|
||||
|
|
||||
Swal.fire("Error", msg, "error"); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
|
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue