=', now()) ->whereHas('subscribe', function (Builder $query) { $query->where('is_free', true); }) ->distinct('user_id') ->count('user_id'); // 3. Get Paid Subscribers & Breakdown by Plan Type AND Market Provider $rawBreakdown = UserSubscriber::where('user_subscribers.expired_at', '>=', now()) ->join('subscribe_plans', 'user_subscribers.subscribe_plan_id', '=', 'subscribe_plans.id') ->where('subscribe_plans.is_free', false) // Replaced redundant whereHas for better performance ->selectRaw('subscribe_plans.name as plan_name, user_subscribers.market_provider, count(DISTINCT user_subscribers.user_id) as total') ->groupBy('subscribe_plans.name', 'user_subscribers.market_provider') ->get(); // 4. Safely group the results in PHP to fix split numbers (merging null, '', and 'web') $paidBreakdown = $rawBreakdown->map(function ($item) { $provider = strtolower(trim($item->market_provider)); // Normalize the provider names if (empty($provider) || $provider === 'web') { $providerName = 'سایت'; } elseif ($provider === 'bazar') { $providerName = 'بازار'; } elseif ($provider === 'myket') { $providerName = 'مایکت'; } else { $providerName = ucfirst($provider); // Dynamic fallback for any future gateways } return [ 'display_name' => $item->plan_name . ' (' . $providerName . ')', 'total' => $item->total ]; })->groupBy('display_name')->map(function ($group, $key) { // Merge any split rows (e.g. 'web' + null) into one accurate total sum return (object) [ 'display_name' => $key, 'total' => $group->sum('total') ]; })->values(); // Total paid is the exact sum of the merged breakdown $paidSubscribers = $paidBreakdown->sum('total'); // 4. Fetch Recent Data (Limit to 5) $recentSuggestions = Suggestion::with('user')->latest()->take(5)->get(); // Order tickets by updated_at so newly replied tickets jump to the top $recentTickets = Ticket::with('user')->latest('updated_at')->take(5)->get(); // 5. Prepare Chart Data (Strictly the last 7 calendar days) $chartDates = []; $newUsersData = []; $paidSubsData = []; $freeSubsData = []; for ($i = 6; $i >= 0; $i--) { $date = now()->subDays($i); $dbDate = $date->format('Y-m-d'); // Format X-axis to Jalali for the chart labels $chartDates[] = \Morilog\Jalali\Jalalian::fromCarbon($date)->format('Y/m/d'); // Count records for this specific exact date $newUsersData[] = User::whereDate('created_at', $dbDate)->count(); $paidSubsData[] = UserSubscriber::whereDate('created_at', $dbDate) ->whereHas('subscribe', fn($q) => $q->where('is_free', false))->count(); $freeSubsData[] = UserSubscriber::whereDate('created_at', $dbDate) ->whereHas('subscribe', fn($q) => $q->where('is_free', true))->count(); } return view('admin.dashboard.index', compact( 'totalUsers', 'paidSubscribers', 'freeSubscribers', 'paidBreakdown', 'recentSuggestions', 'recentTickets', 'chartDates', 'newUsersData', 'paidSubsData', 'freeSubsData' )); } }