import React, { useState, useEffect } from 'react'; import { ShieldAlert, Radio, AlertTriangle, CheckCircle, MapPin, Eye, Activity, ClipboardCheck, History, Search, Zap, OctagonX, Check as CheckIcon, Image as ImageIcon, X, Sparkles, Coins, Trash2, Clock, QrCode, Download, Share2, ShieldCheck, Printer, Camera, Upload, ArrowUpRight, Loader2 } from 'lucide-react'; import { useLanguage } from '../contexts/LanguageContext'; import { Button } from '../components/ui/Button'; import { matchEmergencyReports } from '../services/geminiService'; import { StorageService } from '../services/storageService'; import { FTLStorageService } from '../services/ftl/storage'; import { FTLMission, Sighting, UserProfile } from '../types'; import confetti from 'canvas-confetti'; const FTLLogo = () => (
FTL
); const QRGenerator = ({ onClose }: { onClose: () => void }) => { const [qrData, setQrData] = useState({ name: '', contact: '', info: '', photo: '' }); const [step, setStep] = useState(1); const [isGenerating, setIsGenerating] = useState(false); // Using a public API for QR generation to ensure we have a valid image source for canvas const getQRUrl = (data: string) => `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(data)}&bgcolor=ffffff`; const handlePhoto = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onload = (ev) => setQrData(p => ({ ...p, photo: ev.target?.result as string })); reader.readAsDataURL(file); } }; const generateSmartTag = async () => { setIsGenerating(true); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (!ctx) return; // Card Dimensions const width = 600; const height = 900; canvas.width = width; canvas.height = height; // 1. Background const grd = ctx.createLinearGradient(0, 0, 0, height); grd.addColorStop(0, '#ffffff'); grd.addColorStop(1, '#f8fafc'); ctx.fillStyle = grd; ctx.fillRect(0, 0, width, height); // 2. Header Color (Red) ctx.fillStyle = '#dc2626'; ctx.fillRect(0, 0, width, 20); // 3. User Photo (Circular) if (qrData.photo) { const img = new Image(); img.src = qrData.photo; await new Promise((resolve) => { img.onload = resolve; }); ctx.save(); ctx.beginPath(); ctx.arc(width/2, 200, 120, 0, Math.PI * 2, true); ctx.closePath(); ctx.clip(); ctx.drawImage(img, width/2 - 120, 80, 240, 240); // Border ctx.lineWidth = 10; ctx.strokeStyle = '#dc2626'; ctx.stroke(); ctx.restore(); } // 4. Text Info ctx.textAlign = 'center'; // Name ctx.fillStyle = '#0f172a'; ctx.font = 'bold 50px Inter, sans-serif'; ctx.fillText(qrData.name.toUpperCase(), width/2, 380); // Label ctx.fillStyle = '#dc2626'; ctx.font = 'bold 24px Inter, sans-serif'; ctx.fillText('EMERGENCY RESCUE TAG', width/2, 420); // Info Box ctx.fillStyle = '#f1f5f9'; ctx.beginPath(); ctx.roundRect(50, 450, 500, 100, 20); ctx.fill(); ctx.fillStyle = '#475569'; ctx.font = 'italic 24px Inter, sans-serif'; // Simple text wrapping for info (first line only for simplicity in this demo) const infoText = qrData.info.length > 35 ? qrData.info.substring(0, 35) + '...' : qrData.info; ctx.fillText(`"${infoText}"`, width/2, 510); // 5. QR Code const qrJson = JSON.stringify({ n: qrData.name, c: qrData.contact, i: qrData.info, app: 'Rudraksha' }); const qrImg = new Image(); qrImg.crossOrigin = "Anonymous"; // Crucial for external images on canvas qrImg.src = getQRUrl(qrJson); await new Promise((resolve, reject) => { qrImg.onload = resolve; qrImg.onerror = resolve; // Continue even if QR fails (though it shouldn't) }); ctx.drawImage(qrImg, width/2 - 100, 600, 200, 200); // 6. Footer ctx.fillStyle = '#0f172a'; ctx.font = 'bold 30px Inter, sans-serif'; ctx.fillText(qrData.contact, width/2, 850); // Convert to Download const link = document.createElement('a'); link.download = `Rudraksha-Tag-${qrData.name}.png`; link.href = canvas.toDataURL('image/png'); link.click(); setIsGenerating(false); confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); }; return (

Rescue Tag Studio

Protocol: QR Identification Generator

{step === 1 ? (
{qrData.photo ? ( <> ) : ( )}
setQrData(p => ({...p, name: e.target.value}))} placeholder="e.g. Bruno (Dog)" />
setQrData(p => ({...p, contact: e.target.value}))} placeholder="Phone or Username" />
)}
)} {showQRModal && setShowQRModal(false)} />}
); }; export default Safety;