feat: complete assessment tasks
This commit is contained in:
+205
-50
@@ -5,27 +5,67 @@
|
||||
color: white;
|
||||
/* White text color */
|
||||
}
|
||||
.bulk-actions {
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 5px;
|
||||
display: none;
|
||||
}
|
||||
.bulk-actions.show {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<h2 class="text-left">Licenses <a class="btn btn-primary" href="/admin/license/add">Add</a></h2>
|
||||
|
||||
<!-- Bulk Actions Form -->
|
||||
<div class="bulk-actions" id="bulkActions">
|
||||
<form action="/admin/license/list/multiselect" method="POST" onsubmit="return confirmBulkDelete()">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="mr-3"><strong>Selected items:</strong> <span id="selectedCount">0</span></span>
|
||||
<button type="submit" name="delete" class="btn btn-danger btn-sm mr-2">
|
||||
<i class="fa fa-trash"></i> Delete Selected
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary btn-sm" onclick="clearSelection()">
|
||||
Clear Selection
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" name="selected_items" id="selectedItems" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div class="row mt-2 mb-2">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<form action="?" method="GET">
|
||||
<div class="input-group">
|
||||
<input type="text" name="relationship_num" class="form-control mr-2" placeholder="Enter Relationship #" value="<?php echo $data['relationship_num']; ?>">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="submit">Search</button>
|
||||
</span>
|
||||
</div><!-- /input-group -->
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
<form action="?" method="GET" class="form-inline">
|
||||
<div class="input-group mr-2 mb-2">
|
||||
<label class="mr-2" for="relationship_num">Relationship #</label>
|
||||
<input id="relationship_num" type="text" name="relationship_num" class="form-control" placeholder="Enter Relationship #"
|
||||
value="<?php echo htmlspecialchars($data['relationship_num'] ?? ''); ?>">
|
||||
</div>
|
||||
<div class="input-group mr-2 mb-2">
|
||||
<label class="mr-2" for="email">Email</label>
|
||||
<input id="email" type="text" name="email" class="form-control" placeholder="Fuzzy email search..."
|
||||
value="<?php echo htmlspecialchars($data['email_search'] ?? ''); ?>">
|
||||
</div>
|
||||
<!-- Preserve cursor parameter when searching -->
|
||||
<input type="hidden" name="cursor" value="0">
|
||||
<span class="input-group-btn mb-2">
|
||||
<button class="btn btn-primary mr-2" type="submit">Search</button>
|
||||
<a class="btn btn-secondary" href="/admin/license">Clear</a>
|
||||
</span>
|
||||
</form>
|
||||
</div><!-- /.col-md-6 -->
|
||||
</div><!-- /.col-md-10 -->
|
||||
</div><!-- /.row -->
|
||||
<!-- Table Responsive Wrapper -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover dark-header">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<input type="checkbox" id="selectAll" onchange="toggleSelectAll()">
|
||||
<label for="selectAll" class="ml-1">Select All</label>
|
||||
</th>
|
||||
<th>ID</th>
|
||||
<th>Relationship #</th>
|
||||
<th>Email</th>
|
||||
@@ -38,6 +78,7 @@
|
||||
<tbody>
|
||||
<?php foreach ($data['data'] as $key => $value) {
|
||||
echo ' <tr>';
|
||||
echo ' <td><input type="checkbox" class="item-checkbox" value="' . $value->id . '" onchange="updateBulkActions()"></td>';
|
||||
echo ' <td>' . $value->id . ' <br/><a class=" text-info" href="/admin/license/edit/' . $value->id . '">edit</a> <a class="text-danger" href="/admin/license/delete/' . $value->id . '">delete</a></td>';
|
||||
echo ' <td>' . $value->relationship_num . ' </td>';
|
||||
echo ' <td>' . $value->email . ' </td>';
|
||||
@@ -53,49 +94,163 @@
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// Retrieve parameters
|
||||
// Retrieve cursor pagination parameters
|
||||
$total = $data['total'];
|
||||
$currentPage = $data['page'];
|
||||
$perPage = 10;
|
||||
|
||||
// Calculate the number of pages
|
||||
$totalPages = ceil($total / $perPage);
|
||||
|
||||
// Define a range of pages to show at any given time
|
||||
$range = 2; // This can be adjusted as needed
|
||||
|
||||
$startPage = ($currentPage - $range) > 0 ? ($currentPage - $range) : 1;
|
||||
$endPage = ($currentPage + $range) < $totalPages ? ($currentPage + $range) : $totalPages;
|
||||
|
||||
$lastId = isset($data['id']) ? $data['id'] : 0;
|
||||
$currentCursor = isset($_GET['cursor']) ? intval($_GET['cursor']) : 0;
|
||||
$relationshipNum = isset($_GET['relationship_num']) ? $_GET['relationship_num'] : '';
|
||||
$emailSearch = isset($_GET['email']) ? $_GET['email'] : '';
|
||||
|
||||
// Build query parameters for pagination links
|
||||
$queryParams = [];
|
||||
if (!empty($relationshipNum)) {
|
||||
$queryParams['relationship_num'] = $relationshipNum;
|
||||
}
|
||||
if (!empty($emailSearch)) {
|
||||
$queryParams['email'] = $emailSearch;
|
||||
}
|
||||
|
||||
// Helper function to build query string
|
||||
function buildQueryString($params) {
|
||||
return !empty($params) ? '&' . http_build_query($params) : '';
|
||||
}
|
||||
|
||||
$queryString = buildQueryString($queryParams);
|
||||
|
||||
// Determine if we have previous/next pages
|
||||
$hasPrevious = $currentCursor > 0;
|
||||
$hasNext = count($data['data']) >= $perPage; // If we got a full page, assume there might be more
|
||||
|
||||
?>
|
||||
<!-- Pagination -->
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination">
|
||||
<li class="ml-2">
|
||||
<a href="?page=1" aria-label="Previous">
|
||||
<span aria-hidden="true">««</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="ml-2">
|
||||
<a href="?page=<?= ($currentPage - 1) > 0 ? $currentPage - 1 : 1 ?>" aria-label="Previous">
|
||||
<span aria-hidden="true">«</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php
|
||||
for ($i = $startPage; $i <= $endPage; $i++) {
|
||||
echo '<li class="ml-2' . ($currentPage == $i ? ' active' : '') . '"><a href="?page=' . $i . '">' . $i . '</a></li>';
|
||||
}
|
||||
?>
|
||||
<li class="ml-2">
|
||||
<a href="?page=<?= ($currentPage + 1) < $totalPages ? $currentPage + 1 : $totalPages ?>" aria-label="Next">
|
||||
<span aria-hidden="true">»</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="ml-2">
|
||||
<a href="?page=<?= $totalPages ?>" aria-label="Next">
|
||||
<span aria-hidden="true">»»</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Cursor-based Pagination -->
|
||||
<nav aria-label="Cursor-based page navigation">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pagination-info">
|
||||
<small class="text-muted">
|
||||
Showing <?= count($data['data']) ?> items
|
||||
<?php if ($total > 0): ?>
|
||||
(Total: <?= $total ?> items)
|
||||
<?php endif; ?>
|
||||
</small>
|
||||
</div>
|
||||
<ul class="pagination mb-0">
|
||||
<?php if ($hasPrevious): ?>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?cursor=0<?= $queryString ?>" aria-label="First">
|
||||
<span aria-hidden="true">««</span>
|
||||
<span class="sr-only">First</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?cursor=<?= max(0, $currentCursor - $perPage) ?><?= $queryString ?>" aria-label="Previous">
|
||||
<span aria-hidden="true">«</span>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php else: ?>
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">
|
||||
<span aria-hidden="true">««</span>
|
||||
</span>
|
||||
</li>
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">
|
||||
<span aria-hidden="true">«</span>
|
||||
</span>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
|
||||
<li class="page-item active">
|
||||
<span class="page-link">Current</span>
|
||||
</li>
|
||||
|
||||
<?php if ($hasNext): ?>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?cursor=<?= $lastId ?><?= $queryString ?>" aria-label="Next">
|
||||
<span aria-hidden="true">»</span>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php else: ?>
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">
|
||||
<span aria-hidden="true">»</span>
|
||||
</span>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggleSelectAll() {
|
||||
const selectAll = document.getElementById('selectAll');
|
||||
const checkboxes = document.querySelectorAll('.item-checkbox');
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.checked = selectAll.checked;
|
||||
});
|
||||
|
||||
updateBulkActions();
|
||||
}
|
||||
|
||||
function updateBulkActions() {
|
||||
const checkboxes = document.querySelectorAll('.item-checkbox:checked');
|
||||
const bulkActions = document.getElementById('bulkActions');
|
||||
const selectedCount = document.getElementById('selectedCount');
|
||||
const selectedItems = document.getElementById('selectedItems');
|
||||
const selectAll = document.getElementById('selectAll');
|
||||
|
||||
const count = checkboxes.length;
|
||||
selectedCount.textContent = count;
|
||||
|
||||
if (count > 0) {
|
||||
bulkActions.classList.add('show');
|
||||
const ids = Array.from(checkboxes).map(cb => cb.value);
|
||||
selectedItems.value = ids.join(',');
|
||||
} else {
|
||||
bulkActions.classList.remove('show');
|
||||
selectedItems.value = '';
|
||||
}
|
||||
|
||||
// Update select all checkbox state
|
||||
const allCheckboxes = document.querySelectorAll('.item-checkbox');
|
||||
const checkedCheckboxes = document.querySelectorAll('.item-checkbox:checked');
|
||||
|
||||
if (checkedCheckboxes.length === 0) {
|
||||
selectAll.indeterminate = false;
|
||||
selectAll.checked = false;
|
||||
} else if (checkedCheckboxes.length === allCheckboxes.length) {
|
||||
selectAll.indeterminate = false;
|
||||
selectAll.checked = true;
|
||||
} else {
|
||||
selectAll.indeterminate = true;
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
const checkboxes = document.querySelectorAll('.item-checkbox');
|
||||
const selectAll = document.getElementById('selectAll');
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.checked = false;
|
||||
});
|
||||
selectAll.checked = false;
|
||||
selectAll.indeterminate = false;
|
||||
|
||||
updateBulkActions();
|
||||
}
|
||||
|
||||
function confirmBulkDelete() {
|
||||
const count = document.querySelectorAll('.item-checkbox:checked').length;
|
||||
if (count === 0) {
|
||||
alert('Please select at least one item to delete.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return confirm(`Are you sure you want to delete ${count} selected license(s)? This action cannot be undone.`);
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user