ekran autoryzacji przerobiony

This commit is contained in:
2025-06-10 21:39:52 +02:00
parent 56877548ed
commit 121d9d1e53
2 changed files with 164 additions and 86 deletions

View File

@@ -1,5 +1,5 @@
import React, {useEffect, useState} from 'react'; import React, {useEffect, useState} from 'react';
import {StyleSheet, ActivityIndicator, SafeAreaView, View, Platform} from 'react-native'; import {StyleSheet, ActivityIndicator, SafeAreaView, View, Platform, KeyboardAvoidingView} from 'react-native';
import {useAuthStore} from '@/store/authStore'; import {useAuthStore} from '@/store/authStore';
import {useRouter} from 'expo-router'; import {useRouter} from 'expo-router';
@@ -7,11 +7,11 @@ import {Box} from "@/components/ui/box"
import {Button, ButtonText, ButtonIcon} from "@/components/ui/button" import {Button, ButtonText, ButtonIcon} from "@/components/ui/button"
import {Center} from "@/components/ui/center" import {Center} from "@/components/ui/center"
import {Heading} from "@/components/ui/heading" import {Heading} from "@/components/ui/heading"
import {Input, InputField} from "@/components/ui/input" import {Input, InputField, InputIcon, InputSlot} from "@/components/ui/input"
import {Text} from "@/components/ui/text" import {Text} from "@/components/ui/text"
import {VStack} from "@/components/ui/vstack" import {VStack} from "@/components/ui/vstack"
import {HStack} from "@/components/ui/hstack" import {HStack} from "@/components/ui/hstack"
import {ArrowRightIcon} from "@/components/ui/icon" import {ArrowRightIcon, EyeIcon, EyeOffIcon} from "@/components/ui/icon"
import {Divider} from '@/components/ui/divider'; import {Divider} from '@/components/ui/divider';
import {Ionicons} from "@expo/vector-icons"; import {Ionicons} from "@expo/vector-icons";
@@ -30,6 +30,8 @@ WebBrowser.maybeCompleteAuthSession();
export default function Login() { export default function Login() {
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [emailError, setEmailError] = useState('');
const [showPassword, setShowPassword] = useState(false)
const {signIn, isLoading, signInWithGoogle} = useAuthStore(); const {signIn, isLoading, signInWithGoogle} = useAuthStore();
const router = useRouter(); const router = useRouter();
@@ -52,6 +54,11 @@ export default function Login() {
return; return;
} }
if (!validateEmail(email)) {
setEmailError('Nieprawidłowy format adresu email');
return;
}
try { try {
await signIn(email, password); await signIn(email, password);
alert(`Zalogowano jako ${email}`); alert(`Zalogowano jako ${email}`);
@@ -69,7 +76,7 @@ export default function Login() {
// const user = await AsyncStorage.getItem("@user"); // const user = await AsyncStorage.getItem("@user");
let user = null; let user = null;
if (!user) { if (!user) {
if(response.type === "success") { if (response.type === "success") {
user = await getUserInfo(response.authentication.accessToken) user = await getUserInfo(response.authentication.accessToken)
await signInWithGoogle(response.authentication.accessToken); await signInWithGoogle(response.authentication.accessToken);
alert(`Zalogowano jako ${user.email}`); alert(`Zalogowano jako ${user.email}`);
@@ -83,7 +90,7 @@ export default function Login() {
}; };
const getUserInfo = async (token) => { const getUserInfo = async (token) => {
if(!token) { if (!token) {
return return
} }
try { try {
@@ -103,6 +110,17 @@ export default function Login() {
} }
} }
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const handleShowPassword = () => {
setShowPassword((showState) => {
return !showState
})
}
if (isLoading) { if (isLoading) {
return ( return (
<View style={styles.container}> <View style={styles.container}>
@@ -112,49 +130,70 @@ export default function Login() {
} }
return ( return (
<SafeAreaView style={styles.container}> <KeyboardAvoidingView
<Center> behavior={Platform.OS === "ios" ? "padding" : "height"}
<Box className="p-5 max-w-96 border border-background-300 rounded-lg"> style={{flex: 1}}
<VStack className="pb-4" space="xs"> keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 0}
<Heading className="leading-[30px]">Logowanie</Heading> >
<Box className="flex flex-row"> <SafeAreaView style={styles.container}>
{/* <Link href="/registration" asChild> */} <Center>
<Button variant="link" size="sm" className="p-0" onPress={() => router.replace("/registration")}> <Box className="p-5 max-w-96 border border-background-300 rounded-lg">
<VStack className="pb-4" space="xs">
<Heading className="leading-[30px]">Logowanie</Heading>
<Box className="flex flex-row">
{/* <Link href="/registration" asChild> */}
<Button variant="link" size="sm" className="p-0"
onPress={() => router.replace("/registration")}>
<ButtonText style={styles.signupbutton}>Nie masz jeszcze konta? Załóz je <ButtonText style={styles.signupbutton}>Nie masz jeszcze konta? Załóz je
tutaj!</ButtonText> tutaj!</ButtonText>
<ButtonIcon className="mr-1" size="md" as={ArrowRightIcon}/> <ButtonIcon className="mr-1" size="md" as={ArrowRightIcon}/>
</Button> </Button>
{/* </Link> */} {/* </Link> */}
</Box> </Box>
</VStack> </VStack>
<VStack space="xl" className="py-2"> <VStack space="xl" className="py-2">
<Input> {emailError ? <Text style={styles.errorText}>{emailError}</Text> : null}
<InputField className="py-2" placeholder="Login" onChangeText={setEmail}/> <Input isRequired={true} isInvalid={!!emailError}>
</Input> <InputField className="py-2" inputMode="email" placeholder="Login"
<Input> onChangeText={(text) => {
<InputField type="password" className="py-2" placeholder="Hasło" setEmail(text);
onChangeText={setPassword}/> if (text && !validateEmail(text)) {
</Input> setEmailError('Nieprawidłowy format adresu email');
</VStack> } else {
<VStack space="lg" className="pt-4"> setEmailError('');
<Button size="sm" onPress={handleInternalLogin}> }
<ButtonText>Zaloguj się</ButtonText> }}
</Button> />
</VStack> </Input>
<Input isRequired={true}>
<InputField type={showPassword ? "text" : "password"} className="py-2"
placeholder="Hasło"
onChangeText={setPassword}/>
<InputSlot className="pr-3" onPress={handleShowPassword}>
<InputIcon as={showPassword ? EyeIcon : EyeOffIcon}/>
</InputSlot>
</Input>
</VStack>
<VStack space="lg" className="pt-4">
<Button size="sm" onPress={handleInternalLogin}>
<ButtonText>Zaloguj się</ButtonText>
</Button>
</VStack>
<HStack alignItems="center" space="sm" className="pt-6 pb-6"> <HStack alignItems="center" space="sm" className="pt-6 pb-6">
<Divider flex={1}/> <Divider flex={1}/>
<Text fontSize="$sm" className="text-gray-300"> <Text fontSize="$sm" className="text-gray-300">
lub lub
</Text> </Text>
<Divider flex={1}/> <Divider flex={1}/>
</HStack> </HStack>
<Button size="sm" onPress={() => promptAsync()}> <Button size="sm" onPress={() => promptAsync()}>
<Ionicons name="logo-google" color="#fff"/> <Ionicons name="logo-google" color="#fff"/>
</Button> </Button>
</Box> </Box>
</Center> </Center>
</SafeAreaView> </SafeAreaView>
</KeyboardAvoidingView>
); );
} }
@@ -173,7 +212,7 @@ const styles = StyleSheet.create({
}, },
errorText: { errorText: {
color: 'red', color: 'red',
marginBottom: 10, fontSize: 12,
}, },
signupbutton: { signupbutton: {
fontWeight: '300', fontWeight: '300',

View File

@@ -1,22 +1,24 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import {StyleSheet, ActivityIndicator, SafeAreaView, View} from 'react-native'; import {StyleSheet, ActivityIndicator, SafeAreaView, View, Platform, KeyboardAvoidingView} from 'react-native';
import {useAuthStore} from '@/store/authStore'; import {useAuthStore} from '@/store/authStore';
import {useRouter} from 'expo-router'; import {useRouter} from 'expo-router';
import {Box} from "@/components/ui/box" import {Box} from "@/components/ui/box"
import {Button, ButtonText,ButtonIcon} from "@/components/ui/button" import {Button, ButtonText, ButtonIcon} from "@/components/ui/button"
import {ArrowRightIcon} from "@/components/ui/icon" import {ArrowRightIcon, EyeIcon, EyeOffIcon} from "@/components/ui/icon"
import {Center} from "@/components/ui/center" import {Center} from "@/components/ui/center"
import {Heading} from "@/components/ui/heading" import {Heading} from "@/components/ui/heading"
import {Input, InputField} from "@/components/ui/input" import {Input, InputField, InputIcon, InputSlot} from "@/components/ui/input"
import {VStack} from "@/components/ui/vstack" import {VStack} from "@/components/ui/vstack"
import {Link} from "expo-router" import {Text} from "@/components/ui/text";
export default function Registration() { export default function Registration() {
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [firstName, setFirstName] = useState(''); const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState(''); const [lastName, setLastName] = useState('');
const [emailError, setEmailError] = useState('');
const [showPassword, setShowPassword] = useState(false)
const {signUp, isLoading} = useAuthStore(); const {signUp, isLoading} = useAuthStore();
const router = useRouter(); const router = useRouter();
@@ -26,6 +28,11 @@ export default function Registration() {
return; return;
} }
if (!validateEmail(email)) {
setEmailError('Nieprawidłowy format adresu email');
return;
}
try { try {
await signUp({email, password, firstName, lastName}); await signUp({email, password, firstName, lastName});
alert(`Zalogowano jako ${email}`); alert(`Zalogowano jako ${email}`);
@@ -35,6 +42,17 @@ export default function Registration() {
} }
} }
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const handleShowPassword = () => {
setShowPassword((showState) => {
return !showState
})
}
if (isLoading) { if (isLoading) {
return ( return (
<View style={styles.container}> <View style={styles.container}>
@@ -44,45 +62,66 @@ export default function Registration() {
} }
return ( return (
<SafeAreaView style={styles.container}> <KeyboardAvoidingView
<Center> behavior={Platform.OS === "ios" ? "padding" : "height"}
style={{flex: 1}}
<Box className="p-5 w-[80%] border border-background-300 rounded-lg"> keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 0}
<VStack className="pb-4" space="xs"> >
<Heading className="leading-[30px]">Rejestracja</Heading> <SafeAreaView style={styles.container}>
<Box className="flex flex-row"> <Center>
{/* <Link href="/login" asChild> */}
<Button variant="link" size="sm" className="p-0" onPress={() => router.replace("/login")}> <Box className="p-5 w-[80%] border border-background-300 rounded-lg">
<VStack className="pb-4" space="xs">
<Heading className="leading-[30px]">Rejestracja</Heading>
<Box className="flex flex-row">
{/* <Link href="/login" asChild> */}
<Button variant="link" size="sm" className="p-0"
onPress={() => router.replace("/login")}>
<ButtonText style={styles.signupbutton}>Masz już konto? Zaloguj się!</ButtonText> <ButtonText style={styles.signupbutton}>Masz już konto? Zaloguj się!</ButtonText>
<ButtonIcon className="mr-1" size="md" as={ArrowRightIcon}/> <ButtonIcon className="mr-1" size="md" as={ArrowRightIcon}/>
</Button> </Button>
{/* </Link> */} {/* </Link> */}
</Box> </Box>
</VStack> </VStack>
<VStack space="xl" className="py-2"> <VStack space="xl" className="py-2">
<Input> {emailError ? <Text className="m-0 color-red-600">{emailError}</Text> : null}
<InputField type="email" className="py-2" placeholder="E-mail" onChangeText={setEmail}/> <Input isRequired={true}>
</Input> <InputField type="email" className="py-2" placeholder="E-mail"
<Input> onChangeText={(text) => {
<InputField className="py-2" placeholder="Imię" onChangeText={setFirstName}/> setEmail(text);
</Input> if (text && !validateEmail(text)) {
<Input> setEmailError('Nieprawidłowy format adresu email');
<InputField className="py-2" placeholder="Nazwisko" onChangeText={setLastName}/> } else {
</Input> setEmailError('');
<Input> }
<InputField type="password" className="py-2" placeholder="Hasło" }}
onChangeText={setPassword}/> />
</Input> </Input>
</VStack> <Input isRequired={true}>
<VStack space="lg" className="pt-4"> <InputField className="py-2" placeholder="Imię" onChangeText={setFirstName}/>
<Button size="sm" onPress={handleInternalRegistration}> </Input>
<ButtonText>Zarejestruj się</ButtonText> <Input isRequired={true}>
</Button> <InputField className="py-2" placeholder="Nazwisko" onChangeText={setLastName}/>
</VStack> </Input>
</Box> <Input isRequired={true}>
<InputField type={showPassword ? "text" : "password"} className="py-2"
</Center> placeholder="Hasło"
</SafeAreaView> onChangeText={setPassword}/>
<InputSlot className="pr-3" onPress={handleShowPassword}>
<InputIcon as={showPassword ? EyeIcon : EyeOffIcon}/>
</InputSlot>
</Input>
</VStack>
<VStack space="lg" className="pt-4">
<Button size="sm" onPress={handleInternalRegistration}>
<ButtonText>Zarejestruj się</ButtonText>
</Button>
</VStack>
</Box>
</Center>
</SafeAreaView>
</KeyboardAvoidingView>
); );
} }
@@ -105,7 +144,7 @@ const styles = StyleSheet.create({
color: 'red', color: 'red',
marginBottom: 10, marginBottom: 10,
}, },
signupbutton: { signupbutton: {
fontWeight: '300', fontWeight: '300',
textAlign: 'left', textAlign: 'left',
}, },