Added onboarding + a lightweight install banner to both the mobile login screen and the settings screen, with Android/Chromium
install prompt support and iOS “Share → Add to Home Screen” guidance. Also added a small helper + tests to decide when/which banner variant should show, and shared copy in common.json.
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import React from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Loader2, Lock, Mail } from 'lucide-react';
|
||||
import { Download, Loader2, Lock, Mail, Share2 } from 'lucide-react';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { adminPath, ADMIN_DEFAULT_AFTER_LOGIN_PATH, ADMIN_EVENTS_PATH } from '../constants';
|
||||
import { useAuth } from '../auth/context';
|
||||
import { resolveReturnTarget } from '../lib/returnTo';
|
||||
import { useInstallPrompt } from './hooks/useInstallPrompt';
|
||||
import { resolveInstallBannerState } from './lib/installBanner';
|
||||
|
||||
type LoginResponse = {
|
||||
token: string;
|
||||
@@ -43,8 +45,10 @@ async function performLogin(payload: { login: string; password: string; return_t
|
||||
export default function MobileLoginPage() {
|
||||
const { status, applyToken, abilities } = useAuth();
|
||||
const { t } = useTranslation('auth');
|
||||
const { t: tc } = useTranslation('common');
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const installPrompt = useInstallPrompt();
|
||||
const safeAreaStyle: React.CSSProperties = {
|
||||
paddingTop: 'calc(env(safe-area-inset-top, 0px) + 16px)',
|
||||
paddingBottom: 'calc(env(safe-area-inset-bottom, 0px) + 16px)',
|
||||
@@ -76,6 +80,12 @@ export default function MobileLoginPage() {
|
||||
const [login, setLogin] = React.useState('');
|
||||
const [password, setPassword] = React.useState('');
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
const installBanner = resolveInstallBannerState({
|
||||
isInstalled: installPrompt.isInstalled,
|
||||
isStandalone: installPrompt.isStandalone,
|
||||
canInstall: installPrompt.canInstall,
|
||||
isIos: installPrompt.isIos,
|
||||
});
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationKey: ['tenantAdminLoginMobile'],
|
||||
@@ -179,6 +189,37 @@ export default function MobileLoginPage() {
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{installBanner ? (
|
||||
<div className="rounded-2xl border border-white/10 bg-white/5 px-4 py-3">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-xl bg-white/10">
|
||||
{installBanner.variant === 'prompt' ? (
|
||||
<Download className="h-5 w-5 text-white/80" />
|
||||
) : (
|
||||
<Share2 className="h-5 w-5 text-white/80" />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1 space-y-1">
|
||||
<p className="text-sm font-semibold text-white">{tc('installBanner.title', 'Install Fotospiel Admin')}</p>
|
||||
<p className="text-xs text-white/70">
|
||||
{installBanner.variant === 'prompt'
|
||||
? tc('installBanner.body', 'Add the app to your home screen for faster access and offline support.')
|
||||
: tc('installBanner.iosHint', 'On iOS: Share → Add to Home Screen.')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{installBanner.variant === 'prompt' ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => void installPrompt.promptInstall()}
|
||||
className="mt-3 inline-flex items-center justify-center rounded-full bg-white/10 px-4 py-2 text-xs font-semibold text-white transition hover:bg-white/20"
|
||||
>
|
||||
{tc('installBanner.action', 'Install')}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="text-center text-xs text-white/60">
|
||||
{t('login.support', 'Fragen? Schreib uns an support@fotospiel.de oder antworte direkt auf deine Einladung.')}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user