# Scanner PWA - Offline-First Ticket Scanning ## Overview The BCT Scanner is an offline-first Progressive Web App (PWA) designed for gate staff to scan tickets even without an internet connection. It features automatic background sync, conflict resolution, and a mobile-optimized interface. ## Features ### Core Functionality - **QR Code Scanning**: Uses native BarcodeDetector API with ZXing fallback - **Offline Operation**: Full functionality without internet connection - **Background Sync**: Automatic synchronization when connection is restored - **Conflict Resolution**: Handles duplicate scans and offline/online discrepancies - **Multi-Device Support**: Unique device identification for analytics - **Zone/Gate Tracking**: Configurable location identification ### User Experience - **Optimistic UI**: Instant feedback even when offline - **Haptic Feedback**: Vibration patterns for scan results - **Audio Feedback**: Sound confirmation for successful scans - **Torch Control**: Automatic and manual flashlight control - **Responsive Design**: Optimized for mobile devices - **PWA Features**: Installable, works offline, background sync ## Installation & Setup ### 1. PWA Installation **Mobile (iOS/Android):** 1. Open `/scan?eventId=your-event-id` in browser 2. Look for "Add to Home Screen" prompt 3. Follow device-specific installation steps **Desktop:** 1. Navigate to scanner page 2. Look for install prompt in address bar 3. Click "Install" to add to desktop ### 2. Camera Permissions The scanner requires camera access: - **First Visit**: Browser will prompt for camera permission - **Grant Access**: Select "Allow" to enable scanning - **Denied Access**: Use settings to re-enable camera permission ### 3. Device Configuration Set your gate/zone identifier in scanner settings: 1. Click settings icon (gear) in header 2. Enter zone name (e.g., "Gate A", "Main Entrance") 3. Zone is saved locally and included in scan logs ## Usage Guide ### Basic Scanning 1. **Access Scanner**: Navigate to `/scan?eventId={eventId}` 2. **Position QR Code**: Center QR code within scanning frame 3. **Wait for Scan**: Scanner automatically detects and processes codes 4. **View Result**: Status banner shows scan result with color coding ### Scan Results **Success (Green)** - Valid ticket, entry allowed - Shows ticket information (event, type, customer) **Already Scanned (Yellow)** - Ticket previously used - Shows original scan timestamp **Invalid (Red)** - Invalid or expired ticket - Shows error reason **Offline Accepted (Blue)** - Accepted in offline mode (if optimistic mode enabled) - Will be verified when connection restored ### Settings Configuration **Optimistic Accept (Default: ON)** - When enabled: Show success for scans when offline - When disabled: Queue scans for later verification **Zone/Gate Setting** - Identifies scanning location - Included in all scan logs for analytics - Persisted locally across sessions **Audio/Haptic Feedback** - Success: Short beep + brief vibration - Already Scanned: Double vibration - Invalid: Long vibration ## Offline Behavior ### How It Works 1. **Scan Detection**: QR codes are processed immediately 2. **Local Storage**: Scans stored in IndexedDB queue 3. **Optimistic UI**: Instant feedback based on settings 4. **Background Sync**: Automatic verification when online 5. **Conflict Detection**: Handles offline/online discrepancies ### Queue Management **Pending Scans** - Stored locally until internet connection restored - Automatically synced with exponential backoff - Retry logic handles temporary failures **Sync Status** - Total scans: All scans from this device - Pending sync: Queued scans awaiting verification - Last sync: Timestamp of most recent successful sync ### Conflict Resolution **Conflict Scenarios** - Offline scan shows "success" but server says "already scanned" - Multiple devices scan same ticket while offline **Resolution Process** 1. Conflicts automatically logged when detected 2. Admin can review conflict log in settings 3. Manual resolution may be required for edge cases ## Technical Architecture ### Frontend Components ``` src/features/scanner/ ├── ScannerPage.tsx # Main scanner interface ├── useScanner.ts # Camera/scanning hook ├── useScanQueue.ts # Offline queue management └── types.ts # TypeScript definitions ``` ### Offline Storage **IndexedDB Database: `sentinel_scans`** - `scans`: Individual scan records with sync status - `conflicts`: Offline/online result discrepancies - `settings`: User preferences and device configuration ### Background Sync **Service Worker** (`/public/sw.js`) - Handles background synchronization - Caches essential assets for offline use - Manages retry logic with exponential backoff ### API Endpoints **Verification**: `/api/tickets/verify` - Validates QR codes against ticket database - Returns ticket information and scan history **Logging**: `/api/scans/log` - Records scan events for analytics - Includes device, zone, and timing information ## Security & Access Control ### Authentication - **Required**: User must be authenticated to access scanner - **Permissions**: Requires `scan:tickets` permission - **Roles**: Available to staff, organizers, and admins ### Data Protection - **Local Storage**: Encrypted scan queue in IndexedDB - **Device ID**: Unique identifier for tracking (not personally identifiable) - **No Secrets**: All verification happens server-side ## Testing ### Running Tests ```bash # All scanner tests npm run test tests/scan-offline.spec.ts # With UI (helpful for debugging) npm run test:ui tests/scan-offline.spec.ts # Headed mode (see actual browser) npm run test:headed tests/scan-offline.spec.ts ``` ### Test Coverage **Online Scenarios** 1. Valid ticket scan → success + server verification 2. Invalid ticket scan → error from server 3. Duplicate scan → already_scanned response **Offline Scenarios** 1. Offline scan with optimistic ON → immediate success 2. Offline scan with optimistic OFF → queued status 3. Connection restored → background sync processes queue **Conflict Scenarios** 1. Offline success + server already_scanned → conflict logged 2. Multiple device conflicts → resolution workflow **Access Control** 1. Unauthenticated user → redirect to login 2. User without scan permission → unauthorized error 3. Staff/admin user → scanner access granted ## Troubleshooting ### Common Issues **Camera Not Working** - Check browser permissions in settings - Try different browser (Chrome/Firefox recommended) - Ensure HTTPS connection (required for camera access) **Scans Not Syncing** - Check internet connection - Open settings to view pending sync count - Use "Force Sync" button if available **App Not Installing** - Ensure HTTPS connection - Clear browser cache and retry - Check if PWA is already installed **Performance Issues** - Close other camera-using apps - Restart browser - Clear scanner app data and reinstall ### Browser Support **Recommended Browsers** - Chrome 88+ (best performance) - Safari 14+ (iOS support) - Firefox 85+ (good fallback) - Edge 88+ (Windows support) **Required Features** - Camera API (getUserMedia) - IndexedDB (offline storage) - Service Workers (background sync) - Web App Manifest (PWA installation) ### Debugging Tools **Browser DevTools** - Application tab → Service Workers (check registration) - Application tab → IndexedDB (view scan queue) - Console tab → Look for scanner logs - Network tab → Monitor API calls **Scanner Settings** - View pending sync count - Check last sync timestamp - Review conflict log - Force manual sync ## Analytics & Monitoring ### Scan Metrics **Per Device** - Total scans processed - Success/failure rates - Average scan time - Offline vs online scans **Per Event** - Device coverage (zones/gates) - Peak scanning times - Conflict rates - Sync latency ### Data Export Scan data can be exported for analysis: - Individual scan records with timestamps - Device and zone information - Sync status and conflicts - Customer and ticket details ## API Reference ### Scanner API Service ```typescript // Verify a QR code const result = await api.scanner.verifyTicket(qrCode); // Log scan event (fire-and-forget) await api.scanner.logScan({ eventId: 'evt-123', qr: 'TICKET_456', deviceId: 'device_789', zone: 'Gate A', result: 'valid', latency: 250 }); // Get scan history const history = await api.scanner.getScanHistory(eventId, page, pageSize); ``` ### Response Formats **Verify Response** ```json { "valid": true, "reason": "already_scanned", // if invalid "scannedAt": "2024-01-01T12:00:00Z", // if duplicate "ticketInfo": { "eventTitle": "Sample Event", "ticketTypeName": "General Admission", "customerEmail": "customer@example.com", "seatNumber": "A-15" // if assigned seating } } ``` ## Best Practices ### For Gate Staff 1. **Keep Device Charged**: Scanner is power-intensive 2. **Good Lighting**: Use torch in dark environments 3. **Steady Hands**: Hold device stable for better scanning 4. **Check Sync**: Periodically verify pending sync count 5. **Report Issues**: Note any conflicts or unusual behavior ### For Event Managers 1. **Test Before Event**: Verify scanner works with sample tickets 2. **Multiple Devices**: Deploy scanners at all entry points 3. **Backup Plan**: Have manual ticket list as fallback 4. **Monitor Conflicts**: Review conflict logs after event 5. **Network Planning**: Ensure WiFi coverage at gates ### For Developers 1. **Error Handling**: Graceful degradation when camera fails 2. **Performance**: Optimize for mobile device constraints 3. **Security**: Never store sensitive data locally 4. **Testing**: Include both online and offline scenarios 5. **Monitoring**: Track sync success rates and latency ## Future Enhancements ### Planned Features - **Bulk Scan Mode**: Rapid scanning for high-volume events - **Advanced Analytics**: Real-time dashboard for scan monitoring - **Multi-Event Support**: Switch between events without app restart - **Biometric Integration**: Facial recognition for VIP verification - **Inventory Alerts**: Real-time capacity warnings ### Technical Improvements - **WebAssembly Scanner**: Faster QR code detection - **Machine Learning**: Improved camera auto-focus - **Push Notifications**: Sync status and conflict alerts - **Cloud Sync**: Cross-device scan sharing - **Advanced PWA**: Enhanced installation and app store distribution