- Add comprehensive analytics components with export functionality - Implement territory management with manager performance tracking - Add seatmap components for venue layout management - Create customer management features with modal interface - Add advanced hooks for dashboard flags and territory data - Implement seat selection and venue management utilities - Add type definitions for ticketing and seatmap systems 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
10 KiB
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):
- Open
/scan?eventId=your-event-idin browser - Look for "Add to Home Screen" prompt
- Follow device-specific installation steps
Desktop:
- Navigate to scanner page
- Look for install prompt in address bar
- 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:
- Click settings icon (gear) in header
- Enter zone name (e.g., "Gate A", "Main Entrance")
- Zone is saved locally and included in scan logs
Usage Guide
Basic Scanning
- Access Scanner: Navigate to
/scan?eventId={eventId} - Position QR Code: Center QR code within scanning frame
- Wait for Scan: Scanner automatically detects and processes codes
- 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
- Scan Detection: QR codes are processed immediately
- Local Storage: Scans stored in IndexedDB queue
- Optimistic UI: Instant feedback based on settings
- Background Sync: Automatic verification when online
- 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
- Conflicts automatically logged when detected
- Admin can review conflict log in settings
- 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 statusconflicts: Offline/online result discrepanciessettings: 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:ticketspermission - 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
# 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
- Valid ticket scan → success + server verification
- Invalid ticket scan → error from server
- Duplicate scan → already_scanned response
Offline Scenarios
- Offline scan with optimistic ON → immediate success
- Offline scan with optimistic OFF → queued status
- Connection restored → background sync processes queue
Conflict Scenarios
- Offline success + server already_scanned → conflict logged
- Multiple device conflicts → resolution workflow
Access Control
- Unauthenticated user → redirect to login
- User without scan permission → unauthorized error
- 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
// 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
{
"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
- Keep Device Charged: Scanner is power-intensive
- Good Lighting: Use torch in dark environments
- Steady Hands: Hold device stable for better scanning
- Check Sync: Periodically verify pending sync count
- Report Issues: Note any conflicts or unusual behavior
For Event Managers
- Test Before Event: Verify scanner works with sample tickets
- Multiple Devices: Deploy scanners at all entry points
- Backup Plan: Have manual ticket list as fallback
- Monitor Conflicts: Review conflict logs after event
- Network Planning: Ensure WiFi coverage at gates
For Developers
- Error Handling: Graceful degradation when camera fails
- Performance: Optimize for mobile device constraints
- Security: Never store sensitive data locally
- Testing: Include both online and offline scenarios
- 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