top up batch delete works

This commit is contained in:
armiejean 2025-05-21 23:41:40 +08:00
parent 0d94f37c4b
commit 905ceb0ba5
3 changed files with 185 additions and 166 deletions

View File

@ -22,9 +22,8 @@ class TopUpController extends Controller
return redirect()->route('login')->with('error', 'Please log in to view top-ups.');
}
// Get the requested page from the request (default to 1)
$page = $request->input('page', 1);
$perPage = 5; // Set to 5 items per page
$perPage = 5;
$response = Http::withHeaders([
'Accept' => 'application/json',
@ -55,9 +54,8 @@ class TopUpController extends Controller
];
}, $json['data']);
// Pass pagination metadata to the view
$total = $json['meta']['total'] ?? count($topups); // Total items, adjust based on API response
$lastPage = $json['meta']['last_page'] ?? ceil($total / $perPage); // Calculate last page
$total = $json['meta']['total'] ?? count($topups);
$lastPage = $json['meta']['last_page'] ?? ceil($total / $perPage);
return view('pages.top-up', [
'topups' => $topups,
@ -84,6 +82,7 @@ class TopUpController extends Controller
]);
}
}
public function create()
{
try {
@ -321,37 +320,49 @@ class TopUpController extends Controller
$accessToken = $user['access_token'] ?? null;
if (!$accessToken) {
Log::info('No access token found, redirecting to login from batch delete');
return redirect()->route('login')->with('error', 'Please log in to delete top-ups.');
}
$uuids = $request->input('topup_uuid', []);
if (is_string($uuids)) {
$uuids = json_decode($uuids, true);
if (json_last_error() !== JSON_ERROR_NONE) {
Log::warning('Invalid JSON format for topup_uuid', ['input' => $uuids]);
return redirect()->back()->with('error', 'Invalid top-up UUID format.');
}
}
if (empty($uuids)) {
if (empty($uuids) || !is_array($uuids)) {
Log::warning('No valid topup_uuids provided for batch delete', ['uuids' => $uuids]);
return redirect()->back()->with('error', 'No top-ups selected for deletion.');
}
Log::info('Batch delete UUIDs: ', $uuids);
Log::info('Attempting batch delete for UUIDs: ', ['uuids' => $uuids]);
$response = Http::withHeaders([
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $accessToken,
'Content-Type' => 'application/json',
])->delete("{$this->apiBaseUrl}/cms/topUpBatchDelete", [
'topup_uuid' => $uuids,
]);
$json = $response->json();
if ($response->successful()) {
Log::info('Batch delete successful for UUIDs: ', $uuids);
Log::info('Batch delete response: ', ['response' => $json, 'status' => $response->status(), 'headers' => $response->headers()]);
if ($response->successful() && isset($json['status']) && $json['status'] === 'success') {
Log::info('Batch delete successful for UUIDs: ', ['uuids' => $uuids, 'response' => $json]);
return redirect()->route('top-up')
->with('success', $json['message'] ?? 'Top-ups deleted successfully');
} else {
Log::error('Failed to batch delete top-ups: ', $json);
return redirect()->back()->with('error', $json['message'] ?? 'Failed to delete top-ups.');
Log::error('Batch delete failed: ', ['response' => $json, 'status' => $response->status(), 'headers' => $response->headers()]);
return redirect()->back()->with('error', $json['message'] ?? 'Failed to delete top-ups. Status: ' . $response->status());
}
} catch (\Exception $e) {
Log::error('Error in batch delete: ' . $e->getMessage());
return redirect()->back()->with('error', 'An error occurred while deleting top-ups.');
Log::error('Error in batch delete: ', ['error' => $e->getMessage(), 'uuids' => $uuids ?? [], 'trace' => $e->getTraceAsString()]);
return redirect()->back()->with('error', 'An error occurred while deleting top-ups: ' . $e->getMessage());
}
}
}

View File

@ -217,8 +217,8 @@
total: {{ $total }},
};
const rowsPerPage = 5; // Fixed at 5 per page
let currentPage = tableConfig.currentPage; // Initialize with server-side page
const rowsPerPage = 5;
let currentPage = tableConfig.currentPage;
let filteredRows = [...tableConfig.data];
let originalRows = [...tableConfig.data].map(row => ({ ...row }));
let sortDirection = {};
@ -228,9 +228,11 @@
if (!tableBody) return;
tableBody.innerHTML = '';
// Use the data passed from the server (already paginated to 5)
const paginatedRows = filteredRows; // No client-side slicing needed
const paginatedRows = filteredRows;
if (paginatedRows.length === 0) {
tableBody.innerHTML = `<tr><td colspan="${tableConfig.showCheckboxes ? tableConfig.columns.length + 1 : tableConfig.columns.length}" class="text-center">No data available</td></tr>`;
} else {
paginatedRows.forEach(row => {
const tr = document.createElement('tr');
tr.setAttribute('data-id', row.topup_uuid || row.id);
@ -238,7 +240,7 @@
let rowHtml = '';
if (tableConfig.showCheckboxes) {
rowHtml += `<td class="text-center"><input type="checkbox" class="rowCheckbox"></td>`;
rowHtml += `<td class="text-center"><input type="checkbox" class="rowCheckbox" value="${row.topup_uuid || row.id}"></td>`;
}
tableConfig.columns.forEach(col => {
@ -272,10 +274,10 @@
tr.innerHTML = rowHtml;
tableBody.appendChild(tr);
});
}
attachEventListeners();
updateDeleteButtonState();
updateNoDataMessage();
}
function renderPagination() {
@ -317,15 +319,17 @@
pagination.appendChild(nextLi);
}
function updateNoDataMessage() {
const noDataMessage = document.getElementById('no-data-message');
if (noDataMessage) {
noDataMessage.style.display = filteredRows.length === 0 ? 'block' : 'none';
function updateDeleteButtonState() {
if (tableConfig.showBatchDelete) {
const checkboxes = document.querySelectorAll('.rowCheckbox:checked');
const deleteButton = document.getElementById('deleteSelected');
if (deleteButton) {
deleteButton.disabled = checkboxes.length === 0;
}
}
}
function attachEventListeners() {
// Search
const searchInput = document.getElementById('searchInput');
if (searchInput) {
searchInput.addEventListener('input', function() {
@ -335,13 +339,12 @@
value && value.toString().toLowerCase().includes(searchTerm)
);
});
currentPage = 1; // Reset to first page on search
currentPage = 1;
renderTable();
renderPagination();
});
}
// Sort
document.querySelectorAll('.sortable').forEach(header => {
header.addEventListener('click', function() {
const columnIndex = parseInt(this.getAttribute('data-column')) - (tableConfig.showCheckboxes ? 1 : 0);
@ -365,13 +368,12 @@
return sortDirection[columnIndex] === 'asc' ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
});
currentPage = 1; // Reset to first page on sort
currentPage = 1;
renderTable();
renderPagination();
});
});
// Clear Filters
const clearFilters = document.getElementById('clearFilters');
if (clearFilters) {
clearFilters.addEventListener('click', function() {
@ -388,7 +390,6 @@
});
}
// Checkboxes
if (tableConfig.showCheckboxes) {
const selectAll = document.getElementById('selectAll');
if (selectAll) {
@ -406,14 +407,12 @@
});
}
// Batch Delete
if (tableConfig.showBatchDelete) {
const deleteSelected = document.getElementById('deleteSelected');
if (deleteSelected) {
deleteSelected.addEventListener('click', function() {
const checkboxes = document.querySelectorAll('.rowCheckbox:checked');
const selectedIds = Array.from(checkboxes)
.map(cb => cb.closest('tr').getAttribute('data-id'));
const selectedIds = Array.from(checkboxes).map(cb => cb.value);
if (selectedIds.length === 0) {
alert('Please select at least one top-up to delete.');
@ -421,25 +420,30 @@
}
if (confirm('Are you sure you want to delete the selected top-ups?')) {
axios.delete('{{ route('top-up.batchDelete') }}', {
headers: {
'X-CSRF-TOKEN': tableConfig.csrfToken
},
data: {
topup_uuid: selectedIds
}
}).then(response => {
window.location.reload(); // Reload to fetch new data
}).catch(error => {
console.error('Batch delete error:', error);
alert(error.response?.data?.message || 'Failed to delete top-ups.');
});
}
});
}
}
console.log('Submitting batch delete form with UUIDs:', selectedIds);
const form = document.createElement('form');
form.method = 'POST';
form.action = '{{ route('top-up.batchDelete') }}';
form.style.display = 'none';
// Delete
const csrfInput = document.createElement('input');
csrfInput.type = 'hidden';
csrfInput.name = '_token';
csrfInput.value = tableConfig.csrfToken;
form.appendChild(csrfInput);
const uuidInput = document.createElement('input');
uuidInput.type = 'hidden';
uuidInput.name = 'topup_uuid';
uuidInput.value = JSON.stringify(selectedIds);
form.appendChild(uuidInput);
document.body.appendChild(form);
form.submit();
}
});
}
}
document.querySelectorAll('.delete-btn').forEach(button => {
button.addEventListener('click', function(e) {
e.stopPropagation();
@ -450,7 +454,22 @@
'X-CSRF-TOKEN': tableConfig.csrfToken
}
}).then(response => {
window.location.reload(); // Reload to fetch new data
if (response.data.status === 'success') {
filteredRows = filteredRows.filter(row => row.topup_uuid !== topupId);
tableConfig.data = tableConfig.data.filter(row => row.topup_uuid !== topupId);
tableConfig.total -= 1;
tableConfig.lastPage = Math.ceil(tableConfig.total / rowsPerPage);
if (filteredRows.length === 0 && currentPage > 1) {
window.location.href = `{{ route('top-up') }}?page=${currentPage - 1}`;
} else {
renderTable();
renderPagination();
alert(response.data.message || 'Top-up deleted successfully');
}
} else {
alert(response.data.message || 'Failed to delete top-up.');
}
}).catch(error => {
console.error('Delete error:', error);
alert(error.response?.data?.message || 'Failed to delete top-up.');
@ -459,7 +478,6 @@
});
});
// Row click to view
document.querySelectorAll('.clickable-row').forEach(row => {
row.addEventListener('click', function(e) {
if (e.target.closest('.rowCheckbox, .edit-btn, .view-btn, .delete-btn')) {
@ -471,17 +489,6 @@
});
}
function updateDeleteButtonState() {
if (tableConfig.showBatchDelete) {
const checkboxes = document.querySelectorAll('.rowCheckbox');
const checkedCount = Array.from(checkboxes).filter(cb => cb.checked).length;
const deleteButton = document.getElementById('deleteSelected');
if (deleteButton) {
deleteButton.disabled = checkedCount < 1;
}
}
}
renderTable();
renderPagination();
</script>

View File

@ -146,7 +146,8 @@ Route::get('/top-up/{uuid}', [TopUpController::class, 'show'])->name('top-up.sho
Route::get('/top-up/{uuid}/edit', [TopUpController::class, 'edit'])->name('top-up.edit');
Route::put('/top-up/{uuid}', [TopUpController::class, 'update'])->name('top-up.update');
Route::delete('/top-up/{uuid}', [TopUpController::class, 'destroy'])->name('top-up.destroy');
Route::delete('/top-up/batch', [TopUpController::class, 'batchDelete'])->name('top-up.batchDelete');
Route::post('top-up/batchDelete', [TopUpController::class, 'batchDelete'])->name('top-up.batchDelete');
//Photo Slider
Route::get('/photo-slider', [PhotoSliderController::class, 'index'])->name('photo-slider');