183 lines
7.3 KiB
PHP
183 lines
7.3 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
|
|
class DashboardController extends Controller
|
|
{
|
|
/**
|
|
* Display the admin dashboard overview.
|
|
*/
|
|
public function index()
|
|
{
|
|
// Dynamic Database Queries
|
|
$totalWorkers = \App\Models\Worker::count();
|
|
$activeWorkers = \App\Models\Worker::where('status', 'active')->count();
|
|
$inactiveWorkers = $totalWorkers - $activeWorkers;
|
|
|
|
$totalSponsors = \App\Models\Sponsor::count();
|
|
$activeSponsors = \App\Models\Sponsor::where('status', 'active')->count();
|
|
$inactiveSponsors = $totalSponsors - $activeSponsors;
|
|
|
|
$activeSubs = \App\Models\Sponsor::where('subscription_status', 'active')->count();
|
|
$expiredSubs = \App\Models\Sponsor::where('subscription_status', 'expired')->count();
|
|
$newSponsors = \App\Models\Sponsor::where('created_at', '>=', now()->subDays(7))->count();
|
|
$revenueSum = \Illuminate\Support\Facades\DB::table('payments')->where('status', 'success')->sum('amount');
|
|
|
|
// Dynamic conversion rates
|
|
$verifiedCount = \App\Models\Worker::where('verified', true)->count();
|
|
$verificationRate = $totalWorkers > 0 ? round(($verifiedCount / $totalWorkers) * 100, 1) : 0.0;
|
|
|
|
$hiredCount = \App\Models\Worker::where('status', 'hired')->count();
|
|
$hiringConversionRate = $totalWorkers > 0 ? round(($hiredCount / $totalWorkers) * 100, 1) : 0.0;
|
|
|
|
$chatsCount = \Illuminate\Support\Facades\DB::table('conversations')->count();
|
|
$chatToHireRate = $chatsCount > 0 ? round(($hiredCount / $chatsCount) * 100, 1) : 0.0;
|
|
|
|
$activeRatio = $totalWorkers > 0 ? round(($activeWorkers / $totalWorkers) * 100) : 0;
|
|
$activeUsersRatio = $activeRatio . '% Active';
|
|
|
|
// Custom subscription trends
|
|
$months = [];
|
|
for ($i = 5; $i >= 0; $i--) {
|
|
$months[] = now()->subMonths($i);
|
|
}
|
|
|
|
$trendData = [];
|
|
foreach ($months as $date) {
|
|
$monthStart = $date->copy()->startOfMonth();
|
|
$monthEnd = $date->copy()->endOfMonth();
|
|
|
|
$basic = \App\Models\Sponsor::where('subscription_plan', 'basic')
|
|
->whereBetween('created_at', [$monthStart, $monthEnd])
|
|
->count();
|
|
|
|
$premium = \App\Models\Sponsor::where('subscription_plan', 'premium')
|
|
->whereBetween('created_at', [$monthStart, $monthEnd])
|
|
->count();
|
|
|
|
$vip = \App\Models\Sponsor::where('subscription_plan', 'vip')
|
|
->whereBetween('created_at', [$monthStart, $monthEnd])
|
|
->count();
|
|
|
|
$trendData[] = [
|
|
'month' => $date->format('M'),
|
|
'basic' => $basic,
|
|
'premium' => $premium,
|
|
'vip' => $vip,
|
|
];
|
|
}
|
|
|
|
// Funnel
|
|
$profilesBrowsed = \Illuminate\Support\Facades\DB::table('profile_views')->count();
|
|
$chatsInitiated = \Illuminate\Support\Facades\DB::table('conversations')->count();
|
|
$candidatesShortlisted = \Illuminate\Support\Facades\DB::table('shortlists')->count();
|
|
$workersHired = $hiredCount;
|
|
|
|
$verificationsToday = \App\Models\Worker::where('verified', true)
|
|
->where('updated_at', '>=', now()->startOfDay())
|
|
->count();
|
|
|
|
$stats = [
|
|
'total_workers' => $totalWorkers,
|
|
'active_workers' => $activeWorkers,
|
|
'inactive_workers' => $inactiveWorkers,
|
|
'total_employers' => $totalSponsors,
|
|
'active_employers' => $activeSponsors,
|
|
'inactive_employers' => $inactiveSponsors,
|
|
'active_subscriptions' => $activeSubs,
|
|
'revenue_this_month_aed' => $revenueSum,
|
|
'new_employers_this_week' => $newSponsors,
|
|
'expired_subscriptions' => $expiredSubs,
|
|
'hiring_conversion_rate' => $hiringConversionRate,
|
|
'chat_to_hire_rate' => $chatToHireRate,
|
|
'verification_rate' => $verificationRate,
|
|
'active_users_ratio' => $activeUsersRatio,
|
|
'trend_data' => $trendData,
|
|
'verifications_today' => $verificationsToday,
|
|
'verified_workers_count' => $verifiedCount,
|
|
'funnel' => [
|
|
'profiles_browsed' => $profilesBrowsed,
|
|
'chats_initiated' => $chatsInitiated,
|
|
'candidates_shortlisted' => $candidatesShortlisted,
|
|
'workers_hired' => $workersHired,
|
|
],
|
|
'worker_availability' => [
|
|
'Active' => \App\Models\Worker::where('status', 'active')->count(),
|
|
'Hidden' => \App\Models\Worker::where('status', 'hidden')->count(),
|
|
'Hired' => \App\Models\Worker::where('status', 'hired')->count()
|
|
],
|
|
];
|
|
|
|
// Process verifications automatically or fetched dynamically
|
|
$recentVerifications = \App\Models\Worker::where('verified', true)
|
|
->with(['documents' => function($q) {
|
|
$q->orderBy('created_at', 'desc');
|
|
}])
|
|
->latest('updated_at')
|
|
->take(5)
|
|
->get()
|
|
->map(function ($worker) {
|
|
$doc = $worker->documents->first();
|
|
return [
|
|
'id' => $worker->id,
|
|
'name' => $worker->name,
|
|
'type' => 'Worker',
|
|
'processed_at' => $worker->updated_at ? $worker->updated_at->diffForHumans() : 'Recently',
|
|
'document_type' => $doc ? ucfirst($doc->type) : 'Passport & Visa',
|
|
'status' => 'Auto-Approved',
|
|
];
|
|
})->toArray();
|
|
|
|
// Fetch recent subscriptions from Sponsors table
|
|
$recentSponsorsWithPlans = \App\Models\Sponsor::whereNotNull('subscription_plan')
|
|
->latest('created_at')
|
|
->take(5)
|
|
->get();
|
|
|
|
$recentSubscriptions = [];
|
|
foreach ($recentSponsorsWithPlans as $sp) {
|
|
$recentSubscriptions[] = [
|
|
'id' => $sp->id,
|
|
'employer_name' => $sp->full_name,
|
|
'plan_name' => ucfirst($sp->subscription_plan) . ' Pass',
|
|
'amount_aed' => $sp->subscription_plan === 'vip' ? 499 : ($sp->subscription_plan === 'premium' ? 199 : 99),
|
|
'subscribed_at' => $sp->created_at->diffForHumans(),
|
|
];
|
|
}
|
|
|
|
return Inertia::render('Admin/Dashboard', [
|
|
'stats' => $stats,
|
|
'recent_verifications' => $recentVerifications,
|
|
'recent_subscriptions' => $recentSubscriptions,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Approve a pending verification (Legacy/Manual Override).
|
|
*/
|
|
public function approveVerification(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'id' => 'required|integer',
|
|
]);
|
|
|
|
return back()->with('success', 'Verification document #' . $validated['id'] . ' has been approved manually.');
|
|
}
|
|
|
|
/**
|
|
* Reject a pending verification (Legacy/Manual Override).
|
|
*/
|
|
public function rejectVerification(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'id' => 'required|integer',
|
|
]);
|
|
|
|
return back()->with('success', 'Verification document #' . $validated['id'] . ' has been rejected.');
|
|
}
|
|
}
|