106 lines
3.9 KiB
PHP
106 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Moderation;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Story;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
final class StoriesController extends Controller
|
|
{
|
|
public function index(Request $request): Response
|
|
{
|
|
$filters = [
|
|
'q' => trim((string) $request->query('q', '')),
|
|
'status' => trim((string) $request->query('status', 'all')),
|
|
];
|
|
|
|
$query = Story::query()
|
|
->with('creator:id,name,username')
|
|
->latest('created_at')
|
|
->latest('id');
|
|
|
|
if ($filters['q'] !== '') {
|
|
$search = $filters['q'];
|
|
$query->where(function ($builder) use ($search): void {
|
|
$builder
|
|
->where('title', 'like', '%' . $search . '%')
|
|
->orWhere('slug', 'like', '%' . $search . '%')
|
|
->orWhereHas('creator', function ($creatorQuery) use ($search): void {
|
|
$creatorQuery
|
|
->where('name', 'like', '%' . $search . '%')
|
|
->orWhere('username', 'like', '%' . $search . '%');
|
|
});
|
|
});
|
|
}
|
|
|
|
if ($filters['status'] !== '' && $filters['status'] !== 'all') {
|
|
$query->where('status', $filters['status']);
|
|
}
|
|
|
|
$stories = $query
|
|
->paginate(24)
|
|
->withQueryString()
|
|
->through(fn (Story $story): array => $this->serializeStory($story));
|
|
|
|
$statsQuery = Story::query();
|
|
if ($filters['q'] !== '') {
|
|
$search = $filters['q'];
|
|
$statsQuery->where(function ($builder) use ($search): void {
|
|
$builder
|
|
->where('title', 'like', '%' . $search . '%')
|
|
->orWhere('slug', 'like', '%' . $search . '%')
|
|
->orWhereHas('creator', function ($creatorQuery) use ($search): void {
|
|
$creatorQuery
|
|
->where('name', 'like', '%' . $search . '%')
|
|
->orWhere('username', 'like', '%' . $search . '%');
|
|
});
|
|
});
|
|
}
|
|
|
|
$stats = [
|
|
'total' => (clone $statsQuery)->count(),
|
|
'published' => (clone $statsQuery)->where('status', 'published')->count(),
|
|
'draft' => (clone $statsQuery)->where('status', 'draft')->count(),
|
|
'scheduled' => (clone $statsQuery)->where('status', 'scheduled')->count(),
|
|
'pending_review' => (clone $statsQuery)->where('status', 'pending_review')->count(),
|
|
'archived' => (clone $statsQuery)->where('status', 'archived')->count(),
|
|
];
|
|
|
|
return Inertia::render('Moderation/Stories', [
|
|
'title' => 'Stories',
|
|
'stories' => $stories,
|
|
'filters' => $filters,
|
|
'stats' => $stats,
|
|
'endpoints' => [
|
|
'index' => route('admin.stories'),
|
|
],
|
|
])->rootView('moderation');
|
|
}
|
|
|
|
private function serializeStory(Story $story): array
|
|
{
|
|
return [
|
|
'id' => (int) $story->id,
|
|
'title' => (string) ($story->title ?: 'Untitled story'),
|
|
'slug' => (string) $story->slug,
|
|
'excerpt' => $story->excerpt,
|
|
'status' => (string) ($story->status ?: 'draft'),
|
|
'published_at' => optional($story->published_at)?->toIso8601String(),
|
|
'created_at' => optional($story->created_at)?->toIso8601String(),
|
|
'cover_url' => $story->coverUrl,
|
|
'public_url' => $story->url,
|
|
'open_url' => $story->status === 'published' ? $story->url : null,
|
|
'creator' => $story->creator ? [
|
|
'id' => (int) $story->creator->id,
|
|
'name' => (string) $story->creator->name,
|
|
'username' => (string) $story->creator->username,
|
|
] : null,
|
|
];
|
|
}
|
|
}
|