8 changed files with 1991 additions and 119 deletions
-
9src/main/java/com/gcc/commissionerreview/configuration/DataSourceConfig.java
-
12src/main/java/com/gcc/commissionerreview/controller/MainController.java
-
81src/main/java/com/gcc/commissionerreview/controller/PetLicenseApiController.java
-
29src/main/java/com/gcc/commissionerreview/controller/SofaBedCollectionApiController.java
-
507src/main/java/com/gcc/commissionerreview/service/SofaBedCollectionService.java
-
168src/main/resources/templates/modules/pet/petlicense.html
-
784src/main/resources/templates/modules/sofa_bed/collectiondetails.html
-
440src/main/resources/templates/modules/sofa_bed/pendingdetails.html
@ -0,0 +1,784 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|||
<head> |
|||
<title>Sofa Bed collection Detail Report Summary</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; |
|||
} |
|||
|
|||
#DetailsModal .modal-body{ |
|||
max-height: 85vh; |
|||
overflow-y: auto; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
|
|||
<div class="page-header-title"> |
|||
<h4>Details of Sofa,Bed,furniture and Cloths</h4> |
|||
</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 rowspan="2" class="text-center">Zones</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;">Total request received so far from 11/10/2025</th> |
|||
<th colspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;">Overall Request Cancelled</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="zone_formatted_oca_date">Overall Complaint attended up to</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="zone_formatted_op_date">Overall Pending as on </th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="zone_formatted_cur_date">Today complaint received</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="zone_formatted_twa_date">This week Attended</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;">Balance to be Attended</th> |
|||
</tr> |
|||
<tr> |
|||
|
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">user cancelled</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">officer cancelled</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
|
|||
|
|||
</tbody> |
|||
</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 rowspan="2" class="text-center">Divisions</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;">Total request received so far from 11/10/2025</th> |
|||
<th colspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;">Overall Request Cancelled</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="ward_formatted_oca_date">Overall Complaint attended up to</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="ward_formatted_op_date">Overall Pending as on </th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="ward_formatted_cur_date">Today complaint received</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;" id="ward_formatted_twa_date">This week Attended</th> |
|||
<th rowspan="2" class="text-center" style="white-space: normal; word-wrap: break-word;">Balance to be Attended</th> |
|||
</tr> |
|||
<tr> |
|||
|
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">user cancelled</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">officer cancelled</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
|
|||
|
|||
</tbody> |
|||
</table> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="modal fade" id="DetailsModal" tabindex="-1" aria-labelledby="DetailsLabel" 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="DeatilsModalTitle">Details</h5> |
|||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|||
</div> |
|||
<div class="modal-body" id="detailscontent"> |
|||
|
|||
</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> |
|||
|
|||
|
|||
<!-- Scripts --> |
|||
<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-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
|||
|
|||
<!-- DataTables JS --> |
|||
<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> |
|||
|
|||
|
|||
|
|||
$(document).ready(function () { |
|||
|
|||
$('#pageLoader').show(); |
|||
$.ajax({ |
|||
url: '/commissionerreview/api/sofabedcollection/getZoneDetails', |
|||
method: 'GET', |
|||
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', |
|||
render: function (data, type, row) { |
|||
// Skip last row |
|||
if (row === res.data[res.data.length - 1]) { |
|||
return data; // just plain text |
|||
} else { |
|||
return `<a href="#" onclick="openZoneModal('${data}')" style="text-decoration: underline;">${data}</a>`; |
|||
} |
|||
} |
|||
}, |
|||
{ data: 'Total_Requests_Received', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Cancelled_By_User', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Cancelled_By_Officer', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Overall_Complaints_Attended', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Overall_Pending_Complaints', defaultContent: '-', className: 'text-center' }, |
|||
|
|||
|
|||
{ data: 'Today_Complaint_Received', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'This_Week_Attended', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Balance_To_Be_Attended', defaultContent: '-', className: 'text-center' } |
|||
], |
|||
dom: 'Bfrtip', |
|||
buttons: [ |
|||
{ |
|||
extend: 'excelHtml5', |
|||
title: 'SofaBed_Zonewise_Report', |
|||
text: '<i class="fa fa-file-excel"></i> Export to Excel', |
|||
className: 'btn btn-success btn-sm', |
|||
exportOptions: { columns: ':visible' } |
|||
}, |
|||
{ |
|||
extend: 'pdfHtml5', |
|||
title: 'SofaBed_Zonewise_Report', |
|||
text: '<i class="fa fa-file-pdf"></i> Export to PDF', |
|||
className: 'btn btn-danger btn-sm', |
|||
orientation: 'portrait', // Optional: 'portrait' or 'landscape' |
|||
pageSize: 'A4', // Optional: 'A4', 'LETTER', etc. |
|||
exportOptions: { columns: ':visible' } |
|||
|
|||
} |
|||
], |
|||
lengthMenu: [ |
|||
[50, 100, 200, 500, -1], |
|||
['50 rows', '100 rows', '200 rows', 'Show all'] |
|||
], |
|||
scrollY: 'auto', |
|||
scrollX: true, |
|||
responsive: false, |
|||
searching: false, |
|||
ordering: false |
|||
}); |
|||
|
|||
$('#zone_formatted_oca_date').text('Overall Complaint attended up to ' + res.oca_date); |
|||
$('#zone_formatted_cur_date').text('Today complaint received ' + res.current_date); |
|||
$('#zone_formatted_op_date').text('Overall Pending as on ' + res.current_date); |
|||
$('#zone_formatted_twa_date').text('This week Attended ' + res.oca_date); |
|||
|
|||
|
|||
} |
|||
|
|||
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 if(res.status === "nodata") { |
|||
$('#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: res.message || 'Error', |
|||
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 |
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
}); |
|||
|
|||
$('#zoneDetailsModal').on('shown.bs.modal', function () { |
|||
if ($.fn.DataTable.isDataTable('#WardDatatable')) { |
|||
let questionDatatable = $('#WardDatatable').DataTable(); |
|||
questionDatatable.columns.adjust().draw(); |
|||
} |
|||
}); |
|||
|
|||
|
|||
}); |
|||
|
|||
function openZoneModal(zoneCode) { |
|||
console.log("Opening modal for zone:", zoneCode); |
|||
|
|||
$('#pageLoader').show(); |
|||
|
|||
// Set data in modal (example) |
|||
$('#zoneModalTitle').text('Zone ' + zoneCode + ' Details'); |
|||
|
|||
|
|||
$.ajax({ |
|||
url: '/commissionerreview/api/sofabedcollection/getWardDetails', |
|||
method: 'GET', |
|||
data:{zone:zoneCode}, |
|||
success: function(response) { |
|||
|
|||
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 = $('#WardDatatable').DataTable({ |
|||
destroy: true, |
|||
autoWidth: true, |
|||
info: true, |
|||
data: res.data, |
|||
columns: [ |
|||
{ data: 'Division', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Total_Requests_Received', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Cancelled_By_User', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Cancelled_By_Officer', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Overall_Complaints_Attended', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Overall_Pending_Complaints', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'Today_Complaint_Received', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'This_Week_Attended', defaultContent: '-', className: 'text-center' } , |
|||
{ data: 'Balance_To_Be_Attended', defaultContent: '-', className: 'text-center' } |
|||
], |
|||
dom: 'Bfrtip', |
|||
buttons: [ |
|||
{ |
|||
extend: 'excelHtml5', |
|||
title: 'SofaBed_Zone_'+ zoneCode+'_Wardwise_Report', |
|||
text: '<i class="fa fa-file-excel"></i> Export to Excel', |
|||
className: 'btn btn-success btn-sm', |
|||
exportOptions: { columns: ':visible' } |
|||
}, |
|||
{ |
|||
extend: 'pdfHtml5', |
|||
title: 'SofaBed_Zone_'+ zoneCode+'_Wardwise_Report', |
|||
text: '<i class="fa fa-file-pdf"></i> Export to PDF', |
|||
className: 'btn btn-danger btn-sm', |
|||
orientation: 'portrait', // Optional: 'portrait' or 'landscape' |
|||
pageSize: 'A4', // Optional: 'A4', 'LETTER', etc. |
|||
exportOptions: { columns: ':visible' } |
|||
|
|||
} |
|||
], |
|||
lengthMenu: [ |
|||
[50, 100, 200, 500, -1], |
|||
['50 rows', '100 rows', '200 rows', 'Show all'] |
|||
], |
|||
scrollY: '400px', |
|||
scrollX: true, |
|||
responsive: false, |
|||
searching: false, |
|||
ordering: false, |
|||
createdRow: function (row, data, dataIndex) { |
|||
if (dataIndex === res.data.length - 1) return; |
|||
|
|||
const clickableCols = ['Overall_Complaints_Attended', 'Overall_Pending_Complaints', 'Today_Complaint_Received', 'This_Week_Attended','Balance_To_Be_Attended']; |
|||
|
|||
clickableCols.forEach((col) => { |
|||
const value = parseInt(data[col]); |
|||
if (!isNaN(value) && value > 0) { |
|||
const colIndex = { |
|||
Overall_Complaints_Attended: 4, |
|||
Overall_Pending_Complaints: 5, |
|||
Today_Complaint_Received: 6, |
|||
This_Week_Attended: 7, |
|||
Balance_To_Be_Attended:8 |
|||
}[col]; |
|||
|
|||
$('td:eq(' + colIndex + ')', row).css({ |
|||
'color': '#007bff', |
|||
'text-decoration': 'underline', |
|||
'cursor': 'pointer' |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
}); |
|||
|
|||
$('#ward_formatted_oca_date').text('Overall Complaint attended up to ' + res.oca_date); |
|||
$('#ward_formatted_cur_date').text('Today complaint received ' + res.current_date); |
|||
$('#ward_formatted_twa_date').text('This week Attended ' + res.oca_date); |
|||
$('#ward_formatted_op_date').text('Overall Pending as on ' + res.current_date); |
|||
|
|||
$('#zoneDetailsModal').modal('show'); |
|||
} |
|||
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: res.message || 'Error', |
|||
showConfirmButton: true, |
|||
timer: 3000 |
|||
}); |
|||
} |
|||
} |
|||
else if (res.status === "nodata") { |
|||
$('#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: res.message || 'Error', |
|||
showConfirmButton: true, |
|||
timer: 3000 |
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
// Attach click handler after DataTable initialization |
|||
$('#WardDatatable tbody').off('click').on('click', 'td', function () { |
|||
let table = $('#WardDatatable').DataTable(); |
|||
let rowData = table.row($(this).closest('tr')).data(); |
|||
let columnIndex = table.cell(this).index().column; |
|||
|
|||
// Define column-to-status mapping (based on your requirement) |
|||
const columnMap = { |
|||
4: 1, // open |
|||
5: 2, // completed |
|||
6: 3, // user_cancel |
|||
7: 4, // officer_cancel |
|||
8: 5 // pending |
|||
}; |
|||
|
|||
// Get column name using column index |
|||
let columnName = table.column(columnIndex).dataSrc(); |
|||
|
|||
// If clicked column is one of the target columns |
|||
if (columnMap[columnIndex]) { |
|||
let status = columnMap[columnIndex]; |
|||
let value = rowData[columnName]; |
|||
let division = rowData['Division']; |
|||
|
|||
// Proceed only if value > 0 |
|||
if (parseInt(value) > 0) { |
|||
openWardDetails(division, status); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
|
|||
}, |
|||
error: function(xhr, status, error) { |
|||
$('#pageLoader').hide(); |
|||
//alert("Request failed: " + error); |
|||
|
|||
Swal.fire({ |
|||
icon: 'error', |
|||
title: 'Error', |
|||
text: error, |
|||
showConfirmButton: true, |
|||
timer: 3000 |
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
}); |
|||
|
|||
|
|||
} |
|||
|
|||
function openWardDetails(division, status){ |
|||
console.log("division:",division," status:",status); |
|||
// Optional: show in a modal or send AJAX |
|||
|
|||
$('#pageLoader').show(); |
|||
$.ajax({ |
|||
url: '/commissionerreview/api/sofabedcollection/getWardStatusDetails', |
|||
method: 'GET', |
|||
data: { |
|||
ward: division, |
|||
status: status |
|||
}, |
|||
success: function (response) { |
|||
$('#pageLoader').hide(); |
|||
var res = Array.isArray(response) ? response[0] : response; |
|||
//console.log("Response:", res); |
|||
|
|||
$('#pageLoader').hide(); |
|||
console.log("Details:", res); |
|||
if(res.status === "Success"){ |
|||
|
|||
let modalBody = $("#detailscontent"); |
|||
modalBody.empty(); // Clear previous content |
|||
|
|||
|
|||
|
|||
if (Array.isArray(res.data) && res.data.length > 0){ |
|||
|
|||
res.data.forEach(item => { |
|||
// Create a container div for each record |
|||
let streetDiv = $('<div class="mb-4 p-3 border rounded shadow-sm bg-light"></div>'); |
|||
|
|||
let sourceText = '-'; |
|||
if (item.is_app === "1") sourceText = 'Namma Chennai App'; |
|||
else if (item.is_app === "2") sourceText = 'Whatsapp registration'; |
|||
else if (item.is_app === "3") sourceText = '1913'; |
|||
|
|||
// Info section (2 columns layout) |
|||
let infoHtml = ` |
|||
<div class="container-fluid"> |
|||
<div class="row mb-2"> |
|||
<div class="col-md-4"><strong>Zone:</strong> ${item.zone || '-'}</div> |
|||
<div class="col-md-4"><strong>Ward:</strong> ${item.division || '-'}</div> |
|||
<div class="col-md-4"><strong>Request ID:</strong> ${item.request_id || '-'}</div> |
|||
</div> |
|||
<div class="row mb-2"> |
|||
<div class="col-md-4"><strong>User Name:</strong> ${item.user_name || '-'}</div> |
|||
<div class="col-md-4"><strong>Status:</strong> ${item.status || '-'}</div> |
|||
<div class="col-md-4"><strong>Mobile Number:</strong> ${item.mobile || '-'}</div> |
|||
</div> |
|||
<div class="row mb-2"> |
|||
<div class="col-md-8"><strong>Address:</strong> ${item.address || '-'}</div> |
|||
<div class="col-md-4"><strong>Created Date:</strong> ${item.cdate || '-'}</div> |
|||
</div> |
|||
<div class="row mb-2"> |
|||
<div class="col-md-4"><strong>Source:</strong> ${sourceText}</div> |
|||
|
|||
</div> |
|||
</div> |
|||
`; |
|||
streetDiv.append(infoHtml); |
|||
|
|||
|
|||
// 🧾 Items section (as divs) |
|||
let itemsHtml = ` |
|||
<div class="mt-3"> |
|||
<p><strong>Items:</strong></p> |
|||
${ |
|||
Array.isArray(item.items) && item.items.length > 0 |
|||
? item.items.map((it, idx) => ` |
|||
<div class="d-flex flex-wrap border rounded p-2 mb-2 "> |
|||
<div class="flex-fill"><strong>Item ${idx + 1}:</strong> ${it.item_name || '-'}</div> |
|||
<div class="flex-fill"><strong>Quantity:</strong> ${it.quantity ?? '-'}</div> |
|||
</div> |
|||
`).join("") |
|||
: `<p class="text-muted">No items available.</p>` |
|||
} |
|||
</div> |
|||
`; |
|||
streetDiv.append(itemsHtml); |
|||
|
|||
let imagesHtml; |
|||
|
|||
if(item.status === "completed"){ |
|||
imagesHtml = ` |
|||
<hr> |
|||
<div class="d-flex mt-2"> |
|||
<div class="me-2 text-center" style="flex:1;"> |
|||
<p><strong>User Uploaded Image</strong></p> |
|||
${ |
|||
item.image_url |
|||
? (() => { |
|||
let beforePath = item.image_url.split(",")[0].trim(); |
|||
return `<img src="${beforePath}" |
|||
alt="User's Uploaded Image" |
|||
|
|||
style="width: 250px; height: 200px; object-fit: contain;" |
|||
/>`; |
|||
})() |
|||
: `<p>No image</p>` |
|||
} |
|||
</div> |
|||
<div class="text-center" style="flex:1;"> |
|||
<p><strong>Officer Uploaded Image</strong></p> |
|||
${ |
|||
item.officer_upload_url |
|||
? (() => { |
|||
let afterPath = item.officer_upload_url.split(",")[0].trim(); |
|||
return `<img src="${afterPath}" |
|||
alt="Officer's Uploaded Image" |
|||
|
|||
style="width: 250px; height: 200px; object-fit: contain;" |
|||
/>`; |
|||
})() |
|||
: `<p>No image</p>` |
|||
} |
|||
</div> |
|||
</div> |
|||
`; |
|||
} |
|||
else{ |
|||
imagesHtml = ` |
|||
<hr> |
|||
<div class="mt-2" style="text-align:center;"> |
|||
<p><strong>Image:</strong></p> |
|||
${ |
|||
item.image_url |
|||
? (() => { |
|||
// Handle multiple comma-separated images |
|||
return item.image_url.split(",").map(img => { |
|||
let trimmed = img.trim(); |
|||
return ` |
|||
<img src="${trimmed}" |
|||
alt="Image" |
|||
|
|||
style="width: 250px; height: 200px; object-fit: contain;" |
|||
|
|||
/> |
|||
`; |
|||
}).join(""); |
|||
})() |
|||
: `<p class="text-muted">No image.</p>` |
|||
} |
|||
</div> |
|||
`; |
|||
} |
|||
|
|||
|
|||
streetDiv.append(imagesHtml); |
|||
|
|||
modalBody.append(streetDiv); |
|||
}); |
|||
|
|||
|
|||
$('#DeatilsModalTitle').text('Division '+division +' Details'); |
|||
$('#DetailsModal').modal('show'); |
|||
} |
|||
|
|||
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: response.message, |
|||
showConfirmButton: true, |
|||
timer: 3000 |
|||
}); |
|||
} |
|||
} |
|||
|
|||
else if (res.status === "nodata") { |
|||
$('#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: 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 |
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
</script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,440 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
|||
<head> |
|||
<title>Pending Details of Sofa Bed collection</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; |
|||
} |
|||
.word-wrap { |
|||
white-space: normal !important; |
|||
word-wrap: break-word; |
|||
max-width: 200px; /* Adjust width as needed */ |
|||
} |
|||
|
|||
#opSummaryTable1, #opSummaryTable2 { |
|||
background-color: #fff; |
|||
border-radius: 8px; |
|||
padding: 10px; |
|||
} |
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
|
|||
<div class="page-header-title"> |
|||
<h4>Pending Details of Sofa,Bed,furniture and Cloths</h4> |
|||
</div> |
|||
|
|||
|
|||
<div class="container"> |
|||
<div class="row"> |
|||
<!-- Left side: Source Summary --> |
|||
<div class="col-md-6"> |
|||
<div id="opSummaryTable1" class="table-responsive"> |
|||
<table id="SourceAbstracttable" class="table table-striped table-bordered display nowrap w-100"> |
|||
<thead> |
|||
<tr> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Received From</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Total</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody></tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Right side: Status Summary --> |
|||
<div class="col-md-6"> |
|||
<div id="opSummaryTable2" class="table-responsive"> |
|||
<table id="StatusAbstracttable" class="table table-striped table-bordered display nowrap w-100"> |
|||
<thead> |
|||
<tr> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Status</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Total</th> |
|||
</tr> |
|||
|
|||
</thead> |
|||
<tbody></tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
<hr> |
|||
|
|||
<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">S.No</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Zone</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Division</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Request Id</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Registered Date</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">User Name</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Mobile</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Address</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Street Name</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Image</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Remarks</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Items</th> |
|||
<th class="text-center" style="white-space: normal; word-wrap: break-word;">Source</th> |
|||
</tr> |
|||
|
|||
</thead> |
|||
<tbody> |
|||
|
|||
|
|||
</tbody> |
|||
</table> |
|||
</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> |
|||
|
|||
|
|||
<!-- Scripts --> |
|||
<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-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
|||
|
|||
<!-- DataTables JS --> |
|||
<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> |
|||
|
|||
|
|||
|
|||
$(document).ready(function () { |
|||
|
|||
$('#pageLoader').show(); |
|||
$.ajax({ |
|||
url: '/commissionerreview/api/sofabedcollection/getPendingDetails', |
|||
method: 'GET', |
|||
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: null, |
|||
render: (data, type, row, meta) => meta.row + 1, |
|||
className: 'text-center' |
|||
}, |
|||
{ data: 'zone', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'division', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'request_id', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'cdate', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'user_name', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'mobile', defaultContent: '-', className: 'text-center' }, |
|||
{ data: 'address', defaultContent: '-', className: 'text-center word-wrap' }, |
|||
{ data: 'street_name', defaultContent: '-', className: 'text-center word-wrap' }, |
|||
{ |
|||
data: 'image_url', |
|||
defaultContent: '-', |
|||
className: 'text-center', |
|||
render: function (data, type, row) { |
|||
if (!data || data === "null" || data.trim() === "") { |
|||
return '-'; |
|||
} |
|||
// ✅ Make it a clickable hyperlink opening in a new tab |
|||
return `<a href="${data}" target="_blank" style="color: #007bff; text-decoration: underline;">View</a>`; |
|||
} |
|||
}, |
|||
{ data: 'remarks', defaultContent: '-', className: 'text-center word-wrap' }, |
|||
{ |
|||
data: 'items', |
|||
defaultContent: '-', |
|||
className: 'text-center word-wrap', |
|||
render: function (data, type, row) { |
|||
if (Array.isArray(data) && data.length > 0) { |
|||
|
|||
return data.map(item => `${item.item_name}-${item.quantity}`).join(', '); |
|||
} |
|||
return '-'; |
|||
} |
|||
}, |
|||
{ data: 'Source', defaultContent: '-', className: 'text-center' } |
|||
], |
|||
|
|||
dom: 'Bfrtip', |
|||
buttons: [ |
|||
{ |
|||
extend: 'excelHtml5', |
|||
title: 'SofaBed_Pending_Report', |
|||
text: '<i class="fa fa-file-excel"></i> Export to Excel', |
|||
className: 'btn btn-success btn-sm', |
|||
exportOptions: { columns: ':visible' } |
|||
} |
|||
|
|||
], |
|||
lengthMenu: [ |
|||
[50, 100, 200, 500, -1], |
|||
['50 rows', '100 rows', '200 rows', 'Show all'] |
|||
], |
|||
scrollY: 'auto', |
|||
scrollX: true, |
|||
responsive: false, |
|||
searching: true, |
|||
ordering: false |
|||
}); |
|||
|
|||
|
|||
if (Array.isArray(res.source_data) && res.source_data.length > 0) { |
|||
|
|||
let table1 = $('#SourceAbstracttable').DataTable({ |
|||
destroy: true, |
|||
autoWidth: true, |
|||
info: false, |
|||
data: res.source_data, // using response directly |
|||
columns: [ |
|||
|
|||
{ data: 'SOURCE', |
|||
render: function (data, type, row) { |
|||
// Skip last row |
|||
if (row === res.source_data[res.source_data.length - 1]) { |
|||
return `<b>${data}</b>`; |
|||
} else { |
|||
|
|||
return data; |
|||
} |
|||
} |
|||
}, |
|||
{ data: 'count', defaultContent: '-', className: 'text-center word-wrap' } |
|||
|
|||
], |
|||
|
|||
dom: 'Bfrtip', |
|||
buttons: [ |
|||
{ |
|||
extend: 'excelHtml5', |
|||
title: 'SofaBed_Pending_Source_Report', |
|||
text: '<i class="fa fa-file-excel"></i> Export to Excel', |
|||
className: 'btn btn-success btn-sm', |
|||
exportOptions: { columns: ':visible' } |
|||
} |
|||
|
|||
], |
|||
paging:false, |
|||
scrollY: 'auto', |
|||
scrollX: true, |
|||
responsive: false, |
|||
searching: false, |
|||
ordering: false |
|||
}); |
|||
} |
|||
|
|||
|
|||
if (Array.isArray(res.status_data) && res.status_data.length > 0) { |
|||
|
|||
let table1 = $('#StatusAbstracttable').DataTable({ |
|||
destroy: true, |
|||
autoWidth: true, |
|||
info: false, |
|||
data: res.status_data, // using response directly |
|||
columns: [ |
|||
|
|||
{ data: 'status_category', |
|||
render: function (data, type, row) { |
|||
// Skip last row |
|||
if (row === res.status_data[res.status_data.length - 1]) { |
|||
return `<b>${data}</b>`; |
|||
} else { |
|||
|
|||
return data; |
|||
} |
|||
} |
|||
}, |
|||
{ data: 'total_count', defaultContent: '-', className: 'text-center word-wrap' } |
|||
|
|||
], |
|||
|
|||
dom: 'Bfrtip', |
|||
buttons: [ |
|||
{ |
|||
extend: 'excelHtml5', |
|||
title: 'SofaBed_Pending_Status_Report', |
|||
text: '<i class="fa fa-file-excel"></i> Export to Excel', |
|||
className: 'btn btn-success btn-sm', |
|||
exportOptions: { columns: ':visible' } |
|||
} |
|||
|
|||
], |
|||
paging:false, |
|||
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 if(res.status === "nodata") { |
|||
$('#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: 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 |
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
}); |
|||
|
|||
/* $('#zoneDetailsModal').on('shown.bs.modal', function () { |
|||
if ($.fn.DataTable.isDataTable('#WardDatatable')) { |
|||
let questionDatatable = $('#WardDatatable').DataTable(); |
|||
questionDatatable.columns.adjust().draw(); |
|||
} |
|||
}); */ |
|||
|
|||
}); |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
</script> |
|||
|
|||
</body> |
|||
</html> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue