validated()['registration_code']; $registration = Registration::where('registration_code', $code) ->with('player', 'flightMember.flight.members.registration.player') ->firstOrFail(); $flightMember = $registration->flightMember; $flight = $flightMember?->flight; $members = []; if ($flight) { foreach ($flight->members as $m) { $members[] = [ 'seat' => (int) $m->seat_no, 'name' => $m->registration?->player?->name, 'band' => $m->registration?->handicap_band, 'hcp' => $m->registration?->handicap_value, 'is_you' => $m->registration_id === $registration->id, ]; } } return response()->json([ 'registration' => [ 'status' => $registration->status, 'player' => [ 'name' => $registration->player->name, 'band' => $registration->handicap_band, 'handicap' => $registration->handicap_value, ], 'preferences' => [ 'pairing_mode' => $registration->pairing_mode, 'pairing_mode_label' => strtolower($registration->pairing_mode) === 'LEVEL' ? 'level' : (strtolower($registration->pairing_mode) === 'RANDOM' ? 'random' : 'balanced'), ], ], 'flight' => $flight ? [ 'code' => $flight->code, 'course' => $flight->course, 'start_hole' => (int) $flight->start_hole, 'start_tee' => $flight->start_tee, 'is_final' => $flight->status === 'FINAL', ] : null, 'members' => $members, ]); } public function requestOtp(PairingOtpRequest $request, OtpService $otpService) { $registrationId = $request->validated()['registration_id']; $registration = Registration::with('player')->findOrFail($registrationId); $otpService->sendPairingOtp($registration); return response()->json(['ok' => true]); } public function verifyOtp(PairingOtpVerifyRequest $request, OtpService $otpService, PairingTokenService $tokenService) { $data = $request->validated(); $registration = Registration::with('player')->findOrFail($data['registration_id']); $otpService->verifyPairingOtp($registration, $data['otp']); $token = $tokenService->issue($registration->id); return response()->json([ 'pairing_token' => $token, ]); } public function me(Request $request, PairingTokenService $tokenService) { $auth = $request->header('Authorization', ''); if (!str_starts_with($auth, 'Bearer ')) { return response()->json(['message' => 'Unauthorized'], 401); } $token = trim(substr($auth, 7)); $registrationId = $tokenService->verify($token); if (!$registrationId) { return response()->json(['message' => 'Unauthorized'], 401); } $registration = Registration::with('player', 'flightMember.flight.members.registration.player') ->findOrFail($registrationId); $flightMember = $registration->flightMember; $flight = $flightMember?->flight; // Build members array for diagram (seat 1..4) $members = []; if ($flight) { foreach ($flight->members as $m) { $members[] = [ 'seat' => (int) $m->seat_no, 'name' => $m->registration?->player?->name, 'band' => $m->registration?->handicap_band, 'hcp' => $m->registration?->handicap_value, 'is_you' => $m->registration_id === $registration->id, ]; } } return response()->json([ 'registration' => [ 'status' => $registration->status, 'player' => [ 'name' => $registration->player->name, 'band' => $registration->handicap_band, 'handicap' => $registration->handicap_value, ], // Optional for UI copy; can be expanded later: 'preferences' => [ 'pairing_mode' => $registration->pairing_mode, 'pairing_mode_label' => strtolower($registration->pairing_mode) === 'LEVEL' ? 'level' : (strtolower($registration->pairing_mode) === 'RANDOM' ? 'random' : 'balanced'), ], ], 'flight' => $flight ? [ 'code' => $flight->code, 'course' => $flight->course, 'start_hole' => (int) $flight->start_hole, 'start_tee' => $flight->start_tee, 'is_final' => $flight->status === 'FINAL', ] : null, 'members' => $members, ]); } private function maskPhone(string $phone): string { // crude masking; adjust as needed for E164 normalization $digits = preg_replace('/\D+/', '', $phone); if (strlen($digits) <= 4) return '+**' . $digits; $last4 = substr($digits, -4); return '+'.substr($digits, 0, 2) . '***' . $last4; } }