stadtwerke/innungsapp/apps/mobile/app/(auth)/login.tsx

207 lines
5.1 KiB
TypeScript

import {
View, Text, TextInput, TouchableOpacity,
KeyboardAvoidingView, Platform, ActivityIndicator, StyleSheet,
} from 'react-native'
import { useState } from 'react'
import { useRouter } from 'expo-router'
import { SafeAreaView } from 'react-native-safe-area-context'
import { Ionicons } from '@expo/vector-icons'
import { authClient } from '@/lib/auth-client'
export default function LoginScreen() {
const router = useRouter()
const [email, setEmail] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const canSubmit = email.trim().length > 0 && !loading
async function handleSendLink() {
if (!email.trim()) return
setLoading(true)
setError('')
const result = await authClient.signIn.magicLink({
email: email.trim().toLowerCase(),
callbackURL: '/home',
})
setLoading(false)
if (result.error) {
setError(result.error.message ?? 'Ein Fehler ist aufgetreten.')
} else {
router.push({ pathname: '/(auth)/check-email', params: { email } })
}
}
return (
<SafeAreaView style={styles.safeArea}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardView}
>
<View style={styles.content}>
<View style={styles.logoSection}>
<View style={styles.logoBox}>
<Text style={styles.logoLetter}>I</Text>
</View>
<Text style={styles.appName}>InnungsApp</Text>
<Text style={styles.tagline}>Ihre Kreishandwerkerschaft digital</Text>
</View>
<View style={styles.form}>
<Text style={styles.inputLabel}>Email-Adresse</Text>
<View style={styles.inputWrap}>
<Ionicons name="mail-outline" size={18} color="#94A3B8" />
<TextInput
style={styles.input}
placeholder="beispiel@handwerk.de"
placeholderTextColor="#94A3B8"
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
value={email}
onChangeText={setEmail}
onSubmitEditing={handleSendLink}
returnKeyType="go"
/>
</View>
{error ? (
<View style={styles.errorBox}>
<Text style={styles.errorText}>{error}</Text>
</View>
) : null}
<TouchableOpacity
onPress={handleSendLink}
disabled={!canSubmit}
style={[styles.submitBtn, !canSubmit && styles.submitBtnDisabled]}
activeOpacity={0.85}
>
{loading ? (
<ActivityIndicator color="#FFFFFF" />
) : (
<View style={styles.submitContent}>
<Text style={styles.submitLabel}>Login-Link senden</Text>
<Ionicons name="arrow-forward" size={16} color="#FFFFFF" />
</View>
)}
</TouchableOpacity>
</View>
<Text style={styles.hint}>
Noch kein Zugang? Kontaktieren Sie Ihre Innungsgeschaeftsstelle.
</Text>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: '#FFFFFF',
},
keyboardView: {
flex: 1,
},
content: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 24,
},
logoSection: {
alignItems: 'center',
marginBottom: 40,
},
logoBox: {
width: 64,
height: 64,
backgroundColor: '#003B7E',
borderRadius: 18,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 16,
},
logoLetter: {
color: '#FFFFFF',
fontSize: 30,
fontWeight: '900',
},
appName: {
fontSize: 30,
fontWeight: '800',
color: '#0F172A',
letterSpacing: -0.6,
marginBottom: 4,
},
tagline: {
fontSize: 14,
color: '#64748B',
textAlign: 'center',
},
form: {
gap: 12,
},
inputLabel: {
fontSize: 14,
fontWeight: '700',
color: '#334155',
},
inputWrap: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#F8FAFC',
borderRadius: 14,
borderWidth: 1,
borderColor: '#E2E8F0',
paddingHorizontal: 12,
gap: 8,
},
input: {
flex: 1,
paddingVertical: 13,
color: '#0F172A',
fontSize: 15,
},
errorBox: {
backgroundColor: '#FEF2F2',
borderWidth: 1,
borderColor: '#FECACA',
borderRadius: 12,
paddingHorizontal: 14,
paddingVertical: 10,
},
errorText: {
color: '#B91C1C',
fontSize: 13,
},
submitBtn: {
backgroundColor: '#003B7E',
borderRadius: 14,
paddingVertical: 14,
alignItems: 'center',
marginTop: 4,
},
submitBtnDisabled: {
backgroundColor: '#CBD5E1',
},
submitContent: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
},
submitLabel: {
color: '#FFFFFF',
fontWeight: '700',
fontSize: 15,
},
hint: {
marginTop: 24,
textAlign: 'center',
color: '#64748B',
fontSize: 13,
lineHeight: 18,
},
})