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