| import { useState, useEffect } from 'react'; | |
| import { Download, X } from 'lucide-react'; | |
| import { Button } from '@/components/ui/button'; | |
| export default function InstallPrompt() { | |
| const [deferredPrompt, setDeferredPrompt] = useState<any>(null); | |
| const [showPrompt, setShowPrompt] = useState(false); | |
| useEffect(() => { | |
| const handler = (e: any) => { | |
| e.preventDefault(); | |
| setDeferredPrompt(e); | |
| setShowPrompt(true); | |
| }; | |
| window.addEventListener('beforeinstallprompt', handler); | |
| return () => { | |
| window.removeEventListener('beforeinstallprompt', handler); | |
| }; | |
| }, []); | |
| const handleInstall = async () => { | |
| if (!deferredPrompt) return; | |
| deferredPrompt.prompt(); | |
| const { outcome } = await deferredPrompt.userChoice; | |
| if (outcome === 'accepted') { | |
| setDeferredPrompt(null); | |
| setShowPrompt(false); | |
| } | |
| }; | |
| if (!showPrompt) return null; | |
| return ( | |
| <div className="fixed bottom-4 left-4 right-4 md:left-auto md:right-4 md:w-96 bg-white rounded-lg shadow-lg border border-gray-200 p-4 z-50 animate-in slide-in-from-bottom-4 duration-300"> | |
| <div className="flex items-start justify-between gap-4"> | |
| <div className="flex-1"> | |
| <h3 className="font-semibold text-gray-900 mb-1">Install App</h3> | |
| <p className="text-sm text-gray-600 mb-3"> | |
| Install QA Hub for a better experience and offline access. | |
| </p> | |
| <div className="flex gap-2"> | |
| <Button size="sm" onClick={handleInstall} className="bg-sky-500 hover:bg-sky-600 text-white"> | |
| <Download className="w-4 h-4 mr-2" /> | |
| Install | |
| </Button> | |
| <Button size="sm" variant="ghost" onClick={() => setShowPrompt(false)}> | |
| Not now | |
| </Button> | |
| </div> | |
| </div> | |
| <button | |
| onClick={() => setShowPrompt(false)} | |
| className="text-gray-400 hover:text-gray-600" | |
| > | |
| <X className="w-5 h-5" /> | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| } | |