Skip to content

Commit f2f99a0

Browse files
authored
Merge pull request #102 from SRATRC/dev
Dev
2 parents 4f4b4c1 + 52f5585 commit f2f99a0

7 files changed

Lines changed: 297 additions & 29 deletions

File tree

admin/food/issuePlate.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@
3838
.alert-danger {
3939
color: red;
4040
}
41+
.alert-warning {
42+
/* background-color: #fff3cd; */
43+
color: #856404;
44+
/* border: 2px solid #ffeeba; */
45+
}
46+
4147
</style>
4248
</head>
4349

admin/food/issuePlate.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function showAlert(element, message, type) {
1717
function resetAlert() {
1818
const alertBox = document.getElementById('alert');
1919
const formWrapper = document.getElementById('formWrapper');
20+
2021
alertBox.style.display = 'none';
2122
alertBox.textContent = '';
2223
alertBox.className = 'big-alert';
@@ -56,13 +57,29 @@ async function foodCheckin(cardno) {
5657
showAlert(alertBox, `Plate issued for ${name}`, 'success');
5758
} else {
5859
playErrorSound();
59-
showAlert(alertBox, data.message || 'Error issuing plate', 'danger');
60+
61+
// 🔥 DIFFERENTIATE ERROR TYPE
62+
let alertType = 'danger'; // default = red
63+
64+
if (data.message) {
65+
const msg = data.message.toLowerCase();
66+
67+
if (msg.includes('already issued')) {
68+
alertType = 'warning'; // 🟤 brown
69+
} else if (msg.includes('invalid meal time')) {
70+
alertType = 'info'; // 🔵 blue
71+
} else if (msg.includes('booking not found')) {
72+
alertType = 'danger'; // 🔴 red
73+
}
74+
}
75+
76+
showAlert(alertBox, data.message || 'Error issuing plate', alertType);
6077
}
6178

6279
setTimeout(() => {
63-
cardnoInput.value = ''; // Clear input
64-
resetAlert(); // Show form again
65-
cardnoInput.focus(); // Set focus back to input
80+
cardnoInput.value = '';
81+
resetAlert();
82+
cardnoInput.focus();
6683
}, 400);
6784

6885
} catch (error) {
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6+
<title>Plate Issuance Scanner</title>
7+
8+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
9+
<script src="../../style/js/plugin.js"></script>
10+
<script src="../../style/js/bootstrap-datepicker.min.js"></script>
11+
<script src="../../style/js/clockpicker.js"></script>
12+
<script src="../../style/js/custom.js"></script>
13+
<script src="../../style/js/config.js"></script>
14+
<script src="https://unpkg.com/html5-qrcode"></script>
15+
16+
<link rel="stylesheet" href="../../style/css/styles.css">
17+
18+
<style>
19+
#qr-scanner-section {
20+
text-align: center;
21+
margin-bottom: 20px;
22+
}
23+
24+
#qr-status {
25+
margin: 10px 0;
26+
font-weight: bold;
27+
min-height: 25px;
28+
}
29+
30+
.success-status {
31+
color: green;
32+
}
33+
34+
.error-status {
35+
color: red;
36+
}
37+
38+
.scanning-status {
39+
color: #666;
40+
}
41+
42+
#scan-again-btn {
43+
margin-top: 10px;
44+
}
45+
</style>
46+
</head>
47+
<body>
48+
<div class="header">
49+
<div class="container">
50+
<div class="logout">
51+
<a href="javascript:void(0);" onclick="history.back()">Back</a>
52+
&nbsp; | &nbsp;
53+
<a href="javascript:void(0);" onclick="goToHome()">Home</a>
54+
&nbsp; | &nbsp;
55+
<a href="javascript:void(0);" onclick="logout()">Logout</a>
56+
</div>
57+
</div>
58+
</div>
59+
60+
<div class="middlecontent">
61+
<div class="container">
62+
<div class="whitesec">
63+
<div class="inner-padding">
64+
<div class="frm-head">
65+
<h4><b><u>Plate Issuance</u></b></h4>
66+
</div>
67+
68+
<div class="form">
69+
<div id="alert" class="alert" role="alert" style="display: none;"></div>
70+
71+
<div id="qr-scanner-section">
72+
<div id="reader" style="width: 100%; max-width: 400px; margin: auto;"></div>
73+
<div id="qr-status" class="scanning-status">Initializing scanner...</div>
74+
<button type="button" id="scan-again-btn" class="btn btn-small" style="display: none;">Scan Another</button>
75+
</div>
76+
</div>
77+
</div>
78+
</div>
79+
</div>
80+
</div>
81+
82+
<script src="./issuePlateScanUtsav.js"></script>
83+
</body>
84+
</html>

admin/utsav/issuePlateScanUtsav.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
document.addEventListener('DOMContentLoaded', function () {
2+
const qrStatus = document.getElementById('qr-status');
3+
const scanAgainBtn = document.getElementById('scan-again-btn');
4+
const alertDiv = document.getElementById('alert');
5+
6+
let html5QrCode = null;
7+
let isScanning = false;
8+
9+
startQRScanner();
10+
scanAgainBtn.addEventListener('click', startQRScanner);
11+
12+
function startQRScanner() {
13+
if (isScanning) return;
14+
15+
scanAgainBtn.style.display = 'none';
16+
qrStatus.className = 'scanning-status';
17+
qrStatus.innerText = 'Initializing scanner...';
18+
19+
if (!html5QrCode) {
20+
html5QrCode = new Html5Qrcode('reader');
21+
}
22+
23+
html5QrCode
24+
.start(
25+
{ facingMode: 'environment' },
26+
{ fps: 10, qrbox: { width: 250, height: 250 }, aspectRatio: 1.0 },
27+
onScanSuccess,
28+
onScanFailure
29+
)
30+
.then(() => {
31+
isScanning = true;
32+
qrStatus.innerText = 'Ready to scan...';
33+
})
34+
.catch((err) => {
35+
qrStatus.className = 'error-status';
36+
qrStatus.innerText = '❌ Scanner initialization failed';
37+
console.error(err);
38+
});
39+
}
40+
41+
function stopQRScanner() {
42+
if (html5QrCode && isScanning) {
43+
html5QrCode.stop().then(() => {
44+
isScanning = false;
45+
});
46+
}
47+
}
48+
49+
function onScanSuccess(decodedText) {
50+
stopQRScanner();
51+
52+
const cardno = processScannedText(decodedText);
53+
qrStatus.innerText = `✅ QR Scanned: ${cardno} (issuing plate...)`;
54+
scanAgainBtn.style.display = 'inline-block';
55+
56+
sendIssuePlateRequest(cardno);
57+
}
58+
59+
function onScanFailure() {
60+
if (Math.random() < 0.1) {
61+
qrStatus.innerText = 'Scanning...';
62+
}
63+
}
64+
65+
function processScannedText(text) {
66+
let cardno = text.trim();
67+
if (cardno.toLowerCase().startsWith('cardnumber=')) {
68+
cardno = cardno.split('=')[1].trim();
69+
}
70+
return cardno;
71+
}
72+
73+
function sendIssuePlateRequest(cardno) {
74+
resetAlert();
75+
showInfoMessage('Issuing plate...');
76+
77+
fetch(`${CONFIG.basePath}/utsav/issue/${cardno}`, {
78+
method: 'POST',
79+
headers: { 'Content-Type': 'application/json' },
80+
// body: JSON.stringify({ cardno })
81+
})
82+
.then(async (response) => {
83+
const data = await response.json();
84+
if (!response.ok) throw data;
85+
return data;
86+
})
87+
.then((data) => {
88+
qrStatus.className = 'success-status';
89+
qrStatus.innerText = `✅ Plate issued to ${data.issuedto}`;
90+
showSuccessMessage(data.message);
91+
})
92+
.catch((err) => {
93+
const message = err.message || 'Failed to issue plate';
94+
qrStatus.className = 'error-status';
95+
qrStatus.innerText = '❌ ' + message;
96+
showErrorMessage(message);
97+
});
98+
}
99+
100+
function showMessage(message, type) {
101+
alertDiv.className = `alert alert-${type}`;
102+
alertDiv.textContent = message;
103+
alertDiv.style.display = 'block';
104+
105+
if (type === 'success') {
106+
setTimeout(resetAlert, 4000);
107+
}
108+
}
109+
110+
function showSuccessMessage(message) {
111+
showMessage(message, 'success');
112+
}
113+
114+
function showErrorMessage(message) {
115+
showMessage(message, 'danger');
116+
}
117+
118+
function showInfoMessage(message) {
119+
showMessage(message, 'info');
120+
}
121+
122+
function resetAlert() {
123+
alertDiv.style.display = 'none';
124+
alertDiv.className = 'alert';
125+
alertDiv.textContent = '';
126+
}
127+
128+
window.addEventListener('beforeunload', stopQRScanner);
129+
});

admin/utsav/roomOccupancy.js

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ function createRoomBookingRow(booking, index) {
1818
row.innerHTML = `
1919
<td>${index + 1}</td>
2020
<td>${booking.bookingid}</td>
21-
<td>${booking.CardDb.issuedto}</td>
22-
<td>${booking.CardDb.mobno}</td>
23-
<td>${booking.CardDb.center}</td>
21+
<td>${booking.CardDb?.issuedto || ""}</td>
22+
<td>${booking.CardDb?.mobno || ""}</td>
23+
<td>${booking.CardDb?.center || ""}</td>
2424
<td>${booking.roomno || "Not Assigned"}</td>
25-
<td>${booking.roomtype}</td>
25+
<td>${booking.roomtype || "NA"}</td>
2626
<td>${formatDate(booking.checkin)}</td>
2727
<td>${formatDate(booking.checkout)}</td>
28-
<td>${booking.nights}</td>
28+
<td>${booking.nights ?? 0}</td>
2929
<td>${booking.status}</td>
3030
<td>${booking.bookedBy || "Self"}</td>
3131
`;
@@ -44,18 +44,14 @@ async function fetchReport() {
4444
return;
4545
}
4646

47-
// Collect checkboxes
47+
// Collect checked statuses
4848
const checkedStatuses = [
4949
...document.querySelectorAll('input[name="status"]:checked')
5050
].map(cb => cb.value);
5151

5252
const searchParams = new URLSearchParams();
5353

54-
// If nothing selected → fallback to default "checkedin"
55-
// If all statuses checked → send them all
56-
checkedStatuses.forEach(s => searchParams.append("statuses", s));
57-
58-
54+
checkedStatuses.forEach(s => searchParams.append("statuses", s));
5955
searchParams.append("utsavid", utsav_id);
6056
searchParams.append("type", reportType);
6157

@@ -103,32 +99,58 @@ checkedStatuses.forEach(s => searchParams.append("statuses", s));
10399
----------------------------------------------------*/
104100
document.addEventListener("DOMContentLoaded", async function () {
105101

106-
// Check ALL statuses by default
107-
document.querySelectorAll('input[name="status"]').forEach(cb => cb.checked = true);
102+
// Check ALL statuses by default
103+
document
104+
.querySelectorAll('input[name="status"]')
105+
.forEach(cb => cb.checked = true);
108106

109-
// 3. Read utsav_id
107+
// Read utsav_id
110108
const params = new URLSearchParams(window.location.search);
111-
let utsav_id = params.get("utsav_id") || sessionStorage.getItem("current_utsav_id");
109+
let utsav_id =
110+
params.get("utsav_id") ||
111+
sessionStorage.getItem("current_utsav_id");
112112

113113
if (!utsav_id) {
114114
showErrorMessage("utsav_id missing in URL or session.");
115115
return;
116116
}
117117

118118
sessionStorage.setItem("current_utsav_id", utsav_id);
119+
119120
const hiddenField = document.getElementById("utsav_id");
120121
if (hiddenField) hiddenField.value = utsav_id;
121122

122-
// 4. Load initial report → sends only "checkedin"
123+
// Initial fetch
123124
await fetchReport();
124125

125-
// 5. Submit button triggers fetchReport()
126-
document.getElementById("reportForm").addEventListener("submit", function (event) {
127-
event.preventDefault();
128-
fetchReport();
129-
});
126+
// Submit button
127+
document
128+
.getElementById("reportForm")
129+
.addEventListener("submit", function (event) {
130+
event.preventDefault();
131+
fetchReport();
132+
});
130133
});
131134

135+
/* ---------------------------------------------------
136+
FLATTEN DATA FOR EXCEL EXPORT (🔥 FIX)
137+
----------------------------------------------------*/
138+
function getRoomOccupancyExportData() {
139+
return roomreports.map(b => ({
140+
bookingid: b.bookingid,
141+
guest_name: b.CardDb?.issuedto || "",
142+
mobile_no: b.CardDb?.mobno || "",
143+
center: b.CardDb?.center || "",
144+
roomno: b.roomno || "NA",
145+
roomtype: b.roomtype || "NA",
146+
checkin: formatDate(b.checkin),
147+
checkout: formatDate(b.checkout),
148+
nights: b.nights ?? 0,
149+
status: b.status,
150+
booked_by: b.bookedBy || "Self"
151+
}));
152+
}
153+
132154
/* ---------------------------------------------------
133155
DOWNLOAD EXCEL BUTTON SETUP
134156
----------------------------------------------------*/
@@ -137,7 +159,7 @@ const setupDownloadButton = () => {
137159

138160
renderDownloadButton({
139161
selector: "#downloadBtnContainer",
140-
getData: () => roomreports,
162+
getData: () => getRoomOccupancyExportData(), // ✅ FIXED
141163
fileName: "room_occupancy_report.xlsx",
142164
sheetName: "Room Occupancy"
143165
});

admin/utsav/utsavReport.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ <h1>Utsav Report</h1>
8080
<th>Volunteer List</th>
8181
<th>Status</th>
8282
<th>Action</th>
83-
<th>Scanner</th>
83+
<th>Checkin Scanner</th>
84+
<th>Food Scanner</th>
8485
<th>Register for Mumukshu</th>
8586
<th>Room Occupancy</th>
8687
</tr>

0 commit comments

Comments
 (0)