feat: implement user authentication with login and register
- Add login screen with email/username support - Add register screen with email validation - Implement AuthStore with expo-secure-store (native) / localStorage (web) - Add X-User-Id header authentication (simple auth without JWT) - Rename displayName to userName across codebase - Add findByUserName() to UserRepository - Check for existing email AND username on registration - Add AuthButton component with shadow effect - Add logout button to Header - Add hash-password.js utility script for manual password resets - Update CORS to allow X-User-Id header
This commit is contained in:
@@ -1,31 +1,95 @@
|
||||
import { useState } from "react";
|
||||
import { View, Text, TextInput, Pressable } from "react-native";
|
||||
import { Link, router } from "expo-router";
|
||||
import BaseBackground from "../components/BaseBackground";
|
||||
import AuthButton from "../components/AuthButton";
|
||||
import { AuthService } from "../services";
|
||||
import currentTheme from "../Themes";
|
||||
|
||||
const LoginScreen = () => {
|
||||
// TODO: Email input field
|
||||
// TODO: Password input field
|
||||
// TODO: Login button -> AuthService.login()
|
||||
// TODO: Link to RegisterScreen
|
||||
// TODO: Error handling and display
|
||||
// TODO: Navigate to Calendar on success
|
||||
throw new Error("Not implemented");
|
||||
const [identifier, setIdentifier] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleLogin = async () => {
|
||||
setError(null);
|
||||
|
||||
if (!identifier || !password) {
|
||||
setError("Bitte alle Felder ausfüllen");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await AuthService.login({ identifier, password });
|
||||
router.replace("/(tabs)/chat");
|
||||
} catch {
|
||||
setError("Anmeldung fehlgeschlagen. Überprüfe deine Zugangsdaten.");
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseBackground>
|
||||
<View className="flex-1 justify-center items-center p-4">
|
||||
<Text className="text-2xl mb-8">Login</Text>
|
||||
<View className="flex-1 justify-center items-center p-8">
|
||||
<Text
|
||||
className="text-3xl font-bold mb-8"
|
||||
style={{ color: currentTheme.textPrimary }}
|
||||
>
|
||||
Anmelden
|
||||
</Text>
|
||||
|
||||
{error && (
|
||||
<Text className="mb-4 text-center" style={{ color: currentTheme.rejectButton }}>
|
||||
{error}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<TextInput
|
||||
placeholder="Email"
|
||||
className="w-full border rounded p-2 mb-4"
|
||||
placeholder="E-Mail oder Benutzername"
|
||||
placeholderTextColor={currentTheme.textMuted}
|
||||
value={identifier}
|
||||
onChangeText={setIdentifier}
|
||||
autoCapitalize="none"
|
||||
className="w-full rounded-lg p-4 mb-4"
|
||||
style={{
|
||||
backgroundColor: currentTheme.secondaryBg,
|
||||
color: currentTheme.textPrimary,
|
||||
borderWidth: 1,
|
||||
borderColor: currentTheme.borderPrimary,
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
placeholder="Password"
|
||||
placeholder="Passwort"
|
||||
placeholderTextColor={currentTheme.textMuted}
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
secureTextEntry
|
||||
className="w-full border rounded p-2 mb-4"
|
||||
className="w-full rounded-lg p-4 mb-6"
|
||||
style={{
|
||||
backgroundColor: currentTheme.secondaryBg,
|
||||
color: currentTheme.textPrimary,
|
||||
borderWidth: 1,
|
||||
borderColor: currentTheme.borderPrimary,
|
||||
}}
|
||||
/>
|
||||
<Pressable className="bg-blue-500 p-3 rounded w-full">
|
||||
<Text className="text-white text-center">Login</Text>
|
||||
</Pressable>
|
||||
|
||||
<AuthButton
|
||||
title="Anmelden"
|
||||
onPress={handleLogin}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
|
||||
<Link href="/register" asChild>
|
||||
<Pressable>
|
||||
<Text style={{ color: currentTheme.chatBot }}>
|
||||
Noch kein Konto? Registrieren
|
||||
</Text>
|
||||
</Pressable>
|
||||
</Link>
|
||||
</View>
|
||||
</BaseBackground>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user