@php $healthScore = (int) round(collect($platformProgress)->avg('completion') ?: 0); $cronTone = match ($cronStatus['state']) { 'healthy' => 'db-pill--healthy', 'critical' => 'db-pill--critical', default => 'db-pill--warning', }; $cronServiceLabel = match ($cronStatus['service_status']) { 'active' => 'Active', 'inactive' => 'Inactive', 'failed' => 'Failed', default => 'Unknown', }; @endphp
Operations cockpit

Dashboard

Ringkasan progress automation, kesehatan scheduler, dan readiness tiap platform dalam satu layar yang lebih jelas.

🧩 App 🎨 Image 🎬 Video 🎙️ Voice 🪄 Face 📤 Publish
@csrf
Ready to render Idle
Upload start frame, isi prompt, lalu jalankan render. Kalau provider gagal, error akan muncul langsung di dashboard tanpa meninggalkan hasil palsu.
Open result lab
720p 8s 16:9
🤍 120 320

Recent projects

@if ($recentProjects->count() > 0)
@foreach ($recentProjects as $project) @php $typeIcon = match($project->type) { 'video' => '🎬', 'audio' => '🎙️', default => '🖼️', }; $typeLabel = match($project->type) { 'video' => 'Video', 'audio' => 'Audio', default => 'Image', }; $thumb = $project->thumbnail_url ?: $project->url; $isVideo = $project->type === 'video'; $isAudio = $project->type === 'audio'; $meta = is_array($project->meta) ? $project->meta : []; $editorKey = 'image'; $editorHash = '#image-lab'; $editorLabel = 'Open image lab'; $assetId = $project->type === 'image' ? (string) $project->id : ''; $sourceAssetId = ''; $sourceThumb = ''; if ($isAudio) { $editorKey = 'voice'; $editorHash = '#voice-lab'; $editorLabel = 'Open voice lab'; } elseif (($meta['template_slug'] ?? '') === 'movie-poster' || $project->provider === 'poster') { $editorKey = 'poster'; $editorHash = '#image-lab'; $editorLabel = 'Open movie poster canvas'; $sourceAssetId = (string) ($meta['source_asset_id'] ?? $assetId); } elseif (in_array((string) $project->provider, ['replicate-tryon', 'fal-tryon'], true) || ($meta['source'] ?? '') === 'tools_tryon_async_poll') { $editorKey = 'tryon'; $editorHash = '#image-lab'; $editorLabel = 'Open try on canvas'; $sourceAssetId = (string) ($meta['source_asset_id'] ?? $assetId); } elseif ($isVideo || in_array((string) $project->provider, ['replicate-i2v', 'freepik-runway-i2v', 'hf-motion', 'huggingface-motion', 'openai-sora', 'gemini-veo', 'runway'], true)) { $editorKey = 'video'; $editorHash = '#video-lab'; $editorLabel = 'Open video canvas'; $sourceAssetId = (string) ($meta['source_asset_id'] ?? ''); $sourceThumb = (string) ($project->thumbnail_url ?: ''); } $editorRouteParams = array_filter([ 'editor' => $editorKey, 'asset' => $assetId !== '' ? $assetId : null, 'source_asset_id' => $sourceAssetId !== '' ? $sourceAssetId : null, 'source_thumb' => $sourceThumb !== '' ? $sourceThumb : null, ], fn ($value) => $value !== null && $value !== ''); $editorHref = route('app.index', $editorRouteParams).$editorHash; @endphp @endforeach
Open AI App →
@else
📭
No projects yet

Start creating by choosing an action above

@endif

What would you like to create today?

Automation Pulse

Automation Ops Board

Dashboard sekarang jadi pusat observasi yang lebih premium buat lihat readiness tiap platform, queue health, dan status cronjob yang menentukan apakah scheduled publish benar-benar jalan di server.

{{ $stats['ready_platforms'] }} platform ready {{ $healthScore }}% average progress {{ $cronStatus['headline'] }}
Automation heartbeat
{{ $cronStatus['headline'] }}

{{ $cronStatus['detail'] }}

Cron Service

{{ $cronServiceLabel }}

Schedule Entry

{{ $cronStatus['schedule_entry_found'] ? 'Detected' : 'Missing' }}

Runner

{{ $cronStatus['runner_detected'] ? 'Detected' : 'Idle' }}

Next Queue Focus

{{ $nextScheduledPost?->platform ? ucfirst($nextScheduledPost->platform) : 'No pending post' }}

Scheduled {{ $stats['scheduled'] }}

Item yang siap atau menunggu jalur publish terjadwal.

Posted {{ $stats['posted'] }}

Total post yang sudah pernah berhasil terkirim.

Failed {{ $stats['failed'] }}

Butuh pengecekan token, media requirement, atau retry.

Approval Queue {{ $stats['approval'] }}

Draft yang masih tertahan manual approval.

Ready Platforms {{ $stats['ready_platforms'] }}

Platform dengan token yang sudah siap dipakai automation.

Campaign KPI and alert center

Monitor performa recurring campaign, lihat lane brand/team yang paling aktif, dan tangkap failure scheduler sebelum queue harian ikut terganggu.

{{ $recurringStats['unread_alerts'] }} unread alerts {{ $recurringStats['approval_queue'] }} awaiting approval
Active Campaigns

{{ $recurringStats['active'] }}

Due Today

{{ $recurringStats['due_today'] }}

Generated This Week

{{ $recurringStats['generated_this_week'] }}

Failing Campaigns

{{ $recurringStats['failing_campaigns'] }}

Brand / Team Approval Lanes

Recurring campaign sekarang bisa pakai approval lane khusus per brand dan team.

{{ $recurringLaneSummary->count() }} lanes
@forelse ($recurringLaneSummary as $lane) @empty @endforelse
Lane Active Manual Next Run
{{ $lane['label'] }} {{ $lane['active'] }}/{{ $lane['count'] }} {{ $lane['manual'] }} {{ optional($lane['next_occurrence_at'])->format('d M Y H:i') ?: '-' }}
Belum ada recurring campaign lane yang tersimpan.

Recent Recurring Alerts

Alert dibuat otomatis saat recurring scheduler gagal membuat occurrence baru.

{{ $recurringStats['unread_alerts'] > 0 ? 'Needs attention' : 'Quiet' }}
@forelse ($recentRecurringAlerts as $alert) @empty @endforelse
Campaign Message Status
{{ data_get($alert->context, 'campaign_title') ?: ('Campaign #'.$alert->social_recurring_campaign_id) }} {{ \Illuminate\Support\Str::limit($alert->message, 90) }} {{ $alert->read_at ? 'resolved' : 'unread' }}
Belum ada recurring alert. Scheduler masih bersih.
@forelse ($recentRecurringCampaigns as $campaign) @empty @endforelse
Campaign Lane Approval Next Run
{{ $campaign->title ?: 'Untitled recurring campaign' }} {{ $campaign->brand_label ?: 'General' }} / {{ $campaign->team_label ?: 'Shared' }} {{ strtoupper($campaign->approval_mode) }} {{ optional($campaign->next_occurrence_at)->format('d M Y H:i') ?: '-' }}
Belum ada recurring campaign yang bisa ditampilkan.

Readiness by platform

Setiap platform sekarang punya progress yang menggabungkan credential readiness, aktivitas queue, dan jejak publish supaya gampang kelihatan mana yang sudah live dan mana yang masih butuh perhatian.

@foreach ($platforms as $key => $label) @php $progress = $platformProgress[$key]; $stateClass = match ($progress['state_tone']) { 'healthy' => 'db-state--healthy', 'critical' => 'db-state--critical', 'ready', 'warning' => 'db-state--warning', default => 'db-state--pending', }; @endphp

{{ $label }}

{{ $progress['next_action'] }}

{{ $progress['state'] }}
{{ $progress['completion'] }}%
{{ $progress['credential_ready'] ? 'Token ready' : 'Token missing' }}
Scheduled {{ $progress['counts']['scheduled'] }}
Posted {{ $progress['counts']['posted'] }}
Failed {{ $progress['counts']['failed'] }}
Approval {{ $progress['counts']['approval'] }}
@foreach ($progress['steps'] as $step) {{ $step['label'] }} @endforeach

@if ($progress['last_activity_at']) Aktivitas terakhir {{ $progress['last_activity_at']->format('d M Y H:i') }} dengan status {{ $progress['last_status'] ?? 'unknown' }}. @else Belum ada aktivitas queue untuk platform ini. @endif

@endforeach

Cron Scheduler Status

Status ini dibaca dari server saat halaman dibuka, jadi kamu bisa lihat apakah scheduler Laravel benar-benar punya jalur eksekusi otomatis atau belum.

{{ $cronStatus['state'] }}
Cron Service

{{ $cronServiceLabel }}

Entry Source

{{ $cronStatus['schedule_entry_source'] ?? 'Belum ditemukan' }}

Runner Command

{{ $cronStatus['runner_command'] ?? 'Tidak ada runner artisan yang sedang aktif' }}

Checked At

{{ $cronStatus['checked_at']->format('d M Y H:i:s') }}

Expected cron entry

Kalau mau automation scheduled jalan stabil, server ini seharusnya punya entry cron berikut.

{{ $cronStatus['expected_cron'] }}

Laravel command yang dijadwalkan oleh aplikasi saat ini:

{{ $cronStatus['publish_command'] }}

Latest automation items

Snapshot singkat item terakhir biar kamu bisa lihat platform mana yang paling aktif tanpa harus pindah ke halaman queue penuh.

@forelse ($recentPosts as $post) @empty @endforelse
Platform Status Scheduled Caption
{{ ucfirst($post->platform) }} {{ $post->status }} {{ optional($post->scheduled_at)->format('d M Y H:i') ?: '-' }} {{ \Illuminate\Support\Str::limit($post->caption, 100) }}
Belum ada item queue. Mulai dari halaman Social Automation untuk bikin draft atau scheduled post pertama.