mirror of
https://github.com/dyzulk/trustlab-api.git
synced 2026-01-26 13:22:05 +07:00
First commit
This commit is contained in:
160
app/Http/Controllers/Api/DashboardController.php
Normal file
160
app/Http/Controllers/Api/DashboardController.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use App\Models\Certificate;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Inquiry;
|
||||
use App\Models\ActivityLog;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
// Helper to calculate percentage change
|
||||
$getTrend = function($current, $previous) {
|
||||
if ($previous == 0) return $current > 0 ? 100 : 0;
|
||||
return round((($current - $previous) / $previous) * 100, 1);
|
||||
};
|
||||
|
||||
// Basic Stats
|
||||
$currentMonth = now()->startOfMonth();
|
||||
$previousMonth = now()->subMonth()->startOfMonth();
|
||||
|
||||
// Certificates (Scoped to User)
|
||||
$totalCertificates = Certificate::where('user_id', $user->id)->count();
|
||||
$prevCertificates = Certificate::where('user_id', $user->id)->where('created_at', '<', $currentMonth)->count();
|
||||
|
||||
// Active Certificates (Scoped to User)
|
||||
$activeCertificates = Certificate::where('user_id', $user->id)->where('status', 'ISSUED')->where('valid_to', '>', now())->count();
|
||||
$prevActiveCertificates = Certificate::where('user_id', $user->id)->where('status', 'ISSUED')->where('valid_to', '>', now()->subMonth())->where('created_at', '<', $currentMonth)->count();
|
||||
|
||||
// Expired (Scoped to User)
|
||||
$expiredCertificates = Certificate::where('user_id', $user->id)->where('valid_to', '<', now())->count();
|
||||
|
||||
// Tickets (Role Based)
|
||||
$ticketQuery = Ticket::query()->whereIn('status', ['open', 'answered']);
|
||||
if (!$user->isAdmin()) {
|
||||
$ticketQuery->where('user_id', $user->id);
|
||||
}
|
||||
$activeTickets = $ticketQuery->count();
|
||||
|
||||
// Previous Tickets (Role Based)
|
||||
$prevTicketQuery = Ticket::query()->whereIn('status', ['open', 'answered'])->where('created_at', '<', $currentMonth);
|
||||
if (!$user->isAdmin()) {
|
||||
$prevTicketQuery->where('user_id', $user->id);
|
||||
}
|
||||
$prevActiveTickets = $prevTicketQuery->count();
|
||||
|
||||
$stats = [
|
||||
'total_certificates' => [
|
||||
'value' => $totalCertificates,
|
||||
'trend' => $getTrend($totalCertificates, $prevCertificates),
|
||||
'trend_label' => 'vs last month'
|
||||
],
|
||||
'active_certificates' => [
|
||||
'value' => $activeCertificates,
|
||||
'trend' => $getTrend($activeCertificates, $prevActiveCertificates),
|
||||
'trend_label' => 'vs last month'
|
||||
],
|
||||
'expired_certificates' => [
|
||||
'value' => $expiredCertificates,
|
||||
'trend' => 0,
|
||||
'trend_label' => 'vs last month'
|
||||
],
|
||||
'active_tickets' => [
|
||||
'value' => $activeTickets,
|
||||
'trend' => $getTrend($activeTickets, $prevActiveTickets),
|
||||
'trend_label' => 'vs last month'
|
||||
],
|
||||
];
|
||||
|
||||
// Admin only stats
|
||||
if ($user->isAdmin()) {
|
||||
$totalUsers = User::count();
|
||||
$prevUsers = User::where('created_at', '<', $currentMonth)->count();
|
||||
|
||||
$stats['total_users'] = [
|
||||
'value' => $totalUsers,
|
||||
'trend' => $getTrend($totalUsers, $prevUsers),
|
||||
'trend_label' => 'vs last month'
|
||||
];
|
||||
|
||||
// Inquiries - trend calculation for "Pending" is hard, so we just wrap value to keep consistent structure
|
||||
$stats['pending_inquiries'] = [
|
||||
'value' => Inquiry::where('status', 'unread')->count(),
|
||||
];
|
||||
|
||||
// CA Certificate Downloads
|
||||
$caDownloads = \App\Models\CaCertificate::select('ca_type', 'download_count')->get();
|
||||
foreach ($caDownloads as $ca) {
|
||||
$stats['ca_downloads_' . $ca->ca_type] = [
|
||||
'value' => $ca->download_count ?? 0,
|
||||
'label' => str_replace('_', ' ', strtoupper($ca->ca_type)) . ' Downloads'
|
||||
];
|
||||
}
|
||||
|
||||
$stats['recent_users'] = User::latest()->take(5)->get(['id', 'first_name', 'last_name', 'email', 'created_at']);
|
||||
}
|
||||
|
||||
// Recent Activity
|
||||
$activityLogQuery = ActivityLog::with('user:id,first_name,last_name,email,avatar')
|
||||
->latest()
|
||||
->take(10);
|
||||
|
||||
if (!$user->isAdmin()) {
|
||||
$activityLogQuery->where('user_id', $user->id);
|
||||
}
|
||||
|
||||
$recentActivity = $activityLogQuery->get()->map(function($log) {
|
||||
return [
|
||||
'id' => $log->id,
|
||||
'user_name' => $log->user ? $log->user->first_name . ' ' . $log->user->last_name : 'System',
|
||||
'user_avatar' => $log->user ? $log->user->avatar : null,
|
||||
'action' => $log->action,
|
||||
'description' => $log->description,
|
||||
'created_at' => $log->created_at->toIso8601String(),
|
||||
];
|
||||
});
|
||||
|
||||
// Chart Data (Certificate Issuance Trend - Last 7 Days)
|
||||
$chartData = [];
|
||||
for ($i = 6; $i >= 0; $i--) {
|
||||
$date = now()->subDays($i)->format('Y-m-d');
|
||||
$countQuery = Certificate::whereDate('created_at', $date);
|
||||
if (!$user->isAdmin()) {
|
||||
$countQuery->where('user_id', $user->id);
|
||||
}
|
||||
|
||||
$chartData[] = [
|
||||
'date' => $date,
|
||||
'day' => now()->subDays($i)->format('D'),
|
||||
'count' => $countQuery->count()
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'stats' => $stats,
|
||||
'recent_activity' => $recentActivity,
|
||||
'chart_data' => $chartData,
|
||||
'server_time' => now()->toIso8601String(),
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function ping()
|
||||
{
|
||||
return response()->json([
|
||||
'pong' => true,
|
||||
'time' => microtime(true),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user