fedi-feed-router/resources/views/livewire/articles.blade.php

193 lines
11 KiB
PHP

<div class="p-6">
<div class="mb-6 flex items-start justify-between">
<div>
<h1 class="text-2xl font-bold text-gray-900">Articles</h1>
<p class="mt-1 text-sm text-gray-500">
Review and manage article routing
</p>
</div>
<button
wire:click="refresh"
wire:loading.attr="disabled"
@disabled($isRefreshing)
x-on:refresh-started.window="setTimeout(() => window.location.reload(), 10000)"
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
>
<svg class="h-4 w-4 mr-2 {{ $isRefreshing ? 'animate-spin' : '' }}" wire:loading.class="animate-spin" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
<span wire:loading.remove wire:target="refresh">{{ $isRefreshing ? 'Refreshing...' : 'Refresh' }}</span>
<span wire:loading wire:target="refresh">Refreshing...</span>
</button>
</div>
{{-- Tab bar --}}
<div class="mb-6 border-b border-gray-200">
<nav class="-mb-px flex space-x-8">
<button
wire:click="setTab('pending')"
class="whitespace-nowrap pb-3 px-1 border-b-2 font-medium text-sm {{ $tab === 'pending' ? 'border-blue-500 text-blue-600' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }}"
>
Pending
@if ($pendingCount > 0)
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">
{{ $pendingCount }}
</span>
@endif
</button>
<button
wire:click="setTab('all')"
class="whitespace-nowrap pb-3 px-1 border-b-2 font-medium text-sm {{ $tab === 'all' ? 'border-blue-500 text-blue-600' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }}"
>
All
</button>
</nav>
</div>
{{-- Tab actions --}}
<div class="mb-4 flex items-center justify-between">
@if ($tab === 'pending' && $pendingCount > 0)
<button
wire:click="clear"
wire:confirm="Reject all {{ $pendingCount }} pending route articles?"
class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
<svg class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
Clear All
</button>
@elseif ($tab === 'all')
<div class="flex-1 max-w-sm">
<input
type="text"
wire:model.live.debounce.300ms="search"
placeholder="Search articles..."
class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
</div>
@else
<div></div>
@endif
</div>
{{-- Route articles list --}}
<div class="space-y-4">
@forelse ($routeArticles as $routeArticle)
<div class="bg-white rounded-lg shadow p-5" wire:key="ra-{{ $routeArticle->id }}">
<div class="flex items-start justify-between">
<div class="flex-1 min-w-0">
<h3 class="text-base font-medium text-gray-900 mb-1">
{{ $routeArticle->article->title ?? 'Untitled Article' }}
</h3>
<p class="text-sm text-gray-600 mb-2 line-clamp-2">
{{ $routeArticle->article->description ?? 'No description available' }}
</p>
<div class="flex items-center flex-wrap gap-x-3 gap-y-1 text-xs text-gray-500">
<span class="inline-flex items-center">
<svg class="h-3 w-3 mr-1" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
</svg>
{{ $routeArticle->feed?->name ?? 'Unknown' }} &rarr; {{ $routeArticle->platformChannel?->name ?? 'Unknown' }}
</span>
<span>{{ $routeArticle->created_at->format('M d, Y H:i') }}</span>
</div>
</div>
<div class="flex items-center space-x-2 ml-4">
{{-- Status badge (All tab) --}}
@if ($tab === 'all')
@if ($routeArticle->isApproved())
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
Approved
</span>
@elseif ($routeArticle->isRejected())
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
Rejected
</span>
@else
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">
Pending
</span>
@endif
@endif
{{-- Action buttons --}}
@if ($routeArticle->isPending())
<button
wire:click="approve({{ $routeArticle->id }})"
class="inline-flex items-center p-1.5 text-green-600 hover:text-green-800 hover:bg-green-50 rounded-md"
title="Approve"
>
<svg class="h-5 w-5" 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>
</button>
<button
wire:click="reject({{ $routeArticle->id }})"
class="inline-flex items-center p-1.5 text-red-600 hover:text-red-800 hover:bg-red-50 rounded-md"
title="Reject"
>
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
@elseif ($routeArticle->isRejected())
<button
wire:click="restore({{ $routeArticle->id }})"
class="inline-flex items-center p-1.5 text-blue-600 hover:text-blue-800 hover:bg-blue-50 rounded-md"
title="Restore to pending"
>
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
</svg>
</button>
@endif
{{-- Link to original --}}
@if ($routeArticle->article->url)
<a
href="{{ $routeArticle->article->url }}"
target="_blank"
rel="noopener noreferrer"
class="p-1.5 text-gray-400 hover:text-gray-600 rounded-md"
title="View original article"
>
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
</svg>
</a>
@endif
</div>
</div>
</div>
@empty
<div class="text-center py-12">
<svg class="mx-auto h-12 w-12 text-gray-400" 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>
<h3 class="mt-2 text-sm font-medium text-gray-900">
@if ($tab === 'pending')
No pending articles
@else
No articles found
@endif
</h3>
<p class="mt-1 text-sm text-gray-500">
@if ($tab === 'pending')
All route articles have been reviewed.
@elseif ($search !== '')
No results for "{{ $search }}".
@else
No route articles have been created yet.
@endif
</p>
</div>
@endforelse
@if ($routeArticles->hasPages())
<div class="mt-6">
{{ $routeArticles->links() }}
</div>
@endif
</div>
</div>