diff --git a/src/app/pages/map/map.ts b/src/app/pages/map/map.ts index 6e074681..ff12f861 100644 --- a/src/app/pages/map/map.ts +++ b/src/app/pages/map/map.ts @@ -243,6 +243,9 @@ export class MapPage implements OnInit, OnDestroy { this.refresh_presentation(); setTimeout(this.syncAllPending, 60000); + // Show consent dialog on first use + await this.showConsentDialog(); + // Check if this is a staff user (has door_check but not lead_retrieval) const hasLeadRetrieval = await this.userData.checkHasLeadRetrieval(); const hasDoorCheck = await this.userData.checkHasDoorCheck(); @@ -252,6 +255,36 @@ export class MapPage implements OnInit, OnDestroy { } } + async showConsentDialog() { + const hasConsent = await this.userData.checkScannerConsent(); + if (hasConsent) return; + + const alert = await this.alertCtrl.create({ + header: 'Lead Scanner Consent', + message: 'By using the lead scanner, you confirm that you will only scan badges of attendees who have given you explicit verbal permission. Scanning without consent violates the PyCon US Code of Conduct.', + backdropDismiss: false, + buttons: [ + { + text: 'Cancel', + role: 'cancel', + handler: () => { + // Disable scanning — user didn't consent + this.scan_start_button_visibility = 'hidden'; + }, + }, + { + text: 'I Agree', + handler: () => { + this.userData.setScannerConsent(true); + }, + }, + ], + }); + await alert.present(); + // Wait for dismissal before continuing + await alert.onDidDismiss(); + } + async showSponsorSelector() { try { const result: any = await this.pycon.fetchLeadRetrievalSponsors(); diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 48fd3ab8..b9eba608 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -20,6 +20,7 @@ export class UserData { HAS_DOOR_CHECK = 'hasDoorCheck'; HAS_MASK_VIOLATION = 'hasMaskViolation'; IS_SPEAKER = 'isSpeaker'; + HAS_SCANNER_CONSENT = 'hasScannerConsent'; constructor( public storage: Storage, @@ -168,6 +169,7 @@ export class UserData { this.storage.remove(this.HAS_DOOR_CHECK); this.storage.remove(this.HAS_MASK_VIOLATION); this.storage.remove(this.IS_SPEAKER); + this.storage.remove(this.HAS_SCANNER_CONSENT); }).then(() => { window.dispatchEvent(new CustomEvent('user:logout')); }); @@ -255,6 +257,16 @@ export class UserData { }); } + setScannerConsent(value: boolean): Promise { + return this.storage.set(this.HAS_SCANNER_CONSENT, value); + } + + checkScannerConsent(): Promise { + return this.storage.get(this.HAS_SCANNER_CONSENT).then((value) => { + return value === true; + }); + } + setIsSpeaker(value: boolean): Promise { return this.storage.set(this.IS_SPEAKER, value); }