diff --git a/admin/card/index.js b/admin/card/index.js index adcfdb5..2f8d121 100644 --- a/admin/card/index.js +++ b/admin/card/index.js @@ -20,9 +20,7 @@ document.addEventListener('DOMContentLoaded', () => { try { const url = query - ? `${CONFIG.basePath}/card/search/${encodeURIComponent( - query - )}` + ? `${CONFIG.basePath}/card/search/${encodeURIComponent(query)}` : `${CONFIG.basePath}/card/getAll`; const response = await fetch(url, options); @@ -35,83 +33,112 @@ document.addEventListener('DOMContentLoaded', () => { displayData(data.data); } catch (error) { console.error('Error fetching data:', error); - dataList.innerHTML = 'No results found'; + dataList.innerHTML = + 'No results found'; } }; -const displayData = (data) => { - console.log(`Displaying ${data.length} records`); - dataList.innerHTML = ''; - - if (Array.isArray(data) && data.length > 0) { - document.getElementById('data-list').style.display = 'table'; // Show the table - data.forEach((item) => { - const row = document.createElement('tr'); - - // Name - const nameCell = document.createElement('td'); - nameCell.textContent = item.issuedto; - row.appendChild(nameCell); - - // Card Number - const cardCell = document.createElement('td'); - cardCell.textContent = item.cardno; - row.appendChild(cardCell); - - // Mobile Number - const mobnoCell = document.createElement('td'); - mobnoCell.textContent = item.mobno || '-'; - row.appendChild(mobnoCell); - - // Action Cell - const actionCell = document.createElement('td'); - - // Edit Button - const editButton = document.createElement('button'); - editButton.textContent = 'Edit'; - editButton.classList.add('edit-btn'); - editButton.addEventListener('click', () => { - sessionStorage.setItem('cardno', item.cardno); // use cardno instead - window.location.href = 'updateCard.html'; + const displayData = (data) => { + console.log(`Displaying ${data.length} records`); + dataList.innerHTML = ''; + + if (Array.isArray(data) && data.length > 0) { + document.getElementById('data-list').style.display = 'table'; + + data.forEach((item) => { + const row = document.createElement('tr'); + + // Name + const nameCell = document.createElement('td'); + nameCell.textContent = item.issuedto; + row.appendChild(nameCell); + + // Card Number + const cardCell = document.createElement('td'); + cardCell.textContent = item.cardno; + row.appendChild(cardCell); + + // Mobile Number + const mobnoCell = document.createElement('td'); + mobnoCell.textContent = item.mobno || '-'; + row.appendChild(mobnoCell); + + // Action Cell + const actionCell = document.createElement('td'); + + // ================= EDIT BUTTON ================= + const editButton = document.createElement('button'); + editButton.textContent = 'Edit'; + editButton.classList.add('edit-btn'); + editButton.addEventListener('click', () => { + sessionStorage.setItem('cardno', item.cardno); + window.location.href = 'updateCard.html'; + }); + actionCell.appendChild(editButton); + + // ================= RESET PASSWORD ================= + const resetPwdButton = document.createElement('button'); + resetPwdButton.textContent = 'Reset PWD'; + resetPwdButton.classList.add('reset-btn'); + resetPwdButton.style.marginLeft = '10px'; + + resetPwdButton.addEventListener('click', async () => { + if ( + !confirm( + `Are you sure you want to reset password for ${item.issuedto}?` + ) + ) + return; + + try { + const response = await fetch( + `${CONFIG.basePath}/card/reset-pwd`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${sessionStorage.getItem('token')}` + }, + body: JSON.stringify({ cardno: item.cardno }) + } + ); + + if (!response.ok) throw new Error('Reset failed'); + + showSuccessMessage( + `Password reset to 'vitraag' for ${item.issuedto}` + ); + } catch (err) { + showErrorMessage( + `Failed to reset password: ${err.message}` + ); + } + }); + + actionCell.appendChild(resetPwdButton); + + // ================= ⭐ VIEW HISTORY ================= + const historyButton = document.createElement('button'); + historyButton.textContent = 'View History'; + historyButton.classList.add('history-btn'); + historyButton.style.marginLeft = '10px'; + + historyButton.addEventListener('click', () => { + sessionStorage.setItem('history_cardno', item.cardno); + window.location.href = 'personHistory.html'; + }); + + actionCell.appendChild(historyButton); + + row.appendChild(actionCell); + dataList.appendChild(row); }); - actionCell.appendChild(editButton); - - // Reset Password Button - const resetPwdButton = document.createElement('button'); - resetPwdButton.textContent = 'Reset PWD'; - resetPwdButton.classList.add('reset-btn'); - resetPwdButton.style.marginLeft = '10px'; - resetPwdButton.addEventListener('click', async () => { - if (!confirm(`Are you sure you want to reset password for ${item.issuedto}?`)) return; - - try { - const response = await fetch(`${CONFIG.basePath}/card/reset-pwd`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${sessionStorage.getItem('token')}`, - }, - body: JSON.stringify({ cardno: item.cardno }) - }); - - if (!response.ok) throw new Error('Reset failed'); - - showSuccessMessage(`Password reset to 'vitraag' for ${item.issuedto}`); - } catch (err) { - showErrorMessage(`Failed to reset password: ${err.message}`); - } - }); - actionCell.appendChild(resetPwdButton); - - row.appendChild(actionCell); - dataList.appendChild(row); - }); - } else { - document.getElementById('data-list').style.display = 'none'; // Hide if no results - } -}; + } else { + document.getElementById('data-list').style.display = 'none'; + } + }; - // Debounce function: waits for user to stop typing before triggering search + // ================= DEBOUNCE ================= const debounce = (callback, delay) => { return (...args) => { clearTimeout(debounceTimer); @@ -119,19 +146,19 @@ const displayData = (data) => { }; }; - // Search functionality with debounce (500ms delay) + // ================= SEARCH ================= searchInput.addEventListener( 'input', debounce(async () => { const query = searchInput.value.trim().toLowerCase(); if (query.length === 0) { - document.getElementById('data-list').style.display = 'none'; // Hide the table + document.getElementById('data-list').style.display = 'none'; return; } await fetchData(query); - }, 500) // 500ms delay before search starts + }, 500) ); }); @@ -140,9 +167,7 @@ function showSuccessMessage(message) { } function showErrorMessage(message) { - alert("Error: " + message); + alert('Error: ' + message); } -function resetAlert() { - // This could clear UI banners if used in future (currently placeholder) -} \ No newline at end of file +function resetAlert() {} \ No newline at end of file diff --git a/admin/card/personHistory.html b/admin/card/personHistory.html new file mode 100644 index 0000000..0fa1298 --- /dev/null +++ b/admin/card/personHistory.html @@ -0,0 +1,68 @@ + + + + + + + + Person History + + + + + + + + + + +
+
+
+ Back +   |   + Home +   |   + Logout +
+
+
+ +
+
+
+
+ +
+

Person Booking History

+
+ +
+ +
+

Upcoming

+
+
+ +
+

Past 30 Days

+
+
+ +
+

Open Maintenance

+
+
+ +
+

WiFi Codes

+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/admin/card/personHistory.js b/admin/card/personHistory.js new file mode 100644 index 0000000..e5df708 --- /dev/null +++ b/admin/card/personHistory.js @@ -0,0 +1,185 @@ +document.addEventListener('DOMContentLoaded', async () => { + const cardno = sessionStorage.getItem('history_cardno'); + + if (!cardno) { + alert('Card not found'); + history.back(); + return; + } + + try { + const response = await fetch( + `${CONFIG.basePath}/card/person-activity?cardno=${cardno}`, + { + headers: { + Authorization: `Bearer ${sessionStorage.getItem('token')}` + } + } + ); + + if (!response.ok) throw new Error('API failed'); + + const data = await response.json(); + + renderSummary(data.summary); + renderTimelineTable('upcoming', data.upcoming); + renderTimelineTable('past', data.past30Days); + renderMaintenance(data.maintenanceOpen); + renderWifi(data.wifiCodes); + + } catch (err) { + console.error(err); + alert('Failed to load history'); + } +}); + + +// ================= SUMMARY ================= +function renderSummary(summary) { + const box = document.getElementById('summaryBox'); + + box.innerHTML = ` +
+ Total Upcoming: ${summary.totalUpcoming}    + Past 30 Days: ${summary.totalPast}    + Open Maintenance: ${summary.openMaintenance}    + WiFi Codes: ${summary.wifiCodes} +
+ `; +} + + +// ================= TIMELINE TABLE ================= +function renderTimelineTable(elementId, list) { + const el = document.getElementById(elementId); + + if (!list || list.length === 0) { + el.innerHTML = '

No records found

'; + return; + } + + let html = ` + + + + + + + + + + `; + + list.forEach(item => { + html += ` + + + + + + `; + }); + + html += `
TypeDateStatus
${formatType(item.type)}${formatDate(item.date)}${formatStatus(item.status)}
`; + + el.innerHTML = html; +} + + +// ================= MAINTENANCE ================= +function renderMaintenance(list) { + const el = document.getElementById('maintenance'); + + if (!list || list.length === 0) { + el.innerHTML = '

No open maintenance requests

'; + return; + } + + let html = ` + + + + + + + + + + `; + + list.forEach(item => { + html += ` + + + + + + `; + }); + + html += `
DepartmentWork DetailStatus
${item.department}${item.work_detail}OPEN
`; + + el.innerHTML = html; +} + + +// ================= WIFI ================= +function renderWifi(list) { + const el = document.getElementById('wifi'); + + if (!list || list.length === 0) { + el.innerHTML = '

No WiFi codes

'; + return; + } + + let html = ` + + + + + + + + + + `; + + list.forEach(item => { + html += ` + + + + + + `; + }); + + html += `
UsernameSSIDStatus
${item.username}${item.ssid || '-'}${item.status}
`; + + el.innerHTML = html; +} + + +// ================= HELPERS ================= +function formatType(type) { + if (!type) return '-'; + return type.replace('_', ' ').toUpperCase(); +} + +function formatDate(date) { + if (!date) return '-'; + return new Date(date).toLocaleDateString(); +} + +function formatStatus(status) { + if (!status) return '-'; + + let color = '#444'; + + if (status.includes('CONFIRMED')) color = 'green'; + else if (status.includes('WAITING')) color = 'orange'; + else if (status.includes('CANCELLED')) color = 'red'; + else if (status.includes('CHECKEDIN')) color = 'blue'; + + return `${status}`; +} \ No newline at end of file