diff --git a/app/Http/Controllers/Admin/AdminController.php b/app/Http/Controllers/Admin/AdminController.php index 3160185..e00fcd5 100644 --- a/app/Http/Controllers/Admin/AdminController.php +++ b/app/Http/Controllers/Admin/AdminController.php @@ -18,10 +18,13 @@ class AdminController extends Controller { $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); $search = $request->input('search'); + $status = $request->input('status', (string)User::STATUS_ACTIVE); + $role = $request->input('role'); + $department = $request->input('department'); $flagSend = $request->input('flag_send'); ['users' => $users, 'topReceivedUser' => $topReceivedUser, 'topSentUser' => $topSentUser] - = $this->adminService->getUserListWithStats($selectedMonth, $search, $flagSend); + = $this->adminService->getUserListWithStats($selectedMonth, $search, $status, $role, $department, $flagSend); if ($request->ajax() || $request->wantsJson()) { return response()->json([ @@ -31,7 +34,17 @@ class AdminController extends Controller ]); } - return view('admin.users.index', compact('users', 'selectedMonth', 'topReceivedUser', 'topSentUser', 'search', 'flagSend')); + return view('admin.users.index', compact( + 'users', + 'selectedMonth', + 'topReceivedUser', + 'topSentUser', + 'search', + 'status', + 'role', + 'department', + 'flagSend' + )); } public function create() diff --git a/app/Http/Controllers/User/UserController.php b/app/Http/Controllers/User/UserController.php index b8cd1eb..9e05626 100644 --- a/app/Http/Controllers/User/UserController.php +++ b/app/Http/Controllers/User/UserController.php @@ -75,6 +75,10 @@ class UserController extends Controller { $request->validate([ 'password' => 'required|min:6|confirmed', + ], [ + 'password.required' => 'Mật khẩu mới không được để trống.', + 'password.min' => 'Mật khẩu mới phải có ít nhất 6 ký tự.', + 'password.confirmed' => 'Mật khẩu xác nhận không trùng khớp.', ]); $user = Auth::user(); diff --git a/app/Services/Admin/AdminService.php b/app/Services/Admin/AdminService.php index 36806b8..e66a75b 100644 --- a/app/Services/Admin/AdminService.php +++ b/app/Services/Admin/AdminService.php @@ -14,13 +14,18 @@ use Illuminate\Support\Facades\Hash; class AdminService implements AdminServiceInterface { - public function getUserListWithStats(string $selectedMonth, ?string $search = null, ?string $flagSend = null): array - { + public function getUserListWithStats( + string $selectedMonth, + ?string $search = null, + ?string $status = '1', + ?string $role = null, + ?string $department = null, + ?string $flagSend = null + ): array { $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth(); $endOfMonth = Carbon::parse($selectedMonth)->endOfMonth(); $usersQuery = User::select('user.*') - ->where('status', User::STATUS_ACTIVE) ->addSelect([ 'total_received' => Administration::selectRaw('COALESCE(SUM(received), 0)') ->whereColumn('msnv', 'user.msnv') @@ -30,22 +35,35 @@ class AdminService implements AdminServiceInterface ->whereBetween('date', [$startOfMonth, $endOfMonth]) ]); - $topReceivedUser = (clone $usersQuery)->orderByDesc('total_received')->first(); - $topSentUser = (clone $usersQuery)->orderByDesc('total_sent')->first(); + $topReceivedUser = (clone $usersQuery)->where('status', User::STATUS_ACTIVE)->orderByDesc('total_received')->first(); + $topSentUser = (clone $usersQuery)->where('status', User::STATUS_ACTIVE)->orderByDesc('total_sent')->first(); - if (!is_null($search) && trim($search) !== '') { - $search = trim($search); - $usersQuery->where(function ($q) use ($search) { - $q->whereRaw('LOWER(msnv) LIKE ?', ['%' . strtolower($search) . '%']) - ->orWhereRaw('LOWER(mail) LIKE ?', ['%' . strtolower($search) . '%']); - }); + if (!is_null($status) && $status !== '') { + $usersQuery->where('status', intval($status)); + } + + if (!is_null($role) && $role !== '') { + $usersQuery->where('role', intval($role)); + } + + if (!is_null($department) && $department !== '') { + $usersQuery->where('departments', intval($department)); } if (!is_null($flagSend) && $flagSend !== '') { $usersQuery->where('flag_send', intval($flagSend)); } - $users = $usersQuery->paginate(10)->withQueryString(); + if (!is_null($search) && trim($search) !== '') { + $search = trim($search); + $usersQuery->where(function ($q) use ($search) { + $q->whereRaw('LOWER(msnv) LIKE ?', ['%' . strtolower($search) . '%']) + ->orWhereRaw('LOWER(name) LIKE ?', ['%' . strtolower($search) . '%']) + ->orWhereRaw('LOWER(mail) LIKE ?', ['%' . strtolower($search) . '%']); + }); + } + + $users = $usersQuery->paginate(20)->withQueryString(); return compact('users', 'topReceivedUser', 'topSentUser'); } diff --git a/app/Services/Admin/Contracts/AdminServiceInterface.php b/app/Services/Admin/Contracts/AdminServiceInterface.php index 22dd5b8..e66bcfc 100644 --- a/app/Services/Admin/Contracts/AdminServiceInterface.php +++ b/app/Services/Admin/Contracts/AdminServiceInterface.php @@ -6,7 +6,14 @@ use Illuminate\Pagination\LengthAwarePaginator; interface AdminServiceInterface { - public function getUserListWithStats(string $selectedMonth, ?string $search = null, ?string $flagSend = null): array; + public function getUserListWithStats( + string $selectedMonth, + ?string $search = null, + ?string $status = '1', + ?string $role = null, + ?string $department = null, + ?string $flagSend = null + ): array; public function getUserTransactions(string $msnv, string $selectedMonth): LengthAwarePaginator; diff --git a/resources/css/app.css b/resources/css/app.css index 0836cda..9b2e200 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -106,9 +106,6 @@ @apply min-h-screen flex bg-bg-main; } -.sidebar { - @apply w-60 h-screen sticky top-0 bg-bg-sidebar border-r border-border-light flex flex-col justify-between shrink-0 shadow-sidebar transition-all duration-300 overflow-hidden; -} .main-content { @apply flex-1 flex flex-col min-w-0; diff --git a/resources/js/AjaxTable.js b/resources/js/AjaxTable.js index 8c438d1..8d6c4b9 100644 --- a/resources/js/AjaxTable.js +++ b/resources/js/AjaxTable.js @@ -6,7 +6,7 @@ export class AjaxTable { this.searchInputId = options.searchInputId || 'searchInput'; this.btnClearSearchId = options.btnClearSearchId || 'btnClearSearch'; this.btnClearFiltersId = options.btnClearFiltersId || 'btnClearFilters'; - this.flagSendFilterId = options.flagSendFilterId || 'flagSendFilter'; + this.statusFilterId = options.statusFilterId || 'statusFilter'; this.monthFilterId = options.monthFilterId || 'monthFilter'; this.skeletonColumns = options.skeletonColumns || 7; @@ -22,7 +22,7 @@ export class AjaxTable { this.searchInput = document.getElementById(this.searchInputId); this.btnClearSearch = document.getElementById(this.btnClearSearchId); this.btnClearFilters = document.getElementById(this.btnClearFiltersId); - this.flagSendFilter = document.getElementById(this.flagSendFilterId); + this.statusFilter = document.getElementById(this.statusFilterId); this.monthFilter = document.getElementById(this.monthFilterId); if (this.form) { @@ -35,10 +35,6 @@ export class AjaxTable { if (this.searchInput) { this.searchInput.addEventListener('input', () => { this.toggleClearSearchBtn(); - clearTimeout(this.searchDebounceTimer); - this.searchDebounceTimer = setTimeout(() => { - this.submitForm(); - }, 500); }); } @@ -52,16 +48,26 @@ export class AjaxTable { }); } - if (this.flagSendFilter) { - this.flagSendFilter.addEventListener('change', () => { - this.submitForm(); + if (this.form) { + this.form.querySelectorAll('select').forEach(select => { + select.addEventListener('change', () => { + this.submitForm(); + }); }); } if (this.btnClearFilters) { this.btnClearFilters.addEventListener('click', () => { if (this.searchInput) this.searchInput.value = ''; - if (this.flagSendFilter) this.flagSendFilter.value = ''; + if (this.statusFilter) this.statusFilter.value = '1'; + + const roleFilter = document.getElementById('roleFilter'); + if (roleFilter) roleFilter.value = ''; + const departmentFilter = document.getElementById('departmentFilter'); + if (departmentFilter) departmentFilter.value = ''; + const flagSendFilter = document.getElementById('flagSendFilter'); + if (flagSendFilter) flagSendFilter.value = ''; + if (this.monthFilter) { this.monthFilter.value = new Date().toISOString().slice(0, 7); } @@ -118,6 +124,7 @@ export class AjaxTable {
+
`; } diff --git a/resources/views/admin/users/index.blade.php b/resources/views/admin/users/index.blade.php index 0c00883..6860b78 100644 --- a/resources/views/admin/users/index.blade.php +++ b/resources/views/admin/users/index.blade.php @@ -2,7 +2,7 @@ @section('title', 'Quản lý Users') @section('content') -
+

@@ -29,7 +29,15 @@ @include('admin.users.partials.stats')

- +
@include('admin.users.partials.table') diff --git a/resources/views/admin/users/partials/table.blade.php b/resources/views/admin/users/partials/table.blade.php index 2148f86..bc63edc 100644 --- a/resources/views/admin/users/partials/table.blade.php +++ b/resources/views/admin/users/partials/table.blade.php @@ -1,7 +1,7 @@
@if($users->total() > 0) - Hiển thị {{ $users->firstItem() }}-{{ $users->lastItem() }} trên {{ $users->total() }} nhân viên + Hiển thị {{ $users->firstItem() }}-{{ $users->lastItem() }} trên tổng {{ $users->total() }} nhân viên @else Hiển thị 0 nhân viên @endif @@ -17,6 +17,7 @@ Đã Gửi Số dư thẻ Quyền gửi + Trạng thái Thao tác @@ -40,14 +41,20 @@ Không @endif + + @if($u->status == \App\Models\User::STATUS_ACTIVE) + Đang làm việc + @else + Đã nghỉ việc + @endif + Quản lý - @empty - Chưa có user nào đang hoạt động. + Chưa có user nào đang hoạt động. @endforelse diff --git a/resources/views/components/sidebar.blade.php b/resources/views/components/sidebar.blade.php index 3b4b2ac..e447132 100644 --- a/resources/views/components/sidebar.blade.php +++ b/resources/views/components/sidebar.blade.php @@ -1,6 +1,6 @@ @props(['active' => false]) -