117 lines
4.7 KiB
PHP
117 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Moderation;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
final class UsernameQueueController extends Controller
|
|
{
|
|
public function index(Request $request): Response
|
|
{
|
|
$filters = [
|
|
'q' => trim((string) $request->query('q', '')),
|
|
'status' => trim((string) $request->query('status', 'pending')),
|
|
];
|
|
|
|
$requestColumns = Schema::hasTable('username_approval_requests')
|
|
? Schema::getColumnListing('username_approval_requests')
|
|
: [];
|
|
|
|
$query = DB::table('username_approval_requests as requests')
|
|
->leftJoin('users', 'users.id', '=', 'requests.user_id')
|
|
->select([
|
|
'requests.id',
|
|
'requests.user_id',
|
|
'requests.requested_username',
|
|
'requests.status',
|
|
'requests.context',
|
|
'requests.similar_to',
|
|
'requests.review_note',
|
|
'requests.reviewed_at',
|
|
'requests.created_at',
|
|
'users.username as current_username',
|
|
'users.name as current_name',
|
|
])
|
|
->orderByDesc('requests.created_at');
|
|
|
|
if ($filters['status'] !== '' && $filters['status'] !== 'all') {
|
|
$query->where('requests.status', $filters['status']);
|
|
}
|
|
|
|
if ($filters['q'] !== '') {
|
|
$search = $filters['q'];
|
|
$query->where(function ($builder) use ($search): void {
|
|
$builder
|
|
->where('requests.requested_username', 'like', '%' . $search . '%')
|
|
->orWhere('requests.context', 'like', '%' . $search . '%')
|
|
->orWhere('users.username', 'like', '%' . $search . '%')
|
|
->orWhere('users.name', 'like', '%' . $search . '%');
|
|
});
|
|
}
|
|
|
|
$requests = $query->paginate(20)->withQueryString()->through(function ($row): array {
|
|
return [
|
|
'id' => (int) $row->id,
|
|
'user_id' => $row->user_id !== null ? (int) $row->user_id : null,
|
|
'requested_username' => (string) $row->requested_username,
|
|
'status' => (string) ($row->status ?? 'pending'),
|
|
'context' => $row->context ?? null,
|
|
'similar_to' => $row->similar_to ?? null,
|
|
'review_note' => $row->review_note ?? null,
|
|
'reviewed_at' => $this->serializeTimestamp($row->reviewed_at ?? null),
|
|
'created_at' => $this->serializeTimestamp($row->created_at ?? null),
|
|
'current_username' => $row->current_username,
|
|
'current_name' => $row->current_name,
|
|
'approve_url' => route('api.admin.usernames.approve', ['id' => $row->id]),
|
|
'reject_url' => route('api.admin.usernames.reject', ['id' => $row->id]),
|
|
];
|
|
});
|
|
|
|
$stats = [
|
|
'total' => Schema::hasTable('username_approval_requests') ? DB::table('username_approval_requests')->count() : 0,
|
|
'pending' => Schema::hasTable('username_approval_requests') ? DB::table('username_approval_requests')->where('status', 'pending')->count() : 0,
|
|
'approved' => Schema::hasTable('username_approval_requests') ? DB::table('username_approval_requests')->where('status', 'approved')->count() : 0,
|
|
'rejected' => Schema::hasTable('username_approval_requests') ? DB::table('username_approval_requests')->where('status', 'rejected')->count() : 0,
|
|
];
|
|
|
|
return Inertia::render('Moderation/UsernameQueue', [
|
|
'title' => 'Username Queue',
|
|
'requests' => $requests,
|
|
'stats' => $stats,
|
|
'filters' => $filters,
|
|
'options' => [
|
|
'statuses' => [
|
|
['value' => 'all', 'label' => 'All statuses'],
|
|
['value' => 'pending', 'label' => 'Pending'],
|
|
['value' => 'approved', 'label' => 'Approved'],
|
|
['value' => 'rejected', 'label' => 'Rejected'],
|
|
],
|
|
],
|
|
'endpoints' => [
|
|
'index' => route('admin.usernames'),
|
|
'refresh' => route('admin.usernames'),
|
|
],
|
|
])->rootView('moderation');
|
|
}
|
|
|
|
private function serializeTimestamp(mixed $value): ?string
|
|
{
|
|
if ($value === null || $value === '') {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return \Illuminate\Support\Carbon::parse((string) $value)->toIso8601String();
|
|
} catch (\Throwable) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|