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.
 
 
 
 
 

1075 lines
29 KiB

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Victoria public hall</title>
<!-- Links to Bootstrap CSS and JS, jQuery, and SweetAlert -->
<!-- Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<style>
label {
color: black;
}
/* Header Styling */
.header {
background-color: #1d495a;
padding: 10px 20px;
display: flex;
align-items: center;
justify-content: space-between;
color: white;
font-family: Arial, sans-serif;
}
.header .logo {
display: flex;
align-items: center;
}
.header .logo img {
height: 60px;
}
.header .center-text {
position: absolute;
/* Centered text */
left: 50%;
transform: translateX(-50%);
text-align: center;
font-size: 24px;
}
.header .menu-btn {
background-color: transparent;
border: none;
font-size: 24px;
color: white;
}
.header .menu-btn:hover {
/* text-decoration: underline; */
color: #ccc;
}
/* Menu Dropdown */
.menu-dropdown {
position: relative;
margin-top: 10px;
background-color: #1d495a;
padding: 10px 20px;
display: none;
flex-direction: column;
width: 100%;
}
.menu-dropdown a {
color: white;
margin-bottom: 5px;
text-decoration: none;
}
.menu-dropdown a:hover {
text-decoration: underline;
}
.menu-dropdown {
right: 0;
left: 0;
z-index: 1000;
/* Add z-index to bring the menu above other elements */
}
/* Mobile Specific Styling */
@media (max-width : 768px) {
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.center-text {
font-size: 18px !important;
flex-grow: 1;
text-align: center;
}
.menu-dropdown {
right: 0;
left: 0;
z-index: 1000;
/* Add z-index to bring the menu above other elements */
}
}
/* Ensure content is not hidden behind the fixed navbar */
body {
margin: 0;
/* margin-top: 90px; Adjust based on your header height */
}
.disclaimer-list li {
font-size: 0.95rem;
/* or 1rem */
line-height: 1.6;
}
.flatpickr-calendar {
z-index: 99999 !important;
}
/* Allow calendar to overflow cards */
.card,
.card-body,
.container {
overflow: visible !important;
}
.pickdate[readonly] {
background-color: #fff !important;
cursor: pointer;
}
.readonly-input {
background-color: #e9ecef; /* Bootstrap disabled look */
cursor: not-allowed;
}
</style>
</head>
<body style="background-color: #ebf1fa;">
<!-- Header Start-->
<header>
<div class="header d-flex justify-content-between align-items-center">
<!-- Left: Logo -->
<div class="logo">
<img src="https://gccservices.in/gcc/assets/images/logo.png" alt="Logo">
</div>
<!-- Center: Text -->
<div class="center-text">VICTORIA PUBLIC HALL</div>
</div>
</header>
<!-- Header End-->
<main class="container mt-4">
<div class="container mt-5">
<div class="card">
<div class="card-header bg-dark text-white">
<h5>Request Information:-</h5>
</div>
<div class="card-body">
<div class="container mt-4">
<!-- Row 1: Name and Phone -->
<div class="row mb-3">
<div class="col-md-5">
<label class="form-label" for="name">Name <span class="text-danger">*</span></label> <input type="text"
class="form-control" placeholder="Enter Name here" id="name"
oninput="this.value = this.value.replace(/[^a-zA-Z\s]/g, '')">
</div>
<div class="col-md-5">
<label class="form-label" for="userinput"> Mobile Number/Email
</label> <input type="text" id="userinput" class="form-control readonly-input"
placeholder="Enter Phone number">
</div>
</div>
<div class="row mb-3">
<div class="col-md-5">
<label class="form-label" for="category">
Category <span class="text-danger">*</span>
</label>
<select class="form-control" id="category" name="categoryId" required>
<option value="">-- Select Category --</option>
</select>
</div>
<div class="col-md-5">
<label class="form-label" for="preferdate">
Preferred Date <span class="text-danger">*</span>
</label>
<div class="input-group">
<input type="text"
class="form-control pickdate"
id="preferdate"
placeholder="dd-mm-yyyy"
>
<div class="input-group-append">
<span class="input-group-text" style="cursor:pointer">
📅
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- School / College Card -->
<div class="card mt-3 d-none" id="schoolCollegeCard">
<div class="card-header bg-dark text-white">
<h6 class="mb-0">School / College Details</h6>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-5">
<label for="privateInstitutionName">Institution Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="privateInstitutionName"
placeholder="Enter School / College Name" oninput="allowOnlyAlphabets(this)">
</div>
<!-- ID Proof Dropdown -->
<div class="col-md-5">
<label class="form-label" for="idProof">
ID Proof of accompanying staff <span class="text-danger">*</span>
</label>
<select class="form-control idProofSelect mb-2">
<option value="">-- Select ID Proof --</option>
</select>
</div>
<!-- ID Number Input -->
<div class="col-md-5">
<label class="form-label" for="idProofNumber">
ID Proof Number <span class="text-danger">*</span>
</label>
<input class="form-control idProofNumber" placeholder="Select ID Proof first" disabled>
</div>
</div>
</div>
</div>
<!-- Organization / Association Card -->
<div class="card mt-3 d-none" id="organizationCard">
<div class="card-header bg-dark text-white">
<h6 class="mb-0">Organization / Association Details</h6>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-5">
<label>Organization Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="orgName" placeholder="Enter Organization Name" oninput="allowOnlyAlphabets(this)">
</div>
<!-- ID Proof Dropdown -->
<div class="col-md-5">
<label class="form-label" for="idProof">ID Proof of accompanying staff <span class="text-danger">*</span>
</label>
<select class="form-control idProofSelect mb-2">
<option value="">-- Select ID Proof --</option>
</select>
</div>
<!-- ID Number Input -->
<div class="col-md-5">
<label class="form-label" for="idProofNumber">
ID Proof Number <span class="text-danger">*</span>
</label>
<input class="form-control idProofNumber" placeholder="Select ID Proof first" disabled>
</div>
</div>
</div>
</div>
<div class="card mt-3 d-none" id="visitorDetailsCard">
<div class="card-header bg-dark text-white">
<h6 class="mb-0">Visitor Details</h6>
</div>
<div class="card-body">
<!-- Dynamic User Type Rows -->
<div id="userTypeContainer"></div>
<hr>
<!-- Summary -->
<div class="d-flex justify-content-between">
<strong>Total People:</strong>
<span id="totalPeople">0</span>
</div>
<div class="d-flex justify-content-between mt-2">
<strong>Total Amount:</strong>
<span id="totalAmount">₹0</span>
</div>
</div>
</div>
<div class="card mt-3" id="termsCheckCard">
<div class="card-header bg-dark text-white">
<h6 class="mb-0">Disclaimer</h6>
</div>
<div class="card-body">
<!-- Disclaimer Content -->
<ul class="small text-muted mb-3 disclaimer-list ">
<li>
Submission of this application shall be treated as a <strong>request only</strong>
and shall not be considered as confirmation of booking.
</li>
<li>
The preferred visit date indicated is <strong>subject to availability</strong> and
verification by the Competent Authority.
</li>
<li>
In the event of non-availability of the preferred date, the Competent Authority
reserves the right to allot an <strong>alternate visit date</strong>.
</li>
<li>
The final visit date shall be communicated to the applicant upon approval.
</li>
<li>
The booking shall be deemed confirmed only upon
<strong>administrative approval and successful payment confirmation</strong>,
wherever applicable.
</li>
<li>
Payment shall be made within <strong>24 hours</strong> from the date and time of
approval, failing which the request shall be liable for
<strong>automatic cancellation</strong> without further notice.
</li>
</ul>
<hr>
<!-- Terms and Conditions Checkbox -->
<div class="form-check mt-4 text-center">
<input class="form-check-input" type="checkbox" id="termsCheck">
<label class="form-check-label" for="termsCheck">
I have read the above Disclaimer.
<!-- <a href="#" data-bs-toggle="modal" data-bs-target="#termsModal">
terms and conditions
</a>. -->
</label>
</div>
</div>
</div>
<div class="text-center mt-4">
<button type="button" class="btn btn-success" id="submitBtn" onclick="saveBulkBooking()">Submit</button>
<button type="button" class="btn btn-secondary" onclick="goBack()">Back</button>
</div>
<br>
</div>
</main>
<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">Loading...</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://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Flatpickr CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<!-- Flatpickr JS -->
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script>
$(document).ready(function () {
$.ajax({
url: "/victoriapublichall/bookingapi/category",
type: "GET",
success: function (data) {
const categorySelect = $("#category");
categorySelect.empty();
categorySelect.append('<option value="">-- Select Category --</option>');
data.forEach(row => {
categorySelect.append(
`<option value="${row.id}">${row.category}</option>`
);
});
},
error: function () {
alert("Unable to load categories");
}
});
});
$("#category").on("change", function () {
const selectedVal = $(this).val();
const selectedText = $("#category option:selected").text().toLowerCase();
const isGovtSchool = selectedVal === "1";
// Reset counts & set amounts correctly
userTypes.forEach(u => {
u.count = 0;
u.amount = isGovtSchool ? 0 : u.originalAmount;
});
renderUserTypes();
// Hide / show total amount section
if (isGovtSchool) {
$("#totalAmount").closest(".d-flex").hide();
} else {
$("#totalAmount").closest(".d-flex").show();
}
// Hide all cards first
// $("#govtschoolCard").addClass("d-none");
$("#schoolCollegeCard").addClass("d-none");
$("#organizationCard").addClass("d-none");
// Hide visitor details initially
$("#visitorDetailsCard").addClass("d-none");
// If category is selected
if (selectedVal) {
// Show visitor details (common for all)
$("#visitorDetailsCard").removeClass("d-none");
// School / College
if (
selectedText.includes("school") ||
selectedText.includes("college")
) {
$("#schoolCollegeCard").removeClass("d-none");
}
// Organization / Association / Tourism
else if (
selectedText.includes("organization") ||
selectedText.includes("association") ||
selectedText.includes("tourism")
) {
$("#organizationCard").removeClass("d-none");
}
}
});
document.addEventListener("DOMContentLoaded", function () {
const phoneInput = document.getElementById("userinput");
const storedMobile = sessionStorage.getItem("bulkMobile");
if (phoneInput && storedMobile) {
phoneInput.value = storedMobile;
phoneInput.readOnly = true; // enforce readonly
phoneInput.classList.add("readonly"); // optional styling
}
});
document.addEventListener("DOMContentLoaded", function () {
const fp = flatpickr("#preferdate", {
dateFormat: "Y-m-d", // backend format
altInput: true,
altFormat: "d-m-Y",
minDate: new Date().fp_incr(10),
disable: [
function (date) {
return date.getDay() === 2; // Tuesday
}
],
disableMobile: true
});
// Open calendar when icon is clicked
document.querySelector(".input-group-text").addEventListener("click", function () {
fp.open();
});
});
/*document.addEventListener("DOMContentLoaded", function () {
const dateInput = document.getElementById("preferdate");
const today = new Date();
today.setDate(today.getDate() + 10);
const yyyy = today.getFullYear();
const mm = String(today.getMonth() + 1).padStart(2, '0');
const dd = String(today.getDate()).padStart(2, '0');
dateInput.min = `${yyyy}-${mm}-${dd}`;
dateInput.addEventListener("keydown", function (e) {
e.preventDefault();
});
});*/
// visitor category and calculate amount
let userTypes = [];
$(document).ready(function () {
$.ajax({
url: "/victoriapublichall/bookingapi/getamountbyusertype",
type: "GET",
success: function (data) {
userTypes = data.map(row => ({
id: row.id,
type: row.user_type,
amount: row.amount,
originalAmount: row.amount,
count: 0
}));
renderUserTypes();
},
error: function () {
alert("Unable to load user types");
}
});
});
function renderUserTypes() {
const container = $("#userTypeContainer");
container.empty();
const isGovtSchool = $("#category").val() === "1";
userTypes.forEach((u, index) => {
container.append(`
<div class="row align-items-center mb-2">
<div class="col-md-${isGovtSchool ? 6 : 4}">
<strong>${u.type}</strong>
${isGovtSchool ? "" : `<span class="text-muted ms-1">(₹${u.amount})</span>`}
</div>
<!-- Count input -->
<div class="col-md-${isGovtSchool ? 6 : 4}">
<input type="text"
class="form-control"
maxlength="3"
inputmode="numeric"
value="${u.count}"
oninput="
this.value=this.value.replace(/[^0-9]/g,'').slice(0,3);
updateCount(${index}, this.value)
">
</div>
<!-- Amount column (hidden for Govt School) -->
${isGovtSchool ? "" : `
<div class="col-md-4 text-end">
₹<span id="amount-${index}">${u.count * u.amount}</span>
</div>
`}
</div>
`);
});
updateTotals();
}
function updateCount(index, value) {
let newCount = parseInt(value, 10);
if (isNaN(newCount) || newCount < 0) newCount = 0;
// Calculate total EXCLUDING current index
let totalWithoutCurrent = 0;
userTypes.forEach((u, i) => {
if (i !== index) {
totalWithoutCurrent += u.count;
}
});
// HARD LIMIT CHECK
if (totalWithoutCurrent + newCount > 480) {
Swal.fire(
"Limit Exceeded",
"Total visitor count cannot exceed 480.",
"warning"
);
// Reset only this input
renderUserTypes();
return;
}
// Safe to update
userTypes[index].count = newCount;
// Update row amount safely
const amountEl = document.getElementById(`amount-${index}`);
if (amountEl) {
amountEl.textContent = newCount * userTypes[index].amount;
}
updateTotals();
}
/* Update Totals */
function updateTotals() {
let totalPeople = 0;
let totalAmount = 0;
userTypes.forEach(u => {
totalPeople += u.count;
totalAmount += u.count * u.amount;
});
$("#totalPeople").text(totalPeople);
$("#totalAmount").text("₹" + totalAmount);
}
$(document).ready(function () {
$.ajax({
url: "/victoriapublichall/bookingapi/getidproofs",
type: "GET",
success: function (data) {
$(".idProofSelect").each(function () {
const select = $(this);
select.empty();
select.append('<option value="">-- Select ID Proof --</option>');
data.forEach(row => {
select.append(
`<option value="${row.id}">${row.id_name}</option>`
);
});
});
}
});
});
$(document).on("change", ".idProofSelect", function () {
const selectedText = $(this).find("option:selected").text().toLowerCase();
const input = $(this).closest(".row").find(".idProofNumber");
input.val("");
input.prop("disabled", true);
input.removeAttr("maxlength");
input.off("input");
if (!selectedText || selectedText.includes("select")) {
input.attr("placeholder", "Select ID Proof first");
return;
}
input.prop("disabled", false);
if (selectedText.includes("aadhar")) {
input.attr("placeholder", "Enter 12-digit Aadhaar Number");
input.attr("maxlength", "12");
input.on("input", function () {
this.value = this.value.replace(/[^0-9]/g, "");
});
}
else if (selectedText.includes("passport")) {
input.attr("placeholder", "Enter Passport Number");
input.attr("maxlength", "9");
input.on("input", function () {
this.value = this.value.replace(/[^a-zA-Z0-9]/g, "").toUpperCase();
});
}
else {
input.attr("placeholder", "Enter ID Proof Number");
}
});
function validateBulkBookingForm() {
// Name
if (!$("#name").val().trim()) {
Swal.fire("Validation Error", "Please enter Name", "warning");
return false;
}
// Mobile / Email
if (!$("#userinput").val().trim()) {
Swal.fire("Validation Error", "Please enter Mobile Number or Email", "warning");
return false;
}
// Category
if (!$("#category").val()) {
Swal.fire("Validation Error", "Please select Category", "warning");
return false;
}
// Preferred Date
if (!$("#preferdate").val()) {
Swal.fire("Validation Error", "Please select Preferred Date", "warning");
return false;
}
// Visitor Count
let totalPeople = parseInt($("#totalPeople").text(), 10);
if (!totalPeople || totalPeople <= 0) {
Swal.fire("Validation Error", "Please enter visitor count", "warning");
return false;
}
if ($("#schoolCollegeCard").is(":visible")) {
if (!$("#privateInstitutionName").val().trim()) {
Swal.fire("Validation Error", "Please enter School / College Name", "warning");
return false;
}
const idTypeText = $("#schoolCollegeCard .idProofSelect option:selected")
.text().toLowerCase();
const idNumber = $("#schoolCollegeCard .idProofNumber").val().trim();
if (!idTypeText || idTypeText.includes("select")) {
Swal.fire("Validation Error", "Please select ID Proof", "warning");
return false;
}
if (!idNumber) {
Swal.fire("Validation Error", "Please enter ID Proof Number", "warning");
return false;
}
// Aadhaar validation
if (idTypeText.includes("aadhar") || idTypeText.includes("aadhaar")) {
if (!/^[0-9]{12}$/.test(idNumber)) {
Swal.fire(
"Validation Error",
"Aadhaar number must be exactly 12 digits",
"warning"
);
return false;
}
}
// Passport validation (Indian)
if (idTypeText.includes("passport")) {
if (!/^[A-Z][0-9]{7}$/.test(idNumber)) {
Swal.fire(
"Validation Error",
"Passport number must be 1 uppercase letter followed by 7 digits ",
"warning"
);
return false;
}
}
}
if ($("#organizationCard").is(":visible")) {
if (!$("#orgName").val().trim()) {
Swal.fire("Validation Error", "Please enter Organization Name", "warning");
return false;
}
const idTypeText = $("#organizationCard .idProofSelect option:selected")
.text().toLowerCase();
const idNumber = $("#organizationCard .idProofNumber").val().trim();
if (!idTypeText || idTypeText.includes("select")) {
Swal.fire("Validation Error", "Please select ID Proof", "warning");
return false;
}
if (!idNumber) {
Swal.fire("Validation Error", "Please enter ID Proof Number", "warning");
return false;
}
// Aadhaar
if (idTypeText.includes("aadhar") || idTypeText.includes("aadhaar")) {
if (!/^[0-9]{12}$/.test(idNumber)) {
Swal.fire(
"Validation Error",
"Aadhaar number must be exactly 12 digits",
"warning"
);
return false;
}
}
// Passport
if (idTypeText.includes("passport")) {
if (!/^[A-Z][0-9]{7}$/.test(idNumber)) {
Swal.fire(
"Validation Error",
"Passport number must be 1 uppercase letter followed by 7 digits",
"warning"
);
return false;
}
}
}
return true;
}
function saveBulkBooking() {
let totalPeople = userTypes.reduce((sum, u) => sum + u.count, 0);
if (totalPeople <= 10) {
Swal.fire(
"Minimum Limit Required",
"Total number of visitors must be more than 10.",
"warning"
);
return;
}
if (totalPeople > 480) {
Swal.fire("Limit Exceeded", "Total visitor count cannot exceed 480.", "warning");
return;
}
// Terms check
if (!$("#termsCheck").is(":checked")) {
Swal.fire("Terms Required", "Please agree to the terms and conditions.", "warning");
return;
}
// Local validation
if (!validateBulkBookingForm()) return;
const userInput = $("#userinput").val().trim();
// CHECK DUPLICATE MOBILE / EMAIL
$.ajax({
url: "/victoriapublichall/bookingapi/checkBulkBookingExists",
type: "POST",
data: { userInput: userInput },
success: function (res) {
if (res.exists) {
Swal.fire(
"Booking Not Allowed",
"This Mobile Number / Email is already used for a bulk booking.",
"warning"
);
return;
}
// ONLY IF NOT EXISTS → PROCEED TO SAVE
submitBulkBooking();
}
});
}
function submitBulkBooking() {
let idType = null;
let idProofNumber = null;
if ($("#schoolCollegeCard").is(":visible")) {
idType = $("#schoolCollegeCard .idProofSelect").val();
idProofNumber = $("#schoolCollegeCard .idProofNumber").val();
}
if ($("#organizationCard").is(":visible")) {
idType = $("#organizationCard .idProofSelect").val();
idProofNumber = $("#organizationCard .idProofNumber").val();
}
let institutionName = null;
let organizationName = null;
if ($("#schoolCollegeCard").is(":visible")) {
institutionName = $("#privateInstitutionName").val();
}
if ($("#organizationCard").is(":visible")) {
organizationName = $("#orgName").val();
}
const peopleDetails = [];
userTypes.forEach(u => {
if (u.count > 0) {
peopleDetails.push({ id: u.id, count: u.count });
}
});
const data = {
name: $("#name").val(),
userInput: $("#userinput").val(),
visitDate: $("#preferdate").val(),
categoryId: $("#category").val(),
institutionName,
organizationName,
idType,
idProofNumber,
no_of_people: $("#totalPeople").text(),
totalAmount: $("#totalAmount").text().replace("₹", ""),
peopleDetails: JSON.stringify(peopleDetails),
source: 1
};
$.ajax({
url: "/victoriapublichall/bookingapi/saveBulkRegistration",
type: "POST",
data: data,
success: function (res) {
Swal.fire({
title: "Request Submitted",
text: "Your request has been raised successfully.\nRef ID: " + res.refId,
icon: "success",
allowOutsideClick: false,
allowEscapeKey: false,
confirmButtonText: "OK"
}).then(() => {
sessionStorage.setItem("bulkMobile", $("#userinput").val());
window.location.href =
"/victoriapublichall/acknowledgement?refId=" + res.refId;
});
}
});
}
function goBack() {
window.location.href = "/victoriapublichall";
}
$(document).ready(function () {
// Always keep submit disabled on load
$("#submitBtn").prop("disabled", true);
// Enable submit only if checkbox is checked
$("#termsCheck").on("change", function () {
$("#submitBtn").prop("disabled", !this.checked);
});
});
function allowOnlyAlphabets(input) {
input.value = input.value.replace(/[^a-zA-Z\s]/g, '');
}
</script>
</body>
</html>