top up batch delete works
This commit is contained in:
parent
0d94f37c4b
commit
905ceb0ba5
|
@ -11,62 +11,69 @@ class TopUpController extends Controller
|
|||
{
|
||||
protected $apiBaseUrl = 'http://192.168.100.6:8081/api';
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
$user = Session::get('user');
|
||||
$accessToken = $user['access_token'] ?? null;
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
$user = Session::get('user');
|
||||
$accessToken = $user['access_token'] ?? null;
|
||||
|
||||
if (!$accessToken) {
|
||||
Log::info('No access token found, redirecting to login from top-up');
|
||||
return redirect()->route('login')->with('error', 'Please log in to view top-ups.');
|
||||
}
|
||||
if (!$accessToken) {
|
||||
Log::info('No access token found, redirecting to login from top-up');
|
||||
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
|
||||
$page = $request->input('page', 1);
|
||||
$perPage = 5;
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $accessToken,
|
||||
])->get("{$this->apiBaseUrl}/cms/topUp", [
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
]);
|
||||
|
||||
if ($response->status() === 401 || $response->status() === 403) {
|
||||
Log::warning('Unauthorized or Forbidden API response: ', $response->json());
|
||||
return redirect()->route('login')->with('error', 'Your session has expired. Please log in again.');
|
||||
}
|
||||
|
||||
$json = $response->json();
|
||||
|
||||
Log::info("TopUp API Response (Page {$page}): ", $json);
|
||||
|
||||
if ($response->successful() && isset($json['data']) && is_array($json['data'])) {
|
||||
$topups = array_map(function ($topup) {
|
||||
Log::info('Processing top-up record: ', $topup);
|
||||
return [
|
||||
'topup_uuid' => $topup['topup_uuid'] ?? $topup['id'] ?? null,
|
||||
'freeCode' => $topup['fee_code'] ?? 'N/A',
|
||||
'name' => $topup['name'] ?? 'Unnamed',
|
||||
'value' => $topup['amount'] ?? 0,
|
||||
'type' => $topup['type'] ?? 'Unknown',
|
||||
];
|
||||
}, $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
|
||||
|
||||
return view('pages.top-up', [
|
||||
'topups' => $topups,
|
||||
'currentPage' => $page,
|
||||
'lastPage' => $lastPage,
|
||||
'total' => $total,
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $accessToken,
|
||||
])->get("{$this->apiBaseUrl}/cms/topUp", [
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
]);
|
||||
} else {
|
||||
Log::warning('No top-up data found or invalid API response: ', $json);
|
||||
|
||||
if ($response->status() === 401 || $response->status() === 403) {
|
||||
Log::warning('Unauthorized or Forbidden API response: ', $response->json());
|
||||
return redirect()->route('login')->with('error', 'Your session has expired. Please log in again.');
|
||||
}
|
||||
|
||||
$json = $response->json();
|
||||
|
||||
Log::info("TopUp API Response (Page {$page}): ", $json);
|
||||
|
||||
if ($response->successful() && isset($json['data']) && is_array($json['data'])) {
|
||||
$topups = array_map(function ($topup) {
|
||||
Log::info('Processing top-up record: ', $topup);
|
||||
return [
|
||||
'topup_uuid' => $topup['topup_uuid'] ?? $topup['id'] ?? null,
|
||||
'freeCode' => $topup['fee_code'] ?? 'N/A',
|
||||
'name' => $topup['name'] ?? 'Unnamed',
|
||||
'value' => $topup['amount'] ?? 0,
|
||||
'type' => $topup['type'] ?? 'Unknown',
|
||||
];
|
||||
}, $json['data']);
|
||||
|
||||
$total = $json['meta']['total'] ?? count($topups);
|
||||
$lastPage = $json['meta']['last_page'] ?? ceil($total / $perPage);
|
||||
|
||||
return view('pages.top-up', [
|
||||
'topups' => $topups,
|
||||
'currentPage' => $page,
|
||||
'lastPage' => $lastPage,
|
||||
'total' => $total,
|
||||
]);
|
||||
} else {
|
||||
Log::warning('No top-up data found or invalid API response: ', $json);
|
||||
return view('pages.top-up', [
|
||||
'topups' => [],
|
||||
'currentPage' => 1,
|
||||
'lastPage' => 1,
|
||||
'total' => 0,
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error fetching top-up data: ' . $e->getMessage());
|
||||
return view('pages.top-up', [
|
||||
'topups' => [],
|
||||
'currentPage' => 1,
|
||||
|
@ -74,16 +81,8 @@ class TopUpController extends Controller
|
|||
'total' => 0,
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error fetching top-up data: ' . $e->getMessage());
|
||||
return view('pages.top-up', [
|
||||
'topups' => [],
|
||||
'currentPage' => 1,
|
||||
'lastPage' => 1,
|
||||
'total' => 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,54 +228,56 @@
|
|||
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;
|
||||
|
||||
paginatedRows.forEach(row => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.setAttribute('data-id', row.topup_uuid || row.id);
|
||||
tr.classList.add('clickable-row');
|
||||
let rowHtml = '';
|
||||
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);
|
||||
tr.classList.add('clickable-row');
|
||||
let rowHtml = '';
|
||||
|
||||
if (tableConfig.showCheckboxes) {
|
||||
rowHtml += `<td class="text-center"><input type="checkbox" class="rowCheckbox"></td>`;
|
||||
}
|
||||
if (tableConfig.showCheckboxes) {
|
||||
rowHtml += `<td class="text-center"><input type="checkbox" class="rowCheckbox" value="${row.topup_uuid || row.id}"></td>`;
|
||||
}
|
||||
|
||||
tableConfig.columns.forEach(col => {
|
||||
let value = row[col.key] || '';
|
||||
rowHtml += `<td>${value}</td>`;
|
||||
});
|
||||
|
||||
if (tableConfig.actions.length > 0) {
|
||||
rowHtml += `<td class="text-center">`;
|
||||
tableConfig.actions.forEach(action => {
|
||||
if (action === 'edit') {
|
||||
rowHtml += `
|
||||
<a href="{{ route('top-up.edit', '') }}/${row.topup_uuid || row.id}" class="btn btn-sm edit-btn me-1" title="Edit">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</a>`;
|
||||
} else if (action === 'view') {
|
||||
rowHtml += `
|
||||
<a href="{{ route('top-up.show', '') }}/${row.topup_uuid || row.id}" class="btn btn-sm btn-outline-secondary me-1 view-btn" title="View">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</a>`;
|
||||
} else if (action === 'delete') {
|
||||
rowHtml += `
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn" title="Delete" data-id="${row.topup_uuid || row.id}">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
</button>`;
|
||||
}
|
||||
tableConfig.columns.forEach(col => {
|
||||
let value = row[col.key] || '';
|
||||
rowHtml += `<td>${value}</td>`;
|
||||
});
|
||||
rowHtml += `</td>`;
|
||||
}
|
||||
|
||||
tr.innerHTML = rowHtml;
|
||||
tableBody.appendChild(tr);
|
||||
});
|
||||
if (tableConfig.actions.length > 0) {
|
||||
rowHtml += `<td class="text-center">`;
|
||||
tableConfig.actions.forEach(action => {
|
||||
if (action === 'edit') {
|
||||
rowHtml += `
|
||||
<a href="{{ route('top-up.edit', '') }}/${row.topup_uuid || row.id}" class="btn btn-sm edit-btn me-1" title="Edit">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</a>`;
|
||||
} else if (action === 'view') {
|
||||
rowHtml += `
|
||||
<a href="{{ route('top-up.show', '') }}/${row.topup_uuid || row.id}" class="btn btn-sm btn-outline-secondary me-1 view-btn" title="View">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</a>`;
|
||||
} else if (action === 'delete') {
|
||||
rowHtml += `
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn" title="Delete" data-id="${row.topup_uuid || row.id}">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
</button>`;
|
||||
}
|
||||
});
|
||||
rowHtml += `</td>`;
|
||||
}
|
||||
|
||||
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,40 +407,43 @@
|
|||
});
|
||||
}
|
||||
|
||||
// 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'));
|
||||
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.value);
|
||||
|
||||
if (selectedIds.length === 0) {
|
||||
alert('Please select at least one top-up to delete.');
|
||||
return;
|
||||
}
|
||||
|
||||
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.');
|
||||
});
|
||||
}
|
||||
});
|
||||
if (selectedIds.length === 0) {
|
||||
alert('Please select at least one top-up to delete.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete
|
||||
if (confirm('Are you sure you want to delete the selected 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';
|
||||
|
||||
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>
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Reference in New Issue