2026-01-22 23:38:00 +01:00
|
|
|
<div class="p-6">
|
2026-03-18 21:27:14 +01:00
|
|
|
<x-page-header title="Dashboard" subtitle="Overview of your feed management system" />
|
2026-01-22 23:38:00 +01:00
|
|
|
|
|
|
|
|
<!-- System Statistics -->
|
2026-08-12 00:20:46 +02:00
|
|
|
@island('system-overview')
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="mb-8">
|
2026-08-10 19:40:22 +02:00
|
|
|
<h2 class="text-lg font-semibold text-gray-900 mb-4 dark:text-gray-100">System Overview</h2>
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
|
|
|
<!-- Active Feeds -->
|
2026-08-10 19:40:22 +02:00
|
|
|
<div class="bg-white p-6 rounded-lg shadow-sm dark:bg-gray-800">
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="flex items-center">
|
|
|
|
|
<div class="shrink-0">
|
|
|
|
|
<svg class="h-8 w-8 text-orange-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12.75 19.5v-.75a7.5 7.5 0 0 0-7.5-7.5H4.5m0-6.75h.75c7.87 0 14.25 6.38 14.25 14.25v.75M6 18.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-4">
|
2026-08-10 19:40:22 +02:00
|
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Active Feeds</p>
|
|
|
|
|
<p class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
2026-08-12 00:00:49 +02:00
|
|
|
{{ $this->systemStats['active_feeds'] }}
|
|
|
|
|
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">/{{ $this->systemStats['total_feeds'] }}</span>
|
2026-01-22 23:38:00 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Platform Accounts -->
|
2026-08-10 19:40:22 +02:00
|
|
|
<div class="bg-white p-6 rounded-lg shadow-sm dark:bg-gray-800">
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="flex items-center">
|
|
|
|
|
<div class="shrink-0">
|
|
|
|
|
<svg class="h-8 w-8 text-indigo-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-4">
|
2026-08-10 19:40:22 +02:00
|
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Platform Accounts</p>
|
|
|
|
|
<p class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
2026-08-12 00:00:49 +02:00
|
|
|
{{ $this->systemStats['active_platform_accounts'] }}
|
|
|
|
|
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">/{{ $this->systemStats['total_platform_accounts'] }}</span>
|
2026-01-22 23:38:00 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Platform Channels -->
|
2026-08-10 19:40:22 +02:00
|
|
|
<div class="bg-white p-6 rounded-lg shadow-sm dark:bg-gray-800">
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="flex items-center">
|
|
|
|
|
<div class="shrink-0">
|
|
|
|
|
<svg class="h-8 w-8 text-cyan-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 8.25h15m-16.5 7.5h15m-1.8-13.5-3.9 19.5m-2.1-19.5-3.9 19.5" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-4">
|
2026-08-10 19:40:22 +02:00
|
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Platform Channels</p>
|
|
|
|
|
<p class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
2026-08-12 00:00:49 +02:00
|
|
|
{{ $this->systemStats['active_platform_channels'] }}
|
|
|
|
|
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">/{{ $this->systemStats['total_platform_channels'] }}</span>
|
2026-01-22 23:38:00 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Active Routes -->
|
2026-08-10 19:40:22 +02:00
|
|
|
<div class="bg-white p-6 rounded-lg shadow-sm dark:bg-gray-800">
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="flex items-center">
|
|
|
|
|
<div class="shrink-0">
|
|
|
|
|
<svg class="h-8 w-8 text-pink-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-4">
|
2026-08-10 19:40:22 +02:00
|
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Active Routes</p>
|
|
|
|
|
<p class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
2026-08-12 00:00:49 +02:00
|
|
|
{{ $this->systemStats['active_routes'] }}
|
|
|
|
|
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">/{{ $this->systemStats['total_routes'] }}</span>
|
2026-01-22 23:38:00 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-08-12 00:20:46 +02:00
|
|
|
@endisland
|
2026-01-22 23:38:00 +01:00
|
|
|
|
|
|
|
|
<!-- Article Statistics -->
|
|
|
|
|
<div>
|
2026-08-12 00:00:49 +02:00
|
|
|
<div class="flex flex-col gap-3 mb-4 md:flex-row md:items-end md:justify-between">
|
2026-08-10 19:40:22 +02:00
|
|
|
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Article Statistics</h2>
|
2026-08-12 00:00:49 +02:00
|
|
|
|
|
|
|
|
<div class="flex flex-col gap-2 sm:flex-row sm:items-end">
|
|
|
|
|
<div class="flex flex-wrap gap-1">
|
2026-08-12 00:20:46 +02:00
|
|
|
@foreach ($this->presets as $value => $label)
|
2026-08-12 00:00:49 +02:00
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
wire:click="applyPreset('{{ $value }}')"
|
|
|
|
|
class="rounded-md border border-gray-300 px-2 py-1 text-xs font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700"
|
|
|
|
|
>{{ $label }}</button>
|
|
|
|
|
@endforeach
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="flex items-end gap-2">
|
|
|
|
|
<div>
|
|
|
|
|
<label for="dashboard-from" class="block text-xs font-medium text-gray-500 dark:text-gray-400">From</label>
|
|
|
|
|
<input
|
|
|
|
|
id="dashboard-from"
|
|
|
|
|
type="date"
|
|
|
|
|
wire:model.live="from"
|
|
|
|
|
class="rounded-md border border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label for="dashboard-to" class="block text-xs font-medium text-gray-500 dark:text-gray-400">To</label>
|
|
|
|
|
<input
|
|
|
|
|
id="dashboard-to"
|
|
|
|
|
type="date"
|
|
|
|
|
wire:model.live="to"
|
|
|
|
|
class="rounded-md border border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-01-22 23:38:00 +01:00
|
|
|
</div>
|
2026-08-12 00:00:49 +02:00
|
|
|
|
|
|
|
|
@error('from')
|
|
|
|
|
<p class="mb-4 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
|
|
|
|
@enderror
|
|
|
|
|
@error('to')
|
|
|
|
|
<p class="mb-4 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>
|
|
|
|
|
@enderror
|
|
|
|
|
|
2026-08-12 00:20:46 +02:00
|
|
|
@island('article-statistics')
|
2026-08-12 00:00:49 +02:00
|
|
|
<div @class(['grid grid-cols-1 md:grid-cols-3 gap-6', 'opacity-40' => ! $rangeIsValid])>
|
2026-01-22 23:38:00 +01:00
|
|
|
<!-- Articles Fetched -->
|
2026-08-10 19:40:22 +02:00
|
|
|
<div class="bg-white p-6 rounded-lg shadow-sm dark:bg-gray-800">
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="flex items-center">
|
|
|
|
|
<div class="shrink-0">
|
|
|
|
|
<svg class="h-8 w-8 text-blue-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-4">
|
2026-08-10 19:40:22 +02:00
|
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Articles Fetched</p>
|
|
|
|
|
<p class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
2026-08-12 00:00:49 +02:00
|
|
|
{{ $this->articleStats['articles_fetched'] }}
|
2026-01-22 23:38:00 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Articles Published -->
|
2026-08-10 19:40:22 +02:00
|
|
|
<div class="bg-white p-6 rounded-lg shadow-sm dark:bg-gray-800">
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="flex items-center">
|
|
|
|
|
<div class="shrink-0">
|
|
|
|
|
<svg class="h-8 w-8 text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-4">
|
2026-08-10 19:40:22 +02:00
|
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Articles Published</p>
|
|
|
|
|
<p class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
2026-08-12 00:00:49 +02:00
|
|
|
{{ $this->articleStats['articles_published'] }}
|
2026-01-22 23:38:00 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Published Rate -->
|
2026-08-10 19:40:22 +02:00
|
|
|
<div class="bg-white p-6 rounded-lg shadow-sm dark:bg-gray-800">
|
2026-01-22 23:38:00 +01:00
|
|
|
<div class="flex items-center">
|
|
|
|
|
<div class="shrink-0">
|
|
|
|
|
<svg class="h-8 w-8 text-purple-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18 9 11.25l4.306 4.306a11.95 11.95 0 0 1 5.814-5.518l2.74-1.22m0 0-5.94-2.281m5.94 2.28-2.28 5.941" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-4">
|
2026-08-10 19:40:22 +02:00
|
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">Published Rate</p>
|
|
|
|
|
<p class="text-2xl font-semibold text-gray-900 dark:text-gray-100">
|
2026-08-12 00:00:49 +02:00
|
|
|
{{ $this->articleStats['published_percentage'] }}%
|
2026-01-22 23:38:00 +01:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-08-12 00:20:46 +02:00
|
|
|
@endisland
|
2026-01-22 23:38:00 +01:00
|
|
|
</div>
|
2026-08-12 00:32:46 +02:00
|
|
|
|
2026-08-13 00:40:21 +02:00
|
|
|
<!-- Trend and breakdowns -->
|
2026-08-13 00:54:29 +02:00
|
|
|
<div class="mt-8 grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
|
|
|
<div>
|
2026-08-13 00:40:21 +02:00
|
|
|
<h2 class="text-lg font-semibold text-gray-900 mb-4 dark:text-gray-100">Fetched vs Published</h2>
|
|
|
|
|
|
|
|
|
|
@island('articles-trend')
|
|
|
|
|
@include('livewire.partials.trend-panel', [
|
2026-08-13 00:54:29 +02:00
|
|
|
'island' => 'articles-trend',
|
2026-08-13 00:40:21 +02:00
|
|
|
'result' => $this->articlesTrend,
|
|
|
|
|
'emptyMessage' => 'No articles or publications in this range.',
|
|
|
|
|
'tooWideMessage' => 'This range is too wide to chart by day. Pick a range under two years.',
|
|
|
|
|
])
|
|
|
|
|
@endisland
|
|
|
|
|
</div>
|
2026-08-13 00:10:34 +02:00
|
|
|
|
2026-08-13 00:40:21 +02:00
|
|
|
<div>
|
2026-08-13 00:54:29 +02:00
|
|
|
<h2 class="text-lg font-semibold text-gray-900 mb-4 dark:text-gray-100">Approval Rate</h2>
|
2026-08-12 00:32:46 +02:00
|
|
|
|
2026-08-13 00:54:29 +02:00
|
|
|
@island('approval-rate')
|
|
|
|
|
@include('livewire.partials.trend-panel', [
|
|
|
|
|
'island' => 'approval-rate',
|
|
|
|
|
'result' => $this->approvalRate,
|
|
|
|
|
'emptyMessage' => 'No approval decisions in this range.',
|
|
|
|
|
'tooWideMessage' => 'This range is too wide to chart by day. Pick a range under two years.',
|
|
|
|
|
'suffix' => '%',
|
|
|
|
|
'max' => 100,
|
2026-08-13 17:34:57 +02:00
|
|
|
])
|
|
|
|
|
@endisland
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<h2 class="text-lg font-semibold text-gray-900 mb-4 dark:text-gray-100">Publish Success Rate</h2>
|
|
|
|
|
|
|
|
|
|
@island('publish-success-rate')
|
|
|
|
|
@include('livewire.partials.trend-panel', [
|
|
|
|
|
'island' => 'publish-success-rate',
|
|
|
|
|
'result' => $this->publishSuccessRate,
|
|
|
|
|
'emptyMessage' => 'No publish attempts in this range.',
|
|
|
|
|
'tooWideMessage' => 'This range is too wide to chart by day. Pick a range under two years.',
|
|
|
|
|
'suffix' => '%',
|
|
|
|
|
'max' => 100,
|
2026-08-13 00:40:21 +02:00
|
|
|
])
|
|
|
|
|
@endisland
|
|
|
|
|
</div>
|
2026-08-12 00:41:10 +02:00
|
|
|
|
2026-08-13 00:54:29 +02:00
|
|
|
<div class="space-y-6">
|
|
|
|
|
<div>
|
|
|
|
|
<h2 class="text-lg font-semibold text-gray-900 mb-4 dark:text-gray-100">Articles per Feed</h2>
|
2026-08-12 00:41:10 +02:00
|
|
|
|
2026-08-13 00:54:29 +02:00
|
|
|
@island('articles-per-feed')
|
|
|
|
|
@include('livewire.partials.breakdown-panel', [
|
|
|
|
|
'result' => $this->articlesPerFeed,
|
|
|
|
|
'emptyMessage' => 'No feeds are configured yet.',
|
|
|
|
|
])
|
|
|
|
|
@endisland
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<h2 class="text-lg font-semibold text-gray-900 mb-4 dark:text-gray-100">Publications per Channel</h2>
|
|
|
|
|
|
|
|
|
|
@island('publications-per-channel')
|
|
|
|
|
@include('livewire.partials.breakdown-panel', [
|
|
|
|
|
'result' => $this->publicationsPerChannel,
|
|
|
|
|
'emptyMessage' => 'No channels are configured yet.',
|
|
|
|
|
])
|
|
|
|
|
@endisland
|
|
|
|
|
</div>
|
2026-08-13 00:40:21 +02:00
|
|
|
</div>
|
2026-08-13 17:48:17 +02:00
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<div class="mb-4 flex items-baseline justify-between gap-4">
|
|
|
|
|
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Recent Activity</h2>
|
|
|
|
|
|
|
|
|
|
<a href="{{ route('activity') }}" wire:navigate class="text-sm font-medium text-blue-600 hover:text-blue-500 dark:text-blue-400">
|
|
|
|
|
View all
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
@include('livewire.partials.activity-panel', ['entries' => $this->recentActivity])
|
|
|
|
|
</div>
|
2026-08-12 00:32:46 +02:00
|
|
|
</div>
|
2026-01-22 23:38:00 +01:00
|
|
|
</div>
|