Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 107 additions & 82 deletions admin/card/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -35,103 +33,132 @@ document.addEventListener('DOMContentLoaded', () => {
displayData(data.data);
} catch (error) {
console.error('Error fetching data:', error);
dataList.innerHTML = '<tr><td colspan="3">No results found</td></tr>';
dataList.innerHTML =
'<tr><td colspan="4">No results found</td></tr>';
}
};

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);
debounceTimer = setTimeout(() => callback(...args), delay);
};
};

// 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)
);
});

Expand All @@ -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)
}
function resetAlert() {}
68 changes: 68 additions & 0 deletions admin/card/personHistory.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<script src="/style/js/roleCheck.js"></script>
<script>
checkRoleAccess(['officeAdmin', 'cardAdmin', 'superAdmin']);
</script>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Person History</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The version of jQuery used (1.11.2) is outdated and has known security vulnerabilities, such as Cross-Site Scripting (XSS) (e.g., CVE-2015-9251). Please update to the latest stable version of jQuery (3.x) to mitigate these risks.

Suggested change
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<script src="../../style/js/config.js"></script>
<script src="../../sessionstorage.js"></script>
<script src="personHistory.js"></script>

<link rel="stylesheet" href="../../style/css/styles.css" />
</head>

<body>
<div class="header">
<div class="container">
<div class="logout">
<a href="javascript:void(0);" onclick="history.back()">Back</a>
&nbsp; | &nbsp;
<a href="javascript:void(0);" onclick="goToHome()">Home</a>
&nbsp; | &nbsp;
<a href="javascript:void(0);" onclick="logout()">Logout</a>
</div>
</div>
</div>

<div class="middlecontent">
<div class="container">
<div class="whitesec">
<div class="inner-padding">

<div class="frm-head">
<h1>Person Booking History</h1>
</div>

<div id="summaryBox" style="margin-bottom:20px;"></div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve maintainability and separate concerns, it's best to avoid inline styles. Please move this style to a CSS class in your stylesheet (/style/css/styles.css) and apply the class to the element.

Suggested change
<div id="summaryBox" style="margin-bottom:20px;"></div>
<div id="summaryBox" class="summary-box"></div>


<div class="history-section">
<h3>Upcoming</h3>
<div id="upcoming"></div>
</div>

<div class="history-section">
<h3>Past 30 Days</h3>
<div id="past"></div>
</div>

<div class="history-section">
<h3>Open Maintenance</h3>
<div id="maintenance"></div>
</div>

<div class="history-section">
<h3>WiFi Codes</h3>
<div id="wifi"></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Loading