feat: Phase 2 - admin layout, dashboard, page CRUD, subscribers, user management

This commit is contained in:
2026-04-03 20:09:20 +02:00
parent 904cf1241b
commit 78e1be3e3b
27 changed files with 404 additions and 33 deletions

View File

@@ -5,13 +5,23 @@ declare(strict_types=1);
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Services\DashboardStatisticsService;
use Illuminate\Http\Request;
use Illuminate\View\View;
class DashboardController extends Controller
{
public function __invoke(Request $request): View
public function __invoke(Request $request, DashboardStatisticsService $statistics): View
{
return view('admin.dashboard');
$user = $request->user();
abort_if($user === null, 401);
$stats = $statistics->forUser($user);
return view('admin.dashboard', [
'totalPages' => $stats['total_pages'],
'totalSubscribers' => $stats['total_subscribers'],
'activePages' => $stats['active_pages'],
]);
}
}

View File

@@ -28,7 +28,7 @@ class AuthenticatedSessionController extends Controller
$request->session()->regenerate();
return redirect()->intended(route('dashboard', absolute: false));
return redirect()->intended(route('admin.dashboard', absolute: false));
}
/**

View File

@@ -35,6 +35,6 @@ class ConfirmablePasswordController extends Controller
$request->session()->put('auth.password_confirmed_at', time());
return redirect()->intended(route('dashboard', absolute: false));
return redirect()->intended(route('admin.dashboard', absolute: false));
}
}

View File

@@ -14,7 +14,7 @@ class EmailVerificationNotificationController extends Controller
public function store(Request $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(route('dashboard', absolute: false));
return redirect()->intended(route('admin.dashboard', absolute: false));
}
$request->user()->sendEmailVerificationNotification();

View File

@@ -15,7 +15,7 @@ class EmailVerificationPromptController extends Controller
public function __invoke(Request $request): RedirectResponse|View
{
return $request->user()->hasVerifiedEmail()
? redirect()->intended(route('dashboard', absolute: false))
? redirect()->intended(route('admin.dashboard', absolute: false))
: view('auth.verify-email');
}
}

View File

@@ -46,6 +46,6 @@ class RegisteredUserController extends Controller
Auth::login($user);
return redirect(route('dashboard', absolute: false));
return redirect(route('admin.dashboard', absolute: false));
}
}

View File

@@ -15,13 +15,13 @@ class VerifyEmailController extends Controller
public function __invoke(EmailVerificationRequest $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
return redirect()->intended(route('admin.dashboard', absolute: false).'?verified=1');
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
return redirect()->intended(route('admin.dashboard', absolute: false).'?verified=1');
}
}

View File

@@ -34,7 +34,7 @@ class ProfileController extends Controller
$request->user()->save();
return Redirect::route('profile.edit')->with('status', 'profile-updated');
return Redirect::route('admin.profile.edit')->with('status', 'profile-updated');
}
/**

View File

@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Models\PreregistrationPage;
use App\Models\Subscriber;
use App\Models\User;
use Illuminate\Support\Carbon;
final class DashboardStatisticsService
{
/**
* @return array{total_pages: int, total_subscribers: int, active_pages: int}
*/
public function forUser(User $user): array
{
$pagesQuery = PreregistrationPage::query();
if (! $user->isSuperadmin()) {
$pagesQuery->where('user_id', $user->id);
}
$now = Carbon::now();
$totalPages = (clone $pagesQuery)->count();
$pageIds = (clone $pagesQuery)->pluck('id');
$totalSubscribers = $pageIds->isEmpty()
? 0
: Subscriber::whereIn('preregistration_page_id', $pageIds)->count();
$activePages = (clone $pagesQuery)
->where('start_date', '<=', $now)
->where('end_date', '>=', $now)
->count();
return [
'total_pages' => $totalPages,
'total_subscribers' => $totalSubscribers,
'active_pages' => $activePages,
];
}
}