diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index 98995f2..8971ed5 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -16,7 +16,7 @@ class ReportsController extends Controller $this->apiBaseUrl = env('EXTERNAL_API_URL', 'http://localhost:8081/api/'); } - private function makeApiRequest($endpoint, $params, $isDownload = false) + private function makeApiRequest($endpoint, $params, $isDownload = false) { try { $user = Session::get('user'); @@ -59,7 +59,7 @@ class ReportsController extends Controller } if ($isDownload) { - return $response; // Return raw response for file download + return $response; } return $response->json(); @@ -77,6 +77,7 @@ class ReportsController extends Controller return null; } } + public function mobileUsage(Request $request) { $params = [ @@ -91,7 +92,7 @@ class ReportsController extends Controller $data = $this->makeApiRequest('cms/reportMobileUsage', $params); if (is_a($data, '\Illuminate\Http\RedirectResponse')) { - return $data; // Redirect to login if unauthorized + return $data; } $mobileUsageData = []; @@ -124,6 +125,33 @@ class ReportsController extends Controller return view('pages.reports.mobile-usage-report', compact('mobileUsageData', 'currentPage', 'lastPage', 'total', 'errorMessage')); } + public function exportMobileUsage(Request $request) + { + $params = [ + 'date_start' => $request->input('date_start'), + 'date_end' => $request->input('date_end'), + '_search' => $request->input('_search'), + 'sorting' => $request->input('sort', 'date|desc'), + ]; + + $response = $this->makeApiRequest('cms/reportMobileUsageExport', $params, true); + + if (is_a($response, '\Illuminate\Http\RedirectResponse')) { + return $response; + } + + if (!$response) { + Log::warning("Failed to export mobile usage data", ['params' => $params]); + return redirect()->back()->with('error', 'Failed to export CSV.'); + } + + $filename = "reports_mobile_usage" . date("mdY") . ".csv"; + + return response($response->body(), 200) + ->header('Content-Type', 'text/csv') + ->header('Content-Disposition', "attachment; filename=\"$filename\""); + } + public function registration(Request $request) { $params = [ @@ -170,53 +198,108 @@ class ReportsController extends Controller return view('pages.reports.registration-report', compact('registrationData', 'currentPage', 'lastPage', 'total', 'errorMessage')); } - public function stationRating(Request $request) -{ - $params = [ - 'page' => $request->input('page', 1), - 'page_size' => 5, - 'date_start' => $request->input('date_start'), - 'date_end' => $request->input('date_end'), - 'sorting' => $request->input('sort', 'date|desc'), - '_search' => $request->input('_search'), - ]; + public function exportRegistration(Request $request) + { + $params = [ + 'date_start' => $request->input('date_start'), + 'date_end' => $request->input('date_end'), + '_search' => $request->input('_search'), + 'sorting' => $request->input('sort', 'date|desc'), + ]; - $data = $this->makeApiRequest('cms/reportStationRatings', $params); + $response = $this->makeApiRequest('cms/reportRegistrationExport', $params, true); - if (is_a($data, '\Illuminate\Http\RedirectResponse')) { - return $data; + if (is_a($response, '\Illuminate\Http\RedirectResponse')) { + return $response; + } + + if (!$response) { + Log::warning("Failed to export registration data", ['params' => $params]); + return redirect()->back()->with('error', 'Failed to export CSV.'); + } + + $filename = "registration" . date("mdY") . ".csv"; + + return response($response->body(), 200) + ->header('Content-Type', 'text/csv') + ->header('Content-Disposition', "attachment; filename=\"$filename\""); } - $stationRatingData = []; - $currentPage = $params['page']; - $lastPage = 1; - $total = 0; - $errorMessage = null; + public function stationRating(Request $request) + { + $params = [ + 'page' => $request->input('page', 1), + 'page_size' => 5, + 'date_start' => $request->input('date_start'), + 'date_end' => $request->input('date_end'), + 'sorting' => $request->input('sort', 'date|desc'), + '_search' => $request->input('_search'), + ]; - if ($data && isset($data['data'])) { - $stationRatingData = array_map(function ($item) { - return [ - 'id' => $item['id'] ?? uniqid(), - 'transactionDateTime' => $item['date'], - 'cardNumber' => $item['card_number'], - 'salesInvoice' => $item['invoice'], - 'station' => $item['station'], - 'ratings' => $item['rate'], - ]; - }, $data['data']); - $currentPage = $data['meta']['current_page'] ?? 1; - $lastPage = $data['meta']['last_page'] ?? 1; - $total = $data['meta']['total'] ?? count($stationRatingData); - } elseif ($data && isset($data['message'])) { - Log::info("API returned message for stationRating", ['message' => $data['message']]); - $errorMessage = $data['message']; - } else { - Log::warning("No data returned or invalid response structure for stationRating", ['data' => $data]); - $errorMessage = 'Failed to fetch station rating data.'; + $data = $this->makeApiRequest('cms/reportStationRatings', $params); + + if (is_a($data, '\Illuminate\Http\RedirectResponse')) { + return $data; + } + + $stationRatingData = []; + $currentPage = $params['page']; + $lastPage = 1; + $total = 0; + $errorMessage = null; + + if ($data && isset($data['data'])) { + $stationRatingData = array_map(function ($item) { + return [ + 'id' => $item['id'] ?? uniqid(), + 'transactionDateTime' => $item['date'], + 'cardNumber' => $item['card_number'], + 'salesInvoice' => $item['invoice'], + 'station' => $item['station'], + 'ratings' => $item['rate'], + ]; + }, $data['data']); + $currentPage = $data['meta']['current_page'] ?? 1; + $lastPage = $data['meta']['last_page'] ?? 1; + $total = $data['meta']['total'] ?? count($stationRatingData); + } elseif ($data && isset($data['message'])) { + Log::info("API returned message for stationRating", ['message' => $data['message']]); + $errorMessage = $data['message']; + } else { + Log::warning("No data returned or invalid response structure for stationRating", ['data' => $data]); + $errorMessage = 'Failed to fetch station rating data.'; + } + + return view('pages.reports.station-rating-report', compact('stationRatingData', 'currentPage', 'lastPage', 'total', 'errorMessage')); + } + + public function exportStationRating(Request $request) + { + $params = [ + 'date_start' => $request->input('date_start'), + 'date_end' => $request->input('date_end'), + '_search' => $request->input('_search'), + 'sorting' => $request->input('sort', 'date|desc'), + ]; + + $response = $this->makeApiRequest('cms/reportStationRatingsExport', $params, true); + + if (is_a($response, '\Illuminate\Http\RedirectResponse')) { + return $response; + } + + if (!$response) { + Log::warning("Failed to export station rating data", ['params' => $params]); + return redirect()->back()->with('error', 'Failed to export CSV.'); + } + + $filename = "reports_station_rating" . date("mdY") . ".csv"; + + return response($response->body(), 200) + ->header('Content-Type', 'text/csv') + ->header('Content-Disposition', "attachment; filename=\"$filename\""); } - return view('pages.reports.station-rating-report', compact('stationRatingData', 'currentPage', 'lastPage', 'total', 'errorMessage')); -} public function topUp(Request $request) { $params = [ @@ -263,27 +346,27 @@ class ReportsController extends Controller return view('pages.reports.top-up-usage-report', compact('topUpData', 'currentPage', 'lastPage', 'total', 'errorMessage')); } - public function exportStationRating(Request $request) + public function exportTopUp(Request $request) { $params = [ 'date_start' => $request->input('date_start'), 'date_end' => $request->input('date_end'), '_search' => $request->input('_search'), - 'sorting' => $request->input('sort', 'date|desc'), + 'sorting' => $request->input('sort', 'transaction_date_time|desc'), ]; - $response = $this->makeApiRequest('cms/reportStationRatingsExport', $params, true); + $response = $this->makeApiRequest('cms/reportTopUpExport', $params, true); if (is_a($response, '\Illuminate\Http\RedirectResponse')) { return $response; } if (!$response) { - Log::warning("Failed to export station rating data", ['params' => $params]); + Log::warning("Failed to export top-up data", ['params' => $params]); return redirect()->back()->with('error', 'Failed to export CSV.'); } - $filename = "reports_station_rating" . date("mdY") . ".csv"; + $filename = "reports_top_up" . date("mdY") . ".csv"; return response($response->body(), 200) ->header('Content-Type', 'text/csv') diff --git a/app/Http/Controllers/StationController.php b/app/Http/Controllers/StationController.php index b4350fe..9f400b7 100644 --- a/app/Http/Controllers/StationController.php +++ b/app/Http/Controllers/StationController.php @@ -4,195 +4,141 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Http; -use Illuminate\Support\Str; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Session; class StationController extends Controller { - protected $apiBaseUrl = 'http://192.168.100.6:8081/api/'; + protected $apiBaseUrl = 'http://192.168.100.6:8081/api/cms'; - public function index(Request $request) -{ - $params = [ - 'page' => $request->input('page', 1), - 'page_size' => 5, - '_search' => $request->input('_search'), - 'sort' => $request->input('sort', 'code|asc'), - ]; + public function index(Request $request) + { + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; - $response = Http::get($this->apiBaseUrl . 'cms/getStations', $params); - $data = $response->json(); + if (!$accessToken) { + Log::info('No access token found, redirecting to login from stations'); + return redirect()->route('login')->with('error', 'Please log in to view stations.'); + } - \Log::info('Stations API Response:', ['status' => $response->status(), 'data' => $data]); + $page = $request->input('page', 1); + $pageSize = 5; + $search = $request->input('_search', null); + $sort = $request->input('sort', 'station_code|asc'); - $stations = []; - $currentPage = $params['page']; - $lastPage = 1; - $total = 0; + Log::info('Initiating API request to fetch stations', [ + 'url' => "{$this->apiBaseUrl}/getStations", + 'params' => [ + 'page' => $page, + 'page_size' => $pageSize, + '_search' => $search, + 'sort' => $sort, + ], + ]); - if ($response->successful() && isset($data['data'])) { - $stations = array_map(function ($item) { - return [ - 'id' => $item['station_uuid'], - 'station_code' => $item['code'], - 'station_name' => $item['description'], - 'branch_name' => 'N/A', - 'date_created' => 'N/A', - 'created_by' => 'N/A', - 'modified_by' => 'N/A', - 'date_modified' => 'N/A', - ]; - }, $data['data']); + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->timeout(30)->get("{$this->apiBaseUrl}/getStations", [ + 'page' => $page, + 'page_size' => $pageSize, + '_search' => $search, + 'sort' => $sort, + ]); - $total = count($data['data']); - $lastPage = ceil($total / $params['page_size']); - $currentPage = min($currentPage, $lastPage); + $json = $response->json(); + $rawResponse = $response->body(); - if ($params['_search']) { - $searchTerm = strtolower($params['_search']); - $stations = array_filter($stations, function ($station) use ($searchTerm) { - return str_contains(strtolower($station['station_code']), $searchTerm) || - str_contains(strtolower($station['station_name']), $searchTerm) || - str_contains(strtolower($station['branch_name']), $searchTerm); - }); - $stations = array_values($stations); - $total = count($stations); - $lastPage = ceil($total / $params['page_size']); + Log::info('API response received for stations', [ + 'status' => $response->status(), + 'headers' => $response->headers(), + 'data' => $json, + 'raw_response' => $rawResponse, + 'reason' => $response->reason(), + ]); + + if ($response->status() === 401 || $response->status() === 403) { + Log::warning('Unauthorized or Forbidden API response for stations', ['response' => $json]); + return redirect()->route('login')->with('error', 'Your session has expired. Please log in again.'); + } + + if ($response->successful() && isset($json['code']) && $json['code'] == 200 && isset($json['data']) && is_array($json['data'])) { + $stations = array_map(function ($station) { + return [ + 'id' => $station['station_uuid'] ?? '', + 'station_code' => $station['code'] ?? '', + 'station_name' => $station['description'] ?? '', + 'branch_name' => $station['branch_name'] ?? '', + 'date_created' => $station['date_created'] ?? '', + 'created_by' => $station['created_by'] ?? '', + 'modified_by' => $station['modified_by'] ?? '', + 'date_modified' => $station['date_modified'] ?? '', + ]; + }, $json['data']); + + // Use meta for pagination if provided, else calculate locally + $total = $json['meta']['total'] ?? count($stations); + $lastPage = $json['meta']['last_page'] ?? ceil($total / $pageSize); + + // Apply search filter locally if needed + if ($search) { + $searchTerm = strtolower($search); + $stations = array_filter($stations, function ($station) use ($searchTerm) { + return str_contains(strtolower($station['station_code'] ?? ''), $searchTerm) || + str_contains(strtolower($station['station_name'] ?? ''), $searchTerm); + }); + $stations = array_values($stations); + $total = count($stations); + $lastPage = ceil($total / $pageSize); + } + + // Apply sorting locally + if ($sort) { + [$sortField, $sortDir] = explode('|', $sort); + usort($stations, function ($a, $b) use ($sortField, $sortDir) { + $aValue = $a[$sortField] ?? ''; + $bValue = $b[$sortField] ?? ''; + return $sortDir === 'asc' ? strcmp($aValue, $bValue) : strcmp($bValue, $aValue); + }); + } + + // Paginate locally + $start = ($page - 1) * $pageSize; + $stations = array_slice($stations, $start, $pageSize); + } else { + Log::warning('No station data found or invalid API response', ['response' => $json]); + $stations = []; + $total = 0; + $lastPage = 1; + } + + Log::info('Processed stations data', [ + 'stations_count' => count($stations), + 'total' => $total, + 'currentPage' => $page, + 'lastPage' => $lastPage, + 'stations' => $stations, + ]); + + return view('pages.station locator.stations', [ + 'stations' => $stations, + 'currentPage' => $page, + 'lastPage' => $lastPage, + 'total' => $total, + 'search' => $search, + ]); + } catch (\Exception $e) { + Log::error('Error fetching stations: ' . $e->getMessage(), [ + 'trace' => $e->getTraceAsString(), + ]); + return view('pages.station locator.stations', [ + 'stations' => [], + 'currentPage' => 1, + 'lastPage' => 1, + 'total' => 0, + 'search' => $search, + ])->with('error', 'Failed to fetch stations: ' . $e->getMessage()); } - - if ($params['sort']) { - [$sortField, $sortDir] = explode('|', $params['sort']); - usort($stations, function ($a, $b) use ($sortField, $sortDir) { - $aValue = $a[$sortField] ?? ''; - $bValue = $b[$sortField] ?? ''; - return $sortDir === 'asc' ? strcmp($aValue, $bValue) : strcmp($bValue, $aValue); - }); - } - - $start = ($currentPage - 1) * $params['page_size']; - $stations = array_slice($stations, $start, $params['page_size']); } - - return view('pages.station locator.stations', compact('stations', 'currentPage', 'lastPage', 'total')); -} - - // public function create() - // { - // return view('pages.add-station'); - // } - - // public function store(Request $request) - // { - // $request->validate([ - // 'station_code' => 'required|string|max:50|unique:stations,station_code', - // 'station_name' => 'required|string|max:255', - // 'branch_name' => 'required|string|max:255', - // ]); - - // // Mock API call to store station - // $response = Http::post($this->apiBaseUrl . 'cms/stations/store', [ - // 'code' => $request->station_code, - // 'description' => $request->station_name, - // 'branch_name' => $request->branch_name, - // 'is_viewable' => 1, - // 'is_active' => 1, - // ]); - - // if ($response->successful()) { - // return redirect()->route('station-management')->with('success', 'Station added successfully'); - // } - - // return back()->withErrors(['error' => 'Failed to add station']); - // } - - // public function show($id) - // { - // $response = Http::get($this->apiBaseUrl . 'cms/getStations'); - // $data = $response->json(); - - // $station = null; - // if ($response->successful() && isset($data['data'])) { - // $station = collect($data['data'])->firstWhere('station_uuid', $id); - // if ($station) { - // $station = [ - // 'id' => $station['station_uuid'], - // 'station_code' => $station['code'], - // 'station_name' => $station['description'], - // 'branch_name' => 'N/A', - // 'date_created' => 'N/A', - // 'created_by' => 'N/A', - // 'modified_by' => 'N/A', - // 'date_modified' => 'N/A', - // ]; - // } - // } - - // if (!$station) { - // abort(404, 'Station not found'); - // } - - // return view('pages.view-station', compact('station')); - // } - - // public function edit($id) - // { - // $response = Http::get($this->apiBaseUrl . 'cms/getStations'); - // $data = $response->json(); - - // $station = null; - // if ($response->successful() && isset($data['data'])) { - // $station = collect($data['data'])->firstWhere('station_uuid', $id); - // if ($station) { - // $station = [ - // 'id' => $station['station_uuid'], - // 'station_code' => $station['code'], - // 'station_name' => $station['description'], - // 'branch_name' => 'N/A', - // 'date_created' => 'N/A', - // 'created_by' => 'N/A', - // 'modified_by' => 'N/A', - // 'date_modified' => 'N/A', - // ]; - // } - // } - - // if (!$station) { - // abort(404, 'Station not found'); - // } - - // return view('pages.edit-station', compact('station')); - // } - - // public function update(Request $request, $id) - // { - // $request->validate([ - // 'station_code' => 'required|string|max:50|unique:stations,station_code,' . $id . ',id', - // 'station_name' => 'required|string|max:255', - // 'branch_name' => 'required|string|max:255', - // ]); - - // // Mock API call to update station - // $response = Http::put($this->apiBaseUrl . 'cms/stations/update/' . $id, [ - // 'code' => $request->station_code, - // 'description' => $request->station_name, - // 'branch_name' => $request->branch_name, - // ]); - - // if ($response->successful()) { - // return redirect()->route('station-management')->with('success', 'Station updated successfully'); - // } - - // return back()->withErrors(['error' => 'Failed to update station']); - // } - - // public function destroy($id) - // { - // // Mock API call to delete station - // $response = Http::delete($this->apiBaseUrl . 'cms/stations/delete/' . $id); - - // if ($response->successful()) { - // return redirect()->route('station-management')->with('success', 'Station deleted successfully'); - // } - - // return back()->withErrors(['error' => 'Failed to delete station']); - // } } \ No newline at end of file diff --git a/resources/views/components/station-component.blade.php b/resources/views/components/station-component.blade.php index 38fd179..3b599fa 100644 --- a/resources/views/components/station-component.blade.php +++ b/resources/views/components/station-component.blade.php @@ -12,6 +12,7 @@ 'currentPage' => 1, 'lastPage' => 1, 'total' => 0, + 'search' => null, ])
- - | - @endif @foreach ($columns as $index => $column) -+ | {{ $column['name'] }} @if ($column['sortable']) @@ -69,15 +65,8 @@ |
---|
${col.name}: ${value}
`; }); modalBody.innerHTML = html; @@ -356,16 +371,18 @@ const searchInput = document.getElementById('searchInput'); if (searchInput) { searchInput.addEventListener('input', function() { + console.log('Search input:', this.value); updateUrl(1, this.value); }); } document.querySelectorAll('.sortable').forEach(header => { header.addEventListener('click', function() { - const columnIndex = parseInt(this.getAttribute('data-column')) - (tableConfig.showCheckboxes ? 1 : 0); + const columnIndex = parseInt(this.getAttribute('data-column')); const key = tableConfig.columns[columnIndex].key; sortDirection[columnIndex] = !sortDirection[columnIndex] ? 'asc' : sortDirection[columnIndex] === 'asc' ? 'desc' : 'asc'; + console.log('Sorting:', { key, direction: sortDirection[columnIndex] }); document.querySelectorAll('.sortable i').forEach(icon => { icon.classList.remove('fa-sort-up', 'fa-sort-down'); @@ -384,6 +401,7 @@ const clearFilters = document.getElementById('clearFilters'); if (clearFilters) { clearFilters.addEventListener('click', function() { + console.log('Clearing filters'); if (searchInput) searchInput.value = ''; sortDirection = {}; document.querySelectorAll('.sortable i').forEach(icon => { @@ -394,57 +412,13 @@ }); } - const checkboxes = document.querySelectorAll('.rowCheckbox'); - const selectAll = document.getElementById('selectAll'); - const deleteSelected = document.getElementById('deleteSelected'); - - if (selectAll) { - selectAll.addEventListener('change', function() { - checkboxes.forEach(checkbox => checkbox.checked = this.checked); - updateDeleteButton(); - }); - } - - if (checkboxes.length > 0) { - checkboxes.forEach(checkbox => { - checkbox.addEventListener('change', updateDeleteButton); - }); - } - - if (deleteSelected) { - deleteSelected.addEventListener('click', function() { - const selectedIds = Array.from(document.querySelectorAll('.rowCheckbox:checked')).map(cb => cb.value); - if (selectedIds.length > 0 && confirm('Are you sure you want to delete the selected stations?')) { - fetch('/stations/batch-delete', { - method: 'POST', - headers: { - 'X-CSRF-TOKEN': tableConfig.csrfToken, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - body: JSON.stringify({ station_ids: selectedIds }) - }).then(response => response.json()) - .then(data => { - if (data.success) { - location.reload(); - } else { - alert(data.message || 'Error deleting stations'); - } - }) - .catch(error => { - console.error('Error:', error); - alert('An error occurred while deleting the stations.'); - }); - } - }); - } - document.querySelectorAll('.clickable-row').forEach(row => { row.addEventListener('click', function(e) { - if (e.target.closest('.rowCheckbox, .edit-btn, .view-btn, .delete-btn')) { + if (e.target.closest('.edit-btn, .view-btn, .delete-btn')) { return; } const id = this.getAttribute('data-id'); + console.log('Row clicked:', id); if (tableConfig.showViewModal) { openViewModal(id); } else { @@ -454,14 +428,12 @@ }); } - function updateDeleteButton() { - const deleteSelected = document.getElementById('deleteSelected'); - const checkedBoxes = document.querySelectorAll('.rowCheckbox:checked'); - deleteSelected.disabled = checkedBoxes.length === 0; + try { + renderTable(); + renderPagination(); + } catch (error) { + console.error('Error rendering table:', error); } - - renderTable(); - renderPagination(); - - \ No newline at end of file + + \ No newline at end of file diff --git a/resources/views/pages/reports/mobile-usage-report.blade.php b/resources/views/pages/reports/mobile-usage-report.blade.php index f47c495..c1b3de4 100644 --- a/resources/views/pages/reports/mobile-usage-report.blade.php +++ b/resources/views/pages/reports/mobile-usage-report.blade.php @@ -8,20 +8,23 @@No stations found.
-