Browse Source

Bulk waste report

master
Dizho A 7 months ago
parent
commit
0a60ae9f67
  1. 11
      src/main/java/com/gcc/commissionerreview/configuration/DataSourceConfig.java
  2. 124
      src/main/java/com/gcc/commissionerreview/controller/BulkWasteApicontroller.java
  3. 5
      src/main/java/com/gcc/commissionerreview/controller/MainController.java
  4. 191
      src/main/java/com/gcc/commissionerreview/service/BulkWasteService.java
  5. 823
      src/main/resources/templates/modules/bulkwaste/bulkwastereport.html

11
src/main/java/com/gcc/commissionerreview/configuration/DataSourceConfig.java

@ -157,4 +157,15 @@ public class DataSourceConfig {
return dataSource; return dataSource;
} }
////////////////////////////// Bulk Waste /////////////////
@Bean(name = "mysqlBulkWasteDataSource")
public DataSource mysqlBulkWasteDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://" + host + "/bulk_waste");
dataSource.setUsername("root");
dataSource.setPassword(dbpassword);
return dataSource;
}
} }

124
src/main/java/com/gcc/commissionerreview/controller/BulkWasteApicontroller.java

@ -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);
}
}

5
src/main/java/com/gcc/commissionerreview/controller/MainController.java

@ -291,4 +291,9 @@ public class MainController {
return "modules/greencommittee/gcreport"; return "modules/greencommittee/gcreport";
} }
@GetMapping("/bulkwaste")
public String bulkwastereport(Model model) {
return "modules/bulkwaste/bulkwastereport";
}
} }

191
src/main/java/com/gcc/commissionerreview/service/BulkWasteService.java

@ -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);
}
}

823
src/main/resources/templates/modules/bulkwaste/bulkwastereport.html

@ -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>
Loading…
Cancel
Save