From 099b2f10ca6b7a17e5274f72da22a1aa3603884d Mon Sep 17 00:00:00 2001 From: bisco Date: Thu, 30 Apr 2026 09:50:58 +0200 Subject: [PATCH] fix: point check-in QR links to frontend page --- backend/bookings/qr.py | 4 ++-- backend/bookings/test_admin.py | 2 +- backend/bookings/test_api.py | 4 ++-- backend/bookings/test_services.py | 8 ++++---- .../src/app/pages/check-in-placeholder-page.component.ts | 9 ++++++++- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/backend/bookings/qr.py b/backend/bookings/qr.py index 6d69e08..a256827 100644 --- a/backend/bookings/qr.py +++ b/backend/bookings/qr.py @@ -7,11 +7,11 @@ from django.conf import settings from .models import Reservation -CHECK_IN_PREVIEW_PATH = "/api/check-ins/preview/" +CHECK_IN_PAGE_PATH = "/check-in" def build_check_in_preview_url(raw_check_in_token): - return f"{settings.SITE_BASE_URL}{CHECK_IN_PREVIEW_PATH}?token={raw_check_in_token}" + return f"{settings.SITE_BASE_URL}{CHECK_IN_PAGE_PATH}?token={raw_check_in_token}" def generate_check_in_qr_png(raw_check_in_token): diff --git a/backend/bookings/test_admin.py b/backend/bookings/test_admin.py index 75c0b3d..5f0810f 100644 --- a/backend/bookings/test_admin.py +++ b/backend/bookings/test_admin.py @@ -134,7 +134,7 @@ class ReservationAdminTests(TestCase): self.assertEqual(reservation.status, Reservation.Status.CONFIRMED) self.assertIsNotNone(confirmation_token.used_at) self.assertContains(response, "Reservation confirmed manually") - self.assertContains(response, "/api/check-ins/preview/?token=") + self.assertContains(response, "/check-in?token=") self.assertTrue( ReservationToken.objects.filter( reservation=reservation, diff --git a/backend/bookings/test_api.py b/backend/bookings/test_api.py index ade65de..edec06a 100644 --- a/backend/bookings/test_api.py +++ b/backend/bookings/test_api.py @@ -165,7 +165,7 @@ class BookingApiTests(APITestCase): self.assertEqual(response.data["party_size"], reservation.party_size) self.assertTrue( response.data["qr_code_url"].startswith( - "https://tickets.azionelab.example/api/check-ins/preview/?token=" + "https://tickets.azionelab.example/check-in?token=" ) ) self.assertNotIn(raw_token, response.data["qr_code_url"]) @@ -257,7 +257,7 @@ class BookingApiTests(APITestCase): self.assertEqual(response.data["reservation_id"], reservation.id) self.assertTrue( response.data["qr_code_url"].startswith( - "https://tickets.azionelab.example/api/check-ins/preview/?token=" + "https://tickets.azionelab.example/check-in?token=" ) ) self.assertTrue(response.data["qr_code_image"].startswith("data:image/png;base64,")) diff --git a/backend/bookings/test_services.py b/backend/bookings/test_services.py index af5e972..df545f7 100644 --- a/backend/bookings/test_services.py +++ b/backend/bookings/test_services.py @@ -247,7 +247,7 @@ class BookingServiceTests(TestCase): ) self.assertTrue( result.qr_code_url.startswith( - "https://tickets.azionelab.example/api/check-ins/preview/?token=" + "https://tickets.azionelab.example/check-in?token=" ) ) self.assertTrue(result.qr_code_image.startswith("data:image/png;base64,")) @@ -282,7 +282,7 @@ class BookingServiceTests(TestCase): self.assertGreater(len(qr_code_image), len("data:image/png;base64,")) self.assertEqual( build_check_in_preview_url(raw_check_in_token), - "https://tickets.azionelab.example/api/check-ins/preview/?token=opaque-check-in-token", + "https://tickets.azionelab.example/check-in?token=opaque-check-in-token", ) def test_qr_code_is_not_generated_for_pending_reservation(self): @@ -430,7 +430,7 @@ class BookingServiceTests(TestCase): self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN) self.assertTrue( result.qr_code_url.startswith( - "https://tickets.azionelab.example/api/check-ins/preview/?token=" + "https://tickets.azionelab.example/check-in?token=" ) ) @@ -462,7 +462,7 @@ class BookingServiceTests(TestCase): self.assertEqual(result.reservation, reservation) self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN) self.assertTrue(result.qr_code_image.startswith("data:image/png;base64,")) - self.assertIn("/api/check-ins/preview/?token=", result.qr_code_url) + self.assertIn("/check-in?token=", result.qr_code_url) def create_reservation(self, **overrides): data = { diff --git a/frontend/src/app/pages/check-in-placeholder-page.component.ts b/frontend/src/app/pages/check-in-placeholder-page.component.ts index 55063dc..ca7eddc 100644 --- a/frontend/src/app/pages/check-in-placeholder-page.component.ts +++ b/frontend/src/app/pages/check-in-placeholder-page.component.ts @@ -11,7 +11,7 @@ import { } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; -import { RouterLink } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -326,6 +326,7 @@ type BarcodeDetectorConstructor = new (options?: { formats?: string[] }) => Barc export class CheckInPlaceholderPageComponent { private readonly destroyRef = inject(DestroyRef); private readonly formBuilder = inject(FormBuilder); + private readonly route = inject(ActivatedRoute); private readonly showsApi = inject(ShowsApiService); private readonly barcodeDetectorCtor = (globalThis as { BarcodeDetector?: BarcodeDetectorConstructor }).BarcodeDetector; private readonly scannerSupported = @@ -358,6 +359,12 @@ export class CheckInPlaceholderPageComponent { constructor() { this.destroyRef.onDestroy(() => this.stopScanner()); + const tokenFromQuery = this.route.snapshot.queryParamMap.get('token')?.trim() ?? ''; + if (tokenFromQuery) { + this.tokenForm.controls.token.setValue(tokenFromQuery); + this.tokenForm.controls.token.markAsTouched(); + this.preview(); + } } protected preview(): void {