You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1518 lines
55 KiB
1518 lines
55 KiB
<!DOCTYPE html>
|
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
|
<head th:replace="~{fragments/head-admin :: head}">
|
|
<meta charset="UTF-8">
|
|
<title>Title</title>
|
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
|
|
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/1.11.5/css/jquery.dataTables.min.css">
|
|
<script th:src="@{/js/ajax.js}"></script>
|
|
<link rel="stylesheet" href="/node_modules/amcharts3/amcharts/plugins/export/export.css" type="text/css" media="all" />
|
|
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
|
</head>
|
|
|
|
<style>
|
|
.custom-close-button {
|
|
background-color: red;
|
|
border: none;
|
|
|
|
color: #FFFFFF; /* Change the color to red */
|
|
|
|
transition: color 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
.custom-close-button:hover {
|
|
color:black;
|
|
opacity: 1; /* Fully opaque on hover */
|
|
}
|
|
|
|
.custom-close-button:focus {
|
|
outline: none; /* Remove the default focus outline */
|
|
|
|
}
|
|
|
|
.modal-body {
|
|
max-height: 500px; /* Adjust the height as needed */
|
|
overflow-y: auto; /* Enable vertical scrolling */
|
|
}
|
|
.modal-body {
|
|
max-height: 500px; /* Adjust the height as needed */
|
|
overflow-y: auto; /* Enable vertical scrolling */
|
|
}
|
|
.pagination {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.pagination .btn {
|
|
margin: 0 10px;
|
|
}
|
|
|
|
.pagination .btn.disabled {
|
|
background-color: #cccccc;
|
|
border-color: #cccccc;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.pagination .btn:not(.disabled):hover {
|
|
background-color: #0056b3; /* Darker shade for hover effect */
|
|
border-color: #0056b3;
|
|
}
|
|
|
|
.page-info {
|
|
margin: 0 10px;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
|
|
.pagination span {
|
|
margin: 0 10px;
|
|
line-height: 2;
|
|
}
|
|
.modal-header {
|
|
background-color: darkcyan;
|
|
color: white;
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 20px;
|
|
}
|
|
|
|
.table-responsive {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.modal-footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
|
|
|
|
.btn-secondary {
|
|
background-color: #3cb371;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background-color: #3cb371;
|
|
}
|
|
.btn-warning {
|
|
background-color: red;
|
|
}
|
|
|
|
.btn-warning:hover {
|
|
background-color: orange;
|
|
}
|
|
|
|
.btn-export {
|
|
margin-left: 5px;
|
|
}
|
|
|
|
.hidden {
|
|
display: none;
|
|
}
|
|
#page-container.page-header-fixed #main-container {
|
|
padding-top: 1rem !important;
|
|
}
|
|
.card{
|
|
box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 8px !important;
|
|
}
|
|
.row tail{
|
|
display: flex;
|
|
}
|
|
.col-lg-4, .col-md-4, .col-sm-12 {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
}
|
|
.boxcard {
|
|
height: 100px;
|
|
border-radius: 20px;
|
|
}
|
|
.boxcard1 {
|
|
height: 200px;
|
|
border-radius: 20px;
|
|
}
|
|
@media (min-width: 768px) {
|
|
.card boxcard {
|
|
margin-bottom: 20%;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<body class="light-theme">
|
|
<link rel="stylesheet" href="node_modules/amcharts3/amcharts/plugins/export/export.css" type="text/css" media="all" />
|
|
<div id="page-container" class="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed page-header-dark">
|
|
<aside th:replace="~{fragments/aside-right :: aside}"></aside>
|
|
<nav th:replace="~{fragments/nav-admin :: nav}"></nav>
|
|
<header th:replace="~{fragments/header-admin :: header}"></header>
|
|
|
|
<main id="main-container">
|
|
<div class="content">
|
|
<div class="content content-full">
|
|
|
|
<div class="col-md-12">
|
|
|
|
<div class="card-header">
|
|
<h3>
|
|
<i class="fas fa-chart-pie pr-2"></i><b>Overall Dashboard:</b>
|
|
</h3>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<diV class="card-body">
|
|
<div class="row" >
|
|
<div class="col-sm-3 mb-3">
|
|
<label for="fromDate" style="font-size:medium; ;margin-bottom: 0px;">From Date:</label>
|
|
<input type="date" id="fromDate" name="fromDate" value="${fromDate}" class="form-control">
|
|
</div>
|
|
<div class="col-sm-3 mb-3">
|
|
<label for="toDate" style="font-size:medium;margin-bottom: 0px;">To Date:</label>
|
|
<input type="date" id="toDate" name="toDate" value="${toDate}" class="form-control">
|
|
</div>
|
|
|
|
<div class="col-sm-3 mb-3">
|
|
<label for="zone1" class="pr-2" style="font-size:medium;margin-bottom: 0px;">Select Zone:</label>
|
|
<select class="form-select custom-select" name="zone1" id="zone1" onchange="filterDivisions()" >
|
|
<option value="ALL">--Select Zone--</option>
|
|
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-sm-3 mb-3 hidden" id="divisionContainer">
|
|
<label for="division1" class="pr-2" style="font-size:medium;margin-bottom: 0px;">Select Ward:</label>
|
|
<select id="division1" name="division1" class="form-select custom-select" onchange="filterHalls()">
|
|
<option value="ALL">--Select Div--</option>
|
|
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-sm-3 mb-3 hidden" id="hallContainer">
|
|
<label for="hall1" class="pr-2" style="font-size:medium;margin-bottom: 0px;">Select Hall:</label>
|
|
<select id="hall1" name="hall1" class="form-select custom-select">
|
|
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-sm-3 mb-3">
|
|
<label for="userType" class="pr-2" style="font-size:medium;margin-bottom: 0px;">User Type:</label>
|
|
<select id="userType" name="userType" class="form-select custom-select" >
|
|
<option value="ALL">--Select UserType--</option>
|
|
<option value="PUBLIC">PUBLIC</option>
|
|
<option value="PENSIONER">PENSIONER</option>
|
|
<option value="GCC_EMPLOYEE">GCC EMPLOYEE</option>
|
|
<option value="COUNCILLOR">COUNCILLOR</option>
|
|
<!-- Add userType options dynamically -->
|
|
</select>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12 d-flex justify-content-center">
|
|
<button type="submit" id="filterButton" class="btn btn-primary mx-2">Filter</button>
|
|
|
|
<button class="btn btn-danger mx-2" onclick="resetDate()" name="reset" type="reset">Reset</button>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
|
|
<div class="card-block" style="text-align:center;background-color: #F6F7FB;">
|
|
<div id="chart" class="row">
|
|
|
|
<div class="col-12">
|
|
<div class="row tail">
|
|
<!-- First Part: 2 cards vertically -->
|
|
<div class="col-lg-4 col-md-4 col-sm-12">
|
|
|
|
<div class="card boxcard">
|
|
<div class="card-body">
|
|
<h5 class="card-title" style="font-size: 14px;">Total Amount Received</h5>
|
|
<p class="card-text" id="totalAmount"
|
|
style="font-size: large; font-weight: bold;"></p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="card boxcard">
|
|
<div class="card-body">
|
|
<h5 class="card-title" style="font-size: 14px;">Total Refund Amount</h5>
|
|
<p class="card-text" id="totalRefundedAmount"
|
|
style="font-size: large; font-weight: bold;"></p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Second Part: 1 card, height equal to both cards in the first part -->
|
|
<div class="col-lg-4 col-md-4 col-sm-12 mt-3">
|
|
|
|
<div class="card boxcard1">
|
|
<div class="card-body">
|
|
<h3 class="card-title mt-3 mb-4" style="font-size: 14px;">Total
|
|
Bookings</h3>
|
|
<p class="card-text" id="totalBookings"
|
|
style="font-size:40px; font-weight: bold;"></p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Third Part: 2 cards vertically -->
|
|
<div class="col-lg-4 col-md-4 col-sm-12">
|
|
|
|
<div class="card boxcard">
|
|
<div class="card-body">
|
|
<h5 class="card-title" style="font-size: 14px;">NetAmount</h5>
|
|
<p class="card-text" id="netAmount"
|
|
style="font-size: large; font-weight: bold;"></p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="card boxcard">
|
|
<div class="card-body">
|
|
<h5 class="card-title" style="font-size: 14px;">GST</h5>
|
|
<p class="card-text" id="gstAmount"
|
|
style="font-size: large; font-weight: bold;"></p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<br>
|
|
<div class="card-block" style="text-align:center;background-color: #F6F7FB;">
|
|
<div class="row" >
|
|
<div class="col-sm-12 col-lg-4" >
|
|
<div class="card" style="width:100%;" >
|
|
<div id="booking-status-chartdiv" class="chart-shadow" style="height:420px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12 col-lg-4">
|
|
<div class="card" style="width:100%;">
|
|
<div id="refund-status-chartdiv" class="chart-shadow" style="height:420px;"></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-12 col-lg-4">
|
|
<div class="card" style="width:100%;">
|
|
<div id="reason-chartdiv" class="chart-shadow" style="height:420px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
<br>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12 col-lg-6">
|
|
|
|
<div class="card" style="width:100%;">
|
|
<div id="paymentStatus-chartdiv" class="chart-shadow" style="height:420px;"></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-12 col-lg-6">
|
|
|
|
<div class="card" style="width:100%;">
|
|
<div id="past_future-chartdiv" class="chart-shadow" style="height:420px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<br>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12 col-lg-12">
|
|
<div class="card">
|
|
<div id="zonewise-chartdiv" class="chart-shadow" style="height:600px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Modal -->
|
|
<div class="modal fade backdrop" id="DetailsModal" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="zoneDetailsModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-xl" role="document">
|
|
<div class="modal-content">
|
|
<div id="zone-details-content"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- modal-->
|
|
|
|
<!-- Modal for Hall Details -->
|
|
<div class="modal fade" id="HallDetailsModal" tabindex="-1" role="dialog" aria-labelledby="HallDetailsModalTitle" aria-hidden="true">
|
|
<div class="modal-dialog modal-xl" role="document">
|
|
<div class="modal-content" id="hall-details-content">
|
|
<!-- Content will be injected by JavaScript -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<footer th:replace="~{fragments/footer2 :: footer}"></footer>
|
|
</div>
|
|
|
|
<div th:replace="~{fragments/resetpassword :: div}"></div>
|
|
<script th:replace="~{fragments/script :: script}"></script>
|
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
|
|
<!-- Include AmCharts JavaScript libraries -->
|
|
<script src="node_modules/amcharts3/amcharts/amcharts.js"></script>
|
|
<script src="node_modules/amcharts3/amcharts/serial.js"></script>
|
|
<script src="node_modules/amcharts3/amcharts/plugins/export/export.min.js"></script>
|
|
<script src="node_modules/amcharts3/amcharts/plugins/animate/animate.min.js"></script>
|
|
<script src="node_modules/amcharts3/amcharts/pie.js"></script>
|
|
<script src="node_modules/amcharts3/amcharts/themes/light.js"></script>
|
|
<script src="node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min.js"></script>
|
|
|
|
<!-- Include Tempus Dominus JavaScript -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.1.6/js/tempusdominus-bootstrap-4.min.js"></script>
|
|
|
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
<!-- DataTables JS -->
|
|
|
|
<!-- Bootstrap JavaScript -->
|
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
|
|
<!-- SheetJS -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
|
<!-- jsPDF -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js"></script>
|
|
<!-- jsPDF-AutoTable -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.13/jspdf.plugin.autotable.min.js"></script>
|
|
|
|
|
|
<!-- Script to handle fetching data and rendering charts -->
|
|
<script>
|
|
|
|
|
|
|
|
// Function to generate random dark color
|
|
function getRandomDarkColor() {
|
|
var letters = '0123456789ABCDEF';
|
|
var color = '#';
|
|
for (var i = 0; i < 6; i++) {
|
|
color += letters[Math.floor(Math.random() * 16)];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
// Function to fetch data and update charts
|
|
|
|
function fetchDataAndDisplayCharts(fromDate, toDate, zone, division, hallid,userType) {
|
|
|
|
var apiUrl = "/communityhall/admin/api/bookingstatistics";
|
|
var queryParams = [];
|
|
if (fromDate) {
|
|
queryParams.push("fromDate=" + encodeURIComponent(fromDate));
|
|
}
|
|
if (toDate) {
|
|
queryParams.push("toDate=" + encodeURIComponent(toDate));
|
|
}
|
|
if (zone) {
|
|
queryParams.push("zone=" + encodeURIComponent(zone));
|
|
}
|
|
if (division) {
|
|
queryParams.push("division=" + encodeURIComponent(division));
|
|
}
|
|
if (hallid){
|
|
queryParams.push("hallid=" + encodeURIComponent(hallid));
|
|
}
|
|
if (userType) {
|
|
queryParams.push("userType=" + encodeURIComponent(userType));
|
|
}
|
|
|
|
if (queryParams.length > 0) {
|
|
apiUrl += "?" + queryParams.join("&");
|
|
}
|
|
|
|
//console.log("API URL:", apiUrl);
|
|
|
|
|
|
$.ajax({
|
|
url: apiUrl,
|
|
type: "GET",
|
|
dataType:'json',
|
|
success: function(response) {
|
|
|
|
//console.log('overallreports:',response);
|
|
|
|
const data = response;
|
|
//console.log('Parsed Data:', data);
|
|
|
|
|
|
// Check and create charts if data is available, otherwise display an image
|
|
|
|
if (data.main && Object.keys(data.main).length > 0) {
|
|
document.getElementById('totalBookings').innerText = data.main.total;
|
|
document.getElementById('totalAmount').innerText = "Rs." + data.main.main_total_amount;
|
|
document.getElementById('totalRefundedAmount').innerText = "Rs." + data.main.main_refunded_amount;
|
|
document.getElementById('netAmount').innerText = "Rs." + data.main.main_net_amount;
|
|
document.getElementById('gstAmount').innerText = "Rs." + data.main.main_gst_amount;
|
|
|
|
animateAmount('totalBookings', data.main.total, 2000); // Duration in milliseconds
|
|
animateAmount('totalAmount', data.main.main_total_amount, 2000); // Duration in milliseconds
|
|
animateAmount('totalRefundedAmount', data.main.main_refunded_amount, 2000);
|
|
animateAmount('netAmount', data.main.main_net_amount, 2000);
|
|
animateAmount('gstAmount', data.main.main_gst_amount, 2000);
|
|
|
|
}
|
|
|
|
else{
|
|
document.getElementById("totalBookings").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='/images/nodata_pic.png' alt='No data available' width='50' height='50' />
|
|
</div>
|
|
`;
|
|
document.getElementById("totalAmount").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='staticimages/nodata-founds.png' alt='No data available' width='50' height='50' />
|
|
</div>
|
|
`;
|
|
document.getElementById("netAmount").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='media/images/nodata-founds.png' alt='No data available' width='50' height='50' />
|
|
</div>
|
|
`;
|
|
document.getElementById("totalRefundedAmount").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='/images/nodata_pic.png' alt='No data available' width='50' height='50' />
|
|
</div>
|
|
`;document.getElementById("gstAmount").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='/images/nodata_pic.png' alt='No data available' width='50' height='50' />
|
|
</div>
|
|
`;
|
|
}
|
|
if (data.bookingStatus && Object.keys(data.bookingStatus).length > 0) {
|
|
createDonutChart("booking-status-chartdiv", data.bookingStatus, "Booking Status","bookingStatus");
|
|
} else {
|
|
document.getElementById("booking-status-chartdiv").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='media/images/nodata-founds.png' alt='No data available' width='100' height='100' />
|
|
</div>
|
|
`; }
|
|
|
|
if (data.refundStatus && Object.keys(data.refundStatus).length > 0) {
|
|
createDonutChart("refund-status-chartdiv", data.refundStatus, "Refund Status","refundStatus");
|
|
} else {
|
|
document.getElementById("refund-status-chartdiv").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<!-- <img src='media/images/nodata-founds.png' alt='No data available' width='100' height='100' />
|
|
</div>
|
|
`; }
|
|
|
|
if (data.reason && Object.keys(data.reason).length > 0) {
|
|
createReasonChart("reason-chartdiv", data.reason, "Event Types");
|
|
} else {
|
|
document.getElementById("reason-chartdiv").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='media/images/nodata-founds.png' alt='No data available' width='100' height='100' />
|
|
</div>
|
|
`; }
|
|
|
|
if (data.zonewise && Object.keys(data.zonewise).length > 0) {
|
|
createZoneChart("zonewise-chartdiv", data.zonewise, "Zonewise Bookings","zonewise");
|
|
} else {
|
|
document.getElementById("zonewise-chartdiv").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='media/images/nodata-founds.png' alt='No data available' width='100' height='100' />
|
|
</div>
|
|
`; }
|
|
|
|
if (data.paymentStatus && Object.keys(data.paymentStatus).length > 0) {
|
|
createZoneCharts("paymentStatus-chartdiv", data.paymentStatus, "Paymentstatus Bookings","paymentStatus");
|
|
} else {
|
|
document.getElementById("paymentStatus-chartdiv").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='media/images/nodata-founds.png' alt='No data available' width='100' height='100' />
|
|
</div>
|
|
`; }
|
|
if (data.past_future && Object.keys(data.past_future).length > 0) {
|
|
// Extract only the desired fields
|
|
const filteredData = {
|
|
"PAST_Events": data.past_future.PAST_Events,
|
|
"FUTURE_Events": data.past_future.FUTURE_Events
|
|
};
|
|
createZoneCharts("past_future-chartdiv", filteredData, "Booking Summary","past_future");
|
|
} else {
|
|
document.getElementById("past_future-chartdiv").innerHTML = `
|
|
<div class="d-flex justify-content-center align-items-center" style="height: 100%;">
|
|
<img src='media/images/nodata-founds.png' alt='No data available' width='100' height='100' />
|
|
</div>
|
|
`; }
|
|
|
|
},
|
|
error: function(error) {
|
|
console.error("Error fetching data:", error);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
// Initial call to fetch and display charts with default parameters or initial load
|
|
|
|
fetchDataAndDisplayCharts();
|
|
|
|
// Example of handling date input changes to update charts
|
|
document.getElementById("filterButton").addEventListener("click", function(event) {
|
|
event.preventDefault();
|
|
var fromDate = document.getElementById("fromDate").value;
|
|
var toDate = document.getElementById("toDate").value;
|
|
var zone = document.getElementById("zone1").value;
|
|
var division = document.getElementById("division1").value;
|
|
var hallid = document.getElementById("hall1").value;
|
|
var userType = document.getElementById("userType").value;
|
|
|
|
fetchDataAndDisplayCharts(fromDate, toDate, zone, division, hallid ,userType);
|
|
});
|
|
|
|
function formatValue(value) {
|
|
value = Number(value); // Ensure the value is a number
|
|
|
|
if (value >= 1e9) {
|
|
return (value / 1e9).toFixed(2) + ' Billion';
|
|
} else if (value >= 1e6) {
|
|
return (value / 1e6).toFixed(2) + ' Million';
|
|
} else if (value >= 1e5) {
|
|
return (value / 1e5).toFixed(2) + ' Lakh';
|
|
} else if (value >= 1e4) {
|
|
return (value / 1e4).toFixed(2) + ' Thousand';
|
|
}
|
|
return value.toFixed(2);
|
|
}
|
|
|
|
|
|
|
|
// colors for each field
|
|
function getColorByCategory(category, key) {
|
|
const colors = {
|
|
bookingStatus: {
|
|
"PENDING": "#DBAE58", // Orange
|
|
"APPROVED": "#B3C100", // Greenish
|
|
"REJECTED": "#D32D41",
|
|
"COMPLETED" : "#009900",
|
|
"CANCELED" : "#ff9933",
|
|
"PAYMENT_FAILURE": "#b35900",
|
|
"GCC_BLOCKED" : "#ff6600"
|
|
},
|
|
refundStatus: {
|
|
"WAITING": "#D32D41",
|
|
"INITIATED": "#DBAE58",
|
|
"APPROVED": "#B3C100"
|
|
},
|
|
past_future:{
|
|
"PAST_Events":"#D32D41",
|
|
"FUTURE_Events":"#B3C100"
|
|
},
|
|
paymentStatus:{
|
|
"Not Completed":"#D32D41",
|
|
"Success": "#B3C100"
|
|
},
|
|
zonewise:{
|
|
"01":"#46659b",
|
|
"02":"#46659b",
|
|
"03":"#46659b",
|
|
"04":"#46659b",
|
|
"05":"#46659b",
|
|
"06":"#46659b",
|
|
"08":"#46659b",
|
|
"07":"#46659b",
|
|
"09":"#46659b",
|
|
"10":"#46659b",
|
|
"11":"#46659b",
|
|
"12":"#46659b",
|
|
"13":"#46659b",
|
|
"14":"#46659b",
|
|
"15":"#46659b",
|
|
}
|
|
|
|
};
|
|
|
|
if (!colors[category] || !colors[category][key]) {
|
|
|
|
return "#000000"; // Default color
|
|
}
|
|
|
|
return colors[category][key];
|
|
|
|
}
|
|
|
|
|
|
// Function to create a donut chart
|
|
function createDonutChart(chartId, chartData, chartTitle,category) {
|
|
|
|
chartData = Object.keys(chartData).map(key => ({
|
|
"title": key,
|
|
"value": chartData[key],
|
|
"color": getColorByCategory(category,key)
|
|
|
|
}));
|
|
|
|
/* chartData.forEach(data => {
|
|
data.color = getRandomDarkColor();
|
|
});*/
|
|
var zone = document.getElementById("zone1").value;
|
|
var division = document.getElementById("division1").value;
|
|
|
|
AmCharts.makeChart(chartId, {
|
|
"type": "pie",
|
|
"theme": "dark",
|
|
"dataProvider": chartData,
|
|
"valueField": "value",
|
|
"titleField": "title",
|
|
"colorField": "color",
|
|
"startEffect":"elastic",
|
|
"innerRadius": "45%",
|
|
"pullOutRadius": "12%",
|
|
|
|
"labelText": "[[[[value]]]]",
|
|
"labelsEnabled": true,
|
|
"gradientRatio": [-0.4, -0.4, -0.4, -0.4, -0.4, -0.4, 0, 0.1, 0.2, 0.1, 0, -0.2, -0.5],
|
|
"balloonText": "[[[[title]]]]<br><span style='font-size:14px'><b>[[[[value]]]]</b></span>",
|
|
"export": {
|
|
"enabled": true,
|
|
"fileName": `Zone:${zone}_Div:${division}_${chartTitle}`
|
|
|
|
},
|
|
"responsive": {
|
|
"enabled": true,
|
|
},
|
|
"legend": {
|
|
"position": "bottom",
|
|
"markerType": "diamond",
|
|
"valueAlign": "left",
|
|
"align": "center",
|
|
"labelText": "[[[[title]]]] - ",
|
|
//"reversedOrder": true,
|
|
"enabled": true,
|
|
},
|
|
|
|
"titles": [{
|
|
"text": `Zone:${zone} Div:${division} \n \n ${chartTitle}`,
|
|
"size": 15
|
|
}]
|
|
|
|
});
|
|
}
|
|
|
|
|
|
// Function to create a donut chart
|
|
function createReasonChart(chartId, chartData, chartTitle) {
|
|
|
|
chartData = Object.keys(chartData).map(key => ({
|
|
"title": key,
|
|
"value": chartData[key],
|
|
|
|
|
|
}));
|
|
|
|
var existingColors = new Set();
|
|
chartData.forEach(data => {
|
|
data.color = getRandomDarkColor(existingColors);
|
|
});
|
|
var zone = document.getElementById("zone1").value;
|
|
var division = document.getElementById("division1").value;
|
|
|
|
AmCharts.makeChart(chartId, {
|
|
"type": "pie",
|
|
"theme": "dark",
|
|
"dataProvider": chartData,
|
|
"valueField": "value",
|
|
"titleField": "title",
|
|
"colorField": "color",
|
|
"startEffect":"elastic",
|
|
"innerRadius": "45%",
|
|
"pullOutRadius": "12%",
|
|
|
|
"labelText": "[[[[value]]]]",
|
|
"labelsEnabled": true,
|
|
"gradientRatio": [-0.4, -0.4, -0.4, -0.4, -0.4, -0.4, 0, 0.1, 0.2, 0.1, 0, -0.2, -0.5],
|
|
"balloonText": "[[[[title]]]]<br><span style='font-size:14px'><b>[[[[value]]]]</b></span>",
|
|
"export": {
|
|
"enabled": true,
|
|
"fileName": `Zone:${zone}_Div:${division}_${chartTitle}`
|
|
|
|
},
|
|
"responsive": {
|
|
"enabled": true,
|
|
},
|
|
"legend": {
|
|
"position": "bottom",
|
|
"markerType": "diamond",
|
|
"valueAlign": "left",
|
|
"align": "center",
|
|
"labelText": "[[[[title]]]] - ",
|
|
//"reversedOrder": true,
|
|
"enabled": true,
|
|
},
|
|
|
|
"titles": [{
|
|
"text": `Zone:${zone} Div:${division} \n \n ${chartTitle}`,
|
|
"size": 15
|
|
}]
|
|
|
|
});
|
|
}
|
|
|
|
// Function to payment Status and booking Summary
|
|
|
|
function createZoneCharts(chartId, chartData, chartTitle,category) {
|
|
|
|
chartData = Object.keys(chartData).map(key => ({
|
|
"category": key,
|
|
"value": chartData[key],
|
|
"color": getColorByCategory(category,key)
|
|
})).sort((a, b) => b.value - a.value);
|
|
|
|
|
|
var zone = document.getElementById("zone1").value;
|
|
var division = document.getElementById("division1").value;
|
|
|
|
//console.log("Chart Data for", chartId, chartData);
|
|
|
|
const chartElement = document.getElementById(chartId);
|
|
const minHeight = 150; // Minimum height in pixels
|
|
const heightPerZone = 30; // Height per zone in pixels
|
|
|
|
// Calculate height dynamically
|
|
const dynamicHeight = Math.max(minHeight, chartData.length * heightPerZone);
|
|
chartElement.style.height = dynamicHeight + 'px';
|
|
|
|
AmCharts.makeChart(chartId, {
|
|
"type": "serial",
|
|
"theme": "light",
|
|
"dataProvider": chartData,
|
|
"depth3D": 2,
|
|
"angle": 10,
|
|
"valueAxes": [{
|
|
"gridColor": "#808080",
|
|
"gridAlpha": 0,
|
|
"dashLength": 0,
|
|
"axisAlpha": 0,
|
|
"labelsEnabled": false,
|
|
"dashLength": 0
|
|
}],
|
|
"gridAboveGraphs": true,
|
|
"startDuration": 2,
|
|
"startEffect":"elastic",
|
|
"graphs": [{
|
|
"balloonText": "[[[[category]]]]<br><span style='font-size:14px'><b>[[[[value]]]]</b></span>",
|
|
"fillAlphas": 0.8,
|
|
"lineAlpha": 0.2,
|
|
"topRadius": 1,
|
|
"type": "column",
|
|
"valueField": "value",
|
|
"fillColorsField": "color",
|
|
"labelText": "[[[[value]]]]",
|
|
"labelColorField": "#ffffff",
|
|
"lineThickness": 1,
|
|
}],
|
|
"chartCursor": {
|
|
"valueLineEnabled": false,
|
|
"valueLineBalloonEnabled": false,
|
|
"cursorAlpha": 0,
|
|
"valueLineAlpha": 0.2,
|
|
"pan": false
|
|
},
|
|
"categoryField": "category",
|
|
"categoryAxis": {
|
|
"gridPosition": "start",
|
|
"gridAlpha": 0,
|
|
"axisAlpha": 0,
|
|
"autoWrap": false,
|
|
//"position": "left"
|
|
},
|
|
"rotate": true,
|
|
"export": {
|
|
"enabled": true,
|
|
"fileName": `Zone:${zone}_Div:${division}_${chartTitle}`
|
|
},
|
|
"titles": [{
|
|
"text": `Zone:${zone} Div:${division} \n \n ${chartTitle}`,
|
|
"size": 15
|
|
}],
|
|
|
|
});
|
|
}
|
|
|
|
// Function to create a Zone column chart
|
|
|
|
function createZoneChart(chartId, chartData, chartTitle,category) {
|
|
|
|
chartData = Object.keys(chartData).map(key => ({
|
|
"category": key,
|
|
"value": chartData[key],
|
|
"color": getColorByCategory(category,key)
|
|
})).sort((a, b) => b.value - a.value);
|
|
|
|
/* chartData.forEach(data => {
|
|
data.color = getRandomDarkColor();
|
|
}); */
|
|
var zone = document.getElementById("zone1").value;
|
|
var division = document.getElementById("division1").value;
|
|
|
|
//console.log("Chart Data for", chartId, chartData);
|
|
|
|
const chartElement = document.getElementById(chartId);
|
|
const minHeight = 150; // Minimum height in pixels
|
|
const heightPerZone = 30; // Height per zone in pixels
|
|
|
|
// Calculate height dynamically
|
|
const dynamicHeight = Math.max(minHeight, chartData.length * heightPerZone);
|
|
chartElement.style.height = dynamicHeight + 'px';
|
|
|
|
AmCharts.makeChart(chartId, {
|
|
"type": "serial",
|
|
"theme": "light",
|
|
"dataProvider": chartData,
|
|
"depth3D": 2,
|
|
"angle": 10,
|
|
"valueAxes": [{
|
|
"gridColor": "#808080",
|
|
"gridAlpha": 0,
|
|
"dashLength": 0,
|
|
"axisAlpha": 0,
|
|
"labelsEnabled": false,
|
|
"dashLength": 0
|
|
}],
|
|
"gridAboveGraphs": true,
|
|
"startDuration": 2,
|
|
"startEffect":"elastic",
|
|
"graphs": [{
|
|
"balloonText": "[[[[category]]]]<br><span style='font-size:14px'><b>[[[[value]]]]</b></span>",
|
|
"fillAlphas": 0.8,
|
|
"lineAlpha": 0.2,
|
|
"topRadius": 1,
|
|
"type": "column",
|
|
"valueField": "value",
|
|
"fillColorsField": "color",
|
|
"labelText": "[[[[value]]]]",
|
|
"labelColorField": "#ffffff",
|
|
"lineThickness": 1,
|
|
}],
|
|
"chartCursor": {
|
|
"valueLineEnabled": false,
|
|
"valueLineBalloonEnabled": false,
|
|
"cursorAlpha": 0,
|
|
"valueLineAlpha": 0.2,
|
|
"pan": false
|
|
},
|
|
"categoryField": "category",
|
|
"categoryAxis": {
|
|
"gridPosition": "start",
|
|
"gridAlpha": 0,
|
|
"axisAlpha": 0,
|
|
"autoWrap": false,
|
|
//"position": "left"
|
|
},
|
|
"rotate": true,
|
|
"export": {
|
|
"enabled": true,
|
|
"fileName": `Zone:${zone}_Div:${division}_${chartTitle}`
|
|
},
|
|
"titles": [{
|
|
"text": `Zone:${zone} Div:${division} \n \n ${chartTitle}`,
|
|
"size": 15
|
|
}],
|
|
"listeners": [{
|
|
"event": "clickGraphItem",
|
|
"method": function(event) {
|
|
let zone = event.item.category;
|
|
fetchZoneDetails(zone);
|
|
}
|
|
}]
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
function fetchZoneDetails(zone) {
|
|
$.ajax({
|
|
url: '/communityhall/admin/api/getHallsDetailsByZone',
|
|
type: 'GET',
|
|
data: { zone: zone },
|
|
dataType: 'json', // Ensure response is parsed as JSON
|
|
success: function(response) {
|
|
//console.log("response received:",response);
|
|
displayZoneDetails(response, zone);
|
|
},
|
|
error: function(error) {
|
|
console.error("Error fetching zone details:", error);
|
|
}
|
|
});
|
|
}
|
|
|
|
function displayZoneDetails(response, zone) {
|
|
//console.log("Display Zone Details Response:", response);
|
|
|
|
let totalBooking = response.totalBooking;
|
|
let amountReceived = response.amountReceived;
|
|
let approvedCount = response.approvedCount;
|
|
let rejectedCount = response.rejectedCount;
|
|
let completedCount = response.completedCount;
|
|
let canceledCount = response.canceledCount;
|
|
let paymentFailureCount = response.paymentFailureCount;
|
|
let gccBlockedCount = response.gccBlockedCount;
|
|
|
|
let zoneHalls = response.zonehalls;
|
|
|
|
if (!Array.isArray(zoneHalls)) {
|
|
console.error("zoneHalls is not an array or is undefined:", zoneHalls);
|
|
return;
|
|
}
|
|
|
|
amountReceived = amountReceived.toLocaleString();
|
|
|
|
const rowsPerPage = 10; // Number of rows per page
|
|
let currentPage = 1;
|
|
|
|
function renderTable(page) {
|
|
const startIndex = (page - 1) * rowsPerPage;
|
|
const endIndex = startIndex + rowsPerPage;
|
|
const paginatedData = zoneHalls.slice(startIndex, endIndex);
|
|
|
|
let modalContent = `
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="DetailsModalTitle"><b>Zone: ${zone} Details</b></h5>
|
|
<button type="button" class="close custom-close-button" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="table-responsive" style="max-height: 400px; overflow-y: auto;">
|
|
<table id="Zonetable" class="table table-striped table-bordered table-hover">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th>Zone</th>
|
|
<th>Division</th>
|
|
<th>Hall Name</th>
|
|
<th>Approved</th>
|
|
<th>Rejected</th>
|
|
<th>Completed</th>
|
|
<th>Cancelled</th>
|
|
<th>Payment Failure</th>
|
|
<th>GCC Blocked</th>
|
|
<th>Total Bookings</th>
|
|
<th>Total Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>`;
|
|
|
|
paginatedData.forEach(hall => {
|
|
modalContent += `
|
|
<tr>
|
|
<td>${hall.zonename}</td>
|
|
<td>${hall.division}</td>
|
|
<td>${hall.hallName}</td>
|
|
<td>${hall.approvedCount}</td>
|
|
<td>${hall.rejectedCount}</td>
|
|
<td>${hall.completedCount}</td>
|
|
<td>${hall.canceledCount}</td>
|
|
<td>${hall.paymentFailureCount}</td>
|
|
<td>${hall.gccBlockedCount}</td>
|
|
<td><b><button style="cursor: pointer;
|
|
background-color: darkcyan;
|
|
color: white;
|
|
border: none;
|
|
padding: 4px 10px;
|
|
font-size: 12px;
|
|
border-radius: 5px;"
|
|
href="#" class="total-booking" data-hallid="${hall.hall_id}">${hall.totalBookings}</button></b></td>
|
|
<td>Rs.${hall.totalAmount.toLocaleString()}</td>
|
|
</tr>`;
|
|
});
|
|
|
|
modalContent += `
|
|
<tr>
|
|
<td>Nil</td>
|
|
<td>Nil</td>
|
|
<td><b>Total:</b></td>
|
|
<td><b>${approvedCount}</b></td>
|
|
<td><b>${rejectedCount}</b></td>
|
|
<td><b>${completedCount}</b></td>
|
|
<td><b>${canceledCount}</b></td>
|
|
<td><b>${paymentFailureCount}</b></td>
|
|
<td><b>${gccBlockedCount}</b></td>
|
|
<td><b>${totalBooking}</b></td>
|
|
<td><b>Rs.${amountReceived}</b></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="pagination">
|
|
<button class="btn btn-primary ${page === 1 ? 'disabled' : ''}" onclick="changePage(${page - 1})">Previous</button>
|
|
<span class="page-info">Page ${page} of ${Math.ceil(zoneHalls.length / rowsPerPage)}</span>
|
|
<button class="btn btn-primary ${page === Math.ceil(zoneHalls.length / rowsPerPage) ? 'disabled' : ''}" onclick="changePage(${page + 1})">Next</button>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-warning custom-close-button" data-dismiss="modal">Close</button>
|
|
<div class="btn-group" role="group" aria-label="Export Buttons">
|
|
<button type="button" class="btn btn-primary btn-export" id="export-excel">Excel</button>
|
|
<button type="button" class="btn btn-primary btn-export" id="export-csv">CSV</button>
|
|
<button type="button" class="btn btn-primary btn-export" id="export-pdf">PDF</button>
|
|
</div>
|
|
</div>`;
|
|
|
|
document.getElementById('zone-details-content').innerHTML = modalContent;
|
|
|
|
$('#DetailsModal').modal('show');
|
|
}
|
|
|
|
function changePage(page) {
|
|
currentPage = page;
|
|
renderTable(currentPage);
|
|
}
|
|
|
|
// Expose changePage function to global scope
|
|
window.changePage = changePage;
|
|
|
|
renderTable(currentPage);
|
|
|
|
// Remove existing event listeners to prevent multiple triggers
|
|
$(document).off('click', '#export-excel');
|
|
$(document).off('click', '#export-csv');
|
|
$(document).off('click', '#export-pdf');
|
|
|
|
// Use jQuery to attach event handlers to dynamically added elements
|
|
$(document).on('click', '#export-excel', function() { exportToExcel('Zonetable'); });
|
|
$(document).on('click', '#export-csv', function() { exportToCSV('Zonetable'); });
|
|
$(document).on('click', '#export-pdf', function() { exportToPDF('Zonetable'); });
|
|
|
|
// Attach click event handler to the close button
|
|
$(document).on('click', '.custom-close-button', function() {
|
|
$('#DetailsModal').modal('hide');
|
|
});
|
|
|
|
function exportToExcel(tableId) {
|
|
const wb = XLSX.utils.table_to_book(document.getElementById(tableId), { sheet: "Zone Details" });
|
|
XLSX.writeFile(wb, 'Zone_Details.xlsx');
|
|
}
|
|
|
|
function exportToCSV(tableId) {
|
|
const wb = XLSX.utils.table_to_book(document.getElementById(tableId), { sheet: "Zone Details" });
|
|
XLSX.writeFile(wb, 'Zone_Details.csv', { bookType: 'csv' });
|
|
}
|
|
|
|
function exportToPDF(tableId) {
|
|
const { jsPDF } = window.jspdf;
|
|
const doc = new jsPDF();
|
|
doc.autoTable({ html: '#' + tableId });
|
|
doc.save('Zone_Details.pdf');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
fetchData();
|
|
});
|
|
|
|
function fetchData() {
|
|
fetch('/communityhall/user/api/getZonehalls') // Replace with your actual API endpoint
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
populateDropdowns(data);
|
|
})
|
|
.catch(error => console.error('Error fetching data:', error));
|
|
}
|
|
|
|
function populateDropdowns(data) {
|
|
const zoneDropdown = document.getElementById('zone1');
|
|
const divisionDropdown = document.getElementById('division1');
|
|
const hallDropdown = document.getElementById('hall1');
|
|
|
|
const zones = new Set();
|
|
const divisionsByZone = {};
|
|
const hallsByDivision = {};
|
|
|
|
data.forEach(item => {
|
|
zones.add(item.zone);
|
|
if (!divisionsByZone[item.zone]) {
|
|
divisionsByZone[item.zone] = [];
|
|
}
|
|
if (!divisionsByZone[item.zone].includes(item.division)) {
|
|
divisionsByZone[item.zone].push(item.division);
|
|
}
|
|
if (!hallsByDivision[item.division]) {
|
|
hallsByDivision[item.division] = [];
|
|
}
|
|
hallsByDivision[item.division].push({ hallName: item.hall_name, hallId: item.hall_id });
|
|
});
|
|
|
|
// Populate zones
|
|
zones.forEach(zone => {
|
|
const option = document.createElement('option');
|
|
option.value = zone;
|
|
option.textContent = zone;
|
|
zoneDropdown.appendChild(option);
|
|
});
|
|
|
|
// Populate divisions for the first selected zone
|
|
const selectedZone = zoneDropdown.value;
|
|
populateDivisions(selectedZone, divisionsByZone);
|
|
|
|
// Store divisions and halls by zone and division for later use
|
|
zoneDropdown.dataset.divisionsByZone = JSON.stringify(divisionsByZone);
|
|
divisionDropdown.dataset.hallsByDivision = JSON.stringify(hallsByDivision);
|
|
}
|
|
|
|
function populateDivisions(zone, divisionsByZone) {
|
|
const divisionDropdown = document.getElementById('division1');
|
|
divisionDropdown.innerHTML = ''; // Clear existing options
|
|
|
|
// Add 'All' option
|
|
const allOption = document.createElement('option');
|
|
allOption.value = 'ALL';
|
|
allOption.textContent = '--Select Div--';
|
|
divisionDropdown.appendChild(allOption);
|
|
|
|
if (zone === 'ALL') {
|
|
// Get all unique divisions across all zones
|
|
const allDivisions = new Set();
|
|
for (const zone in divisionsByZone) {
|
|
divisionsByZone[zone].forEach(division => allDivisions.add(division));
|
|
}
|
|
allDivisions.forEach(division => {
|
|
const option = document.createElement('option');
|
|
option.value = division;
|
|
option.textContent = division;
|
|
divisionDropdown.appendChild(option);
|
|
});
|
|
} else {
|
|
// Populate divisions for the selected zone
|
|
divisionsByZone[zone].forEach(division => {
|
|
const option = document.createElement('option');
|
|
option.value = division;
|
|
option.textContent = division;
|
|
divisionDropdown.appendChild(option);
|
|
});
|
|
}
|
|
}
|
|
|
|
function filterDivisions() {
|
|
const zoneDropdown = document.getElementById('zone1');
|
|
const selectedZone = zoneDropdown.value;
|
|
const divisionsByZone = JSON.parse(zoneDropdown.dataset.divisionsByZone);
|
|
if (selectedZone === 'ALL') {
|
|
document.getElementById('divisionContainer').classList.add('hidden');
|
|
} else {
|
|
document.getElementById('divisionContainer').classList.remove('hidden');
|
|
}
|
|
populateDivisions(selectedZone, divisionsByZone);
|
|
filterHalls(); // Reset and hide the hall dropdown when the zone changes
|
|
}
|
|
|
|
function filterHalls() {
|
|
const divisionDropdown = document.getElementById('division1');
|
|
const selectedDivision = divisionDropdown.value;
|
|
const hallDropdown = document.getElementById('hall1');
|
|
const hallsByDivision = JSON.parse(divisionDropdown.dataset.hallsByDivision);
|
|
|
|
hallDropdown.innerHTML = ''; // Clear existing options
|
|
|
|
const allOption = document.createElement('option');
|
|
allOption.value = '1000';
|
|
allOption.textContent = '--Select Hall--';
|
|
hallDropdown.appendChild(allOption);
|
|
|
|
if (selectedDivision === 'ALL') {
|
|
document.getElementById('hallContainer').classList.add('hidden');
|
|
} else {
|
|
document.getElementById('hallContainer').classList.remove('hidden');
|
|
// Populate halls for the selected division
|
|
hallsByDivision[selectedDivision].forEach(hall => {
|
|
const option = document.createElement('option');
|
|
option.value = hall.hallId; // Pass hall ID as value
|
|
option.textContent = hall.hallName;
|
|
hallDropdown.appendChild(option);
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Function to reset date fields
|
|
function resetDate() {
|
|
|
|
window.location.href = "/communityhall/admin/dashboard";
|
|
|
|
}
|
|
|
|
|
|
|
|
function animateAmount(elementId, targetAmount, duration) {
|
|
const element = document.getElementById(elementId);
|
|
let startTime = null;
|
|
const startAmount = 0;
|
|
|
|
function updateAmount(currentTime) {
|
|
if (!startTime) startTime = currentTime;
|
|
const progress = Math.min((currentTime - startTime) / duration, 1);
|
|
const animatedAmount = Math.floor(progress * targetAmount);
|
|
|
|
if (elementId === 'totalAmount' || elementId === 'netAmount' || elementId === 'totalRefundedAmount' || elementId === 'gstAmount') {
|
|
element.innerText = "Rs. " + animatedAmount; // Format with commas and prepend "Rs."
|
|
} else {
|
|
element.innerText = animatedAmount; // Format with commas
|
|
}
|
|
|
|
if (progress < 1) {
|
|
requestAnimationFrame(updateAmount);
|
|
} else {
|
|
if (elementId === 'totalAmount' || elementId === 'netAmount' || elementId === 'totalRefundedAmount' || elementId === 'gstAmount') {
|
|
element.innerText = "Rs. " + targetAmount; // Ensure it ends exactly at targetAmount
|
|
} else {
|
|
element.innerText = targetAmount; // Ensure it ends exactly at targetAmount
|
|
}
|
|
}
|
|
}
|
|
|
|
requestAnimationFrame(updateAmount);
|
|
}
|
|
|
|
|
|
|
|
|
|
//Function to generate random dark color and ensure uniqueness
|
|
function getRandomDarkColor(existingColors) {
|
|
var letters = '0123456789ABCDEF';
|
|
var color = '#';
|
|
do {
|
|
color = '#';
|
|
for (var i = 0; i < 6; i++) {
|
|
color += letters[Math.floor(Math.random() * 16)];
|
|
}
|
|
} while (existingColors.has(color) || !isDarkColor(color));
|
|
|
|
existingColors.add(color);
|
|
return color;
|
|
}
|
|
|
|
// Helper function to check if the color is dark
|
|
function isDarkColor(color) {
|
|
// Convert hex color to RGB
|
|
var r = parseInt(color.slice(1, 3), 16);
|
|
var g = parseInt(color.slice(3, 5), 16);
|
|
var b = parseInt(color.slice(5, 7), 16);
|
|
|
|
// Calculate brightness using the formula for luminance
|
|
var brightness = (r * 0.299 + g * 0.587 + b * 0.114) / 255;
|
|
|
|
// Return true if the color is dark (brightness < 0.5)
|
|
return brightness < 0.5;
|
|
}
|
|
|
|
|
|
//03/
|
|
|
|
function fetchHallDetails(hall_id) {
|
|
$.ajax({
|
|
url: '/communityhall/admin/api/byhallid',
|
|
type: 'GET',
|
|
data: { hallId: hall_id },
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
|
|
displayHallDetails(response);
|
|
//console.log(response);
|
|
},
|
|
error: function(error) {
|
|
console.error("Error fetching hall details:", error);
|
|
}
|
|
});
|
|
}
|
|
function displayHallDetails(response) {
|
|
const rowsPerPage = 10; // Number of rows per page
|
|
let currentPage = 1;
|
|
|
|
function renderTable(page) {
|
|
const startIndex = (page - 1) * rowsPerPage;
|
|
const endIndex = startIndex + rowsPerPage;
|
|
const paginatedData = response.slice(startIndex, endIndex);
|
|
|
|
let hallDetailsContent = `
|
|
<div class="modal-header">
|
|
<h5 class="modal-title"><b>Hall Booking Details</b></h5>
|
|
<button type="button" class="close custom-close-button" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="table-responsive">
|
|
<table id="halldetails" class="table table-striped table-bordered table-hover">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th>Booking Date</th>
|
|
<th>User Name</th>
|
|
<th>User Type</th>
|
|
<th>Reason</th>
|
|
<th>Event Date</th>
|
|
<th>No of Days</th>
|
|
<th>Status</th>
|
|
<th>Amount Paid</th>
|
|
<th>Amount Refunded</th>
|
|
<th>Net Revenue</th>
|
|
|
|
</tr>
|
|
</thead>
|
|
<tbody>`;
|
|
|
|
paginatedData.forEach(booking => {
|
|
hallDetailsContent += `
|
|
<tr>
|
|
<td>${booking.booking_date}</td>
|
|
<td>${booking.name}</td>
|
|
<td>${booking.usertype}</td>
|
|
<td>${booking.reason}</td>
|
|
<td>${booking.start_date} to ${booking.end_date}</td>
|
|
<td>${booking.no_of_days}</td>
|
|
<td>${booking.booking_status}</td>
|
|
<td>Rs.${booking.amount_received.toFixed(2)}</td>
|
|
<td>Rs.${booking.amount_refunded}</td>
|
|
<td>Rs.${booking.balance_amount}</td>
|
|
</tr>`;
|
|
});
|
|
|
|
hallDetailsContent += `
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="pagination">
|
|
<button class="btn btn-primary ${page === 1 ? 'disabled' : ''}" onclick="changePage(${page - 1})">Previous</button>
|
|
<span class="page-info">Page ${page} of ${Math.ceil(response.length / rowsPerPage)}</span>
|
|
<button class="btn btn-primary ${page === Math.ceil(response.length / rowsPerPage) ? 'disabled' : ''}" onclick="changePage(${page + 1})">Next</button>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-warning custom-close-button" data-dismiss="modal">Close</button>
|
|
<div class="btn-group" role="group" aria-label="Export Buttons">
|
|
<button type="button" class="btn btn-primary btn-export" id="export-excel">Excel</button>
|
|
<button type="button" class="btn btn-primary btn-export" id="export-csv">CSV</button>
|
|
<button type="button" class="btn btn-primary btn-export" id="export-pdf">PDF</button>
|
|
</div>
|
|
</div>`;
|
|
|
|
document.getElementById('hall-details-content').innerHTML = hallDetailsContent;
|
|
$('#HallDetailsModal').modal('show');
|
|
}
|
|
|
|
function changePage(page) {
|
|
currentPage = page;
|
|
renderTable(currentPage);
|
|
}
|
|
|
|
// Expose changePage function to global scope
|
|
window.changePage = changePage;
|
|
|
|
renderTable(currentPage);
|
|
|
|
// Remove existing event listeners to prevent multiple triggers
|
|
$(document).off('click', '#export-excel');
|
|
$(document).off('click', '#export-csv');
|
|
$(document).off('click', '#export-pdf');
|
|
|
|
// Use jQuery to attach event handlers to dynamically added elements
|
|
$(document).on('click', '#export-excel', function() { exportToExcel('halldetails'); });
|
|
$(document).on('click', '#export-csv', function() { exportToCSV('halldetails'); });
|
|
$(document).on('click', '#export-pdf', function() { exportToPDF('halldetails'); });
|
|
|
|
function exportToExcel(tableId) {
|
|
const wb = XLSX.utils.table_to_book(document.getElementById(tableId), { sheet: "Halldetails" });
|
|
XLSX.writeFile(wb, 'Halldetails.xlsx');
|
|
}
|
|
|
|
function exportToCSV(tableId) {
|
|
const wb = XLSX.utils.table_to_book(document.getElementById(tableId), { sheet: "Halldetails" });
|
|
XLSX.writeFile(wb, 'Halldetails.csv', { bookType: 'csv' });
|
|
}
|
|
|
|
function exportToPDF(tableId) {
|
|
const { jsPDF } = window.jspdf;
|
|
const doc = new jsPDF();
|
|
doc.autoTable({ html: '#' + tableId });
|
|
doc.save('Halldetails.pdf');
|
|
}
|
|
|
|
}
|
|
|
|
|
|
$(document).ready(function() {
|
|
// Attach click event handler to the total bookings links
|
|
$(document).on('click', '.total-booking', function(event) {
|
|
event.preventDefault();
|
|
$('#DetailsModal').modal('hide');
|
|
let hallId = $(this).data('hallid');
|
|
fetchHallDetails(hallId);
|
|
});
|
|
|
|
// Close button event handler
|
|
$(document).on('click', '.custom-close-button', function() {
|
|
$('#DetailsModal').modal('hide');
|
|
$('#HallDetailsModal').modal('hide');
|
|
});
|
|
});
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const fromDate = document.getElementById('fromDate');
|
|
const toDate = document.getElementById('toDate');
|
|
|
|
// Initially disable the "To Date" field
|
|
toDate.disabled = true;
|
|
|
|
fromDate.addEventListener('change', function() {
|
|
if (fromDate.value) {
|
|
// Enable the "To Date" field when "From Date" is selected
|
|
toDate.disabled = false;
|
|
|
|
// Get the selected "From Date"
|
|
const selectedFromDate = new Date(fromDate.value);
|
|
|
|
// Set the "To Date" minimum to the same day as the "From Date"
|
|
const sameDayString = selectedFromDate.toISOString().split('T')[0];
|
|
toDate.setAttribute('min', sameDayString);
|
|
|
|
// Set the "To Date" value to the next day by default
|
|
toDate.value = sameDayString;
|
|
|
|
} else {
|
|
// Disable the "To Date" field if "From Date" is cleared
|
|
toDate.disabled = true;
|
|
toDate.value = ''; // Clear the "To Date" input
|
|
}
|
|
});
|
|
});
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|