- 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>
175 lines
5.8 KiB
TypeScript
175 lines
5.8 KiB
TypeScript
/**
|
|
* QR System Demonstration Script
|
|
* Shows QR validation, backup code generation, and manual entry flow
|
|
*/
|
|
|
|
import { QRValidator, createQRValidator, getQRErrorMessage, formatBackupCode } from '../src/lib/qr-validator';
|
|
import { QRGenerator, createQRGenerator, generateTicketQR, generateQRForFormat, validateQRData } from '../src/lib/qr-generator';
|
|
|
|
console.log('🎫 Black Canyon Tickets - QR System Demonstration\n');
|
|
|
|
// Sample ticket data
|
|
const sampleTicketData = {
|
|
ticketId: '550e8400-e29b-41d4-a716-446655440000',
|
|
eventId: 'evt_789012345',
|
|
zone: 'GA',
|
|
seat: 'A12',
|
|
expiresInDays: 30
|
|
};
|
|
|
|
console.log('1. Ticket Data Validation');
|
|
console.log('=========================');
|
|
const validation = validateQRData(sampleTicketData);
|
|
console.log(`✅ Valid: ${validation.valid}`);
|
|
if (!validation.valid) {
|
|
console.log(`❌ Errors: ${validation.errors.join(', ')}`);
|
|
}
|
|
console.log();
|
|
|
|
console.log('2. QR Code Generation');
|
|
console.log('====================');
|
|
const generator = createQRGenerator();
|
|
|
|
// Generate QR for different formats
|
|
const formats = ['email', 'print', 'thermal', 'wallet'] as const;
|
|
for (const format of formats) {
|
|
const { qr, svg } = generateQRForFormat(sampleTicketData, format);
|
|
console.log(`📱 ${format.toUpperCase()} Format:`);
|
|
console.log(` QR Data: ${qr.qrData.substring(0, 50)}...`);
|
|
console.log(` Backup Code: ${qr.backupCode}`);
|
|
console.log(` Format: ${qr.metadata.format}`);
|
|
console.log(` Generated: ${new Date(qr.metadata.generatedAt).toLocaleString()}`);
|
|
if (qr.metadata.expiresAt) {
|
|
console.log(` Expires: ${new Date(qr.metadata.expiresAt).toLocaleString()}`);
|
|
}
|
|
console.log();
|
|
}
|
|
|
|
console.log('3. QR Code Validation');
|
|
console.log('====================');
|
|
const validator = createQRValidator();
|
|
|
|
// Test different QR formats
|
|
const testQRs = [
|
|
// Simple format
|
|
`TICKET_${sampleTicketData.ticketId}`,
|
|
|
|
// Signed token format (generated)
|
|
generateTicketQR(sampleTicketData).qrData,
|
|
|
|
// Invalid formats
|
|
'INVALID_QR_CODE',
|
|
'BCT.v2.invalid.signature',
|
|
'TICKET_not-a-uuid'
|
|
];
|
|
|
|
testQRs.forEach((qr, index) => {
|
|
console.log(`Test ${index + 1}: ${qr.substring(0, 40)}${qr.length > 40 ? '...' : ''}`);
|
|
const result = validator.validateQR(qr);
|
|
console.log(` ✅ Valid: ${result.valid}`);
|
|
console.log(` 📱 Format: ${result.format}`);
|
|
if (result.ticketId) {
|
|
console.log(` 🎫 Ticket ID: ${result.ticketId}`);
|
|
}
|
|
if (result.eventId) {
|
|
console.log(` 🎪 Event ID: ${result.eventId}`);
|
|
}
|
|
if (!result.valid) {
|
|
console.log(` ❌ Error: ${getQRErrorMessage(result)}`);
|
|
}
|
|
if (result.metadata) {
|
|
if (result.metadata.expiresAt) {
|
|
const expires = new Date(result.metadata.expiresAt * 1000);
|
|
console.log(` ⏰ Expires: ${expires.toLocaleString()}`);
|
|
}
|
|
if (result.metadata.zone) {
|
|
console.log(` 🏟️ Zone: ${result.metadata.zone}`);
|
|
}
|
|
if (result.metadata.seat) {
|
|
console.log(` 💺 Seat: ${result.metadata.seat}`);
|
|
}
|
|
}
|
|
console.log();
|
|
});
|
|
|
|
console.log('4. Backup Code Validation');
|
|
console.log('=========================');
|
|
const testBackupCodes = [
|
|
'55440000', // Valid (last 8 chars of ticket ID)
|
|
'1234ABCD', // Valid hex format
|
|
'12345', // Too short
|
|
'123456789', // Too long
|
|
'1234GHIJ', // Invalid characters
|
|
'' // Empty
|
|
];
|
|
|
|
testBackupCodes.forEach((code, index) => {
|
|
console.log(`Test ${index + 1}: "${code}"`);
|
|
const result = validator.validateBackupCode(code);
|
|
console.log(` ✅ Valid: ${result.valid}`);
|
|
if (result.valid && result.normalizedCode) {
|
|
console.log(` 🔢 Normalized: ${formatBackupCode(result.normalizedCode)}`);
|
|
}
|
|
console.log();
|
|
});
|
|
|
|
console.log('5. Backup Code Generation');
|
|
console.log('========================');
|
|
const testTicketIds = [
|
|
sampleTicketData.ticketId,
|
|
'123e4567-e89b-12d3-a456-426614174000',
|
|
'invalid-uuid'
|
|
];
|
|
|
|
testTicketIds.forEach((ticketId, index) => {
|
|
console.log(`Test ${index + 1}: ${ticketId}`);
|
|
try {
|
|
const backupCode = generator.generateBackupCode(ticketId);
|
|
console.log(` 🔢 Backup Code: ${formatBackupCode(backupCode)}`);
|
|
} catch (error) {
|
|
console.log(` ❌ Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
}
|
|
console.log();
|
|
});
|
|
|
|
console.log('6. QR Format Detection');
|
|
console.log('======================');
|
|
const mixedQRs = [
|
|
'TICKET_550e8400-e29b-41d4-a716-446655440000',
|
|
'BCT.v2.eyJ0aWQiOiIxMjMiLCJlaWQiOiI0NTYifQ.signature',
|
|
'550e8400-e29b-41d4-a716-446655440000', // Legacy UUID only
|
|
'MANUAL_55440000'
|
|
];
|
|
|
|
mixedQRs.forEach((qr, index) => {
|
|
console.log(`QR ${index + 1}: ${qr}`);
|
|
const ticketId = validator.extractTicketId(qr);
|
|
if (ticketId) {
|
|
console.log(` 🎫 Extracted Ticket ID: ${ticketId}`);
|
|
const backupCode = generator.generateBackupCode(ticketId);
|
|
console.log(` 🔢 Backup Code: ${formatBackupCode(backupCode)}`);
|
|
} else {
|
|
console.log(` ❌ Could not extract ticket ID`);
|
|
}
|
|
console.log();
|
|
});
|
|
|
|
console.log('7. Production Recommendations');
|
|
console.log('=============================');
|
|
console.log('✅ Use signed tokens (BCT.v2.{payload}.{signature}) for security');
|
|
console.log('✅ Implement proper HMAC-SHA256 signatures in production');
|
|
console.log('✅ Rotate signing keys quarterly');
|
|
console.log('✅ Use Error Correction Level M (15%) for most use cases');
|
|
console.log('✅ Use Error Correction Level H (30%) for thermal printers');
|
|
console.log('✅ Include backup codes on all printed tickets');
|
|
console.log('✅ Train gate staff on manual entry procedures');
|
|
console.log('✅ Test QR codes across different devices and lighting conditions');
|
|
console.log('✅ Monitor QR scan success rates and manual entry frequency');
|
|
console.log();
|
|
|
|
console.log('🚀 QR System Demo Complete!');
|
|
console.log('Visit /scanner?eventId=test-event-123 to test the scanner interface');
|
|
console.log(`Server running at: http://localhost:5174`);
|
|
console.log();
|
|
|
|
export {}; |