import React, { useState, useEffect, useRef } from 'react';
import { initializeApp } from 'firebase/app';
import { getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken } from 'firebase/auth';
import {
getFirestore,
collection,
addDoc,
doc,
getDoc,
updateDoc,
serverTimestamp
} from 'firebase/firestore';
import {
Camera,
CheckCircle,
User,
Mail,
QrCode,
AlertCircle,
ArrowLeft,
Calendar,
MapPin,
Loader2,
Building2,
Briefcase,
Phone
} from 'lucide-react';
// --- FIREBASE CONFIGURATION ---
const firebaseConfig = JSON.parse(__firebase_config);
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id';
// --- HELPER: Load External Scripts for QR Functionality ---
const useScript = (src) => {
const [loaded, setLoaded] = useState(false);
useEffect(() => {
const script = document.createElement('script');
script.src = src;
script.async = true;
script.onload = () => setLoaded(true);
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, [src]);
return loaded;
};
// --- COMPONENT: QR Code Generator ---
const QRCodeGenerator = ({ value, size = 200 }) => {
const canvasRef = useRef(null);
const qriousLoaded = useScript('https://cdnjs.cloudflare.com/ajax/libs/qrious/4.0.2/qrious.min.js');
useEffect(() => {
if (qriousLoaded && canvasRef.current && window.QRious) {
new window.QRious({
element: canvasRef.current,
value: value,
size: size,
level: 'H', // High error correction
});
}
}, [value, size, qriousLoaded]);
if (!qriousLoaded) return
;
return ;
};
// --- COMPONENT: QR Code Scanner ---
const QRScanner = ({ onScanResult }) => {
const scannerLoaded = useScript('https://unpkg.com/html5-qrcode');
const [isScanning, setIsScanning] = useState(true);
const scannerRef = useRef(null);
useEffect(() => {
if (!scannerLoaded || !isScanning) return;
const html5QrcodeScanner = new window.Html5QrcodeScanner(
"reader",
{ fps: 10, qrbox: { width: 250, height: 250 } },
false
);
html5QrcodeScanner.render(
(decodedText) => {
// Stop scanning after success to prevent multiple triggers
html5QrcodeScanner.clear().then(() => {
setIsScanning(false);
onScanResult(decodedText);
});
},
(errorMessage) => {
// console.log(errorMessage); // Ignore parse errors, they are common while moving camera
}
);
scannerRef.current = html5QrcodeScanner;
return () => {
if (scannerRef.current) {
scannerRef.current.clear().catch(err => console.error("Failed to clear scanner", err));
}
};
}, [scannerLoaded, isScanning, onScanResult]);
if (!scannerLoaded) return
;
return (
) : (
Scanner paused/finished.
)}
);
};
// --- MAIN APP COMPONENT ---
export default function EventApp() {
const [user, setUser] = useState(null);
const [view, setView] = useState('register'); // 'register', 'confirmation', 'admin'
// Registration State
const [formData, setFormData] = useState({
name: '',
email: '',
designation: '',
company: '',
mobile: ''
});
const [loading, setLoading] = useState(false);
const [ticketData, setTicketData] = useState(null);
// Admin Scan State
const [scanStatus, setScanStatus] = useState(null); // 'loading', 'success', 'already-checked-in', 'error'
const [scannedUser, setScannedUser] = useState(null);
// 1. Initialize Auth
useEffect(() => {
const initAuth = async () => {
if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) {
await signInWithCustomToken(auth, __initial_auth_token);
} else {
await signInAnonymously(auth);
}
};
initAuth();
const unsubscribe = onAuthStateChanged(auth, setUser);
return () => unsubscribe();
}, []);
// 2. Handle Registration
const handleRegister = async (e) => {
e.preventDefault();
if (!user) return;
setLoading(true);
try {
// Create a document in the public data collection
const collectionRef = collection(db, 'artifacts', appId, 'public', 'data', 'registrations');
const newReg = {
name: formData.name,
email: formData.email,
designation: formData.designation,
company: formData.company,
mobile: formData.mobile,
checkedIn: false,
timestamp: serverTimestamp(),
registrationId: Math.random().toString(36).substr(2, 9).toUpperCase() // Friendly ID
};
const docRef = await addDoc(collectionRef, newReg);
setTicketData({ ...newReg, id: docRef.id });
setView('confirmation');
setFormData({ name: '', email: '', designation: '', company: '', mobile: '' }); // Reset form
} catch (error) {
console.error("Error registering:", error);
alert("Registration failed. Please try again.");
} finally {
setLoading(false);
}
};
// 3. Handle QR Scan (Admin Side)
const handleScanResult = async (docId) => {
setScanStatus('loading');
setScannedUser(null);
try {
const docRef = doc(db, 'artifacts', appId, 'public', 'data', 'registrations', docId);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const data = docSnap.data();
setScannedUser(data);
if (data.checkedIn) {
setScanStatus('already-checked-in');
} else {
// Check them in
await updateDoc(docRef, {
checkedIn: true,
checkInTime: serverTimestamp()
});
setScanStatus('success');
}
} else {
setScanStatus('error');
}
} catch (err) {
console.error(err);
setScanStatus('error');
}
};
// --- RENDERERS ---
if (!user) {
return (
);
}
// --- ADMIN / SCANNER VIEW ---
if (view === 'admin') {
return (
Scan attendee QR codes to verify entry.
{/* Feedback Area */}
{scanStatus === 'loading' && (
)}
{scanStatus === 'success' && (
{scannedUser?.name}
{scannedUser?.designation} at {scannedUser?.company}
{scannedUser?.email}
)}
{scanStatus === 'already-checked-in' && (
Ticket belonging to {scannedUser?.name} has already been scanned.
Do not admit twice.
)}
{scanStatus === 'error' && (
This QR code was not found in the system.
)}
{scanStatus && scanStatus !== 'loading' && (
)}
);
}
// --- CONFIRMATION / TICKET VIEW ---
if (view === 'confirmation' && ticketData) {
return (
{/* Header */}
Please save your ticket.
{/* Ticket Body */}
Event Ticket
{ticketData.designation}
{ticketData.company}
{/* QR Section */}
Scan at entrance for check-in
Reg Number
{ticketData.registrationId}
Status
Confirmed
{/* Footer Actions */}
);
}
// --- REGISTRATION VIEW ---
return (
{/* Event Header Card */}
Women Empowerment
{/* Registration Form */}
Fill in your details to get your QR pass.
);
}