You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
6.1 KiB

<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Models\Application;
use App\Models\ApplicationReviewScore;
use App\Models\Competition;
use App\Models\Reviewer;
use App\Models\ReviewerScope;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
class DashboardController extends Controller
{
public function show(Competition $competition): JsonResponse
{
$competition->loadMissing(['tracks', 'formSchema', 'reviewFormSchema']);
$applicationCounts = Application::query()
->select('status', DB::raw('COUNT(*) as total'))
->where('competition_id', $competition->id)
->groupBy('status')
->pluck('total', 'status');
$totalApplications = (int) $applicationCounts->sum();
$submittedApplications = (int) ($applicationCounts['submitted'] ?? 0);
$draftApplications = (int) ($applicationCounts['draft'] ?? 0);
$reviewedApplications = Application::query()
->where('competition_id', $competition->id)
->where('status', 'submitted')
->whereHas('reviewScores')
->count();
$reviewScoreCount = ApplicationReviewScore::query()
->whereHas('application', fn ($query) => $query->where('competition_id', $competition->id))
->count();
$reviewerCount = Reviewer::query()->count();
$activeReviewerCount = Reviewer::query()->where('status', 'active')->count();
$reviewerScopeCount = ReviewerScope::query()
->where('competition_id', $competition->id)
->count();
$scopeCountsByTrack = ReviewerScope::query()
->select('track_code', DB::raw('COUNT(*) as total'))
->where('competition_id', $competition->id)
->groupBy('track_code')
->pluck('total', 'track_code');
$applicationCountsByTrack = Application::query()
->select([
'track',
DB::raw('COUNT(*) as total'),
DB::raw("SUM(CASE WHEN status = 'submitted' THEN 1 ELSE 0 END) as submitted_total"),
])
->where('competition_id', $competition->id)
->groupBy('track')
->get()
->keyBy(fn ($row) => (string) ($row->track ?? ''));
$trackStats = $competition->tracks
->map(function ($track) use ($applicationCountsByTrack, $scopeCountsByTrack): array {
$row = $applicationCountsByTrack->get((string) $track->track_code);
return [
'track_code' => $track->track_code,
'track_title' => $track->title,
'is_enabled' => (bool) $track->is_enabled,
'applications_count' => (int) ($row?->total ?? 0),
'submitted_count' => (int) ($row?->submitted_total ?? 0),
'reviewer_scope_count' => (int) ($scopeCountsByTrack[$track->track_code] ?? 0),
];
})
->values();
$recentApplications = Application::query()
->where('competition_id', $competition->id)
->withCount('reviewScores')
->orderByDesc('submitted_at')
->orderByDesc('updated_at')
->orderByDesc('id')
->limit(8)
->get()
->map(fn (Application $app) => [
'id' => $app->id,
'status' => $app->status,
'project_name' => $app->project_name ?? '',
'player_name' => $app->player_name ?? '',
'track_code' => $app->track ?? '',
'track_title' => $trackStats
->firstWhere('track_code', $app->track ?? '')['track_title']
?? ($app->track ?? ''),
'submitted_at' => $app->submitted_at?->toIso8601String(),
'updated_at' => $app->updated_at?->toIso8601String(),
'submitted_review_count' => (int) ($app->review_scores_count ?? 0),
])
->values();
return response()->json([
'competition' => [
'id' => $competition->id,
'slug' => $competition->slug,
'name' => $competition->name,
'status' => $competition->status,
'published' => (bool) $competition->published,
'signup_open_at' => $competition->signup_open_at?->toIso8601String(),
'signup_close_at' => $competition->signup_close_at?->toIso8601String(),
'form_schema_id' => $competition->form_schema_id,
'review_form_schema_id' => $competition->review_form_schema_id,
'pledge_content_html' => $competition->pledge_content_html,
],
'summary' => [
'applications_total' => $totalApplications,
'applications_draft' => $draftApplications,
'applications_submitted' => $submittedApplications,
'applications_reviewed' => (int) $reviewedApplications,
'applications_pending_review' => max(0, $submittedApplications - (int) $reviewedApplications),
'review_scores_total' => (int) $reviewScoreCount,
'reviewers_total' => (int) $reviewerCount,
'reviewers_active' => (int) $activeReviewerCount,
'reviewer_scopes_total' => (int) $reviewerScopeCount,
'tracks_total' => $competition->tracks->count(),
'tracks_enabled' => $competition->tracks->where('is_enabled', true)->count(),
],
'setup' => [
'published' => (bool) $competition->published,
'signup_form_schema' => $competition->form_schema_id !== null,
'tracks' => $competition->tracks->where('is_enabled', true)->count() > 0,
'pledge' => trim(strip_tags((string) $competition->pledge_content_html)) !== '',
'review_form_schema' => $competition->review_form_schema_id !== null,
'reviewer_scopes' => $reviewerScopeCount > 0,
],
'track_stats' => $trackStats,
'recent_applications' => $recentApplications,
]);
}
}