import { auth } from '@chat-app/shared'; import { Redirect } from 'expo-router'; import { useState } from 'react'; import { ActivityIndicator, Pressable, StyleSheet, Text, TextInput, View, } from 'react-native'; import { useAuth } from '../lib/authContext'; import { env } from '../lib/env'; import { supabase } from '../lib/supabase'; import { colors } from '../theme/colors'; // Phase 1 landing — magic-link login. Signup with invite code is not // part of this MVP (accounts come from desktop / admin). After a // successful request the user sees a "Check your inbox" state until // they tap the email link and Expo Router routes the deep link to // app/auth/callback.tsx. export default function Landing() { const { session, ready } = useAuth(); const [email, setEmail] = useState(''); const [submitting, setSubmitting] = useState(false); const [sent, setSent] = useState(false); const [error, setError] = useState(null); if (!ready) return null; if (session) return ; async function handleSubmit() { if (!email.includes('@')) { setError('Bitte gültige E-Mail eingeben'); return; } setSubmitting(true); setError(null); try { await auth.loginWithMagicLink(supabase, email.trim(), env.authRedirectUrl); setSent(true); } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Login fehlgeschlagen'); } finally { setSubmitting(false); } } if (sent) { return ( Netralax Check deine Mails Wir haben dir einen Anmelde-Link an {email} geschickt. Tipp auf den Link, um dich anzumelden. { setSent(false); setEmail(''); }} > Andere E-Mail verwenden ); } return ( Netralax Mit Magic-Link anmelden {error && {error}} {submitting ? ( ) : ( Magic Link senden )} ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.bg, padding: 24, }, title: { color: colors.text, fontSize: 32, fontWeight: '700', letterSpacing: 1, marginBottom: 8 }, subtitle: { color: colors.textMuted, fontSize: 14, marginBottom: 24 }, help: { color: colors.textMuted, fontSize: 14, textAlign: 'center', marginHorizontal: 16, marginBottom: 24, lineHeight: 20, }, input: { width: '100%', maxWidth: 360, backgroundColor: colors.surface, borderColor: colors.border, borderWidth: 1, borderRadius: 12, color: colors.text, paddingHorizontal: 16, paddingVertical: 14, fontSize: 15, marginBottom: 12, }, error: { color: colors.danger, fontSize: 13, marginBottom: 12 }, button: { width: '100%', maxWidth: 360, backgroundColor: colors.accent, paddingHorizontal: 24, paddingVertical: 14, borderRadius: 12, alignItems: 'center', }, buttonGhost: { backgroundColor: 'transparent', borderWidth: 1, borderColor: colors.border }, buttonDisabled: { opacity: 0.6 }, buttonText: { color: colors.text, fontWeight: '600', fontSize: 15 }, });