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.

134 lines
4.2 KiB

5 months ago
<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreCompetitionTrackRequest;
use App\Http\Requests\Admin\UpdateCompetitionTrackRequest;
use App\Models\Competition;
use App\Models\CompetitionTrack;
2 months ago
use App\Support\TrackScoringSheet;
5 months ago
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
2 months ago
use Illuminate\Validation\ValidationException;
5 months ago
class CompetitionTrackController extends Controller
{
public function index(Competition $competition): JsonResponse
{
$tracks = $competition->tracks()->orderBy('sort')->orderBy('id')->get()->map(fn (CompetitionTrack $t) => $this->toArray($t));
return response()->json([
'data' => $tracks,
]);
}
public function store(StoreCompetitionTrackRequest $request, Competition $competition): JsonResponse
{
/** @var array<string, mixed> $validated */
$validated = $request->validated();
2 months ago
$validated = $this->normalizeScoringSheetInPayload($validated);
5 months ago
/** @var CompetitionTrack $track */
$track = $competition->tracks()->create($validated);
return response()->json($this->toArray($track), 201);
}
public function show(Competition $competition, CompetitionTrack $track): JsonResponse
{
return response()->json($this->ensureTrackBelongsAndReturn($competition, $track));
}
public function update(UpdateCompetitionTrackRequest $request, Competition $competition, CompetitionTrack $track): JsonResponse
{
$this->ensureTrackBelongs($competition, $track);
2 months ago
/** @var array<string, mixed> $validated */
$validated = $request->validated();
$validated = $this->normalizeScoringSheetInPayload($validated);
$track->fill($validated);
5 months ago
$track->save();
return response()->json($this->toArray($track));
}
public function destroy(Competition $competition, CompetitionTrack $track): Response
{
$this->ensureTrackBelongs($competition, $track);
$track->delete();
return response()->noContent();
}
2 months ago
/**
* @param array<string, mixed> $validated
* @return array<string, mixed>
*/
private function normalizeScoringSheetInPayload(array $validated): array
{
if (! array_key_exists('scoring_sheet_json', $validated)) {
return $validated;
}
$raw = $validated['scoring_sheet_json'];
if ($raw === null) {
$validated['scoring_sheet_json'] = null;
return $validated;
}
$parsed = TrackScoringSheet::parseAndValidateConfig($raw);
if ($parsed['ok'] !== true) {
throw ValidationException::withMessages([
'scoring_sheet_json' => [$parsed['message']],
]);
}
$validated['scoring_sheet_json'] = $parsed['sheet'];
return $validated;
}
5 months ago
/**
* @return array<string, mixed>
*/
private function toArray(CompetitionTrack $track): array
{
2 months ago
$sheet = is_array($track->scoring_sheet_json) ? $track->scoring_sheet_json : null;
$configured = TrackScoringSheet::isConfigured($sheet);
5 months ago
return [
'id' => $track->id,
'competition_id' => $track->competition_id,
'track_code' => $track->track_code,
'title' => $track->title,
'description' => $track->description,
'sort' => $track->sort,
'is_enabled' => $track->is_enabled,
2 months ago
'scoring_sheet_json' => $sheet,
'scoring_sheet_configured' => $configured,
5 months ago
'created_at' => $track->created_at?->toIso8601String(),
'updated_at' => $track->updated_at?->toIso8601String(),
];
}
/**
* @return array<string, mixed>
*/
private function ensureTrackBelongsAndReturn(Competition $competition, CompetitionTrack $track): array
{
$this->ensureTrackBelongs($competition, $track);
return $this->toArray($track);
}
private function ensureTrackBelongs(Competition $competition, CompetitionTrack $track): void
{
if ($track->competition_id !== $competition->id) {
abort(404);
}
}
}