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.
153 lines
6.7 KiB
153 lines
6.7 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 App\Support\BizDateTime;
|
|
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();
|
|
|
|
// 待评仅统计「参与评审」的已提交项目
|
|
$eligibleSubmitted = Application::query()
|
|
->where('competition_id', $competition->id)
|
|
->where('status', 'submitted')
|
|
->where('review_eligible', true)
|
|
->count();
|
|
$eligibleReviewed = Application::query()
|
|
->where('competition_id', $competition->id)
|
|
->where('status', 'submitted')
|
|
->where('review_eligible', true)
|
|
->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' => BizDateTime::toIso8601($competition->signup_open_at),
|
|
'signup_close_at' => BizDateTime::toIso8601($competition->signup_close_at),
|
|
'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, $eligibleSubmitted - $eligibleReviewed),
|
|
'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,
|
|
]);
|
|
}
|
|
}
|