diff --git a/app/Http/Controllers/Api/V1/ServiceMeetController.php b/app/Http/Controllers/Api/V1/ServiceMeetController.php index 5758ae3..08a6fee 100644 --- a/app/Http/Controllers/Api/V1/ServiceMeetController.php +++ b/app/Http/Controllers/Api/V1/ServiceMeetController.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Controller; use App\Models\QrCode; use App\Models\User; use App\Services\Meet\EventMeetRoomLinkService; +use App\Services\Meet\EventRegistrationVerifyService; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -46,4 +47,24 @@ class ServiceMeetController extends Controller return response()->json(['event' => $result]); } + + public function verifyRegistration(Request $request, QrCode $event): JsonResponse + { + $validated = $request->validate([ + 'owner_ref' => ['required', 'string', 'max:64'], + 'badge_code' => ['required', 'string', 'max:16'], + ]); + + $owner = User::query()->where('public_id', $validated['owner_ref'])->firstOrFail(); + abort_unless($event->user_id === $owner->id, 403); + abort_unless($event->type === QrCode::TYPE_EVENT, 404); + + $result = app(EventRegistrationVerifyService::class)->verifyBadge($event, $validated['badge_code']); + + if (! $result) { + return response()->json(['message' => 'Badge not found.'], 404); + } + + return response()->json(['registration' => $result]); + } } diff --git a/app/Http/Controllers/Public/EventRegistrationController.php b/app/Http/Controllers/Public/EventRegistrationController.php index b54f4a6..7459182 100644 --- a/app/Http/Controllers/Public/EventRegistrationController.php +++ b/app/Http/Controllers/Public/EventRegistrationController.php @@ -33,6 +33,7 @@ class EventRegistrationController extends Controller 'attendee_email' => ['nullable', 'email', 'max:200'], 'attendee_phone' => ['required', 'string', 'max:30'], 'badge_fields' => ['nullable', 'array'], + 'meet_return' => ['nullable', 'string', 'max:2048'], ]); try { @@ -45,7 +46,7 @@ class EventRegistrationController extends Controller 'paid' => $result['paid'], 'checkout_url' => $result['checkout_url'], 'badge_code' => $result['registration']->badge_code, - 'success_url' => LadillLink::path($qrCode->short_code, 'registered/'.$result['registration']->reference), + 'success_url' => $this->confirmedUrl($qrCode, $result['registration'], $request->input('meet_return')), ]); } @@ -60,22 +61,43 @@ class EventRegistrationController extends Controller try { $registration = $this->eventService->complete($reference); - return redirect()->away(LadillLink::path($shortCode, 'registered/'.$registration->reference)); + return redirect()->away($this->confirmedUrl($registration->qrCode, $registration)); } catch (\Throwable $e) { return redirect()->away(LadillLink::url($shortCode))->with('order_error', 'Payment could not be verified. Reference: ' . $reference); } } - public function confirmed(string $shortCode, string $ref): View + public function confirmed(Request $request, string $shortCode, string $ref): View { $registration = QrEventRegistration::query() ->where('reference', $ref) ->whereHas('qrCode', fn ($q) => $q->where('short_code', $shortCode)) ->firstOrFail(); + $meetReturn = (string) $request->query('meet_return', ''); + if ($meetReturn === '') { + $meetReturn = (string) (($registration->metadata ?? [])['meet_return'] ?? ''); + } + return view('public.qr.event-confirmed', [ 'registration' => $registration, 'qrCode' => $registration->qrCode, + 'meetReturn' => $meetReturn, ]); } + + private function confirmedUrl(QrCode $qrCode, QrEventRegistration $registration, ?string $meetReturn = null): string + { + $url = LadillLink::path($qrCode->short_code, 'registered/'.$registration->reference); + $meetReturn = trim((string) ($meetReturn ?? '')); + if ($meetReturn === '') { + $meetReturn = trim((string) (($registration->metadata ?? [])['meet_return'] ?? '')); + } + + if ($meetReturn !== '') { + $url .= '?meet_return='.urlencode($meetReturn); + } + + return $url; + } } diff --git a/app/Http/Controllers/Public/QrScanController.php b/app/Http/Controllers/Public/QrScanController.php index db8d519..aee3cc0 100644 --- a/app/Http/Controllers/Public/QrScanController.php +++ b/app/Http/Controllers/Public/QrScanController.php @@ -44,7 +44,10 @@ class QrScanController extends Controller } if ($qrCode->usesLandingPage()) { - return view('public.qr.landing', ['qrCode' => $qrCode]); + return view('public.qr.landing', [ + 'qrCode' => $qrCode, + 'meetReturn' => trim((string) $request->query('meet_return', '')), + ]); } abort(404); diff --git a/app/Services/Events/EventRegistrationService.php b/app/Services/Events/EventRegistrationService.php index c468098..83b8654 100644 --- a/app/Services/Events/EventRegistrationService.php +++ b/app/Services/Events/EventRegistrationService.php @@ -98,6 +98,9 @@ class EventRegistrationService } $amountMinor = (int) round($priceGhs * 100); + $meetReturn = trim((string) ($data['meet_return'] ?? '')); + $metadata = $meetReturn !== '' ? ['meet_return' => $meetReturn] : null; + $registration = QrEventRegistration::create([ 'qr_code_id' => $qrCode->id, 'user_id' => $qrCode->user_id, @@ -111,6 +114,7 @@ class EventRegistrationService 'attendee_phone' => trim((string) ($data['attendee_phone'] ?? '')) ?: null, 'badge_fields' => $badgeFields ?: null, 'status' => $amountMinor > 0 ? QrEventRegistration::STATUS_PENDING : QrEventRegistration::STATUS_CONFIRMED, + 'metadata' => $metadata, ]); if ($amountMinor === 0) { diff --git a/app/Services/Meet/EventRegistrationVerifyService.php b/app/Services/Meet/EventRegistrationVerifyService.php new file mode 100644 index 0000000..e320e89 --- /dev/null +++ b/app/Services/Meet/EventRegistrationVerifyService.php @@ -0,0 +1,37 @@ +|null */ + public function verifyBadge(QrCode $event, string $badgeCode): ?array + { + abort_unless($event->type === QrCode::TYPE_EVENT, 404); + + $normalized = strtoupper(trim($badgeCode)); + if ($normalized === '') { + return null; + } + + $registration = QrEventRegistration::query() + ->where('qr_code_id', $event->id) + ->where('badge_code', $normalized) + ->where('status', QrEventRegistration::STATUS_CONFIRMED) + ->first(); + + if (! $registration) { + return null; + } + + return [ + 'attendee_name' => $registration->attendee_name, + 'attendee_email' => $registration->attendee_email, + 'badge_code' => $registration->badge_code, + 'tier_name' => $registration->tier_name, + ]; + } +} diff --git a/resources/views/public/qr/event-confirmed.blade.php b/resources/views/public/qr/event-confirmed.blade.php index f80facf..cce85a9 100644 --- a/resources/views/public/qr/event-confirmed.blade.php +++ b/resources/views/public/qr/event-confirmed.blade.php @@ -13,6 +13,12 @@ } } } + $meetContinueUrl = ''; + if (! empty($meetReturn ?? '')) { + $meetContinueUrl = $meetReturn . (str_contains($meetReturn, '?') ? '&' : '?') . 'badge=' . urlencode($registration->badge_code); + } elseif ($joinUrl !== '') { + $meetContinueUrl = $joinUrl . (str_contains($joinUrl, '?') ? '&' : '?') . 'badge=' . urlencode($registration->badge_code); + } @endphp @@ -81,11 +87,11 @@
Show this badge code at check-in.
@endif - @if($joinUrl !== '') - - Join webinar + Continue to session @endif @endif diff --git a/resources/views/public/qr/landing.blade.php b/resources/views/public/qr/landing.blade.php index 5d34a11..03cde80 100644 --- a/resources/views/public/qr/landing.blade.php +++ b/resources/views/public/qr/landing.blade.php @@ -640,6 +640,7 @@ $evHeading = $evMode === 'contributions' ? 'Make a contribution' : 'Register'; $evRegRoute = $qrCode->publicPath('register'); $evCsrf = csrf_token(); + $evMeetReturn = trim((string) ($meetReturn ?? '')); @endphp