distinct('user_id')->count('user_id'); $trialCustomers = Subscription::onTrial()->distinct('user_id')->count('user_id'); $churnedCustomers = Subscription::where('status', 'cancelled')->distinct('user_id')->count('user_id'); $mrr = $this->calculateMRR(); $arr = $mrr * 12; $arpu = $payingCustomers > 0 ? $mrr / $payingCustomers : 0; $ltv = $arpu * 12; // Simplified LTV calculation return [ Stat::make('Total Customers', $totalCustomers) ->description('All registered users') ->descriptionIcon('heroicon-o-users') ->color('primary'), Stat::make('Paying Customers', $payingCustomers) ->description($this->getCustomerGrowthRate($payingCustomers)) ->descriptionIcon($this->getGrowthIcon($payingCustomers)) ->color($this->getGrowthColor($payingCustomers)), Stat::make('Trial Customers', $trialCustomers) ->description('Currently on trial') ->descriptionIcon('heroicon-o-clock') ->color('warning'), Stat::make('Churned Customers', $churnedCustomers) ->description($this->getChurnRate($churnedCustomers, $payingCustomers + $churnedCustomers)) ->descriptionIcon('heroicon-o-arrow-trending-down') ->color('danger'), Stat::make('Monthly Recurring Revenue', '$'.number_format($mrr, 2)) ->description('MRR from active subscriptions') ->descriptionIcon('heroicon-o-currency-dollar') ->color('success'), Stat::make('Annual Recurring Revenue', '$'.number_format($arr, 2)) ->description('ARR projection') ->descriptionIcon('heroicon-o-chart-bar') ->color('success'), Stat::make('Average Revenue Per User', '$'.number_format($arpu, 2)) ->description('ARPU for paying customers') ->descriptionIcon('heroicon-o-calculator') ->color('info'), Stat::make('Lifetime Value', '$'.number_format($ltv, 2)) ->description('Estimated customer LTV') ->descriptionIcon('heroicon-o-gift') ->color('purple'), ]; } private function calculateMRR(): float { return Subscription::active() ->join('plans', 'subscriptions.plan_id', '=', 'plans.id') ->sum('plans.price'); } private function getCustomerGrowthRate(int $current): string { $previous = Subscription::active() ->where('created_at', '<', now()->subMonth()) ->distinct('user_id') ->count('user_id'); if ($previous == 0) { return 'New customers'; } $growth = (($current - $previous) / $previous) * 100; return $growth >= 0 ? "+{$growth}%" : "{$growth}%"; } private function getGrowthIcon(int $current): string { $previous = Subscription::active() ->where('created_at', '<', now()->subMonth()) ->distinct('user_id') ->count('user_id'); return $current > $previous ? 'heroicon-o-arrow-trending-up' : 'heroicon-o-arrow-trending-down'; } private function getGrowthColor(int $current): string { $previous = Subscription::active() ->where('created_at', '<', now()->subMonth()) ->distinct('user_id') ->count('user_id'); return $current > $previous ? 'success' : 'danger'; } private function getChurnRate(int $churned, int $total): string { if ($total == 0) { return '0% churn rate'; } $rate = ($churned / $total) * 100; return "{$rate}% churn rate"; } }