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:
41
apps/client/src/components/AuthButton.tsx
Normal file
41
apps/client/src/components/AuthButton.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Pressable, Text, ActivityIndicator } from "react-native";
|
||||
import currentTheme from "../Themes";
|
||||
|
||||
interface AuthButtonProps {
|
||||
title: string;
|
||||
onPress: () => void;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const AuthButton = ({ title, onPress, isLoading = false }: AuthButtonProps) => {
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
disabled={isLoading}
|
||||
className="w-full rounded-lg p-4 mb-4 border-4"
|
||||
style={{
|
||||
backgroundColor: isLoading
|
||||
? currentTheme.disabledButton
|
||||
: currentTheme.chatBot,
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 3.84,
|
||||
elevation: 5,
|
||||
}}
|
||||
>
|
||||
{isLoading ? (
|
||||
<ActivityIndicator color={currentTheme.buttonText} />
|
||||
) : (
|
||||
<Text
|
||||
className="text-center font-semibold text-lg"
|
||||
style={{ color: currentTheme.buttonText }}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
)}
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthButton;
|
||||
@@ -1,12 +1,20 @@
|
||||
import { View } from "react-native";
|
||||
import { View, Pressable } from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { router } from "expo-router";
|
||||
import currentTheme from "../Themes";
|
||||
import { ReactNode } from "react";
|
||||
import { AuthService } from "../services";
|
||||
|
||||
type HeaderProps = {
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
await AuthService.logout();
|
||||
router.replace("/login");
|
||||
};
|
||||
|
||||
const Header = (props: HeaderProps) => {
|
||||
return (
|
||||
<View>
|
||||
@@ -17,6 +25,13 @@ const Header = (props: HeaderProps) => {
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
<Pressable
|
||||
onPress={handleLogout}
|
||||
className="absolute right-1 top-0 p-2"
|
||||
hitSlop={8}
|
||||
>
|
||||
<Ionicons name="log-out-outline" size={24} color={currentTheme.primeFg} />
|
||||
</Pressable>
|
||||
</View>
|
||||
<View
|
||||
className="h-2 bg-black"
|
||||
|
||||
Reference in New Issue
Block a user