feat: add advanced analytics and territory management system
- 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>
This commit is contained in:
175
reactrebuild0825/scripts/qr-system-demo.ts
Normal file
175
reactrebuild0825/scripts/qr-system-demo.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* 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 {};
|
||||
Reference in New Issue
Block a user