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.

137 lines
4.9 KiB

1 month ago
<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreAudienceSessionRequest;
use App\Http\Requests\Admin\UpdateAudienceSessionRequest;
use App\Models\AudienceSession;
use App\Models\Competition;
use App\Support\BizDateTime;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
class AudienceSessionController extends Controller
{
public function index(Competition $competition): JsonResponse
{
$sessions = $competition->audienceSessions()
->withCount([
'registrations',
'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'),
])
->orderBy('sort')
->orderBy('id')
->get()
->map(fn (AudienceSession $session) => $this->toArray($session));
return response()->json(['data' => $sessions]);
}
public function store(StoreAudienceSessionRequest $request, Competition $competition): JsonResponse
{
/** @var array<string, mixed> $validated */
$validated = $request->validated();
$session = $competition->audienceSessions()->create($validated);
$session->loadCount([
'registrations',
'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'),
]);
return response()->json($this->toArray($session), 201);
}
public function show(Competition $competition, AudienceSession $audience_session): JsonResponse
{
$this->ensureBelongs($competition, $audience_session);
$audience_session->loadCount([
'registrations',
'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'),
]);
return response()->json($this->toArray($audience_session));
}
public function update(
UpdateAudienceSessionRequest $request,
Competition $competition,
AudienceSession $audience_session,
): JsonResponse {
$this->ensureBelongs($competition, $audience_session);
/** @var array<string, mixed> $validated */
$validated = $request->validated();
if (array_key_exists('capacity', $validated)) {
$registered = $audience_session->registeredCount();
if ((int) $validated['capacity'] < $registered) {
throw ValidationException::withMessages([
'capacity' => ['容量不能小于已报名人数('.$registered.')'],
]);
}
}
$audience_session->fill($validated);
$audience_session->save();
$audience_session->loadCount([
'registrations',
'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'),
]);
return response()->json($this->toArray($audience_session));
}
public function destroy(Competition $competition, AudienceSession $audience_session): Response
{
$this->ensureBelongs($competition, $audience_session);
if ($audience_session->registrations()->exists()) {
throw ValidationException::withMessages([
'audience_session' => ['该场次已有报名记录,请停用而不是删除'],
]);
}
$audience_session->delete();
return response()->noContent();
}
/**
* @return array<string, mixed>
*/
private function toArray(AudienceSession $session): array
{
return [
'id' => $session->id,
'competition_id' => $session->competition_id,
'code' => $session->code,
'name' => $session->name,
1 month ago
'name_en' => $session->name_en,
1 month ago
'event_date_text' => $session->event_date_text,
1 month ago
'event_date_text_en' => $session->event_date_text_en,
1 month ago
'address' => $session->address,
1 month ago
'address_en' => $session->address_en,
1 month ago
'capacity' => (int) $session->capacity,
'registered_count' => $session->registeredCount(),
'checked_in_count' => $session->checkedInCount(),
'remaining' => $session->remainingCount(),
'signup_start_at' => BizDateTime::toIso8601($session->signup_start_at),
'signup_end_at' => BizDateTime::toIso8601($session->signup_end_at),
'is_final' => (bool) $session->is_final,
'sort' => (int) $session->sort,
'enabled' => (bool) $session->enabled,
'status' => $session->windowStatus(),
'status_label' => $session->statusLabel(),
'created_at' => BizDateTime::toIso8601($session->created_at),
'updated_at' => BizDateTime::toIso8601($session->updated_at),
];
}
private function ensureBelongs(Competition $competition, AudienceSession $session): void
{
if ((int) $session->competition_id !== (int) $competition->id) {
abort(404);
}
}
}