where('services', 'LIKE', '%ussd%') ->orWhere('services', 'LIKE', '%A2P%'); })->count(); $airtime_clients = Client::where('services', 'LIKE', '%airtime%')->count(); $sms_clients = Client::where('services', 'LIKE', '%sms%')->count(); $voice_clients = Client::where('services', 'LIKE', '%ivr%')->count(); // Cleaned up the null/empty checks and removed the dangerous global orWhere $expiring_contracts = Client::where('contract_auto_renew', '!=', 'YES') ->whereNotNull('contract_validity') ->where('contract_validity', '!=', '') ->orderBy('contract_validity', 'ASC') ->take(5) ->get(); $user_activities = UserActivity::where('user_id', '>', 1) ->with('userInfo') ->orderBy('created_at', 'DESC') ->take(5) ->get(); $recent_clients = Client::with('auth_user_info') ->orderBy('id', 'DESC') ->take(5) ->get(); // Cleaner raw query for upcoming birthdays ignoring the current year $upcoming_birthdays = StaffMember::whereRaw("DATE_FORMAT(dob, '%m-%d') >= DATE_FORMAT(CURDATE(), '%m-%d')") ->orderByRaw("DATE_FORMAT(dob, '%m-%d') ASC") ->take(5) ->get(); $upcoming_hodidays = NationalHoliday::whereDate('event_date', '>=', Carbon::today()) ->orderBy('event_date', 'ASC') ->take(15) ->get(); $main_quote = DailyQuote::where('status', 'active')->first(); return view('dashboard.index_two', [ 'page_title' => 'Dashboard', 'sms' => $sms_clients, 'ussd' => $ussd_clients, 'voice' => $voice_clients, 'airtime' => $airtime_clients, 'total' => Client::count(), 'main_quote' => $main_quote, 'recent_clients' => $recent_clients, 'user_activities' => $user_activities, 'expiring_contracts' => $expiring_contracts, 'upcoming_birthdays' => $upcoming_birthdays, 'upcoming_hodidays' => $upcoming_hodidays ]); } public function index() { // --- 1. TELECOM & CLIENT INSIGHTS (Top Section) --- $totalClients = Client::count(); $activeClients = Client::where('status', 'Live')->count(); // Assuming you have a status column $activeNetworks = NetworkOperator::where('connection_status', 'ACTIVE')->count(); $activeShortCodes = ShortCode::where('status', 'LIVE')->count(); $totalSenderIds = SenderId::where('status', 'LIKE', 'APPROVED%')->count(); // Calculate a quick insight (e.g., percentage of active clients) $clientActiveRate = $totalClients > 0 ? round(($activeClients / $totalClients) * 100) : 0; // --- 2. HR & INTERNAL METRICS (Bottom Section) --- $totalStaff = StaffMember::where('status', 'ACTIVE')->count(); $pendingLeaves = LeaveRequest::where('status', 'PENDING')->count(); $totalDocuments = GeneralDocument::count(); $activeLeavesThisMonth = LeaveRequest::where('status', 'APPROVED') ->whereMonth('start_date', Carbon::now()->month) ->count(); $recentPendingLeaves = LeaveRequest::with('staff')->where('status', 'PENDING')->orderBy('created_at', 'desc')->take(5)->get(); $recentDocuments = GeneralDocument::with('uploader')->orderBy('created_at', 'desc')->take(5)->get(); // Upcoming Birthdays $currentMonthDay = Carbon::now()->format('m-d'); $futureMonthDay = Carbon::now()->addDays(30)->format('m-d'); $upcomingBirthdays = StaffMember::where(function($query) use ($currentMonthDay, $futureMonthDay) { if ($currentMonthDay <= $futureMonthDay) { $query->whereBetween('dob', [$currentMonthDay, $futureMonthDay]); } else { $query->where('dob', '>=', $currentMonthDay)->orWhere('dob', '<=', $futureMonthDay); } })->orderBy('dob', 'asc')->take(5)->get(); $main_quote = DailyQuote::where('status', 'active')->first(); // dd($main_quote); return view('dashboard.index', compact( 'totalClients', 'activeClients', 'activeNetworks', 'activeShortCodes', 'totalSenderIds', 'clientActiveRate', 'totalStaff', 'pendingLeaves', 'totalDocuments', 'activeLeavesThisMonth', 'main_quote', 'recentPendingLeaves', 'recentDocuments', 'upcomingBirthdays' )); } public function indexHr() { // 1. Key Metrics $totalStaff = StaffMember::where('status', 'ACTIVE')->count(); $pendingLeaves = LeaveRequest::where('status', 'PENDING')->count(); $totalDocuments = GeneralDocument::count(); // Approved leaves happening this month $activeLeavesThisMonth = LeaveRequest::where('status', 'APPROVED') ->whereMonth('start_date', Carbon::now()->month) ->count(); // 2. Pending Leave Requests for HR Action $recentPendingLeaves = LeaveRequest::with('staff') ->where('status', 'PENDING') ->orderBy('created_at', 'desc') ->take(5) ->get(); // 3. Recently Uploaded Documents $recentDocuments = GeneralDocument::with('uploader') ->orderBy('created_at', 'desc') ->take(5) ->get(); // 4. Upcoming Birthdays (Using our MM-DD string format logic) $currentMonthDay = Carbon::now()->format('m-d'); $futureMonthDay = Carbon::now()->addDays(30)->format('m-d'); if ($currentMonthDay <= $futureMonthDay) { $upcomingBirthdays = StaffMember::whereBetween('dob', [$currentMonthDay, $futureMonthDay]) ->orderBy('dob', 'asc') ->take(5) ->get(); } else { $upcomingBirthdays = StaffMember::where(function($query) use ($currentMonthDay, $futureMonthDay) { $query->where('dob', '>=', $currentMonthDay) ->orWhere('dob', '<=', $futureMonthDay); }) ->orderBy('dob', 'asc') ->take(5) ->get(); } $totalClients = Client::count(); // Or where('status', 'ACTIVE') $totalNetworks = NetworkOperator::count(); $recentClients = Client::orderBy('created_at', 'desc')->take(5)->get(); $activeNetworks = NetworkOperator::where('connection_status', 'ACTIVE')->get(); $activeShortCodes = ShortCode::where('status', 'ACTIVE')->get(); $activeSenderIds = SenderId::where('status', 'ACTIVE')->get(); return view('dashboard.index', compact( 'totalStaff', 'pendingLeaves', 'totalDocuments', 'activeLeavesThisMonth', 'recentPendingLeaves', 'recentDocuments', 'upcomingBirthdays', 'totalClients', 'totalNetworks', 'recentClients', 'activeNetworks', 'activeShortCodes', 'activeSenderIds' )); return view('dashboard.index', compact( 'totalStaff', 'pendingLeaves', 'totalDocuments', 'activeLeavesThisMonth', 'recentPendingLeaves', 'recentDocuments', 'upcomingBirthdays' )); } public function getEvents(): JsonResponse { $event_arr = [ [ "title" => 'Airtel MW Top Up', "start" => date("Y-m-d") // Fixed format: Most JS calendars expect Y-m-d, not Y, m, d ], [ "title" => 'Airtel MW Top Down', "start" => date("Y-m-d") ], ]; return response()->json($event_arr); } public function getQuotes(): JsonResponse { // Replaced complex raw SQL with Laravel's native randomized sorting $daily_quote = DailyQuote::inRandomOrder()->first(); return response()->json($daily_quote); } public function getMnosContracts(): JsonResponse { $threeMonthsLater = Carbon::now()->addMonths(3)->format('m-d'); $currentMonth = Carbon::now()->format('m'); // Added ->count() directly to the query builder to save RAM $expiring_three_months = NetworkOps::where('contract_auto_renew', 'NO') ->whereRaw("DATE_FORMAT(contract_validity, '%m-%d') = ?", [$threeMonthsLater]) ->count(); $expired_overall = NetworkOps::whereDate('contract_validity', '<', Carbon::now())->count(); $expiring_current_month = NetworkOps::whereMonth('contract_validity', $currentMonth)->count(); return response()->json([ 'expiring_three_months' => $expiring_three_months, 'expired_overall' => $expired_overall, 'expiring_current_month' => $expiring_current_month ]); } public function getClientContracts(): JsonResponse { $threeMonthsLater = Carbon::now()->addMonths(3)->format('m-d'); $currentMonth = Carbon::now()->format('m'); $expiring_three_months = Client::where('contract_auto_renew', 'NO') ->whereRaw("DATE_FORMAT(contract_validity, '%m-%d') = ?", [$threeMonthsLater]) ->count(); $expired_overall = Client::whereDate('contract_validity', '<', Carbon::now())->count(); $expiring_current_month = Client::whereMonth('contract_validity', $currentMonth)->count(); return response()->json([ 'expiring_three_months' => $expiring_three_months, 'expired_overall' => $expired_overall, 'expiring_current_month' => $expiring_current_month ]); } }