5 changed files with 1154 additions and 0 deletions
-
11src/main/java/com/gcc/commissionerreview/configuration/DataSourceConfig.java
-
124src/main/java/com/gcc/commissionerreview/controller/BulkWasteApicontroller.java
-
5src/main/java/com/gcc/commissionerreview/controller/MainController.java
-
191src/main/java/com/gcc/commissionerreview/service/BulkWasteService.java
-
823src/main/resources/templates/modules/bulkwaste/bulkwastereport.html
@ -0,0 +1,124 @@ |
|||||
|
package com.gcc.commissionerreview.controller; |
||||
|
|
||||
|
import com.gcc.commissionerreview.service.BulkWasteService; |
||||
|
import com.gcc.commissionerreview.service.GreenCommitteeService; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
|
||||
|
import java.util.*; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/commissionerreview/api/bulkwaste") |
||||
|
public class BulkWasteApicontroller { |
||||
|
|
||||
|
@Autowired |
||||
|
private BulkWasteService gcservice; |
||||
|
|
||||
|
@GetMapping("/getZoneReport") |
||||
|
public Map<String, Object> getabscount(@RequestParam(required = false) String startDate, |
||||
|
@RequestParam(required = false) String endDate, |
||||
|
@RequestParam(required = false) String category) |
||||
|
{ |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
|
||||
|
try { |
||||
|
List<Map<String, Object>> data = gcservice.getabscount(startDate, endDate,category); |
||||
|
|
||||
|
response.put("data", data); |
||||
|
response.put("message", "Zone-wise abstract report"); |
||||
|
response.put("status", "Success"); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
|
||||
|
response.put("data", Collections.emptyList()); |
||||
|
response.put("message", "Failed to fetch abstract report"); |
||||
|
response.put("status", "Error"); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@GetMapping("/getWardDetailsByZone") |
||||
|
public Map<String, Object> getWardDetailsByZone(@RequestParam(required = true) String zone, |
||||
|
@RequestParam(required = false) String startDate, |
||||
|
@RequestParam(required = false) String endDate, |
||||
|
@RequestParam(required = false) String category) |
||||
|
{ |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
|
||||
|
try { |
||||
|
List<Map<String, Object>> data = gcservice.getWardDetailsByZone(zone,startDate,endDate,category); |
||||
|
|
||||
|
response.put("data", data); |
||||
|
response.put("message", "Ward-wise abstract report"); |
||||
|
response.put("status", "Success"); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
|
||||
|
response.put("data", Collections.emptyList()); |
||||
|
response.put("message", "Failed to fetch abstract report"); |
||||
|
response.put("status", "Error"); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/getEstabllishmentDetailsByZoneWard") |
||||
|
public Map<String, Object> getEstabllishmentDetailsByZoneWard( |
||||
|
@RequestParam String zone, |
||||
|
@RequestParam String ward, |
||||
|
@RequestParam(required = false) String startDate, |
||||
|
@RequestParam(required = false) String endDate, |
||||
|
@RequestParam(required = false) String category) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
|
||||
|
try { |
||||
|
|
||||
|
List<Map<String, Object>> data = |
||||
|
gcservice.getEstabllishmentDetailsByZoneWard( zone, ward, startDate, endDate, category); |
||||
|
|
||||
|
response.put("data", data); |
||||
|
response.put("message", "Category wise report"); |
||||
|
response.put("status", "Success"); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
|
||||
|
e.printStackTrace(); |
||||
|
|
||||
|
response.put("data", Collections.emptyList()); |
||||
|
response.put("message", "Failed to fetch report"); |
||||
|
response.put("status", "Error"); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/getCategoryList") |
||||
|
public List<Map<String, Object>> getCategoryList() { |
||||
|
|
||||
|
List<Map<String, Object>> list = gcservice.getCategoryList(); |
||||
|
|
||||
|
Map<String, Object> res = new HashMap<>(); |
||||
|
|
||||
|
if (list != null && !list.isEmpty()) { |
||||
|
res.put("status", "Success"); |
||||
|
res.put("data", list); |
||||
|
} else { |
||||
|
res.put("status", "Fail"); |
||||
|
res.put("data", new ArrayList<>()); |
||||
|
} |
||||
|
|
||||
|
return List.of(res); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,191 @@ |
|||||
|
package com.gcc.commissionerreview.service; |
||||
|
|
||||
|
import com.gcc.commissionerreview.configuration.AppConfig; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.core.env.Environment; |
||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
|
||||
|
import javax.sql.DataSource; |
||||
|
import java.util.*; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Service |
||||
|
public class BulkWasteService { |
||||
|
|
||||
|
|
||||
|
@Autowired |
||||
|
private JdbcTemplate jdbcTemplate; |
||||
|
@Autowired |
||||
|
private Environment environment; |
||||
|
|
||||
|
@Autowired |
||||
|
private AppConfig appConfig; |
||||
|
|
||||
|
@Autowired |
||||
|
@Value("${fileBaseUrl}") |
||||
|
|
||||
|
private String fileBaseUrl; |
||||
|
|
||||
|
public BulkWasteService(Environment environment) { |
||||
|
|
||||
|
this.environment = environment; |
||||
|
|
||||
|
this.fileBaseUrl = environment.getProperty("fileBaseUrl"); |
||||
|
} |
||||
|
|
||||
|
@Autowired |
||||
|
public void setFeedbackDataSource(@Qualifier("mysqlBulkWasteDataSource") DataSource dataSource) { |
||||
|
this.jdbcTemplate = new JdbcTemplate(dataSource); |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getabscount(String startDate, String endDate,String category) { |
||||
|
|
||||
|
StringBuilder sql = new StringBuilder( |
||||
|
"SELECT z.zone_name, " + |
||||
|
"COALESCE(COUNT(DISTINCT bw.request_id), 0) AS total_requests " + |
||||
|
"FROM zones z " + |
||||
|
"LEFT JOIN bulk_waste_request bw " + |
||||
|
"ON bw.zone_id = z.zone_name " + |
||||
|
"AND bw.is_active = 1 " + |
||||
|
"WHERE z.is_active = 1 " + |
||||
|
"AND z.is_delete = 0 " |
||||
|
); |
||||
|
|
||||
|
List<Object> params = new ArrayList<>(); |
||||
|
|
||||
|
if (startDate != null && !startDate.isEmpty()) { |
||||
|
sql.append(" AND DATE(bw.cdate) >= ? "); |
||||
|
params.add(startDate); |
||||
|
} |
||||
|
|
||||
|
if (endDate != null && !endDate.isEmpty()) { |
||||
|
sql.append(" AND DATE(bw.cdate) <= ? "); |
||||
|
params.add(endDate); |
||||
|
} |
||||
|
|
||||
|
if (category != null && !category.isEmpty()) { |
||||
|
sql.append(" AND bw.category_id= ? "); |
||||
|
params.add(category); |
||||
|
} |
||||
|
|
||||
|
sql.append( |
||||
|
" GROUP BY z.zone_name " + |
||||
|
" ORDER BY z.zone_name " |
||||
|
); |
||||
|
|
||||
|
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getWardDetailsByZone( |
||||
|
String zone, |
||||
|
String startDate, |
||||
|
String endDate, |
||||
|
String category) { |
||||
|
|
||||
|
StringBuilder sql = new StringBuilder( |
||||
|
"SELECT z.zone_name, w.ward_name, " + |
||||
|
"COALESCE(COUNT(DISTINCT bw.request_id), 0) AS total_requests " + |
||||
|
"FROM wards w " + |
||||
|
"JOIN zones z ON z.id = w.zone_id AND z.zone_name = ? " + |
||||
|
"LEFT JOIN bulk_waste_request bw " + |
||||
|
"ON bw.ward_id = w.ward_name " + |
||||
|
"AND bw.is_active = 1 " + |
||||
|
"WHERE w.is_active = 1 " |
||||
|
); |
||||
|
|
||||
|
List<Object> params = new ArrayList<>(); |
||||
|
params.add(zone); |
||||
|
|
||||
|
if (startDate != null && !startDate.isEmpty()) { |
||||
|
sql.append(" AND DATE(bw.cdate) >= ? "); |
||||
|
params.add(startDate); |
||||
|
} |
||||
|
|
||||
|
if (endDate != null && !endDate.isEmpty()) { |
||||
|
sql.append(" AND DATE(bw.cdate) <= ? "); |
||||
|
params.add(endDate); |
||||
|
} |
||||
|
|
||||
|
if (category != null && !category.isEmpty()) { |
||||
|
sql.append(" AND bw.category_id= ? "); |
||||
|
params.add(category); |
||||
|
} |
||||
|
|
||||
|
sql.append( |
||||
|
" GROUP BY w.ward_name " + |
||||
|
" ORDER BY w.ward_name " |
||||
|
); |
||||
|
|
||||
|
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getEstabllishmentDetailsByZoneWard( |
||||
|
String zone, |
||||
|
String ward, |
||||
|
String startDate, |
||||
|
String endDate, |
||||
|
String category) { |
||||
|
|
||||
|
StringBuilder sql = new StringBuilder( |
||||
|
"SELECT z.zone_name, w.ward_name, cm.category_name, " + |
||||
|
"COALESCE(COUNT(bw.request_id),0) AS total_requests " + |
||||
|
|
||||
|
"FROM wards w " + |
||||
|
|
||||
|
"JOIN zones z ON z.id = w.zone_id " + |
||||
|
"AND z.zone_name = ? " + |
||||
|
"AND w.ward_name = ? " + |
||||
|
|
||||
|
"CROSS JOIN category_master cm " + |
||||
|
|
||||
|
" JOIN bulk_waste_request bw " + |
||||
|
"ON bw.ward_id = w.ward_name " + |
||||
|
"AND bw.category_id = cm.category_id " + |
||||
|
"AND bw.is_active = 1 " |
||||
|
); |
||||
|
|
||||
|
List<Object> params = new ArrayList<>(); |
||||
|
|
||||
|
params.add(zone); |
||||
|
params.add(ward); |
||||
|
|
||||
|
if (startDate != null && !startDate.isEmpty()) { |
||||
|
sql.append(" AND DATE(bw.cdate) >= ? "); |
||||
|
params.add(startDate); |
||||
|
} |
||||
|
|
||||
|
if (endDate != null && !endDate.isEmpty()) { |
||||
|
sql.append(" AND DATE(bw.cdate) <= ? "); |
||||
|
params.add(endDate); |
||||
|
} |
||||
|
|
||||
|
if (category != null && !category.isEmpty()) { |
||||
|
sql.append(" AND bw.category_id= ? "); |
||||
|
params.add(category); |
||||
|
} |
||||
|
|
||||
|
sql.append( |
||||
|
" GROUP BY z.zone_name, w.ward_name, cm.category_name " + |
||||
|
" ORDER BY w.ward_name, cm.category_name " |
||||
|
); |
||||
|
|
||||
|
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getCategoryList() { |
||||
|
|
||||
|
String sql = """ |
||||
|
SELECT category_id, category_name |
||||
|
FROM category_master |
||||
|
WHERE is_active = 1 |
||||
|
ORDER BY category_name |
||||
|
"""; |
||||
|
|
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,823 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<title>Bul Waste Report</title> |
||||
|
|
||||
|
<!-- Bootstrap 5 CSS --> |
||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
||||
|
|
||||
|
<!-- DataTables CSS --> |
||||
|
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet"/> |
||||
|
<link href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css" rel="stylesheet"/> |
||||
|
|
||||
|
|
||||
|
<style> |
||||
|
table.dataTable th, table.dataTable td { |
||||
|
text-align: center; |
||||
|
vertical-align: middle; |
||||
|
border: 1px solid #000; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
table.dataTable th{ |
||||
|
background-color: #003366 !important; |
||||
|
color: white; |
||||
|
} |
||||
|
|
||||
|
.dataTables_wrapper .dt-buttons { |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
.dataTables_filter { |
||||
|
margin-bottom: 25px; /* adjust as needed */ |
||||
|
} |
||||
|
|
||||
|
.page-header-title h4 { |
||||
|
margin: 20px 0; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
#zoneDetailsTable_wrapper .dataTables_scrollBody { |
||||
|
border: none !important; |
||||
|
} |
||||
|
|
||||
|
#zoneDetailsTable td, #zoneDetailsTable th { |
||||
|
vertical-align: middle; |
||||
|
text-align: center; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.filter-btn { |
||||
|
height: 38px; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.page-header-title { |
||||
|
margin-bottom: 25px; |
||||
|
} |
||||
|
|
||||
|
#pendingModal .modal-body{ |
||||
|
min-height: 60vh; |
||||
|
max-height: 70vh; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
/* Thumbnail styling */ |
||||
|
.complaint-thumb { |
||||
|
width: 110px; |
||||
|
height: 110px; |
||||
|
object-fit: cover; |
||||
|
margin: 5px; |
||||
|
cursor: pointer; |
||||
|
transition: transform 0.2s ease-in-out, box-shadow 0.2s; |
||||
|
} |
||||
|
|
||||
|
.complaint-thumb:hover { |
||||
|
transform: scale(1.05); |
||||
|
box-shadow: 0 4px 10px rgba(0,0,0,0.2); |
||||
|
} |
||||
|
|
||||
|
/* Image grid alignment */ |
||||
|
.image-grid { |
||||
|
gap: 8px; |
||||
|
} |
||||
|
|
||||
|
body.modal-open { |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.modal { |
||||
|
overflow-x: hidden; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
|
||||
|
.modal-dialog { |
||||
|
margin: 1.75rem auto !important; |
||||
|
} |
||||
|
|
||||
|
.modal-xl { |
||||
|
max-width: 90%; |
||||
|
} |
||||
|
|
||||
|
.modal-backdrop + .modal-backdrop { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
.modal-dialog { |
||||
|
margin: 1.75rem auto !important; |
||||
|
} |
||||
|
|
||||
|
.modal-xl { |
||||
|
max-width: 95% !important; |
||||
|
} |
||||
|
|
||||
|
.dataTables_wrapper { |
||||
|
width: 100% !important; |
||||
|
} |
||||
|
|
||||
|
.modal-stack { |
||||
|
filter: brightness(0.9); |
||||
|
} |
||||
|
|
||||
|
.modal-backdrop.modal-stack { |
||||
|
opacity: 0.2 !important; |
||||
|
} |
||||
|
|
||||
|
#requestDetailsModal .modal-xl { |
||||
|
max-width: 85% !important; |
||||
|
} |
||||
|
|
||||
|
#requestDetailsModal .modal-dialog { |
||||
|
max-width: 90% !important; |
||||
|
margin: 1.75rem auto !important; |
||||
|
} |
||||
|
|
||||
|
</style> |
||||
|
|
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<div class="page-header-title"> |
||||
|
<h4>Bulk Waste - Zonewise Report</h4> |
||||
|
</div> |
||||
|
|
||||
|
<div class="container-fluid mb-4"> |
||||
|
|
||||
|
<!-- ROW 1 --> |
||||
|
<div class="row justify-content-center gx-3"> |
||||
|
|
||||
|
<!-- From Date --> |
||||
|
<div class="col-lg-3 col-md-4 col-sm-6 mb-2"> |
||||
|
<label>From Date</label> |
||||
|
<input type="date" id="startDate" class="form-control" |
||||
|
onclick="this.showPicker()"> |
||||
|
</div> |
||||
|
|
||||
|
<!-- To Date --> |
||||
|
<div class="col-lg-3 col-md-4 col-sm-6 mb-2"> |
||||
|
<label>To Date</label> |
||||
|
<input type="date" id="endDate" class="form-control" |
||||
|
onclick="this.showPicker()"> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Category --> |
||||
|
<div class="col-lg-3 col-md-4 col-sm-6 mb-2"> |
||||
|
<label>Category</label> |
||||
|
|
||||
|
<select id="categoryId" class="form-control"> |
||||
|
<option value="">All Category</option> |
||||
|
</select> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<br> |
||||
|
|
||||
|
<!-- ROW 2 (Buttons) --> |
||||
|
<div class="row justify-content-center mt-2"> |
||||
|
|
||||
|
<div class="col-lg-3 col-md-4 col-sm-6 d-flex gap-2"> |
||||
|
|
||||
|
<button |
||||
|
class="btn btn-success w-100" |
||||
|
onclick="loadZoneReport()"> |
||||
|
Apply Filter |
||||
|
</button> |
||||
|
|
||||
|
<button |
||||
|
class="btn btn-outline-secondary w-100" |
||||
|
onclick="resetvalues()"> |
||||
|
Reset |
||||
|
</button> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div id="opSummaryTable" style="display: block;" class="container"> |
||||
|
<table id="ZoneOpDatatable" class="table table-striped table-bordered display nowrap w-100"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th class="text-center">Zones</th> |
||||
|
<th class="text-center">Total Request</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
|
||||
|
|
||||
|
</tbody> |
||||
|
<tfoot> |
||||
|
<tr class="font-weight-bold bg-light"> |
||||
|
<th class="text-center">TOTAL</th> |
||||
|
<th class="text-center"></th> |
||||
|
</tr> |
||||
|
</tfoot> |
||||
|
</table> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="modal fade" id="zoneDetailsModal" tabindex="-1" aria-labelledby="zoneDetailsLabel" aria-hidden="true" data-bs-keyboard="false" data-bs-backdrop="static"> |
||||
|
<div class="modal-dialog modal-xl"> |
||||
|
<div class="modal-content"> |
||||
|
<div class="modal-header"> |
||||
|
<h5 class="modal-title" id="zoneModalTitle">Zone Details</h5> |
||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
||||
|
</div> |
||||
|
<div class="modal-body"> |
||||
|
|
||||
|
<table id="WardDatatable" class="table table-striped table-bordered display nowrap w-100"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th class="text-center">Zones</th> |
||||
|
<th class="text-center">Wards</th> |
||||
|
<th class="text-center">Total Request</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
|
||||
|
|
||||
|
</tbody> |
||||
|
</table> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="modal fade" id="requestDetailsModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false"> |
||||
|
|
||||
|
<div class="modal-dialog modal-xl"> |
||||
|
<div class="modal-content"> |
||||
|
|
||||
|
<div class="modal-header"> |
||||
|
<h5 class="modal-title" id="requestModalTitle"> |
||||
|
Establishment Table Details |
||||
|
</h5> |
||||
|
|
||||
|
<button type="button" |
||||
|
class="btn-close" |
||||
|
data-bs-dismiss="modal"> |
||||
|
</button> |
||||
|
</div> |
||||
|
|
||||
|
<div class="modal-body"> |
||||
|
|
||||
|
<table id="RequestDatatable" |
||||
|
class="table table-bordered table-striped w-100"> |
||||
|
|
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>Zone</th> |
||||
|
<th>Ward</th> |
||||
|
<th>Category</th> |
||||
|
<th>Request Id</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
|
||||
|
<tbody></tbody> |
||||
|
|
||||
|
</table> |
||||
|
|
||||
|
</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"></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> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> |
||||
|
|
||||
|
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script> |
||||
|
<script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script> |
||||
|
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script> |
||||
|
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script> |
||||
|
|
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script> |
||||
|
<!-- SweetAlert --> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> |
||||
|
|
||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
let CURRENT_ZONE = null; |
||||
|
|
||||
|
function resetvalues(){ |
||||
|
location.reload(); |
||||
|
} |
||||
|
function openImagePreview(src) { |
||||
|
$('#previewImage').attr('src', src); |
||||
|
$('#imagePreviewModal').modal('show'); |
||||
|
} |
||||
|
|
||||
|
function loadZoneReport(){ |
||||
|
const startDate = $('#startDate').val(); // yyyy-mm-dd or "" |
||||
|
const endDate = $('#endDate').val(); |
||||
|
const category = $('#categoryId').val(); |
||||
|
|
||||
|
|
||||
|
<!-- console.log("category=="+category);--> |
||||
|
|
||||
|
$('#pageLoader').show(); |
||||
|
$.ajax({ |
||||
|
url: '/commissionerreview/api/bulkwaste/getZoneReport', |
||||
|
method: 'GET', |
||||
|
data: { |
||||
|
startDate: startDate, |
||||
|
endDate: endDate, |
||||
|
category: category |
||||
|
}, |
||||
|
success: function(response) { |
||||
|
|
||||
|
// Safely extract data whether it's an array or an object |
||||
|
var res = Array.isArray(response) ? response[0] : response; |
||||
|
console.log("Response:", res); |
||||
|
|
||||
|
$('#pageLoader').hide(); |
||||
|
|
||||
|
if (res.status === "Success") { |
||||
|
|
||||
|
if (Array.isArray(res.data) && res.data.length > 0) { |
||||
|
console.log("Details Array:", response); |
||||
|
|
||||
|
let table = $('#ZoneOpDatatable').DataTable({ |
||||
|
destroy: true, |
||||
|
autoWidth: true, |
||||
|
info: true, |
||||
|
data: res.data, // using response directly |
||||
|
columns: [ |
||||
|
{ |
||||
|
data: 'zone_name' |
||||
|
}, |
||||
|
{ |
||||
|
data: 'total_requests', |
||||
|
render: function (data, type, row) { |
||||
|
|
||||
|
if (data == 0 || data === "0") { |
||||
|
return data; // no link |
||||
|
} |
||||
|
|
||||
|
return `<a href="javascript:void(0)" |
||||
|
onclick="openZoneModal('${row.zone_name}')"> |
||||
|
${data} |
||||
|
</a>`; |
||||
|
}, |
||||
|
className: 'text-center' |
||||
|
} |
||||
|
|
||||
|
], |
||||
|
dom: 'frtip', |
||||
|
lengthMenu: [ |
||||
|
[50, 100, 200, 500, -1], |
||||
|
['50 rows', '100 rows', '200 rows', 'Show all'] |
||||
|
], |
||||
|
footerCallback: footerSumCallback, |
||||
|
scrollY: 'auto', |
||||
|
scrollX: true, |
||||
|
responsive: false, |
||||
|
searching: false, |
||||
|
ordering: false |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
else if(Array.isArray(res.data) && res.data.length === 0) { |
||||
|
$('#pageLoader').hide(); |
||||
|
//alert("No data available."); |
||||
|
|
||||
|
Swal.fire({ |
||||
|
icon: 'info', |
||||
|
title: 'No Data', |
||||
|
text: 'No data available.', |
||||
|
showConfirmButton: true, |
||||
|
timer: 3000 |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
else { |
||||
|
$('#pageLoader').hide(); |
||||
|
//alert("Error: " + response.message); |
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: 'Error', |
||||
|
showConfirmButton: true, |
||||
|
timer: 3000 |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
else { |
||||
|
$('#pageLoader').hide(); |
||||
|
//alert("Error: " + response.message); |
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: res.message, |
||||
|
showConfirmButton: true, |
||||
|
timer: 3000 |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
error: function(xhr, status, error) { |
||||
|
$('#pageLoader').hide(); |
||||
|
// alert("Request failed: " + error); |
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: error, |
||||
|
showConfirmButton: true, |
||||
|
timer: 3000 |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
function openZoneModal(zoneCode) { |
||||
|
|
||||
|
CURRENT_ZONE = zoneCode; |
||||
|
|
||||
|
console.log("Opening modal for zone:", zoneCode); |
||||
|
|
||||
|
const startDate = $('#startDate').val(); |
||||
|
const endDate = $('#endDate').val(); |
||||
|
const category = $('#categoryId').val(); |
||||
|
|
||||
|
console.log("category ward=="+category); |
||||
|
|
||||
|
$('#pageLoader').show(); |
||||
|
|
||||
|
$('#zoneModalTitle').text('Zone ' + zoneCode + ' Details'); |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: '/commissionerreview/api/bulkwaste/getWardDetailsByZone', |
||||
|
method: 'GET', |
||||
|
data: { |
||||
|
zone: zoneCode, |
||||
|
startDate: startDate, |
||||
|
endDate: endDate, |
||||
|
category:category |
||||
|
}, |
||||
|
|
||||
|
success: function (response) { |
||||
|
let res = Array.isArray(response) ? response[0] : response; |
||||
|
console.log("Response:", res); |
||||
|
$('#pageLoader').hide(); |
||||
|
if (res.status === "Success") { |
||||
|
if (Array.isArray(res.data) && res.data.length > 0) { |
||||
|
console.log("Details Array:", res.data); |
||||
|
// ✅ destroy only if exists |
||||
|
if ($.fn.DataTable.isDataTable('#WardDatatable')) { |
||||
|
$('#WardDatatable').DataTable().clear().destroy(); |
||||
|
} |
||||
|
$('#WardDatatable').DataTable({ |
||||
|
data: res.data, |
||||
|
destroy: true, |
||||
|
autoWidth: true, |
||||
|
info: true, |
||||
|
columns: [ |
||||
|
{ data: 'zone_name', className: 'text-center' }, |
||||
|
{ data: 'ward_name', className: 'text-center' }, |
||||
|
{ |
||||
|
data: 'total_requests', |
||||
|
render: function (data, type, row) { |
||||
|
|
||||
|
if (data == 0 || data === "0") { |
||||
|
return data; // no link if zero |
||||
|
} |
||||
|
|
||||
|
return `<a href="javascript:void(0)" |
||||
|
onclick="openRequestModal('${row.zone_name}','${row.ward_name}')"> |
||||
|
${data} |
||||
|
</a>`; |
||||
|
}, |
||||
|
className: 'text-center' |
||||
|
} |
||||
|
|
||||
|
], |
||||
|
scrollY: '400px', |
||||
|
scrollX: true, |
||||
|
searching: false, |
||||
|
ordering: false, |
||||
|
paging: true |
||||
|
}); |
||||
|
|
||||
|
// ✅ Bootstrap 5 modal open |
||||
|
const modal = new bootstrap.Modal( |
||||
|
document.getElementById('zoneDetailsModal') |
||||
|
); |
||||
|
modal.show(); |
||||
|
} else { |
||||
|
|
||||
|
Swal.fire({ |
||||
|
icon: 'info', |
||||
|
title: 'No Data', |
||||
|
text: 'No data available.' |
||||
|
}); |
||||
|
} |
||||
|
} else { |
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: res.message |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
error: function (xhr, status, error) { |
||||
|
$('#pageLoader').hide(); |
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: error |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function openRequestModal(zoneCode, wardCode) { |
||||
|
|
||||
|
console.log("Open new modal", zoneCode, wardCode); |
||||
|
|
||||
|
const startDate = $('#startDate').val(); |
||||
|
const endDate = $('#endDate').val(); |
||||
|
const category = $('#categoryId').val(); |
||||
|
|
||||
|
console.log("category Est=="+category); |
||||
|
|
||||
|
|
||||
|
$.ajax({ |
||||
|
|
||||
|
url: '/commissionerreview/api/bulkwaste/getEstabllishmentDetailsByZoneWard', |
||||
|
|
||||
|
method: 'GET', |
||||
|
|
||||
|
data: { |
||||
|
zone: zoneCode, |
||||
|
ward: wardCode, |
||||
|
startDate: startDate, |
||||
|
endDate: endDate, |
||||
|
category:category |
||||
|
}, |
||||
|
|
||||
|
success: function (response) { |
||||
|
|
||||
|
let res = Array.isArray(response) ? response[0] : response; |
||||
|
|
||||
|
console.log(res); |
||||
|
|
||||
|
if (res.status === "Success") { |
||||
|
|
||||
|
if ($.fn.DataTable.isDataTable('#RequestDatatable')) { |
||||
|
$('#RequestDatatable').DataTable().clear().destroy(); |
||||
|
} |
||||
|
|
||||
|
$('#RequestDatatable').DataTable({ |
||||
|
|
||||
|
data: res.data, |
||||
|
|
||||
|
columns: [ |
||||
|
{ data: 'zone_name' }, |
||||
|
{ data: 'ward_name' }, |
||||
|
{ data: 'category_name' }, |
||||
|
{ data: 'total_requests' } |
||||
|
] |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
// close first modal |
||||
|
let zoneModal = bootstrap.Modal.getInstance( |
||||
|
document.getElementById('zoneDetailsModal') |
||||
|
); |
||||
|
|
||||
|
|
||||
|
let zoneModalEl = document.getElementById('zoneDetailsModal'); |
||||
|
|
||||
|
// add shadow only when second modal opens |
||||
|
zoneModalEl.classList.add("modal-stack"); |
||||
|
|
||||
|
// make backdrop lighter only now |
||||
|
setTimeout(function () { |
||||
|
$(".modal-backdrop").first().addClass("modal-stack"); |
||||
|
}, 50); |
||||
|
|
||||
|
// open second modal after small delay |
||||
|
setTimeout(function () { |
||||
|
|
||||
|
var modal = new bootstrap.Modal( |
||||
|
document.getElementById('requestDetailsModal') |
||||
|
); |
||||
|
|
||||
|
modal.show(); |
||||
|
|
||||
|
}, 300); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
function footerSumCallback(row, data) { |
||||
|
let api = this.api(); |
||||
|
|
||||
|
const sum = idx => |
||||
|
api.column(idx).data() |
||||
|
.reduce((a, b) => Number(a) + Number(b || 0), 0); |
||||
|
|
||||
|
for (let i = 1; i <= 1; i++) { |
||||
|
$(api.column(i).footer()).html(sum(i)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function openPendingModal(zone, ward, type, startDate, endDate, level) { |
||||
|
|
||||
|
console.log("data="+zone+","+ward+","+startDate+","+endDate); |
||||
|
|
||||
|
$('#pendingModal').modal('show'); |
||||
|
$('#pendingModalTitle').text( |
||||
|
`${type} Pending - Zone ${zone}${ward ? ', Ward ' + ward : ''}` |
||||
|
); |
||||
|
|
||||
|
$('#pageLoader').show(); |
||||
|
|
||||
|
$.ajax({ |
||||
|
url: '/commissionerreview/api/greencommittee/getPendingDetails', |
||||
|
method: 'GET', |
||||
|
data: { |
||||
|
zone: zone, |
||||
|
ward: ward || null, |
||||
|
type: type, |
||||
|
startDate: startDate || null, |
||||
|
endDate: endDate || null |
||||
|
}, |
||||
|
success: function (res) { |
||||
|
$('#pageLoader').hide(); |
||||
|
|
||||
|
if (res.status === 'Success' && res.data.length > 0) { |
||||
|
renderComplaintCards(res.data); |
||||
|
} else { |
||||
|
$('#pendingModalBody').html( |
||||
|
`<p class="text-center text-muted">No complaints found</p>` |
||||
|
); |
||||
|
} |
||||
|
}, |
||||
|
error: function () { |
||||
|
$('#pageLoader').hide(); |
||||
|
Swal.fire('Error', 'Failed to load details', 'error'); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
|
||||
|
loadZoneReport(); |
||||
|
|
||||
|
loadCategoryList(); // ✅ must |
||||
|
|
||||
|
|
||||
|
// Set today's date as max |
||||
|
const today = new Date().toISOString().split('T')[0]; |
||||
|
$('#startDate, #endDate').attr('max', today); |
||||
|
|
||||
|
// When start date changes → set min for end date |
||||
|
$('#startDate').on('change', function () { |
||||
|
const startDate = $(this).val(); |
||||
|
|
||||
|
$('#endDate').attr('min', startDate); |
||||
|
|
||||
|
// If endDate already selected but invalid → clear it |
||||
|
if ($('#endDate').val() && $('#endDate').val() < startDate) { |
||||
|
$('#endDate').val(''); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// When end date changes → validate against start date |
||||
|
$('#endDate').on('change', function () { |
||||
|
const startDate = $('#startDate').val(); |
||||
|
const endDate = $(this).val(); |
||||
|
|
||||
|
if (startDate && endDate < startDate) { |
||||
|
Swal.fire({ |
||||
|
icon: 'warning', |
||||
|
title: 'Invalid Date Range', |
||||
|
text: 'End date cannot be before start date' |
||||
|
}); |
||||
|
$(this).val(''); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$('#zoneDetailsModal').on('shown.bs.modal', function () { |
||||
|
if ($.fn.DataTable.isDataTable('#WardDatatable')) { |
||||
|
let questionDatatable = $('#WardDatatable').DataTable(); |
||||
|
questionDatatable.columns.adjust().draw(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
function loadCategoryList() { |
||||
|
|
||||
|
$.ajax({ |
||||
|
|
||||
|
url: '/commissionerreview/api/bulkwaste/getCategoryList', |
||||
|
|
||||
|
method: 'GET', |
||||
|
|
||||
|
success: function (response) { |
||||
|
|
||||
|
console.log("Category API:", response); |
||||
|
|
||||
|
let res = Array.isArray(response) |
||||
|
? response[0] |
||||
|
: response; |
||||
|
|
||||
|
if (res.status === "Success") { |
||||
|
|
||||
|
let dropdown = $('#categoryId'); |
||||
|
|
||||
|
dropdown.empty(); |
||||
|
|
||||
|
dropdown.append( |
||||
|
'<option value="">All Category</option>' |
||||
|
); |
||||
|
|
||||
|
res.data.forEach(function (row) { |
||||
|
|
||||
|
dropdown.append( |
||||
|
`<option value="${row.category_id}"> |
||||
|
${row.category_name} |
||||
|
</option>` |
||||
|
); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
error: function () { |
||||
|
|
||||
|
Swal.fire( |
||||
|
"Error", |
||||
|
"Category load failed", |
||||
|
"error" |
||||
|
); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
$('#requestDetailsModal').on('hidden.bs.modal', function () { |
||||
|
|
||||
|
// remove stack effect from zone modal |
||||
|
let zoneModalEl = document.getElementById('zoneDetailsModal'); |
||||
|
zoneModalEl.classList.remove("modal-stack"); |
||||
|
|
||||
|
// remove stack from backdrop |
||||
|
$(".modal-backdrop").removeClass("modal-stack"); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue