teknolis / app /Http /Controllers /DashboardController.php
Codex
Deploy latest assistant, DeepSeek defaults, and automation updates
74acf19
Raw
History Blame Contribute Delete
5.76 kB
<?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',
];
}
}