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.

129 lines
4.4 KiB

2 weeks ago
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Activity;
use App\Models\ActivitySession;
use App\Support\ApiResponse;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class ActivitySessionController extends Controller
{
use ApiResponse;
public function index(int $activity): JsonResponse
{
Activity::query()->findOrFail($activity);
$items = ActivitySession::query()
->where('activity_id', $activity)
->orderBy('sort')
->orderBy('id')
->get()
->map(fn (ActivitySession $s) => $this->serialize($s));
return $this->ok(['items' => $items]);
}
public function store(Request $request, int $activity): JsonResponse
{
$activityModel = Activity::query()->findOrFail($activity);
$data = $request->validate([
'title' => ['nullable', 'string', 'max:255'],
'starts_at' => ['nullable', 'date'],
'ends_at' => ['nullable', 'date', 'after_or_equal:starts_at'],
'venue' => ['nullable', 'string', 'max:255'],
'capacity' => ['nullable', 'integer', 'min:0'],
'sort' => ['nullable', 'integer'],
]);
$this->assertSessionWithinActivity($activityModel, $data);
$session = ActivitySession::query()->create([
'activity_id' => $activity,
...$data,
]);
return $this->ok(['id' => $session->id], '已创建');
}
public function update(Request $request, int $activity, int $session): JsonResponse
{
$activityModel = Activity::query()->findOrFail($activity);
$model = ActivitySession::query()->where('activity_id', $activity)->findOrFail($session);
$data = $request->validate([
'title' => ['nullable', 'string', 'max:255'],
'starts_at' => ['nullable', 'date'],
'ends_at' => ['nullable', 'date'],
'venue' => ['nullable', 'string', 'max:255'],
'capacity' => ['nullable', 'integer', 'min:0'],
'sort' => ['nullable', 'integer'],
]);
$this->assertSessionWithinActivity($activityModel, $data, $model);
$model->fill($data);
$model->save();
return $this->ok(null, '已保存');
}
public function destroy(int $activity, int $session): JsonResponse
{
$model = ActivitySession::query()->where('activity_id', $activity)->findOrFail($session);
$model->delete();
return $this->ok(null, '已删除');
}
/**
* @return array<string, mixed>
*/
/**
* @param array<string, mixed> $data
*/
protected function assertSessionWithinActivity(Activity $activity, array $data, ?ActivitySession $existing = null): void
{
$startsAt = $data['starts_at'] ?? $existing?->starts_at?->toIso8601String();
$endsAt = $data['ends_at'] ?? $existing?->ends_at?->toIso8601String();
if ($startsAt && $activity->event_start_date) {
$start = Carbon::parse($startsAt);
if ($start->toDateString() < $activity->event_start_date->toDateString()) {
throw ValidationException::withMessages([
'starts_at' => ['场次开始时间不能早于活动开始日期'],
]);
}
}
if ($endsAt && $activity->event_end_date) {
$end = Carbon::parse($endsAt);
if ($end->toDateString() > $activity->event_end_date->toDateString()) {
throw ValidationException::withMessages([
'ends_at' => ['场次结束时间不能晚于活动结束日期'],
]);
}
}
if ($startsAt && $endsAt && Carbon::parse($endsAt)->lt(Carbon::parse($startsAt))) {
throw ValidationException::withMessages([
'ends_at' => ['场次结束时间不能早于开始时间'],
]);
}
}
protected function serialize(ActivitySession $s): array
{
return [
'id' => $s->id,
'activity_id' => $s->activity_id,
'title' => $s->title,
'starts_at' => $s->starts_at?->toIso8601String(),
'ends_at' => $s->ends_at?->toIso8601String(),
'venue' => $s->venue,
'capacity' => $s->capacity !== null ? (int) $s->capacity : null,
'sort' => (int) $s->sort,
];
}
}