From 131498259065c6620d149c829e7eb95b01a9ebc3 Mon Sep 17 00:00:00 2001 From: Andrej Spielmann Date: Thu, 26 Mar 2026 15:01:26 +0100 Subject: [PATCH] feat(pwa): add InstallPrompt component for Add to Home Screen --- frontend/src/components/ui/install-prompt.tsx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 frontend/src/components/ui/install-prompt.tsx diff --git a/frontend/src/components/ui/install-prompt.tsx b/frontend/src/components/ui/install-prompt.tsx new file mode 100644 index 0000000..c38e32a --- /dev/null +++ b/frontend/src/components/ui/install-prompt.tsx @@ -0,0 +1,55 @@ +"use client" + +import { useState, useEffect } from "react" +import { Button } from "@/components/ui/button" +import { X } from "lucide-react" + +export function InstallPrompt() { + const [show, setShow] = useState(false) + const [isIOS, setIsIOS] = useState(false) + const [isStandalone, setIsStandalone] = useState(false) + + useEffect(() => { + const standalone = window.matchMedia('(display-mode: standalone)').matches || + (window.navigator as any).standalone || + document.referrer.includes('android-app://') + setIsStandalone(standalone) + + const isIOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream + setIsIOS(isIOSDevice) + + const dismissed = localStorage.getItem('install-prompt-dismissed') + if (!standalone && !dismissed) { + setTimeout(() => setShow(true), 3000) + } + }, []) + + const handleDismiss = () => { + setShow(false) + localStorage.setItem('install-prompt-dismissed', 'true') + } + + if (!show || isStandalone) return null + + return ( +
+
+
+

WrestleDesk als App installieren

+ {isIOS ? ( +

+ Tippe auf Teilen → "Zum Home Screen hinzufügen" +

+ ) : ( +

+ Installieren für schnellen Zugriff +

+ )} +
+ +
+
+ ) +}