| <?php |
|
|
| namespace App\Http\Controllers; |
|
|
| use App\Models\SocialRecurringCampaign; |
| use App\Services\SocialAutomationHealthService; |
| use Illuminate\Http\Request; |
| use Illuminate\View\View; |
|
|
| class DashboardController extends Controller |
| { |
| public function __invoke(Request $request, SocialAutomationHealthService $health): View |
| { |
| $user = $request->user(); |
| $platforms = $this->platforms(); |
| $platformProgress = $health->platformProgress($user, $platforms); |
| $cronStatus = $health->cronStatus(); |
|
|
| $stats = [ |
| 'scheduled' => $user->socialPosts()->where('status', 'scheduled')->count(), |
| 'posted' => $user->socialPosts()->where('status', 'posted')->count(), |
| 'failed' => $user->socialPosts()->where('status', 'failed')->count(), |
| 'approval' => $user->socialPosts()->where('requires_approval', true)->where('status', 'draft')->count(), |
| 'ready_platforms' => collect($platformProgress)->filter(fn (array $item) => $item['credential_ready'])->count(), |
| ]; |
|
|
| $recentPosts = $user->socialPosts() |
| ->latest() |
| ->limit(6) |
| ->get(); |
|
|
| $recentProjects = $user->socialMediaAssets() |
| ->latest() |
| ->limit(12) |
| ->get(); |
|
|
| $allRecurringCampaigns = $user->socialRecurringCampaigns() |
| ->latest('id') |
| ->get(); |
|
|
| $recentRecurringCampaigns = $allRecurringCampaigns |
| ->sortBy(fn (SocialRecurringCampaign $campaign) => $campaign->next_occurrence_at?->timestamp ?? PHP_INT_MAX) |
| ->take(6) |
| ->values(); |
|
|
| $recentRecurringAlerts = $user->socialRecurringAlerts() |
| ->latest('id') |
| ->limit(6) |
| ->get(); |
|
|
| $unreadRecurringAlertCount = $user->socialRecurringAlerts() |
| ->whereNull('read_at') |
| ->count(); |
|
|
| $recurringStats = [ |
| 'active' => $allRecurringCampaigns->where('status', 'active')->count(), |
| 'paused' => $allRecurringCampaigns->where('status', 'paused')->count(), |
| 'completed' => $allRecurringCampaigns->where('status', 'completed')->count(), |
| 'due_today' => $allRecurringCampaigns |
| ->filter(fn (SocialRecurringCampaign $campaign) => $campaign->status === 'active' |
| && $campaign->next_occurrence_at |
| && $campaign->next_occurrence_at->between(now(), now()->endOfDay())) |
| ->count(), |
| 'generated_this_week' => $user->socialPosts() |
| ->whereNotNull('recurrence_campaign_id') |
| ->where('scheduled_at', '>=', now()->startOfWeek()) |
| ->count(), |
| 'approval_queue' => $user->socialPosts() |
| ->whereNotNull('recurrence_campaign_id') |
| ->where('requires_approval', true) |
| ->where('status', 'draft') |
| ->count(), |
| 'unread_alerts' => $unreadRecurringAlertCount, |
| 'failing_campaigns' => $allRecurringCampaigns |
| ->filter(fn (SocialRecurringCampaign $campaign) => filled(data_get($campaign->meta, 'last_enqueue_error.message'))) |
| ->count(), |
| ]; |
|
|
| $recurringLaneSummary = $allRecurringCampaigns |
| ->groupBy(fn (SocialRecurringCampaign $campaign) => $this->laneLabel($campaign)) |
| ->map(function ($items, $laneLabel) { |
| $first = $items->sortBy(fn (SocialRecurringCampaign $campaign) => $campaign->next_occurrence_at?->timestamp ?? PHP_INT_MAX)->first(); |
|
|
| return [ |
| 'label' => $laneLabel, |
| 'count' => $items->count(), |
| 'active' => $items->where('status', 'active')->count(), |
| 'manual' => $items->filter(fn (SocialRecurringCampaign $campaign) => $campaign->approval_mode === 'manual')->count(), |
| 'auto' => $items->filter(fn (SocialRecurringCampaign $campaign) => $campaign->approval_mode === 'auto')->count(), |
| 'next_occurrence_at' => $first?->next_occurrence_at, |
| ]; |
| }) |
| ->sortByDesc('active') |
| ->take(6) |
| ->values(); |
|
|
| $nextScheduledPost = $user->socialPosts() |
| ->whereIn('status', ['draft', 'scheduled', 'failed']) |
| ->orderByRaw('scheduled_at is null, scheduled_at asc') |
| ->first(); |
|
|
| return view('dashboard', [ |
| 'cronStatus' => $cronStatus, |
| 'nextScheduledPost' => $nextScheduledPost, |
| 'platformProgress' => $platformProgress, |
| 'platforms' => $platforms, |
| 'recentPosts' => $recentPosts, |
| 'recentProjects' => $recentProjects, |
| 'recentRecurringAlerts' => $recentRecurringAlerts, |
| 'recentRecurringCampaigns' => $recentRecurringCampaigns, |
| 'recurringLaneSummary' => $recurringLaneSummary, |
| 'recurringStats' => $recurringStats, |
| 'stats' => $stats, |
| ]); |
| } |
|
|
| private function laneLabel(SocialRecurringCampaign $campaign): string |
| { |
| $brand = trim((string) $campaign->brand_label); |
| $team = trim((string) $campaign->team_label); |
|
|
| if ($brand === '' && $team === '') { |
| return 'General / Shared'; |
| } |
|
|
| if ($brand === '') { |
| return 'General / '.$team; |
| } |
|
|
| if ($team === '') { |
| return $brand.' / Shared'; |
| } |
|
|
| return $brand.' / '.$team; |
| } |
|
|
| private function platforms(): array |
| { |
| return [ |
| 'facebook' => 'Facebook Page', |
| 'instagram' => 'Instagram Business', |
| 'tiktok' => 'TikTok', |
| 'x' => 'X / Twitter', |
| ]; |
| } |
| } |
|
|