diff --git a/app/Http/Controllers/Admin/AdminInvitationController.php b/app/Http/Controllers/Admin/AdminInvitationController.php index 8a117196c..bab9334a7 100644 --- a/app/Http/Controllers/Admin/AdminInvitationController.php +++ b/app/Http/Controllers/Admin/AdminInvitationController.php @@ -8,6 +8,7 @@ use App\Models\User; use App\Services\InvitationService; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\View\View; class AdminInvitationController extends BasePageController { @@ -22,7 +23,7 @@ class AdminInvitationController extends BasePageController /** * Display all invitations statistics and management page */ - public function index(Request $request): void + public function index(Request $request): View { $this->setAdminPrefs(); @@ -33,7 +34,6 @@ class AdminInvitationController extends BasePageController $invited_by = $request->get('invited_by', ''); $email = $request->get('email', ''); $orderBy = $request->get('ob', 'created_at_desc'); - $page = $request->get('page', 1); // Build query $query = Invitation::with(['invitedBy', 'usedBy']); @@ -93,7 +93,7 @@ class AdminInvitationController extends BasePageController } // Paginate results - $invitations = $query->paginate(config('nntmux.items_per_page', 25)); + $invitations = $query->paginate(config('nntmux.items_per_page', 25))->withQueryString(); // Get overall statistics $stats = $this->getOverallStats(); @@ -101,27 +101,26 @@ class AdminInvitationController extends BasePageController // Get user statistics (top inviters) $topInviters = $this->getTopInviters(); - $this->smarty->assign([ - 'invitations' => $invitations, - 'stats' => $stats, - 'topInviters' => $topInviters, - 'status' => $status, - 'invited_by' => $invited_by, - 'email' => $email, - 'orderBy' => $orderBy, - 'statusOptions' => [ - '' => 'All', - 'pending' => 'Pending', - 'used' => 'Used', - 'expired' => 'Expired', - 'cancelled' => 'Cancelled', - ], - ]); + $statusOptions = [ + '' => 'All', + 'pending' => 'Pending', + 'used' => 'Used', + 'expired' => 'Expired', + 'cancelled' => 'Cancelled', + ]; - $content = $this->smarty->fetch('admin-invitation-list.tpl'); - $this->smarty->assign(compact('title', 'meta_title', 'content')); - - $this->adminrender(); + return view('admin.invitations.index', compact( + 'invitations', + 'stats', + 'topInviters', + 'status', + 'invited_by', + 'email', + 'orderBy', + 'statusOptions', + 'title', + 'meta_title' + )); } /** @@ -210,7 +209,7 @@ class AdminInvitationController extends BasePageController /** * View detailed invitation */ - public function show(Request $request): void + public function show(Request $request): View { $this->setAdminPrefs(); @@ -219,14 +218,7 @@ class AdminInvitationController extends BasePageController $meta_title = $title = 'Invitation Details'; - $this->smarty->assign([ - 'invitation' => $invitation, - ]); - - $content = $this->smarty->fetch('admin-invitation-show.tpl'); - $this->smarty->assign(compact('title', 'meta_title', 'content')); - - $this->adminrender(); + return view('admin.invitations.show', compact('invitation', 'title', 'meta_title')); } /** diff --git a/resources/views/admin/invitations/index.blade.php b/resources/views/admin/invitations/index.blade.php new file mode 100644 index 000000000..5011c3452 --- /dev/null +++ b/resources/views/admin/invitations/index.blade.php @@ -0,0 +1,294 @@ +@extends('layouts.admin') + +@section('content') +
+
+ +
+
+

+ {{ $title }} +

+
+
+ @csrf + +
+
+
+
+ + +
+
+
+
Total Invitations
+
{{ $stats['total'] }}
+
+
+
Pending
+
{{ $stats['pending'] }}
+
+
+
Used
+
{{ $stats['used'] }}
+
+
+
Expired
+
{{ $stats['expired'] }}
+
+
+ +
+
+
Today
+
{{ $stats['today'] }}
+
+
+
This Week
+
{{ $stats['this_week'] }}
+
+
+
This Month
+
{{ $stats['this_month'] }}
+
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + Clear + +
+
+
+ + +
+
+ @csrf + + + + + + + + + + + + + + @forelse($invitations as $invitation) + + + + + + + + + + @empty + + + + @endforelse + +
+ + EmailInvited ByStatusCreatedExpiresActions
+ + + {{ $invitation->email }} + + {{ optional($invitation->invitedBy)->username ?? '—' }} + + @if($invitation->used_at) + + Used + + @elseif(!$invitation->is_active) + + Cancelled + + @elseif($invitation->expires_at && $invitation->expires_at->isPast()) + + Expired + + @else + + Pending + + @endif + + {{ $invitation->created_at->format('Y-m-d H:i') }} + + {{ $invitation->expires_at ? $invitation->expires_at->format('Y-m-d H:i') : 'Never' }} + + + + + @if(!$invitation->used_at) + + @csrf + + +
+ @csrf + +
+ @endif +
+ No invitations found. +
+ + +
+
+
+ + +
+
+ {{ $invitations->links() }} +
+
+
+ +
+
+ + + @if(count($topInviters) > 0) +
+
+

+ Top Inviters +

+
+
+
+ + + + + + + + + + + + + @foreach($topInviters as $index => $user) + + + + + + + + + @endforeach + +
RankUsernameEmailTotal InvitationsSuccessfulSuccess Rate
+ #{{ $index + 1 }} + + {{ $user['username'] ?? '—' }} + + {{ $user['email'] ?? '' }} + + {{ $user['total_invitations'] ?? 0 }} + + {{ $user['successful_invitations'] ?? 0 }} + + @php + $total = $user['total_invitations'] ?? 0; + $successful = $user['successful_invitations'] ?? 0; + $rate = $total > 0 ? round(($successful / $total) * 100, 1) : 0; + @endphp +
+
+
+
+ {{ $rate }}% +
+
+
+
+
+ @endif +
+ +@push('scripts') + +@endpush +@endsection + diff --git a/resources/views/admin/invitations/show.blade.php b/resources/views/admin/invitations/show.blade.php new file mode 100644 index 000000000..a1be58043 --- /dev/null +++ b/resources/views/admin/invitations/show.blade.php @@ -0,0 +1,215 @@ +@extends('layouts.admin') + +@section('content') +
+
+ +
+
+

+ {{ $title }} +

+
+ @if(!$invitation->used_at) +
+ @csrf + +
+
+ @csrf + +
+ @endif + + Back to List + +
+
+
+ + +
+
+ +
+

+ Basic Information +

+
+
+
Email
+
{{ $invitation->email }}
+
+
+
Status
+
+ @if($invitation->used_at) + + Used + + @elseif(!$invitation->is_active) + + Cancelled + + @elseif($invitation->expires_at && $invitation->expires_at->isPast()) + + Expired + + @else + + Pending + + @endif +
+
+
+
Token
+
+ {{ $invitation->token }} +
+
+
+
Active
+
+ @if($invitation->is_active) + Yes + @else + No + @endif +
+
+
+
+ + +
+

+ User Information +

+
+
+
Invited By
+
+ @if($invitation->invitedBy) +
+ {{ $invitation->invitedBy->username }} + ({{ $invitation->invitedBy->email }}) +
+ @else + + @endif +
+
+
+
Used By
+
+ @if($invitation->usedBy) +
+ {{ $invitation->usedBy->username }} + ({{ $invitation->usedBy->email }}) +
+ @else + + @endif +
+
+
+
+ + +
+

+ Timestamps +

+
+
+
Created At
+
+ {{ $invitation->created_at->format('Y-m-d H:i:s') }} + ({{ $invitation->created_at->diffForHumans() }}) +
+
+
+
Updated At
+
+ {{ $invitation->updated_at->format('Y-m-d H:i:s') }} + ({{ $invitation->updated_at->diffForHumans() }}) +
+
+
+
Expires At
+
+ @if($invitation->expires_at) + {{ $invitation->expires_at->format('Y-m-d H:i:s') }} + ({{ $invitation->expires_at->diffForHumans() }}) + @if($invitation->expires_at->isPast()) + Expired + @endif + @else + Never + @endif +
+
+
+
Used At
+
+ @if($invitation->used_at) + {{ $invitation->used_at->format('Y-m-d H:i:s') }} + ({{ $invitation->used_at->diffForHumans() }}) + @else + Not used yet + @endif +
+
+
+
+ + +
+

+ Additional Information +

+
+
+
Invitation Link
+
+ @if(!$invitation->used_at && $invitation->is_active && (!$invitation->expires_at || !$invitation->expires_at->isPast())) +
+ {{ url('register?invitation=' . $invitation->token) }} +
+ + @else + Invitation not active + @endif +
+
+
+
ID
+
{{ $invitation->id }}
+
+
+
+
+
+
+
+ +@push('scripts') + +@endpush +@endsection + diff --git a/resources/views/partials/admin-menu.blade.php b/resources/views/partials/admin-menu.blade.php index 8365b04ea..6be71cbe7 100644 --- a/resources/views/partials/admin-menu.blade.php +++ b/resources/views/partials/admin-menu.blade.php @@ -21,6 +21,12 @@ + + + + Invitations + +