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.

156 lines
5.5 KiB

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Activity;
use App\Models\ActivitySession;
use App\Models\ActivitySignup;
use App\Models\ActivitySignupCheckin;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ActivitySignupController extends Controller
{
use ApiResponse;
public function index(Request $request, int $activity): JsonResponse
{
Activity::query()->findOrFail($activity);
$sessionId = $request->query('activity_session_id');
$checkinStatus = $request->query('checkin_status');
$query = ActivitySignup::query()->where('activity_id', $activity)->orderByDesc('id');
if ($kw = $request->query('keyword')) {
$query->where(function ($q) use ($kw) {
$q->where('name', 'like', "%{$kw}%")
->orWhere('mobile', 'like', "%{$kw}%")
->orWhere('company', 'like', "%{$kw}%");
});
}
if ($sessionId) {
$sid = (int) $sessionId;
$query->where('activity_session_id', $sid);
if ((string) $checkinStatus === '1') {
$query->whereHas('checkins', function ($q) use ($sid) {
$q->where('activity_session_id', $sid)->whereNotNull('checked_in_at');
});
} elseif ((string) $checkinStatus === '0') {
$query->whereDoesntHave('checkins', function ($q) use ($sid) {
$q->where('activity_session_id', $sid)->whereNotNull('checked_in_at');
});
}
}
$paginator = $query
->with(['checkins' => function ($q) use ($sessionId) {
if ($sessionId) {
$q->where('activity_session_id', (int) $sessionId);
}
}])
->paginate((int) $request->query('page_size', 20))
->withQueryString();
$paginator->getCollection()->transform(
fn (ActivitySignup $r) => $this->serialize($r, $sessionId ? (int) $sessionId : null)
);
return $this->paginated($paginator);
}
public function store(Request $request, int $activity): JsonResponse
{
Activity::query()->findOrFail($activity);
$data = $request->validate([
'activity_session_id' => ['nullable', 'integer', 'exists:activity_sessions,id'],
'name' => ['required', 'string', 'max:64'],
'mobile' => ['required', 'string', 'max:32'],
'company' => ['nullable', 'string', 'max:128'],
]);
if (! empty($data['activity_session_id'])) {
$sid = (int) $data['activity_session_id'];
$ok = ActivitySession::query()->where('activity_id', $activity)->where('id', $sid)->exists();
if (! $ok) {
return $this->fail('场次不属于该活动', 422);
}
}
$signup = ActivitySignup::query()->create([
'activity_id' => $activity,
'activity_session_id' => $data['activity_session_id'] ?? null,
'name' => $data['name'],
'mobile' => $data['mobile'],
'company' => $data['company'] ?? null,
'signed_up_at' => now(),
'status' => 1,
]);
return $this->ok(['id' => $signup->id], '报名已登记');
}
public function destroy(int $activity, int $signup): JsonResponse
{
$model = ActivitySignup::query()->where('activity_id', $activity)->findOrFail($signup);
$model->delete();
return $this->ok(null, '已删除');
}
public function checkin(Request $request, int $activity, int $signup): JsonResponse
{
Activity::query()->findOrFail($activity);
$model = ActivitySignup::query()->where('activity_id', $activity)->findOrFail($signup);
$data = $request->validate([
'activity_session_id' => ['required', 'integer', 'exists:activity_sessions,id'],
]);
$sessionId = (int) $data['activity_session_id'];
$ok = ActivitySession::query()->where('activity_id', $activity)->where('id', $sessionId)->exists();
if (! $ok) {
return $this->fail('场次不属于该活动', 422);
}
ActivitySignupCheckin::query()->updateOrCreate(
[
'activity_signup_id' => $model->id,
'activity_session_id' => $sessionId,
],
['checked_in_at' => now()]
);
return $this->ok(null, '签到成功');
}
/**
* @return array<string, mixed>
*/
protected function serialize(ActivitySignup $r, ?int $sessionId = null): array
{
$sessionCheckedInAt = null;
if ($sessionId) {
$checkin = $r->relationLoaded('checkins')
? $r->checkins->first()
: $r->checkins()->where('activity_session_id', $sessionId)->first();
$sessionCheckedInAt = $checkin?->checked_in_at;
}
return [
'id' => $r->id,
'activity_id' => $r->activity_id,
'activity_session_id' => $r->activity_session_id,
'name' => $r->name,
'mobile' => $r->mobile,
'company' => $r->company,
'signed_up_at' => $r->signed_up_at?->toIso8601String(),
'status' => (int) $r->status,
'activity_session_id_filter' => $sessionId,
'session_checked_in_at' => $sessionCheckedInAt?->toIso8601String(),
];
}
}