detect PWA install state, skip install screen if installed, show warning banner in browser

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 15:17:13 +01:00
parent e48566ca9e
commit 795662461a
2 changed files with 34 additions and 6 deletions

View File

@@ -17,8 +17,19 @@ function detectPlatform(): "ios" | "android" | "unknown" {
return "unknown";
}
export function isInstalledPwa(): boolean {
if (window.matchMedia("(display-mode: standalone)").matches) return true;
if (
"standalone" in navigator &&
(navigator as { standalone?: boolean }).standalone
)
return true;
return false;
}
export function OnboardingForm() {
const navigate = useNavigate();
const installed = useMemo(() => isInstalledPwa(), []);
const [step, setStep] = useState(0);
const [dbReady, setDbReady] = useState(false);
const [submitting, setSubmitting] = useState(false);
@@ -55,8 +66,8 @@ export function OnboardingForm() {
<div className="flex min-h-[80vh] flex-col items-center justify-center">
<div className="w-full max-w-md space-y-6">
{step === 0 && <IntroScreen />}
{step === 1 && <InstallScreen />}
{step === 2 && (
{!installed && step === 1 && <InstallScreen />}
{step === (installed ? 1 : 2) && (
<>
<div className="space-y-2 text-center">
<h1 className="text-2xl font-bold">Über dich</h1>
@@ -167,13 +178,13 @@ export function OnboardingForm() {
</>
)}
{step < 2 && (
{step < (installed ? 1 : 2) && (
<Button className="w-full" onClick={() => setStep(step + 1)}>
Weiter
</Button>
)}
<DotIndicator current={step} />
<DotIndicator current={step} installed={installed} />
</div>
</div>
);
@@ -267,8 +278,16 @@ function InstallScreen() {
);
}
function DotIndicator({ current }: { current: number }) {
const dots = ["intro", "install", "form"] as const;
function DotIndicator({
current,
installed,
}: {
current: number;
installed: boolean;
}) {
const dots = installed
? (["intro", "form"] as const)
: (["intro", "install", "form"] as const);
return (
<div className="flex justify-center gap-2">
{dots.map((id, i) => (

View File

@@ -5,6 +5,8 @@ import {
useMatchRoute,
} from "@tanstack/react-router";
import { ListChecks, Settings, Users } from "lucide-react";
import { useMemo } from "react";
import { isInstalledPwa } from "@/features/onboarding/components/onboarding-form";
export const Route = createRootRoute({
component: () => {
@@ -12,9 +14,16 @@ export const Route = createRootRoute({
const isOnboarding = matchRoute({ to: "/onboarding" });
const isRoot = matchRoute({ to: "/" });
const hideNav = isOnboarding || isRoot;
const installed = useMemo(() => isInstalledPwa(), []);
return (
<div className="flex min-h-screen flex-col bg-background text-foreground">
{!hideNav && !installed && (
<div className="bg-amber-500 px-4 py-2 text-center text-sm font-medium text-white dark:bg-amber-600">
App nicht installiert füge TherapyFinder zum Home-Bildschirm
hinzu, um Datenverlust zu vermeiden.
</div>
)}
<main className="mx-auto w-full max-w-2xl flex-1 px-4 pb-20 pt-6">
<Outlet />
</main>