What changed:
- Onboarding tracking: admin_app_opened on first authenticated dashboard load; event_created, branding_configured,
and invite_created on their respective actions.
- Tour replay: Settings now has an “Experience” section to replay the tour (clears tour seen flag and opens via ?tour=1).
- Empty states: Tasks, Members, and Guest Messages now include richer copy + quick actions.
- New helpers + copy: Tour storage helpers, new translations, and related UI wiring.
96 lines
3.3 KiB
TypeScript
96 lines
3.3 KiB
TypeScript
import React from 'react';
|
|
import { Download, Share2, X } from 'lucide-react';
|
|
import { YStack, XStack } from '@tamagui/stacks';
|
|
import { SizableText as Text } from '@tamagui/text';
|
|
import { useTheme } from '@tamagui/core';
|
|
import { Pressable } from '@tamagui/react-native-web-lite';
|
|
import { InstallBannerState } from '../lib/installBanner';
|
|
import { CTAButton, MobileCard } from './Primitives';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
type MobileInstallBannerProps = {
|
|
state: InstallBannerState | null;
|
|
onInstall?: () => void;
|
|
onDismiss?: () => void;
|
|
density?: 'default' | 'compact';
|
|
};
|
|
|
|
export function MobileInstallBanner({
|
|
state,
|
|
onInstall,
|
|
onDismiss,
|
|
density = 'default',
|
|
}: MobileInstallBannerProps) {
|
|
const { t } = useTranslation('common');
|
|
const theme = useTheme();
|
|
const text = String(theme.color12?.val ?? theme.color?.val ?? '#0f172a');
|
|
const muted = String(theme.gray11?.val ?? theme.gray?.val ?? '#6b7280');
|
|
const border = String(theme.gray6?.val ?? theme.borderColor?.val ?? '#e5e7eb');
|
|
const accent = String(theme.primary?.val ?? '#2563eb');
|
|
const surface = String(theme.gray2?.val ?? '#f8fafc');
|
|
const accentSoft = String(theme.blue3?.val ?? '#dbeafe');
|
|
|
|
if (!state) {
|
|
return null;
|
|
}
|
|
|
|
const isPrompt = state.variant === 'prompt';
|
|
const isCompact = density === 'compact';
|
|
|
|
return (
|
|
<MobileCard
|
|
space={isCompact ? '$1.5' : '$2'}
|
|
borderColor={border}
|
|
backgroundColor={surface}
|
|
padding={isCompact ? '$2' : '$3'}
|
|
>
|
|
<XStack alignItems="center" justifyContent="space-between" gap="$2">
|
|
<XStack alignItems="center" space="$2" flex={1}>
|
|
<XStack
|
|
width={isCompact ? 32 : 36}
|
|
height={isCompact ? 32 : 36}
|
|
borderRadius={12}
|
|
alignItems="center"
|
|
justifyContent="center"
|
|
backgroundColor={accentSoft}
|
|
>
|
|
{isPrompt ? <Download size={16} color={accent} /> : <Share2 size={16} color={accent} />}
|
|
</XStack>
|
|
<YStack flex={1} space="$0.5">
|
|
<Text fontSize={isCompact ? '$xs' : '$sm'} fontWeight="800" color={text}>
|
|
{t('installBanner.title', 'Install Fotospiel Admin')}
|
|
</Text>
|
|
<Text fontSize={isCompact ? 10 : '$xs'} color={muted}>
|
|
{isPrompt
|
|
? t('installBanner.body', 'Add the app to your home screen for faster access and offline support.')
|
|
: t('installBanner.iosHint', 'On iOS: Share → Add to Home Screen.')}
|
|
</Text>
|
|
</YStack>
|
|
</XStack>
|
|
<XStack alignItems="center" space="$2">
|
|
{isPrompt && onInstall && isCompact ? (
|
|
<Pressable onPress={onInstall}>
|
|
<Text fontSize={10} fontWeight="700" color={accent}>
|
|
{t('installBanner.action', 'Install')}
|
|
</Text>
|
|
</Pressable>
|
|
) : null}
|
|
{onDismiss ? (
|
|
<Pressable onPress={onDismiss} aria-label={t('actions.dismiss', 'Dismiss')}>
|
|
<X size={14} color={muted} />
|
|
</Pressable>
|
|
) : null}
|
|
</XStack>
|
|
</XStack>
|
|
{isPrompt && onInstall && !isCompact ? (
|
|
<CTAButton
|
|
label={t('installBanner.action', 'Install')}
|
|
onPress={onInstall}
|
|
fullWidth={false}
|
|
tone="ghost"
|
|
/>
|
|
) : null}
|
|
</MobileCard>
|
|
);
|
|
}
|