user-management frontend page done

This commit is contained in:
armiejean 2025-04-15 23:04:43 +08:00
parent f1514e7613
commit 3ee7695dc9
6 changed files with 10271 additions and 119 deletions

File diff suppressed because one or more lines are too long

View File

@ -188,11 +188,11 @@
<i class="fa-solid fa-user-circle" style="padding-right:5px"></i> <i class="fa-solid fa-user-circle" style="padding-right:5px"></i>
</a> </a>
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-sm"> <ul class="dropdown-menu dropdown-menu-end dropdown-menu-sm">
<li> <li style="margin-right:5px">
<a class="dropdown-item d-flex align-items-center gap-2" <a class="dropdown-item d-flex align-items-center gap-2"
href="{{ route('my-profile') }}"> href="{{ route('my-profile') }}">
<i class="fa-solid fa-user" style="font-size:16px; color:gray;"></i> <i class="fa-solid fa-user" style="font-size:16px; color:gray;"></i>
<span>My Profile</span> <span style="margin-left:5px">My Profile</span>
</a> </a>
</li> </li>
<li> <li>
@ -200,7 +200,7 @@
href="{{ route('login') }}"> href="{{ route('login') }}">
<i class="fa-solid fa-right-from-bracket" <i class="fa-solid fa-right-from-bracket"
style="font-size:16px; color:gray;"></i> style="font-size:16px; color:gray;"></i>
<span>Logout</span> <span style="margin-left:5px">Logout</span>
</a> </a>
</li> </li>
</ul> </ul>

View File

@ -14,14 +14,16 @@
<form> <form>
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-semibold" style="font-size: 13px; color: #003366;">Enter Username</label> <label class="form-label fw-semibold" style="font-size: 13px; color: #003366;">Enter
Username</label>
<input type="text" class="form-control" placeholder="Username"> <input type="text" class="form-control" placeholder="Username">
</div> </div>
<!-- Mockup password input --> <!-- Mockup password input -->
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-semibold text-primary" style="font-size: 13px; color: #003366 !important;">Enter Password</label> <label class="form-label fw-semibold text-primary"
style="font-size: 13px; color: #003366 !important;">Enter Password</label>
<input type="password" class="form-control" placeholder="Password"> <input type="password" class="form-control" placeholder="Password">
</div> </div>
@ -30,7 +32,8 @@
<a href="#" class="text-decoration-none text-primary">Forgot Username</a> <a href="#" class="text-decoration-none text-primary">Forgot Username</a>
</div> </div>
<div class="col-6 text-end"> <div class="col-6 text-end">
<button type="submit" class="btn btn-primary w-100" style="background-color: #E74610; border-color: #E74610;"> <button type="submit" class="btn btn-primary w-100"
style="background-color: #E74610; border-color: #E74610;">
Login Login
</button> </button>
</div> </div>

View File

@ -3,11 +3,11 @@
@section('page_title', 'User Management') @section('page_title', 'User Management')
@section('content') @section('content')
<div class="card border-0 shadow-sm" style="min-height: 500px;">
<div class="card-header border-0 bg-transparent"> <div class="card-header border-0 bg-transparent">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0 fw-bold text-dark">User Management</h5> <h5 class="mb-0 fw-bold text-dark">User Management</h5>
<a href="#" class="btn btn-primary btn-sm px-3"> <a href="{{ url('add-user') }}" class="btn btn-primary btn-sm px-3">
<i class="fa-solid fa-plus me-1"></i> Add User <i class="fa-solid fa-plus me-1"></i> Add User
</a> </a>
</div> </div>
@ -20,8 +20,7 @@
<span class="input-group-text bg-light border-end-0"> <span class="input-group-text bg-light border-end-0">
<i class="fa-solid fa-magnifying-glass text-muted"></i> <i class="fa-solid fa-magnifying-glass text-muted"></i>
</span> </span>
<input type="text" class="form-control border-start-0" placeholder="Search users..." <input type="text" class="form-control border-start-0" placeholder="Search users..." id="searchInput">
id="searchInput">
</div> </div>
</div> </div>
<div class="col-12 col-md-6 d-flex justify-content-end"> <div class="col-12 col-md-6 d-flex justify-content-end">
@ -56,13 +55,11 @@
<!-- Delete Selected Button and Pagination --> <!-- Delete Selected Button and Pagination -->
<div class="d-flex justify-content-between align-items-center mt-4"> <div class="d-flex justify-content-between align-items-center mt-4">
<!-- Delete Selected Button -->
<div> <div>
<button class="btn btn-danger btn-sm" id="deleteSelected" disabled> <button class="btn btn-danger btn-sm" id="deleteSelected" disabled>
<i class="fa-solid fa-trash-can me-1"></i> Delete Selected <i class="fa-solid fa-trash-can me-1"></i> Delete Selected
</button> </button>
</div> </div>
<!-- Pagination -->
<nav aria-label="Page navigation"> <nav aria-label="Page navigation">
<ul class="pagination pagination-sm" id="pagination"> <ul class="pagination pagination-sm" id="pagination">
<!-- Pagination links will be generated dynamically --> <!-- Pagination links will be generated dynamically -->
@ -70,7 +67,7 @@
</nav> </nav>
</div> </div>
</div> </div>
</div>
<!-- Edit User Modal --> <!-- Edit User Modal -->
<div class="modal fade" id="editUserModal" tabindex="-1" aria-labelledby="editUserModalLabel" aria-hidden="true"> <div class="modal fade" id="editUserModal" tabindex="-1" aria-labelledby="editUserModalLabel" aria-hidden="true">
@ -78,7 +75,9 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="editUserModalLabel">Edit User</h5> <h5 class="modal-title" id="editUserModalLabel">Edit User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="modal-close-btn" data-bs-dismiss="modal" aria-label="Close">
<i class="fa-solid fa-xmark"></i>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form id="editUserForm"> <form id="editUserForm">
@ -119,6 +118,34 @@
</div> </div>
</div> </div>
<!-- View User Modal -->
<div class="modal fade" id="viewUserModal" tabindex="-1" aria-labelledby="viewUserModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="viewUserModalLabel">View User Details</h5>
<button type="button" class="modal-close-btn" data-bs-dismiss="modal" aria-label="Close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="modal-body">
<div class="view-user-details">
<p><strong>ID:</strong> <span id="viewId"></span></p>
<p><strong>Username:</strong> <span id="viewUsername"></span></p>
<p><strong>First Name:</strong> <span id="viewFirstName"></span></p>
<p><strong>Last Name:</strong> <span id="viewLastName"></span></p>
<p><strong>User Role:</strong> <span id="viewUserRole"></span></p>
<p><strong>Email:</strong> <span id="viewEmail"></span></p>
<p><strong>Status:</strong> <span id="viewStatus"></span></p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Custom CSS for Styling --> <!-- Custom CSS for Styling -->
<style> <style>
/* Font Styling */ /* Font Styling */
@ -128,18 +155,19 @@
.form-control, .form-control,
.input-group-text, .input-group-text,
.modal-content { .modal-content {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
font-weight: 400; font-weight: 400;
line-height: 1.5; line-height: 1.5;
} }
.card-header h5, .card-header h5,
.modal-title { .modal-title {
font-weight: 600; font-weight: 500;
} }
.table th { .table thead th {
font-weight: 500; font-weight: 500;
font-size: 0.8rem;
} }
.form-label { .form-label {
@ -156,13 +184,13 @@
} }
.btn-primary { .btn-primary {
background-color: #007bff; background-color: #E74610;
border-color: #007bff; border-color: #E74610;
} }
.btn-primary:hover { .btn-primary:hover {
background-color: #0056b3; background-color: #E74610;
border-color: #0056b3; border-color: #E74610;
} }
.sortable { .sortable {
@ -201,19 +229,16 @@
} }
.table td:nth-child(5), .table td:nth-child(5),
/* User Role */
.table th:nth-child(5) { .table th:nth-child(5) {
width: 100px; width: 100px;
} }
.table td:nth-child(6), .table td:nth-child(6),
/* Email */
.table th:nth-child(6) { .table th:nth-child(6) {
max-width: 200px; max-width: 200px;
} }
.table td:nth-child(7), .table td:nth-child(7),
/* Status */
.table th:nth-child(7) { .table th:nth-child(7) {
width: 120px; width: 120px;
} }
@ -231,12 +256,15 @@
font-size: 0.85rem; font-size: 0.85rem;
} }
/* Table Container to Prevent Scrollbar */ .table thead .sortable i {
font-size: 0.7rem;
vertical-align: middle;
}
.table-container { .table-container {
overflow-x: hidden; overflow-x: hidden;
} }
/* Modal Styling */
.modal-content { .modal-content {
border-radius: 8px; border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
@ -244,6 +272,7 @@
.modal-header { .modal-header {
border-bottom: 1px solid #e9ecef; border-bottom: 1px solid #e9ecef;
position: relative;
} }
.modal-footer { .modal-footer {
@ -256,18 +285,81 @@
border-radius: 5px; border-radius: 5px;
} }
/* Pagination Styling */ .modal-close-btn {
background: none;
border: none;
font-size: 1rem;
color: #6c757d;
position: absolute;
right: 15px;
top: 15px;
cursor: pointer;
}
.modal-close-btn:hover {
color: #343a40;
}
.view-user-details p {
margin-bottom: 0.75rem;
font-size: 0.9rem;
}
.view-user-details strong {
display: inline-block;
width: 120px;
font-weight: 500;
color: #343a40;
}
.view-user-details span {
color: #495057;
}
.pagination-sm .page-link { .pagination-sm .page-link {
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
font-size: 0.85rem; font-size: 0.85rem;
border-color: #E74610;
color: #E74610;
}
.pagination-sm .page-item.active .page-link {
background-color: #E74610;
border-color: #E74610;
color: #fff;
}
.pagination-sm .page-link:hover {
background-color: #E74610;
border-color: #E74610;
color: #fff;
}
.pagination-sm .page-item.disabled .page-link {
border-color: #dee2e6;
color: #6c757d;
}
.edit-btn {
border-color: #E74610;
color: #E74610;
}
.edit-btn:hover {
background-color: #E74610;
border-color: #E74610;
color: #fff;
} }
/* Responsive adjustments */
@media (max-width: 576px) { @media (max-width: 576px) {
.table { .table {
font-size: 0.75rem; font-size: 0.75rem;
} }
.table thead th {
font-size: 0.75rem;
}
.table th, .table th,
.table td { .table td {
padding: 0.3rem; padding: 0.3rem;
@ -290,13 +382,16 @@
font-size: 0.75rem; font-size: 0.75rem;
} }
.table thead .sortable i {
font-size: 0.65rem;
}
.pagination-sm .page-link { .pagination-sm .page-link {
padding: 0.2rem 0.4rem; padding: 0.2rem 0.4rem;
font-size: 0.75rem; font-size: 0.75rem;
} }
.table td:nth-child(6) { .table td:nth-child(6) {
/* Email */
max-width: 150px; max-width: 150px;
} }
@ -304,12 +399,24 @@
.form-select { .form-select {
font-size: 0.85rem; font-size: 0.85rem;
} }
.modal-close-btn {
font-size: 0.9rem;
}
.view-user-details p {
font-size: 0.85rem;
}
.view-user-details strong {
width: 100px;
}
} }
</style> </style>
<!-- JavaScript for Interactivity --> <!-- JavaScript for Interactivity -->
<script> <script>
// Sample data (replace with dynamic data from backend in real implementation) // Sample data
const allRows = [{ const allRows = [{
id: 1, id: 1,
username: 'superadmin', username: 'superadmin',
@ -375,15 +482,11 @@
} }
]; ];
// Pagination settings
const rowsPerPage = 5; const rowsPerPage = 5;
let currentPage = 1; let currentPage = 1;
let filteredRows = [...allRows]; let filteredRows = [...allRows];
let originalRows = [...allRows].map(row => ({ let originalRows = [...allRows].map(row => ({ ...row }));
...row
})); // Deep copy for original data
// Function to render table rows for the current page
function renderTable() { function renderTable() {
const tableBody = document.getElementById('userTableBody'); const tableBody = document.getElementById('userTableBody');
tableBody.innerHTML = ''; tableBody.innerHTML = '';
@ -424,10 +527,10 @@
</div> </div>
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="#" class="btn btn-sm btn-outline-primary me-1 edit-btn" title="Edit" data-id="${row.id}"> <a href="#" class="btn btn-sm edit-btn me-1" title="Edit" data-id="${row.id}">
<i class="fa-solid fa-pen-to-square"></i> <i class="fa-solid fa-pen-to-square"></i>
</a> </a>
<a href="#" class="btn btn-sm btn-outline-secondary me-1" title="View"> <a href="#" class="btn btn-sm btn-outline-secondary me-1 view-btn" title="View" data-id="${row.id}">
<i class="fa-solid fa-eye"></i> <i class="fa-solid fa-eye"></i>
</a> </a>
<button class="btn btn-sm btn-outline-danger" onclick="confirmDelete(${row.id})" title="Delete"> <button class="btn btn-sm btn-outline-danger" onclick="confirmDelete(${row.id})" title="Delete">
@ -438,21 +541,19 @@
tableBody.appendChild(tr); tableBody.appendChild(tr);
}); });
// Reattach event listeners
attachStatusListeners(); attachStatusListeners();
attachCheckboxListeners(); attachCheckboxListeners();
attachEditListeners(); attachEditListeners();
attachViewListeners();
updateDeleteButtonState(); updateDeleteButtonState();
} }
// Function to render pagination
function renderPagination() { function renderPagination() {
const pagination = document.getElementById('pagination'); const pagination = document.getElementById('pagination');
pagination.innerHTML = ''; pagination.innerHTML = '';
const pageCount = Math.ceil(filteredRows.length / rowsPerPage); const pageCount = Math.ceil(filteredRows.length / rowsPerPage);
// Previous button
const prevLi = document.createElement('li'); const prevLi = document.createElement('li');
prevLi.className = `page-item ${currentPage === 1 ? 'disabled' : ''}`; prevLi.className = `page-item ${currentPage === 1 ? 'disabled' : ''}`;
prevLi.innerHTML = `<a class="page-link" href="#" aria-label="Previous"><span aria-hidden="true">«</span></a>`; prevLi.innerHTML = `<a class="page-link" href="#" aria-label="Previous"><span aria-hidden="true">«</span></a>`;
@ -466,7 +567,6 @@
}); });
pagination.appendChild(prevLi); pagination.appendChild(prevLi);
// Page numbers
for (let i = 1; i <= pageCount; i++) { for (let i = 1; i <= pageCount; i++) {
const li = document.createElement('li'); const li = document.createElement('li');
li.className = `page-item ${currentPage === i ? 'active' : ''}`; li.className = `page-item ${currentPage === i ? 'active' : ''}`;
@ -480,7 +580,6 @@
pagination.appendChild(li); pagination.appendChild(li);
} }
// Next button
const nextLi = document.createElement('li'); const nextLi = document.createElement('li');
nextLi.className = `page-item ${currentPage === pageCount ? 'disabled' : ''}`; nextLi.className = `page-item ${currentPage === pageCount ? 'disabled' : ''}`;
nextLi.innerHTML = `<a class="page-link" href="#" aria-label="Next"><span aria-hidden="true">»</span></a>`; nextLi.innerHTML = `<a class="page-link" href="#" aria-label="Next"><span aria-hidden="true">»</span></a>`;
@ -495,7 +594,6 @@
pagination.appendChild(nextLi); pagination.appendChild(nextLi);
} }
// Search Functionality
document.getElementById('searchInput').addEventListener('input', function() { document.getElementById('searchInput').addEventListener('input', function() {
const searchTerm = this.value.toLowerCase(); const searchTerm = this.value.toLowerCase();
filteredRows = allRows.filter(row => { filteredRows = allRows.filter(row => {
@ -503,12 +601,11 @@
value.toString().toLowerCase().includes(searchTerm) value.toString().toLowerCase().includes(searchTerm)
); );
}); });
currentPage = 1; // Reset to first page currentPage = 1;
renderTable(); renderTable();
renderPagination(); renderPagination();
}); });
// Sorting Functionality
let sortDirection = {}; let sortDirection = {};
document.querySelectorAll('.sortable').forEach(header => { document.querySelectorAll('.sortable').forEach(header => {
header.addEventListener('click', function() { header.addEventListener('click', function() {
@ -523,11 +620,8 @@
}; };
const key = columnMap[column]; const key = columnMap[column];
// Toggle sort direction sortDirection[column] = !sortDirection[column] ? 'asc' : sortDirection[column] === 'asc' ? 'desc' : 'asc';
sortDirection[column] = !sortDirection[column] ? 'asc' : sortDirection[column] === 'asc' ?
'desc' : 'asc';
// Update sort icons
document.querySelectorAll('.sortable i').forEach(icon => { document.querySelectorAll('.sortable i').forEach(icon => {
icon.classList.remove('fa-sort-up', 'fa-sort-down'); icon.classList.remove('fa-sort-up', 'fa-sort-down');
icon.classList.add('fa-sort'); icon.classList.add('fa-sort');
@ -536,7 +630,6 @@
icon.classList.remove('fa-sort'); icon.classList.remove('fa-sort');
icon.classList.add(sortDirection[column] === 'asc' ? 'fa-sort-up' : 'fa-sort-down'); icon.classList.add(sortDirection[column] === 'asc' ? 'fa-sort-up' : 'fa-sort-down');
// Sort filtered rows
filteredRows.sort((a, b) => { filteredRows.sort((a, b) => {
const aValue = a[key].toLowerCase(); const aValue = a[key].toLowerCase();
const bValue = b[key].toLowerCase(); const bValue = b[key].toLowerCase();
@ -547,32 +640,25 @@
} }
}); });
currentPage = 1; // Reset to first page currentPage = 1;
renderTable(); renderTable();
renderPagination(); renderPagination();
}); });
}); });
// Clear Filters and Reset Sorting
document.getElementById('clearFilters').addEventListener('click', function() { document.getElementById('clearFilters').addEventListener('click', function() {
// Clear search input
document.getElementById('searchInput').value = ''; document.getElementById('searchInput').value = '';
// Reset sort icons
document.querySelectorAll('.sortable i').forEach(icon => { document.querySelectorAll('.sortable i').forEach(icon => {
icon.classList.remove('fa-sort-up', 'fa-sort-down'); icon.classList.remove('fa-sort-up', 'fa-sort-down');
icon.classList.add('fa-sort'); icon.classList.add('fa-sort');
}); });
sortDirection = {}; sortDirection = {};
// Reset filtered rows to original
filteredRows = [...allRows]; filteredRows = [...allRows];
currentPage = 1; currentPage = 1;
renderTable(); renderTable();
renderPagination(); renderPagination();
}); });
// Select All Checkbox Functionality
document.getElementById('selectAll').addEventListener('change', function() { document.getElementById('selectAll').addEventListener('change', function() {
const checkboxes = document.querySelectorAll('.rowCheckbox'); const checkboxes = document.querySelectorAll('.rowCheckbox');
checkboxes.forEach(checkbox => { checkboxes.forEach(checkbox => {
@ -581,7 +667,6 @@
updateDeleteButtonState(); updateDeleteButtonState();
}); });
// Checkbox Listeners for Batch Delete
function attachCheckboxListeners() { function attachCheckboxListeners() {
const checkboxes = document.querySelectorAll('.rowCheckbox'); const checkboxes = document.querySelectorAll('.rowCheckbox');
checkboxes.forEach(checkbox => { checkboxes.forEach(checkbox => {
@ -589,7 +674,6 @@
}); });
} }
// Update Delete Button State
function updateDeleteButtonState() { function updateDeleteButtonState() {
const checkboxes = document.querySelectorAll('.rowCheckbox'); const checkboxes = document.querySelectorAll('.rowCheckbox');
const checkedCount = Array.from(checkboxes).filter(cb => cb.checked).length; const checkedCount = Array.from(checkboxes).filter(cb => cb.checked).length;
@ -597,7 +681,6 @@
deleteButton.disabled = checkedCount < 2; deleteButton.disabled = checkedCount < 2;
} }
// Delete Selected (UI Only)
document.getElementById('deleteSelected').addEventListener('click', function() { document.getElementById('deleteSelected').addEventListener('click', function() {
if (confirm('Are you sure you want to delete the selected users?')) { if (confirm('Are you sure you want to delete the selected users?')) {
const checkboxes = document.querySelectorAll('.rowCheckbox'); const checkboxes = document.querySelectorAll('.rowCheckbox');
@ -605,12 +688,10 @@
.filter(cb => cb.checked) .filter(cb => cb.checked)
.map(cb => cb.closest('tr').getAttribute('data-id')); .map(cb => cb.closest('tr').getAttribute('data-id'));
// Simulate deletion by removing from allRows and filteredRows
allRows = allRows.filter(row => !selectedIds.includes(row.id.toString())); allRows = allRows.filter(row => !selectedIds.includes(row.id.toString()));
filteredRows = filteredRows.filter(row => !selectedIds.includes(row.id.toString())); filteredRows = filteredRows.filter(row => !selectedIds.includes(row.id.toString()));
originalRows = originalRows.filter(row => !selectedIds.includes(row.id.toString())); originalRows = originalRows.filter(row => !selectedIds.includes(row.id.toString()));
// Reset to first page if necessary
const maxPage = Math.ceil(filteredRows.length / rowsPerPage); const maxPage = Math.ceil(filteredRows.length / rowsPerPage);
if (currentPage > maxPage) { if (currentPage > maxPage) {
currentPage = maxPage || 1; currentPage = maxPage || 1;
@ -618,13 +699,10 @@
renderTable(); renderTable();
renderPagination(); renderPagination();
// Reset select all checkbox
document.getElementById('selectAll').checked = false; document.getElementById('selectAll').checked = false;
} }
}); });
// Status Dropdown Functionality
function attachStatusListeners() { function attachStatusListeners() {
const options = document.querySelectorAll('.status-option'); const options = document.querySelectorAll('.status-option');
options.forEach(option => { options.forEach(option => {
@ -640,12 +718,10 @@
const userId = row.getAttribute('data-id'); const userId = row.getAttribute('data-id');
const statusText = row.querySelector('.status-text'); const statusText = row.querySelector('.status-text');
// Update the button text
if (statusText) { if (statusText) {
statusText.textContent = newStatus; statusText.textContent = newStatus;
} }
// Update the data in allRows, filteredRows, and originalRows
const rowData = allRows.find(r => r.id == userId); const rowData = allRows.find(r => r.id == userId);
if (rowData) { if (rowData) {
rowData.status = newStatus; rowData.status = newStatus;
@ -659,11 +735,9 @@
originalRowData.status = newStatus; originalRowData.status = newStatus;
} }
// Simulate an API call to update the status
updateUserStatus(userId, newStatus); updateUserStatus(userId, newStatus);
} }
// Edit Button Functionality
function attachEditListeners() { function attachEditListeners() {
const editButtons = document.querySelectorAll('.edit-btn'); const editButtons = document.querySelectorAll('.edit-btn');
editButtons.forEach(button => { editButtons.forEach(button => {
@ -672,7 +746,6 @@
const userId = this.getAttribute('data-id'); const userId = this.getAttribute('data-id');
const user = allRows.find(row => row.id == userId); const user = allRows.find(row => row.id == userId);
// Populate modal fields with user data
document.getElementById('editUsername').value = user.username; document.getElementById('editUsername').value = user.username;
document.getElementById('editFirstName').value = user.firstName; document.getElementById('editFirstName').value = user.firstName;
document.getElementById('editLastName').value = user.lastName; document.getElementById('editLastName').value = user.lastName;
@ -680,54 +753,49 @@
document.getElementById('editEmail').value = user.email; document.getElementById('editEmail').value = user.email;
document.getElementById('editStatus').value = user.status; document.getElementById('editStatus').value = user.status;
// Show the modal
const modal = new bootstrap.Modal(document.getElementById('editUserModal')); const modal = new bootstrap.Modal(document.getElementById('editUserModal'));
modal.show(); modal.show();
}); });
}); });
} }
// Update Button in Modal (Static for now) function attachViewListeners() {
const viewButtons = document.querySelectorAll('.view-btn');
viewButtons.forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
const userId = this.getAttribute('data-id');
const user = allRows.find(row => row.id == userId);
document.getElementById('viewId').textContent = user.id;
document.getElementById('viewUsername').textContent = user.username;
document.getElementById('viewFirstName').textContent = user.firstName;
document.getElementById('viewLastName').textContent = user.lastName;
document.getElementById('viewUserRole').textContent = user.role;
document.getElementById('viewEmail').textContent = user.email;
document.getElementById('viewStatus').textContent = user.status;
const modal = new bootstrap.Modal(document.getElementById('viewUserModal'));
modal.show();
});
});
}
document.getElementById('updateUserBtn').addEventListener('click', function() { document.getElementById('updateUserBtn').addEventListener('click', function() {
// For static purposes, just close the modal
const modal = bootstrap.Modal.getInstance(document.getElementById('editUserModal')); const modal = bootstrap.Modal.getInstance(document.getElementById('editUserModal'));
modal.hide(); modal.hide();
}); });
// Simulated API call to update status
function updateUserStatus(userId, status) { function updateUserStatus(userId, status) {
console.log(`Updating user ${userId} status to ${status}`); console.log(`Updating user ${userId} status to ${status}`);
// Replace with actual AJAX call to your backend, e.g.:
/*
fetch(`/user/update-status/${userId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
body: JSON.stringify({ status: status })
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Status updated successfully');
} else {
console.error('Failed to update status');
}
})
.catch(error => console.error('Error:', error));
*/
} }
// Delete Confirmation
function confirmDelete(id) { function confirmDelete(id) {
if (confirm('Are you sure you want to delete this user?')) { if (confirm('Are you sure you want to delete this user?')) {
// Simulate deletion by removing from allRows and filteredRows
allRows = allRows.filter(row => row.id != id); allRows = allRows.filter(row => row.id != id);
filteredRows = filteredRows.filter(row => row.id != id); filteredRows = filteredRows.filter(row => row.id != id);
originalRows = originalRows.filter(row => row.id != id); originalRows = originalRows.filter(row => row.id != id);
// Reset to first page if necessary
const maxPage = Math.ceil(filteredRows.length / rowsPerPage); const maxPage = Math.ceil(filteredRows.length / rowsPerPage);
if (currentPage > maxPage) { if (currentPage > maxPage) {
currentPage = maxPage || 1; currentPage = maxPage || 1;
@ -738,7 +806,6 @@
} }
} }
// Initial render
renderTable(); renderTable();
renderPagination(); renderPagination();
</script> </script>

View File

@ -0,0 +1,82 @@
@extends('layouts.app')
@section('page_title', 'Add User')
@section('content')
<div class="card-header border-0 bg-transparent py-2">
<h5 class="mb-0 fw-bold text-dark" style="font-size: 1.25rem;">Add New User</h5>
</div>
<div class="card-body py-2">
<form action="#" method="POST" id="addUserForm">
@csrf
<div class="mb-2">
<label for="username" class="form-label mb-1">Username</label>
<input type="text" class="form-control form-control-sm" id="username" name="username" required>
</div>
<div class="mb-2">
<label for="firstName" class="form-label mb-1">First Name</label>
<input type="text" class="form-control form-control-sm" id="firstName" name="firstName" required>
</div>
<div class="mb-2">
<label for="lastName" class="form-label mb-1">Last Name</label>
<input type="text" class="form-control form-control-sm" id="lastName" name="lastName" required>
</div>
<div class="mb-2">
<label for="role" class="form-label mb-1">User Role</label>
<input type="text" class="form-control form-control-sm" id="role" name="role" required>
</div>
<div class="mb-2">
<label for="email" class="form-label mb-1">Email</label>
<input type="email" class="form-control form-control-sm" id="email" name="email" required>
</div>
<div class="mb-2">
<label for="status" class="form-label mb-1">Status</label>
<select class="form-select form-select-sm" id="status" name="status" required>
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div>
<div class="d-flex justify-content-end mt-3">
<a href="{{ url('user-management') }}" class="btn btn-outline-secondary btn-sm me-2" style="margin-right:5px">Cancel</a>
<button type="submit" class="btn btn-primary btn-sm">Add User</button>
</div>
</form>
</div>
<style>
.card {
border-radius: 8px;
}
.form-control,
.form-select {
font-size: 0.85rem;
border-radius: 4px;
padding: 0.375rem 0.75rem;
}
.form-label {
font-weight: 500;
font-size: 0.85rem;
line-height: 1.2;
}
.btn-primary {
background-color: #E74610;
border-color: #E74610;
font-size: 0.85rem;
padding: 0.375rem 0.75rem;
}
.btn-primary:hover {
background-color: #d63f0e;
border-color: #d63f0e;
}
.btn-outline-secondary {
font-size: 0.85rem;
padding: 0.375rem 0.75rem;
}
.form-control-sm,
.form-select-sm {
height: calc(1.5em + 0.5rem + 2px);
}
</style>
@endsection

View File

@ -83,3 +83,7 @@ Route::get('/fuels', function () {
Route::get('/my-profile', function () { Route::get('/my-profile', function () {
return view('pages.my-profile'); return view('pages.my-profile');
})->name('my-profile'); })->name('my-profile');
Route::get('add-user', function () {
return view('pages.user-management.add-user');
})->name('add-user');