diff --git a/app/Http/Controllers/UserManagementController.php b/app/Http/Controllers/UserManagementController.php index 62284f3..432779c 100644 --- a/app/Http/Controllers/UserManagementController.php +++ b/app/Http/Controllers/UserManagementController.php @@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Session; class UserManagementController extends Controller { + protected $apiBaseUrl = 'http://192.168.100.6:8081/api'; public function index() @@ -38,7 +39,7 @@ class UserManagementController extends Controller 'username' => $admin['username'], 'firstName' => $admin['firstname'], 'lastName' => $admin['lastname'], - 'role' => 'Admin', + 'role' => $admin['role'] == '1' ? 'Admin' : 'User', 'email' => $admin['email'], 'status' => $admin['status'] ? 'Active' : 'Inactive', ]; @@ -107,7 +108,7 @@ class UserManagementController extends Controller 'role' => $validated['role'], 'email' => $validated['email'], 'password' => $generatedPassword, - 'status' => $validated['status'], // Send as 'active' or 'inactive' + 'status' => $validated['status'], ]; Log::info('API Payload for creating user: ', $payload); @@ -140,7 +141,8 @@ class UserManagementController extends Controller $accessToken = $user['access_token'] ?? null; if (!$accessToken) { - return response()->json(['error' => 'Unauthorized'], 401); + Log::info('No access token found, redirecting to login from user-management show'); + return redirect()->route('login')->with('error', 'Please log in to view user details.'); } $response = Http::withHeaders([ @@ -156,19 +158,19 @@ class UserManagementController extends Controller 'username' => $json['data']['username'], 'firstName' => $json['data']['firstname'], 'lastName' => $json['data']['lastname'], - 'role' => 'Admin', + 'role' => $json['data']['role'] == '1' ? 'Admin' : 'User', 'email' => $json['data']['email'], 'status' => $json['data']['status'] ? 'Active' : 'Inactive', 'generated_password' => $json['data']['generated_password'] ?? null, ]; - return response()->json(['data' => $userData]); + return view('pages.user-management.show-user', ['user' => $userData]); } else { Log::warning('User not found: ', $json); - return response()->json(['error' => $json['message'] ?? 'User not found'], 404); + return redirect()->route('user.management')->with('error', $json['message'] ?? 'User not found.'); } } catch (\Exception $e) { Log::error('Error fetching user: ' . $e->getMessage()); - return response()->json(['error' => 'An error occurred'], 500); + return redirect()->route('user.management')->with('error', 'An error occurred while fetching the user.'); } } @@ -196,20 +198,18 @@ class UserManagementController extends Controller 'username' => $json['data']['username'], 'firstName' => $json['data']['firstname'], 'lastName' => $json['data']['lastname'], - 'role' => 'Admin', + 'role' => $json['data']['role'] == '1' ? 'Admin' : 'User', 'email' => $json['data']['email'], 'status' => $json['data']['status'] ? 'Active' : 'Inactive', ]; - return view('pages.user-management.edit-user', [ - 'user' => $userData, - ]); + return view('pages.user-management.edit-user', ['user' => $userData]); } else { Log::warning('User not found: ', $json); - return redirect()->route('user-management.index')->with('error', $json['message'] ?? 'User not found.'); + return redirect()->route('user.management')->with('error', $json['message'] ?? 'User not found.'); } } catch (\Exception $e) { Log::error('Error fetching user for edit: ' . $e->getMessage()); - return redirect()->route('user-management.index')->with('error', 'An error occurred while fetching the user.'); + return redirect()->route('user.management')->with('error', 'An error occurred while fetching the user.'); } } @@ -220,13 +220,14 @@ class UserManagementController extends Controller $accessToken = $user['access_token'] ?? null; if (!$accessToken) { - return response()->json(['error' => 'Unauthorized'], 401); + return redirect()->route('login')->with('error', 'Please log in to update a user.'); } $validated = $request->validate([ 'username' => 'required|string|max:255', 'firstName' => 'required|string|max:255', 'lastName' => 'required|string|max:255', + 'role' => 'required|in:0,1', 'email' => 'required|email|max:255', 'password' => 'nullable|string|min:8', 'status' => 'required|in:active,inactive', @@ -236,6 +237,7 @@ class UserManagementController extends Controller 'username' => $validated['username'], 'firstname' => $validated['firstName'], 'lastname' => $validated['lastName'], + 'role' => $validated['role'], 'email' => $validated['email'], 'status' => $validated['status'], ]; @@ -244,6 +246,8 @@ class UserManagementController extends Controller $data['password'] = $validated['password']; } + Log::info('API Payload for updating user: ', $data); + $response = Http::withHeaders([ 'Accept' => 'application/json', 'Authorization' => 'Bearer ' . $accessToken, @@ -253,14 +257,15 @@ class UserManagementController extends Controller if ($response->successful()) { Log::info('User updated successfully: ', $json); - return response()->json(['message' => $json['message'] ?? 'User updated successfully']); + return redirect()->route('user.management') + ->with('success', $json['message'] ?? 'User updated successfully'); } else { Log::error('Failed to update user: ', $json); - return response()->json(['error' => $json['message'] ?? 'Failed to update user'], 400); + return redirect()->back()->with('error', $json['message'] ?? 'Failed to update user.'); } } catch (\Exception $e) { Log::error('Error updating user: ' . $e->getMessage()); - return response()->json(['error' => 'An error occurred'], 500); + return redirect()->back()->with('error', 'An error occurred while updating the user.'); } } @@ -271,7 +276,7 @@ class UserManagementController extends Controller $accessToken = $user['access_token'] ?? null; if (!$accessToken) { - return response()->json(['error' => 'Unauthorized'], 401); + return redirect()->route('login')->with('error', 'Please log in to delete a user.'); } $response = Http::withHeaders([ @@ -283,14 +288,15 @@ class UserManagementController extends Controller if ($response->successful()) { Log::info('User deleted successfully: ', $json); - return response()->json(['message' => $json['message'] ?? 'User deleted successfully']); + return redirect()->route('user.management') + ->with('success', $json['message'] ?? 'User deleted successfully'); } else { Log::error('Failed to delete user: ', $json); - return response()->json(['error' => $json['message'] ?? 'Failed to delete user'], 400); + return redirect()->back()->with('error', $json['message'] ?? 'Failed to delete user.'); } } catch (\Exception $e) { Log::error('Error deleting user: ' . $e->getMessage()); - return response()->json(['error' => 'An error occurred'], 500); + return redirect()->back()->with('error', 'An error occurred while deleting the user.'); } } @@ -301,15 +307,17 @@ class UserManagementController extends Controller $accessToken = $user['access_token'] ?? null; if (!$accessToken) { - return response()->json(['error' => 'Unauthorized'], 401); + return redirect()->route('login')->with('error', 'Please log in to delete users.'); } $uuids = $request->input('admin_uuid', []); if (empty($uuids)) { - return response()->json(['error' => 'No users selected'], 400); + return redirect()->back()->with('error', 'No users selected for deletion.'); } + Log::info('Batch delete UUIDs: ', $uuids); + $response = Http::withHeaders([ 'Accept' => 'application/json', 'Authorization' => 'Bearer ' . $accessToken, @@ -320,15 +328,16 @@ class UserManagementController extends Controller $json = $response->json(); if ($response->successful()) { - Log::info('Batch delete successful for UUIDs: ' . implode(',', $uuids)); - return response()->json(['message' => $json['message'] ?? 'Users deleted successfully']); + Log::info('Batch delete successful for UUIDs: ', $uuids); + return redirect()->route('user.management') + ->with('success', $json['message'] ?? 'Users deleted successfully'); } else { Log::error('Failed to batch delete users: ', $json); - return response()->json(['error' => $json['message'] ?? 'Failed to delete users'], 400); + return redirect()->back()->with('error', $json['message'] ?? 'Failed to delete users.'); } } catch (\Exception $e) { Log::error('Error in batch delete: ' . $e->getMessage()); - return response()->json(['error' => 'An error occurred'], 500); + return redirect()->back()->with('error', 'An error occurred while deleting users.'); } } @@ -339,33 +348,38 @@ class UserManagementController extends Controller $accessToken = $user['access_token'] ?? null; if (!$accessToken) { - return response()->json(['error' => 'Unauthorized'], 401); + return redirect()->route('login')->with('error', 'Please log in to change user status.'); } $validated = $request->validate([ 'status' => 'required|in:active,inactive', ]); + $payload = [ + 'admin_uuid' => $uuid, + 'status' => $validated['status'], + ]; + + Log::info('API Payload for changing status: ', $payload); + $response = Http::withHeaders([ 'Accept' => 'application/json', 'Authorization' => 'Bearer ' . $accessToken, - ])->post("{$this->apiBaseUrl}/cms/adminChangeStatus", [ - 'admin_uuid' => $uuid, - 'status' => $validated['status'], - ]); + ])->post("{$this->apiBaseUrl}/cms/adminChangeStatus", $payload); $json = $response->json(); if ($response->successful()) { Log::info('Status changed successfully for UUID: ' . $uuid); - return response()->json(['message' => $json['message'] ?? 'Status updated successfully']); + return redirect()->route('user.management') + ->with('success', $json['message'] ?? 'Status updated successfully'); } else { Log::error('Failed to change status: ', $json); - return response()->json(['error' => $json['message'] ?? 'Failed to update status'], 400); + return redirect()->back()->with('error', $json['message'] ?? 'Failed to update status.'); } } catch (\Exception $e) { Log::error('Error changing status: ' . $e->getMessage()); - return response()->json(['error' => 'An error occurred'], 500); + return redirect()->back()->with('error', 'An error occurred while changing status.'); } } } \ No newline at end of file diff --git a/resources/views/components/user-management-component.blade.php b/resources/views/components/user-management-component.blade.php index 7330f08..ddcf3c0 100644 --- a/resources/views/components/user-management-component.blade.php +++ b/resources/views/components/user-management-component.blade.php @@ -6,9 +6,7 @@ 'showAddButton' => false, 'addButtonUrl' => '#', 'showCheckboxes' => false, - 'showBatchDelete' => false, - 'showEditModal' => false, - 'showViewModal' => false + 'showBatchDelete' => false ])
@@ -32,7 +30,7 @@
-
+
@@ -172,7 +170,7 @@ vertical-align: middle; } .table-container { - overflow-x: hidden; + overflow-x: auto; } .pagination-sm .page-link { padding: 0.25rem 0.5rem; @@ -234,6 +232,7 @@ .table thead .sortable i { font-size: 0.65rem; } + . personally identifiable information like names, addresses, or other sensitive data. .pagination-sm .page-link { padding: 0.2rem 0.4rem; font-size: 0.75rem; @@ -255,8 +254,6 @@ actions: @json($actions), showCheckboxes: {{ json_encode($showCheckboxes) }}, showBatchDelete: {{ json_encode($showBatchDelete) }}, - showEditModal: {{ json_encode($showEditModal) }}, - showViewModal: {{ json_encode($showViewModal) }}, pageTitle: @json($pageTitle), csrfToken: '{{ csrf_token() }}' }; @@ -287,22 +284,26 @@ } tableConfig.columns.forEach(col => { - if (col.key === 'status') { + let value = row[col.key] || ''; + if (col.key === 'role') { + value = row[col.key] === '1' ? 'Admin' : 'User'; + } else if (col.key === 'status') { + const displayStatus = value === 'Active' ? 'Active' : 'Inactive'; rowHtml += ` `; - } else { - rowHtml += `${row[col.key] || ''}`; + return; } + rowHtml += `${value}`; }); if (tableConfig.actions.length > 0) { @@ -320,12 +321,12 @@ tableConfig.actions.forEach(action => { if (action === 'edit') { rowHtml += ` - + `; } else if (action === 'view') { rowHtml += ` - + `; } else if (action === 'delete') { @@ -344,6 +345,7 @@ attachEventListeners(); updateDeleteButtonState(); + updateNoDataMessage(); } function renderPagination() { @@ -393,6 +395,13 @@ pagination.appendChild(nextLi); } + function updateNoDataMessage() { + const noDataMessage = document.getElementById('no-data-message'); + if (noDataMessage) { + noDataMessage.style.display = filteredRows.length === 0 ? 'block' : 'none'; + } + } + function attachEventListeners() { // Search const searchInput = document.getElementById('searchInput'); @@ -413,7 +422,7 @@ // Sort document.querySelectorAll('.sortable').forEach(header => { header.addEventListener('click', function() { - const columnIndex = parseInt(this.getAttribute('data-column')) - 1; + const columnIndex = parseInt(this.getAttribute('data-column')) - (tableConfig.showCheckboxes ? 1 : 0); const key = tableConfig.columns[columnIndex].key; sortDirection[columnIndex] = !sortDirection[columnIndex] ? 'asc' : sortDirection[columnIndex] === 'asc' ? 'desc' : 'asc'; @@ -429,12 +438,15 @@ } filteredRows.sort((a, b) => { - const aValue = (a[key] || '').toString().toLowerCase(); - const bValue = (b[key] || '').toString().toLowerCase(); + let aValue = (a[key] || '').toString().toLowerCase(); + let bValue = (b[key] || '').toString().toLowerCase(); + if (key === 'role') { + aValue = a[key] === '1' ? 'Admin' : 'User'; + bValue = b[key] === '1' ? 'Admin' : 'User'; + } return sortDirection[columnIndex] === 'asc' ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); }); - currentPage = 1; renderTable(); renderPagination(); }); @@ -480,12 +492,16 @@ const deleteSelected = document.getElementById('deleteSelected'); if (deleteSelected) { deleteSelected.addEventListener('click', function() { - if (confirm('Are you sure you want to delete the selected items?')) { - const checkboxes = document.querySelectorAll('.rowCheckbox'); - const selectedIds = Array.from(checkboxes) - .filter(cb => cb.checked) - .map(cb => cb.closest('tr').getAttribute('data-id')); + const checkboxes = document.querySelectorAll('.rowCheckbox:checked'); + const selectedIds = Array.from(checkboxes) + .map(cb => cb.closest('tr').getAttribute('data-id')); + if (selectedIds.length === 0) { + alert('Please select at least one user to delete.'); + return; + } + + if (confirm('Are you sure you want to delete the selected users?')) { axios.delete('{{ route('user-management.batchDelete') }}', { headers: { 'X-CSRF-TOKEN': tableConfig.csrfToken @@ -499,14 +515,14 @@ originalRows = originalRows.filter(row => !selectedIds.includes(row.admin_uuid)); const maxPage = Math.ceil(filteredRows.length / rowsPerPage); - if (currentPage > maxPage) { - currentPage = maxPage || 1; + if (currentPage > maxPage && maxPage > 0) { + currentPage = maxPage; } renderTable(); renderPagination(); if (selectAll) selectAll.checked = false; - alert(response.data.message || 'Users deleted successfully'); + window.location.reload(); }).catch(error => { console.error('Batch delete error:', error); alert(error.response?.data?.message || 'Failed to delete users. You may have included your own account.'); @@ -524,24 +540,25 @@ const row = this.closest('tr'); const userId = row.getAttribute('data-id'); const statusText = row.querySelector('.status-text'); + const originalStatus = statusText.textContent; if (statusText) { - statusText.textContent = newStatus; + statusText.textContent = newStatus.charAt(0).toUpperCase() + newStatus.slice(1); } const rowData = filteredRows.find(r => r.admin_uuid === userId); if (rowData) { - rowData.status = newStatus; + rowData.status = newStatus.charAt(0).toUpperCase() + newStatus.slice(1); axios.post(`{{ route('user-management.changeStatus', '') }}/${userId}`, { status: newStatus, _token: tableConfig.csrfToken }).then(response => { - alert(response.data.message || `User account is ${newStatus.toLowerCase()}`); + window.location.reload(); }).catch(error => { console.error('Status update error:', error); alert(error.response?.data?.message || 'Failed to update status. You cannot update your own account.'); - // Revert status on error - statusText.textContent = rowData.status; + statusText.textContent = originalStatus; + rowData.status = originalStatus; }); } }); @@ -552,7 +569,7 @@ button.addEventListener('click', function(e) { e.stopPropagation(); const userId = this.getAttribute('data-id'); - if (confirm('Are you sure you want to delete this item?')) { + if (confirm('Are you sure you want to delete this user?')) { axios.delete(`{{ route('user-management.destroy', '') }}/${userId}`, { headers: { 'X-CSRF-TOKEN': tableConfig.csrfToken @@ -563,13 +580,13 @@ originalRows = originalRows.filter(row => row.admin_uuid !== userId); const maxPage = Math.ceil(filteredRows.length / rowsPerPage); - if (currentPage > maxPage) { - currentPage = maxPage || 1; + if (currentPage > maxPage && maxPage > 0) { + currentPage = maxPage; } renderTable(); renderPagination(); - alert(response.data.message || 'User deleted successfully'); + window.location.reload(); }).catch(error => { console.error('Delete error:', error); alert(error.response?.data?.message || 'Failed to delete user. You cannot delete your own account.'); @@ -578,6 +595,27 @@ }); }); + //Edit + document.querySelectorAll('.edit-btn').forEach(button => { + button.addEventListener('click', function(e) { + e.preventDefault(); + const userId = this.getAttribute('data-id'); + const href = this.getAttribute('href').replace(':id', userId); + window.location.href = href; + }); + }); + + // View + document.querySelectorAll('.view-btn').forEach(button => { + button.addEventListener('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + const href = this.getAttribute('href'); + console.log('View redirect:', href); // Debug + window.location.href = href; + }); + }); + // Row click to view document.querySelectorAll('.clickable-row').forEach(row => { row.addEventListener('click', function(e) { @@ -585,7 +623,9 @@ return; } const userId = this.getAttribute('data-id'); - window.location.href = `{{ route('user-management.show', '') }}/${userId}`; + const url = `{{ route('user-management.show', '') }}/${userId}`; + console.log('Row redirect:', url); // Debug + window.location.href = url; }); }); } diff --git a/resources/views/pages/user-management.blade.php b/resources/views/pages/user-management.blade.php index 67fa014..18f163e 100644 --- a/resources/views/pages/user-management.blade.php +++ b/resources/views/pages/user-management.blade.php @@ -1,30 +1,80 @@ + @extends('layouts.app') -@section('page_title', 'User Management') - @section('content') -
- @include('components.user-management-component', [ - 'pageTitle' => 'User Management', - 'data' => $users, - 'columns' => [ - ['name' => 'Username', 'key' => 'username', 'sortable' => true], - ['name' => 'First Name', 'key' => 'firstName', 'sortable' => true], - ['name' => 'Last Name', 'key' => 'lastName', 'sortable' => true], - ['name' => 'User Role', 'key' => 'role', 'sortable' => true], - ['name' => 'Email', 'key' => 'email', 'sortable' => true], - ['name' => 'Status', 'key' => 'status', 'sortable' => true], - ], - 'actions' => ['edit', 'view', 'delete'], - 'showAddButton' => true, - 'addButtonUrl' => route('user-management.create'), - 'showCheckboxes' => true, - 'showBatchDelete' => true, - 'showEditModal' => false, - 'showViewModal' => false, - ]) -
-

No users found.

+
+
+
+
+
+
+
User Management
+ Add User +
+
+
+ @if (session('success')) +
{{ session('success') }}
+ @endif + @if (session('error')) +
{{ session('error') }}
+ @endif +
+ @csrf + @method('DELETE') +
+ +
+ + + + + + + + + + + + + + @forelse ($users as $user) + + + + + + + + + + @empty + + + + @endforelse + +
UsernameNameEmailRoleStatusActions
{{ $user['username'] }}{{ $user['firstName'] }} {{ $user['lastName'] }}{{ $user['email'] }}{{ $user['role'] }}{{ $user['status'] }} + View + Edit + + @csrf + @method('DELETE') + + +
No users found.
+ +
+
-@endsection \ No newline at end of file +
+@endsection +@section('scripts') + +@endsection diff --git a/resources/views/pages/user-management/edit-user.blade.php b/resources/views/pages/user-management/edit-user.blade.php index 22f7198..5c74591 100644 --- a/resources/views/pages/user-management/edit-user.blade.php +++ b/resources/views/pages/user-management/edit-user.blade.php @@ -1,3 +1,4 @@ + @extends('layouts.app') @section('content') @@ -14,28 +15,28 @@ @method('PUT')
- + @error('username') {{ $message }} @enderror
- + @error('firstName') {{ $message }} @enderror
- + @error('lastName') {{ $message }} @enderror
- + @error('email') {{ $message }} @enderror @@ -47,18 +48,28 @@ {{ $message }} @enderror
+
+ + + @error('role') + {{ $message }} + @enderror +
@error('status') {{ $message }} @enderror
- Cancel + Cancel
@@ -67,27 +78,4 @@
- -@push('scripts') - -@endpush -@endsection \ No newline at end of file +@endsection diff --git a/resources/views/pages/user-management/show-user.blade.php b/resources/views/pages/user-management/show-user.blade.php index 03633aa..87c245b 100644 --- a/resources/views/pages/user-management/show-user.blade.php +++ b/resources/views/pages/user-management/show-user.blade.php @@ -1,82 +1,52 @@ +```blade @extends('layouts.app') -@section('page_title', 'View User') - @section('content') -
-
-
-
View User Details
-
-
-
-

Username: {{ $user['username'] }}

-

First Name: {{ $user['firstName'] }}

-

Last Name: {{ $user['lastName'] }}

-

User Role: {{ $user['role'] }}

-

Email: {{ $user['email'] }}

-

Status: {{ $user['status'] }}

-
-
- - Edit - - - Back - +
+
+
+
+
+
View User Details
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ @if($user['generated_password']) +
+ + +
+ @endif + +
- - -@endsection \ No newline at end of file +@endsection +``` \ No newline at end of file