Client::count(), 'active_clients' => Client::where('status', 'active')->count(), 'upcoming_events' => Event::upcoming(24 * 90)->count(), // 3 months 'pending_invoices' => Invoice::where('status', 'sent')->count(), 'total_revenue' => Invoice::where('status', 'paid')->sum('total'), 'content_in_progress' => ContentBrief::whereNotIn('status', ['posted', 'archived'])->count(), ]; } /** * Combined today's activities: events (today or ongoing), invoices due, content targets. */ public function getTodayActivities(): Collection { $activities = collect(); // Events starting today OR currently ongoing (started before today, ends today or later) $events = Event::with('client') ->where(function ($q) { $q->whereDate('start_time', today()) ->orWhere(function ($q2) { $q2->whereDate('start_time', '<', today()) ->where(function ($q3) { $q3->whereDate('end_time', '>=', today()) ->orWhereNull('end_time'); }) ->whereNotIn('status', ['completed', 'cancelled']); }); }) ->orderBy('start_time') ->limit(15) ->get(); foreach ($events as $e) { $timeLabel = $e->is_all_day ? 'All day' : ($e->start_time->format('H:i') . ($e->end_time ? ' – ' . $e->end_time->format('H:i') : '')); $activities->push([ 'type' => 'event', 'icon' => '📅', 'title' => $e->title, 'subtitle' => $timeLabel . ($e->client ? ' · ' . $e->client->name : ''), 'label' => $e->event_type, 'badge' => $e->status->label(), 'badge_class' => $e->status->badgeClass(), 'color' => $e->color ?? '#FFB7C5', 'priority' => $e->is_priority, 'sort_key' => $e->start_time->timestamp, ]); } // Invoices due today (not yet paid or cancelled) $invoices = Invoice::with('client') ->whereDate('due_date', today()) ->whereNotIn('status', ['paid', 'cancelled']) ->get(); foreach ($invoices as $inv) { $activities->push([ 'type' => 'invoice', 'icon' => '🧾', 'title' => $inv->title ?? $inv->invoice_number, 'subtitle' => ($inv->client?->name ?? 'No client') . ' · ' . ($inv->formatted_total ?? ''), 'label' => 'Invoice Due', 'badge' => $inv->status->label(), 'badge_class' => $inv->status->badgeClass(), 'color' => '#FDFD96', 'priority' => false, 'sort_key' => today()->setTime(23, 59, 0)->timestamp, ]); } // Content briefs with target date today (not posted/archived) $content = ContentBrief::with('client') ->whereDate('target_date', today()) ->whereNotIn('status', ['posted', 'archived']) ->get(); foreach ($content as $c) { $activities->push([ 'type' => 'content', 'icon' => $c->platform_icon, 'title' => $c->title, 'subtitle' => ucfirst($c->platform) . ($c->client ? ' · ' . $c->client->name : ''), 'label' => 'Content Target', 'badge' => $c->status->label(), 'badge_class' => 'badge-ghost', 'color' => '#E8D5F5', 'priority' => false, 'sort_key' => today()->setTime(12, 0, 0)->timestamp, ]); } return $activities->sortBy('sort_key')->values(); } public function getAlertCount(): int { return Event::upcoming(24)->count(); } public function getLatestInvoices(): Collection { return Invoice::with('client') ->latest() ->limit(5) ->get(); } public function getSocialStats(): Collection { return SocialStat::whereIn('id', function ($query): void { $query->selectRaw('MAX(id)') ->from('social_stats') ->groupBy('platform'); })->get(); } }