Skip to content

Commit fad8bad

Browse files
authored
Merge pull request #108 from SRATRC/dev
added package wise summary also along with centre wise summary in uts…
2 parents 083deff + cba3cd0 commit fad8bad

2 files changed

Lines changed: 271 additions & 21 deletions

File tree

admin/utsav/utsavBookingslist.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ <h1>Utsav Bookings <span id="utsavName"></span></h1>
5252
<button id="downloadRoomNoFormat" class="btn btn-secondary">Download RoomNo Upload Format</button>
5353
<button id="uploadRoomNoBtn" class="btn btn-primary">Upload Room No</button>
5454
<button id="downloadPackage" class="btn btn-primary">Download This Package Registrations</button>
55-
<button id="centerSummaryBtn" class="btn btn-secondary">Center-wise Summary</button>
55+
<button id="centerSummaryBtn" class="btn btn-secondary">Center-wise & Package-wise Summary</button>
5656
</div>
5757

5858
<input type="text" id="tableSearch" class="form-control search-box" placeholder="Search...">
@@ -67,7 +67,10 @@ <h1>Utsav Bookings <span id="utsavName"></span></h1>
6767
<div id="centerSummaryModal" class="modal" style="display:none;">
6868
<div class="modal-content">
6969
<span class="close">&times;</span>
70-
<h3>Center-wise Summary</h3>
70+
<h3>Center-wise & Package-wise Summary</h3>
71+
<p style="font-size:13px;color:#666;margin-bottom:10px;">
72+
Click on a center row to view package-wise breakup
73+
</p>
7174
<div id="centerSummaryTableContainer"></div>
7275
</div>
7376
</div>
@@ -124,7 +127,12 @@ <h3>Center-wise Summary</h3>
124127
.modal-content span {position:absolute; top:10px; right:20px; font-size:24px; cursor:pointer;}
125128
#centerSummaryTableContainer table {width:100%; border-collapse:collapse;}
126129
#centerSummaryTableContainer th, #centerSummaryTableContainer td {border:1px solid #ccc; padding:8px; text-align:center;}
127-
#centerSummaryTableContainer th {background-color:#f2f2f2;}
130+
#centerSummaryTableContainer th {
131+
background-color: #1f3c60; /* same as page headers */
132+
color: #ffffff;
133+
font-weight: bold;
134+
}
135+
128136
</style>
129137
</body>
130138
</html>

admin/utsav/utsavBookingslist.js

Lines changed: 260 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -252,32 +252,274 @@ function triggerExcelDownload(data, fileName, sheetName) {
252252

253253
// Move this above the DOMContentLoaded or make sure it's declared as a function
254254
function openCenterSummaryModal(summary){
255-
const modal=document.getElementById('centerSummaryModal');
256-
const container=document.getElementById('centerSummaryTableContainer');
257-
container.innerHTML='';
258-
const table=document.createElement('table');
259-
table.innerHTML=`<thead><tr><th>Center</th><th>Total</th><th>Males</th><th>Females</th></tr></thead>`;
260-
const tbody=document.createElement('tbody');
261-
const sortedSummary = Object.entries(summary).sort((a, b) => a[0].localeCompare(b[0]));
255+
const modal = document.getElementById('centerSummaryModal');
256+
const container = document.getElementById('centerSummaryTableContainer');
257+
container.innerHTML = '';
258+
259+
const table = document.createElement('table');
260+
table.innerHTML = `
261+
<thead>
262+
<tr>
263+
<th>Center</th>
264+
<th>Package</th>
265+
<th>Total</th>
266+
<th>Males</th>
267+
<th>Females</th>
268+
</tr>
269+
</thead>
270+
`;
271+
272+
const tbody = document.createElement('tbody');
273+
274+
let grandTotal = 0, grandM = 0, grandF = 0;
275+
const packageTotals = {}; // totals across all centers
276+
const packageCenterMap = {}; // package → center breakup
277+
278+
const sortedCenters = Object.keys(summary).sort();
279+
280+
// ================= CENTER → PACKAGE =================
281+
sortedCenters.forEach(center => {
282+
const centerData = summary[center];
283+
const centerRowId = `center-${center.replace(/\s+/g,'_')}`;
284+
285+
grandTotal += centerData.total;
286+
grandM += centerData.M;
287+
grandF += centerData.F;
288+
289+
tbody.innerHTML += `
290+
<tr style="cursor:pointer;font-weight:bold;background:#f9f9f9;"
291+
onclick="toggleRows('${centerRowId}')">
292+
<td>${center}</td>
293+
<td>All Packages</td>
294+
<td>${centerData.total}</td>
295+
<td>${centerData.M}</td>
296+
<td>${centerData.F}</td>
297+
</tr>
298+
`;
299+
300+
Object.entries(centerData.packages)
301+
.sort((a,b)=>a[0].localeCompare(b[0]))
302+
.forEach(([pkg, pkgData]) => {
303+
304+
// collect package totals
305+
if(!packageTotals[pkg]){
306+
packageTotals[pkg] = { total:0, M:0, F:0 };
307+
packageCenterMap[pkg] = {};
308+
}
309+
310+
packageTotals[pkg].total += pkgData.total;
311+
packageTotals[pkg].M += pkgData.M;
312+
packageTotals[pkg].F += pkgData.F;
313+
314+
packageCenterMap[pkg][center] = pkgData;
315+
316+
tbody.innerHTML += `
317+
<tr data-parent="${centerRowId}" style="display:none;">
318+
<td></td>
319+
<td>${pkg}</td>
320+
<td>${pkgData.total}</td>
321+
<td>${pkgData.M}</td>
322+
<td>${pkgData.F}</td>
323+
</tr>
324+
`;
325+
});
326+
});
262327

263-
const rowsHtml = sortedSummary.map(([center, data]) => {
264-
return `<tr><td>${center}</td><td>${data.total}</td><td>${data.M}</td><td>${data.F}</td></tr>`;
265-
}).join('');
328+
// ================= GRAND TOTAL =================
329+
tbody.innerHTML += `
330+
<tr style="font-weight:bold;background:#eaeaea;">
331+
<td>GRAND TOTAL</td>
332+
<td>All Packages</td>
333+
<td>${grandTotal}</td>
334+
<td>${grandM}</td>
335+
<td>${grandF}</td>
336+
</tr>
337+
`;
338+
339+
// ================= PACKAGE → CENTER =================
340+
Object.entries(packageTotals)
341+
.sort((a,b)=>a[0].localeCompare(b[0]))
342+
.forEach(([pkg, data]) => {
343+
344+
const pkgRowId = `pkg-${pkg.replace(/\s+/g,'_')}`;
345+
346+
// package total row (CLICKABLE)
347+
tbody.innerHTML += `
348+
<tr style="cursor:pointer;font-weight:bold;background:#f4f6ff;"
349+
onclick="toggleRows('${pkgRowId}')">
350+
<td>All Centers</td>
351+
<td>${pkg}</td>
352+
<td>${data.total}</td>
353+
<td>${data.M}</td>
354+
<td>${data.F}</td>
355+
</tr>
356+
`;
357+
358+
// center rows under package
359+
Object.entries(packageCenterMap[pkg])
360+
.sort((a,b)=>a[0].localeCompare(b[0]))
361+
.forEach(([center, cData]) => {
362+
tbody.innerHTML += `
363+
<tr data-parent="${pkgRowId}" style="display:none;">
364+
<td>${center}</td>
365+
<td></td>
366+
<td>${cData.total}</td>
367+
<td>${cData.M}</td>
368+
<td>${cData.F}</td>
369+
</tr>
370+
`;
371+
});
372+
373+
});
374+
375+
table.appendChild(tbody);
376+
container.appendChild(table);
377+
// Add Download Excel button (once)
378+
if (!document.getElementById('downloadCenterSummaryExcel')) {
379+
const btn = document.createElement('button');
380+
btn.id = 'downloadCenterSummaryExcel';
381+
btn.className = 'btn btn-primary';
382+
btn.style.marginBottom = '10px';
383+
btn.innerText = 'Download Summary Excel';
384+
385+
btn.onclick = () => downloadCenterSummaryExcel(summary);
386+
387+
container.prepend(btn);
388+
}
389+
390+
modal.style.display = 'block';
266391

267-
tbody.innerHTML = rowsHtml;
268-
table.appendChild(tbody); container.appendChild(table); modal.style.display='block';
269-
document.querySelector('#centerSummaryModal .close').onclick=()=>modal.style.display='none';
270-
window.onclick=e=>{if(e.target===modal) modal.style.display='none';};
392+
393+
document.querySelector('#centerSummaryModal .close').onclick = () =>
394+
modal.style.display = 'none';
395+
396+
window.onclick = e => {
397+
if(e.target === modal) modal.style.display = 'none';
398+
};
271399
}
272400

273401
function getCenterWiseSummary(bookings){
274402
const map = {};
403+
275404
bookings.forEach(b => {
276405
const center = b.center || 'Unknown';
277-
if(!map[center]) map[center] = { total: 0, M: 0, F: 0 };
278-
map[center].total += 1;
279-
if(b.gender === 'M') map[center].M += 1;
280-
if(b.gender === 'F') map[center].F += 1;
406+
const pkg = b.package_name || 'Unknown Package';
407+
const gender = b.gender;
408+
409+
if(!map[center]){
410+
map[center] = {
411+
total: 0,
412+
M: 0,
413+
F: 0,
414+
packages: {}
415+
};
416+
}
417+
418+
map[center].total++;
419+
if(gender === 'M') map[center].M++;
420+
if(gender === 'F') map[center].F++;
421+
422+
if(!map[center].packages[pkg]){
423+
map[center].packages[pkg] = { total: 0, M: 0, F: 0 };
424+
}
425+
426+
map[center].packages[pkg].total++;
427+
if(gender === 'M') map[center].packages[pkg].M++;
428+
if(gender === 'F') map[center].packages[pkg].F++;
281429
});
430+
282431
return map;
283432
}
433+
434+
435+
function togglePackageRows(className){
436+
document.querySelectorAll(`.${className}`).forEach(row => {
437+
row.style.display = row.style.display === 'none' ? 'table-row' : 'none';
438+
});
439+
}
440+
441+
function toggleRows(groupKey){
442+
const rows = document.querySelectorAll(`tr[data-parent="${groupKey}"]`);
443+
const shouldShow = [...rows].some(r => r.style.display === 'none');
444+
445+
rows.forEach(row => {
446+
row.style.display = shouldShow ? 'table-row' : 'none';
447+
});
448+
}
449+
450+
451+
function downloadCenterSummaryExcel(summary){
452+
const wb = XLSX.utils.book_new();
453+
454+
/* =======================
455+
SHEET 1: CENTER SUMMARY
456+
======================= */
457+
const centerRows = [];
458+
centerRows.push(['Center', 'Package', 'Total', 'Males', 'Females']);
459+
460+
let grandTotal = 0, grandM = 0, grandF = 0;
461+
const packageTotals = {};
462+
const packageCenterMap = {};
463+
464+
Object.keys(summary).sort().forEach(center => {
465+
const c = summary[center];
466+
467+
centerRows.push([center, 'All Packages', c.total, c.M, c.F]);
468+
469+
grandTotal += c.total;
470+
grandM += c.M;
471+
grandF += c.F;
472+
473+
Object.entries(c.packages).forEach(([pkg, p]) => {
474+
centerRows.push(['', pkg, p.total, p.M, p.F]);
475+
476+
if(!packageTotals[pkg]){
477+
packageTotals[pkg] = { total:0, M:0, F:0 };
478+
packageCenterMap[pkg] = {};
479+
}
480+
481+
packageTotals[pkg].total += p.total;
482+
packageTotals[pkg].M += p.M;
483+
packageTotals[pkg].F += p.F;
484+
485+
packageCenterMap[pkg][center] = p;
486+
});
487+
});
488+
489+
centerRows.push([]);
490+
centerRows.push(['GRAND TOTAL', 'All Packages', grandTotal, grandM, grandF]);
491+
492+
Object.entries(packageTotals).forEach(([pkg, d]) => {
493+
centerRows.push(['All Centers', pkg, d.total, d.M, d.F]);
494+
});
495+
496+
const ws1 = XLSX.utils.aoa_to_sheet(centerRows);
497+
XLSX.utils.book_append_sheet(wb, ws1, 'Center Summary');
498+
499+
/* =========================
500+
SHEET 2: PACKAGE BREAKDOWN
501+
========================= */
502+
const pkgRows = [];
503+
504+
Object.keys(packageCenterMap).sort().forEach(pkg => {
505+
pkgRows.push([pkg]); // Package title row
506+
pkgRows.push(['Center', 'Total', 'Males', 'Females']);
507+
508+
Object.keys(packageCenterMap[pkg])
509+
.sort()
510+
.forEach(center => {
511+
const d = packageCenterMap[pkg][center];
512+
pkgRows.push([center, d.total, d.M, d.F]);
513+
});
514+
515+
pkgRows.push([]); // spacing between packages
516+
});
517+
518+
const ws2 = XLSX.utils.aoa_to_sheet(pkgRows);
519+
XLSX.utils.book_append_sheet(wb, ws2, 'Package Breakdown');
520+
521+
/* ===================
522+
DOWNLOAD FILE
523+
=================== */
524+
XLSX.writeFile(wb, 'center_package_summary.xlsx');
525+
}

0 commit comments

Comments
 (0)