diff options
Diffstat (limited to 'screens')
| -rw-r--r-- | screens/discover.js | 12 | ||||
| -rw-r--r-- | screens/home.js | 324 | ||||
| -rw-r--r-- | screens/modal.js | 34 | ||||
| -rw-r--r-- | screens/passwordRecovery.js | 108 | ||||
| -rw-r--r-- | screens/profile.js | 42 | ||||
| -rw-r--r-- | screens/signin.js | 356 | ||||
| -rw-r--r-- | screens/signup.js | 402 | ||||
| -rw-r--r-- | screens/topRated.js | 12 |
8 files changed, 645 insertions, 645 deletions
diff --git a/screens/discover.js b/screens/discover.js index 0213eed..924308a 100644 --- a/screens/discover.js +++ b/screens/discover.js @@ -1,6 +1,6 @@ -import {Text} from 'react-native'; -const Discover = () => { - return <Text>Discover</Text>; -}; - -export default Discover; +import {Text} from 'react-native';
+const Discover = () => {
+ return <Text>Discover</Text>;
+};
+
+export default Discover;
diff --git a/screens/home.js b/screens/home.js index 184bbf9..9d5addc 100644 --- a/screens/home.js +++ b/screens/home.js @@ -1,162 +1,162 @@ -import {useCallback, useEffect, useState} from 'react'; -import { - ImageBackground, - Platform, - Pressable, - SafeAreaView, - ScrollView, - Text, - TextInput, - View, -} from 'react-native'; -import tw from 'twrnc'; -import {useDeviceContext} from 'twrnc'; -import requests from '../lib/requests'; -import PreviewCard from '../components/PreviewCard'; -import Modal from './modal'; -//ICONS -import {TvIcon} from 'react-native-heroicons/outline'; -import {MagnifyingGlassIcon} from 'react-native-heroicons/outline'; -import {ChevronDownIcon} from 'react-native-heroicons/solid'; -import {UserIcon} from 'react-native-heroicons/outline'; -import ImageColors from 'react-native-image-colors'; -import LinearGradient from 'react-native-linear-gradient'; - -const Home = ({navigation}) => { - useDeviceContext(tw); - const imgAssets = process.env.IMG_ASSETS; - const [heroMovie, setHeroMovie] = useState(); - const [heroMovieColor, setHeroMovieColor] = useState(); - const [topRatedMovies, setTopRatedMovies] = useState(); - const [isModalVisible, setModalVisible] = useState(false); - const [modalContent, setModalContent] = useState(); - - const toggleModal = (movie) => { - setModalVisible(!isModalVisible); - setModalContent(movie); -}; - - useEffect(() => { - fetch(`https://api.themoviedb.org/3/movie/top_rated?api_key=f247ff737ec8062f3b5e027789eab748&language=en`) - .then(res => res.json()) - .then(data => { - setHeroMovie(data.results[1]); - setTopRatedMovies(data.results) - }); - }, []); - - useEffect(() => { - const fetchColor = async () => { - const data = await ImageColors.getColors( - `https://image.tmdb.org/t/p/original${heroMovie?.poster_path}`, - { - fallback: '#000000', - cache: true, - key: 'unique_key', - }, - ).then(data => { - if (Platform.OS === 'ios') { - setHeroMovieColor(data.primary); - } else { - setHeroMovieColor(data.average); - } - }); - } - if (heroMovie?.poster_path != undefined) { - fetchColor() - .catch(e => { - console.log(e) - return e - }); - } - }, [heroMovie]) - - return ( - <ScrollView style={tw`bg-black flex-1`}> - <SafeAreaView> - <View - style={tw`relative z-10 flex flex-row justify-between items-center px-6 gap-4 android:pt-4`} - > - <Text style={tw`android:hidden text-white font-bold text-xl`}> - For Matias - </Text> - <View style={tw`ios:hidden flex-6 relative`}> - <MagnifyingGlassIcon - style={tw`absolute z-10 left-2 top-2.5`} - color={tw.color('gray-300')} - size={20} - /> - <TextInput - style={tw`pr-4 pl-8 h-10 font-medium bg-white rounded w-full text-white`} - autoCorrect={false} - autoCapitalize={'none'} - placeholderTextColor={tw.color('text-gray-400')} - placeholder={'Search'} - /> - </View> - <View style={tw`flex android:flex-1 flex-row items-center gap-4`}> - <MagnifyingGlassIcon - style={tw`android:hidden`} - color={tw.color('white')} - size={20} - /> - <TvIcon color={tw.color('white')} size={20} /> - <Pressable - onPress={() => navigation.navigate('Profile')} - style={tw`rounded bg-white/20 w-6 h-6 flex items-center justify-center`} - > - <UserIcon color={tw.color('white')} size={16} /> - </Pressable> - </View> - </View> - <View style={tw`flex flex-row px-6 pt-3 gap-4 relative z-10`}> - <Pressable style={tw`border border-white/30 rounded-full px-2 py-1`}> - <Text style={tw`text-white`}>TV Shows</Text> - </Pressable> - <Pressable style={tw`border border-white/30 rounded-full px-2 py-1`}> - <Text style={tw`text-white`}>Movies</Text> - </Pressable> - <Pressable - style={tw`border border-white/30 rounded-full px-2 py-1 flex flex-row items-center gap-1`} - > - <Text style={tw`text-white`}>Categories</Text> - <ChevronDownIcon color={tw.color('gray-300')} size={16} /> - </Pressable> - </View> - <View style={tw`p-6 relative z-10`}> - <ImageBackground - source={{uri: `https://image.tmdb.org/t/p/original${heroMovie?.poster_path}`}} - resizeMode={'cover'} - style={tw`rounded-xl bg-white h-[500px] border border-white/30 overflow-hidden`} - ></ImageBackground> - </View> - {heroMovieColor !== undefined && ( - <LinearGradient - style={tw`absolute top-0 left-0 w-screen h-screen z-0`} - colors={[`${heroMovieColor}`, tw.color('black')]} - /> - )} - <View> - <Text style={tw`text-white mx-8`}>Popular on Netflix</Text> - <ScrollView - contentContainerStyle={tw`p-3 flex gap-3`} - horizontal - showsHorizontalScrollIndicator={false} - > - { - topRatedMovies?.map((movie, index) => ( - <Pressable key={index} onPress={() => toggleModal(movie)}> - <PreviewCard key={index} movie={movie} /> - </Pressable> - ))} - </ScrollView> - </View> - {isModalVisible && ( - <Modal closeModal={toggleModal} movie={modalContent}/> - )} - </SafeAreaView> - </ScrollView> - ); -}; - -export default Home; +import {useCallback, useEffect, useState} from 'react';
+import {
+ ImageBackground,
+ Platform,
+ Pressable,
+ SafeAreaView,
+ ScrollView,
+ Text,
+ TextInput,
+ View,
+} from 'react-native';
+import tw from 'twrnc';
+import {useDeviceContext} from 'twrnc';
+import requests from '../lib/requests';
+import PreviewCard from '../components/PreviewCard';
+import Modal from './modal';
+//ICONS
+import {TvIcon} from 'react-native-heroicons/outline';
+import {MagnifyingGlassIcon} from 'react-native-heroicons/outline';
+import {ChevronDownIcon} from 'react-native-heroicons/solid';
+import {UserIcon} from 'react-native-heroicons/outline';
+import ImageColors from 'react-native-image-colors';
+import LinearGradient from 'react-native-linear-gradient';
+
+const Home = ({navigation}) => {
+ useDeviceContext(tw);
+ const imgAssets = process.env.IMG_ASSETS;
+ const [heroMovie, setHeroMovie] = useState();
+ const [heroMovieColor, setHeroMovieColor] = useState();
+ const [topRatedMovies, setTopRatedMovies] = useState();
+ const [isModalVisible, setModalVisible] = useState(false);
+ const [modalContent, setModalContent] = useState();
+
+ const toggleModal = (movie) => {
+ setModalVisible(!isModalVisible);
+ setModalContent(movie);
+};
+
+ useEffect(() => {
+ fetch(`https://api.themoviedb.org/3/movie/top_rated?api_key=f247ff737ec8062f3b5e027789eab748&language=en`)
+ .then(res => res.json())
+ .then(data => {
+ setHeroMovie(data.results[1]);
+ setTopRatedMovies(data.results)
+ });
+ }, []);
+
+ useEffect(() => {
+ const fetchColor = async () => {
+ const data = await ImageColors.getColors(
+ `https://image.tmdb.org/t/p/original${heroMovie?.poster_path}`,
+ {
+ fallback: '#000000',
+ cache: true,
+ key: 'unique_key',
+ },
+ ).then(data => {
+ if (Platform.OS === 'ios') {
+ setHeroMovieColor(data.primary);
+ } else {
+ setHeroMovieColor(data.average);
+ }
+ });
+ }
+ if (heroMovie?.poster_path != undefined) {
+ fetchColor()
+ .catch(e => {
+ console.log(e)
+ return e
+ });
+ }
+ }, [heroMovie])
+
+ return (
+ <ScrollView style={tw`bg-black flex-1`}>
+ <SafeAreaView>
+ <View
+ style={tw`relative z-10 flex flex-row justify-between items-center px-6 gap-4 android:pt-4`}
+ >
+ <Text style={tw`android:hidden text-white font-bold text-xl`}>
+ For Matias
+ </Text>
+ <View style={tw`ios:hidden flex-6 relative`}>
+ <MagnifyingGlassIcon
+ style={tw`absolute z-10 left-2 top-2.5`}
+ color={tw.color('gray-300')}
+ size={20}
+ />
+ <TextInput
+ style={tw`pr-4 pl-8 h-10 font-medium bg-white rounded w-full text-white`}
+ autoCorrect={false}
+ autoCapitalize={'none'}
+ placeholderTextColor={tw.color('text-gray-400')}
+ placeholder={'Search'}
+ />
+ </View>
+ <View style={tw`flex android:flex-1 flex-row items-center gap-4`}>
+ <MagnifyingGlassIcon
+ style={tw`android:hidden`}
+ color={tw.color('white')}
+ size={20}
+ />
+ <TvIcon color={tw.color('white')} size={20} />
+ <Pressable
+ onPress={() => navigation.navigate('Profile')}
+ style={tw`rounded bg-white/20 w-6 h-6 flex items-center justify-center`}
+ >
+ <UserIcon color={tw.color('white')} size={16} />
+ </Pressable>
+ </View>
+ </View>
+ <View style={tw`flex flex-row px-6 pt-3 gap-4 relative z-10`}>
+ <Pressable style={tw`border border-white/30 rounded-full px-2 py-1`}>
+ <Text style={tw`text-white`}>TV Shows</Text>
+ </Pressable>
+ <Pressable style={tw`border border-white/30 rounded-full px-2 py-1`}>
+ <Text style={tw`text-white`}>Movies</Text>
+ </Pressable>
+ <Pressable
+ style={tw`border border-white/30 rounded-full px-2 py-1 flex flex-row items-center gap-1`}
+ >
+ <Text style={tw`text-white`}>Categories</Text>
+ <ChevronDownIcon color={tw.color('gray-300')} size={16} />
+ </Pressable>
+ </View>
+ <View style={tw`p-6 relative z-10`}>
+ <ImageBackground
+ source={{uri: `https://image.tmdb.org/t/p/original${heroMovie?.poster_path}`}}
+ resizeMode={'cover'}
+ style={tw`rounded-xl bg-white h-[500px] border border-white/30 overflow-hidden`}
+ ></ImageBackground>
+ </View>
+ {heroMovieColor !== undefined && (
+ <LinearGradient
+ style={tw`absolute top-0 left-0 w-screen h-screen z-0`}
+ colors={[`${heroMovieColor}`, tw.color('black')]}
+ />
+ )}
+ <View>
+ <Text style={tw`text-white mx-8`}>Popular on Netflix</Text>
+ <ScrollView
+ contentContainerStyle={tw`p-3 flex gap-3`}
+ horizontal
+ showsHorizontalScrollIndicator={false}
+ >
+ {
+ topRatedMovies?.map((movie, index) => (
+ <Pressable key={index} onPress={() => toggleModal(movie)}>
+ <PreviewCard key={index} movie={movie} />
+ </Pressable>
+ ))}
+ </ScrollView>
+ </View>
+ {isModalVisible && (
+ <Modal closeModal={toggleModal} movie={modalContent}/>
+ )}
+ </SafeAreaView>
+ </ScrollView>
+ );
+};
+
+export default Home;
diff --git a/screens/modal.js b/screens/modal.js index 43181e4..1d51891 100644 --- a/screens/modal.js +++ b/screens/modal.js @@ -1,18 +1,18 @@ -import { Pressable, SafeAreaView, Text, View } from 'react-native'; -import tw from 'twrnc'; -import PreviewCard from '../components/PreviewCard'; - -const Modal = ({ closeModal, movie }) => { - return ( - <View style={tw`z-100 absolute top-0 left-0 px-12 py-30`}> - <View style={tw`h-120 w-80 bg-red-500 flex items-center justify-center`}> - <Text style={tw`text-xl text-black`}>{movie?.original_name || movie?.original_title}</Text> - <Pressable onPress={closeModal}> - <Text style={tw`text-xl text-black`}>Dismiss</Text> - </Pressable> - </View> - </View> - ); -}; - +import { Pressable, SafeAreaView, Text, View } from 'react-native';
+import tw from 'twrnc';
+import PreviewCard from '../components/PreviewCard';
+
+const Modal = ({ closeModal, movie }) => {
+ return (
+ <View style={tw`z-100 absolute top-0 left-0 px-12 py-30`}>
+ <View style={tw`h-120 w-80 bg-red-500 flex items-center justify-center`}>
+ <Text style={tw`text-xl text-black`}>{movie?.original_name || movie?.original_title}</Text>
+ <Pressable onPress={closeModal}>
+ <Text style={tw`text-xl text-black`}>Dismiss</Text>
+ </Pressable>
+ </View>
+ </View>
+ );
+};
+
export default Modal;
\ No newline at end of file diff --git a/screens/passwordRecovery.js b/screens/passwordRecovery.js index 61a5f10..94d00f2 100644 --- a/screens/passwordRecovery.js +++ b/screens/passwordRecovery.js @@ -1,54 +1,54 @@ -import { - Keyboard, - KeyboardAvoidingView, - Platform, - Pressable, - SafeAreaView, - Text, - TextInput, - TouchableWithoutFeedback, - View, -} from 'react-native'; - -import tw from 'twrnc'; - -import Logo from '../static/images/netflix-logo.svg'; - -const PasswordRecovery = ({navigation}) => { - return ( - <SafeAreaView style={tw`bg-black flex-1`}> - <TouchableWithoutFeedback - onPress={() => { - Keyboard.dismiss(); - }} - > - <KeyboardAvoidingView - behavior={Platform.OS === 'ios' ? 'padding' : 'height'} - style={tw`flex-1`} - > - <View style={tw`py-6 px-8 flex items-center justify-center`}> - </View> - <View style={tw`flex-1 items-center justify-center px-12`}> - <Text style={tw`text-white text-2xl mb-12 self-start`}>Recuperar contraseña</Text> - <TextInput - style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-8`} - placeholderTextColor={tw.color('text-white/20')} - placeholder={'Email'} - autoCorrect={false} - autoCapitalize={'none'} - keyboardType={'email-address'} - /> - <Pressable style={tw`mb-12`}> - <Text style={tw`text-white/40 text-xl`}>Recuperar contraseña</Text> - </Pressable> - <Pressable onPress={() => navigation.goBack()} style={tw`mb-16`}> - <Text style={tw`text-white`}>Volver</Text> - </Pressable> - </View> - </KeyboardAvoidingView> - </TouchableWithoutFeedback> - </SafeAreaView> - ); -}; - -export default PasswordRecovery; +import {
+ Keyboard,
+ KeyboardAvoidingView,
+ Platform,
+ Pressable,
+ SafeAreaView,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
+
+import tw from 'twrnc';
+
+import Logo from '../static/images/netflix-logo.svg';
+
+const PasswordRecovery = ({navigation}) => {
+ return (
+ <SafeAreaView style={tw`bg-black flex-1`}>
+ <TouchableWithoutFeedback
+ onPress={() => {
+ Keyboard.dismiss();
+ }}
+ >
+ <KeyboardAvoidingView
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ style={tw`flex-1`}
+ >
+ <View style={tw`py-6 px-8 flex items-center justify-center`}>
+ </View>
+ <View style={tw`flex-1 items-center justify-center px-12`}>
+ <Text style={tw`text-white text-2xl mb-12 self-start`}>Recuperar contraseña</Text>
+ <TextInput
+ style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-8`}
+ placeholderTextColor={tw.color('text-white/20')}
+ placeholder={'Email'}
+ autoCorrect={false}
+ autoCapitalize={'none'}
+ keyboardType={'email-address'}
+ />
+ <Pressable style={tw`mb-12`}>
+ <Text style={tw`text-white/40 text-xl`}>Recuperar contraseña</Text>
+ </Pressable>
+ <Pressable onPress={() => navigation.goBack()} style={tw`mb-16`}>
+ <Text style={tw`text-white`}>Volver</Text>
+ </Pressable>
+ </View>
+ </KeyboardAvoidingView>
+ </TouchableWithoutFeedback>
+ </SafeAreaView>
+ );
+};
+
+export default PasswordRecovery;
diff --git a/screens/profile.js b/screens/profile.js index 0bd1cd9..53f71f0 100644 --- a/screens/profile.js +++ b/screens/profile.js @@ -1,21 +1,21 @@ -import React, { Component } from 'react'; -import { View, Text , Pressable} from 'react-native'; -import tw from 'twrnc' -import auth from '@react-native-firebase/auth'; - - -const Profile = () => { - return ( - <View style={tw`flex flex-1 items-center justify-center`}> - <Pressable - style={tw`bg-red-500`} - onPress={() => auth().signOut()} - > - <Text> Logout </Text> - </Pressable> - </View> - ); -} - - -export default Profile; +import React, { Component } from 'react';
+import { View, Text , Pressable} from 'react-native';
+import tw from 'twrnc'
+import auth from '@react-native-firebase/auth';
+
+
+const Profile = () => {
+ return (
+ <View style={tw`flex flex-1 items-center justify-center`}>
+ <Pressable
+ style={tw`bg-red-500`}
+ onPress={() => auth().signOut()}
+ >
+ <Text> Logout </Text>
+ </Pressable>
+ </View>
+ );
+}
+
+
+export default Profile;
diff --git a/screens/signin.js b/screens/signin.js index 49d328d..85a179e 100644 --- a/screens/signin.js +++ b/screens/signin.js @@ -1,178 +1,178 @@ -import {useEffect, useState} from 'react'; -import { - Image, - Keyboard, - KeyboardAvoidingView, - Platform, - Pressable, - SafeAreaView, - Text, - TextInput, - TouchableWithoutFeedback, - View, -} from 'react-native'; - -import tw from 'twrnc'; - -import {EyeIcon} from 'react-native-heroicons/outline'; -import {EyeSlashIcon} from 'react-native-heroicons/outline'; -import auth from '@react-native-firebase/auth'; - -const SignIn = ({navigation}) => { - - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [isValidEmail, setIsValidEmail] = useState(false); - const [isValidPassword, setIsValidPassword] = useState(false); - const [isPasswordVisible, setIsPasswordVisible] = useState(true); - - useEffect(() => { - debounce(emailValidation()); - }, [email]); - - useEffect(() => { - debounce(passwordValidation()); - }, [password]); - - const emailValidation = () => { - const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; - if (!email || emailRegex.test(email) === false) { - setIsValidEmail(false); - return false; - } - setIsValidEmail(true); - return true; - }; - - const passwordValidation = () => { - const passwordRegex = /^(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+])[A-Za-z\d!@#$%^&*()_+]{8,}$/i; - - - if (!password || passwordRegex.test(password) === false) { - setIsValidPassword(false) - return false - } - setIsValidPassword(true) - return true - } - - // Utility FN · Mover a carpeta utils/utils.js - const debounce = fn => { - let id = null; - - return (...args) => { - if (id) { - clearTimeout(id); - } - id = setTimeout(() => { - fn(...args); - id = null; - }, 300); - }; - }; - - const loginUser = () => { - if (isValidEmail && isValidPassword) { - auth() - .signInWithEmailAndPassword(email, password) - .then(() => { - console.log('User signed in successfully!'); - // Navigate to the home screen or other desired screen - }) - .catch(error => { - console.error(error); - // Display an error message to the user - }); - } -}; - - return ( - <SafeAreaView style={tw`bg-black flex-1`}> - <TouchableWithoutFeedback - onPress={() => { - Keyboard.dismiss(); - }} - > - <KeyboardAvoidingView - behavior={Platform.OS === 'ios' ? 'padding' : 'height'} - style={tw`flex-1`} - > - <View style={tw`py-6 px-8 flex items-center justify-center`}> - <Image - source={require('../static/images/Vector.png')} - style={{ width: 140, height: 37 }} - /> - </View> - <View style={tw`flex-1 items-center justify-center px-12`}> - <Text style={tw`text-white text-2xl mb-12 self-start`}> - ingresar - </Text> - <TextInput - style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${(!isValidEmail && email !== '') ? 'border border-red-500' : ''}`} - placeholderTextColor={tw.color('text-white/20')} - placeholder={'Email'} - value={email} - onChangeText={textInput => { - setEmail(textInput); - }} - autoCapitalize={'none'} - keyboardType={'email-address'} - /> - <Text - style={tw`text-red-500 self-start mb-6 ${ - (isValidEmail || email === '') && 'opacity-0' - }`} - > - email incorrecto. - </Text> - <View style={tw`relative flex flex-row`}> - <Pressable onPress={() => { - setIsPasswordVisible(!isPasswordVisible) - }} style={tw`absolute top-3 right-3 z-10`}> - {!isPasswordVisible? ( - <EyeSlashIcon style={tw`w-6 h-6 text-white/40`} /> - ) : ( - <EyeIcon style={tw`w-6 h-6 text-white/40`} /> - )} - </Pressable> - <TextInput - style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${(!isValidPassword && password !== '') ? 'border border-red-500' : ''}`} - placeholderTextColor={tw.color('text-white/20')} - placeholder={'Contraseña'} - value={password} - onChangeText={passwordInput => { - setPassword(passwordInput) - }} - secureTextEntry={!isPasswordVisible} - /> - </View> - <Text - style={tw`text-red-500 self-start mb-6 ${ - (isValidPassword || password === '') && 'opacity-0' - }`} - > - debe contener a-b-0-! - </Text> - <Pressable style={tw`mb-12`} onPress={loginUser}> - <Text style={tw`text-white/40 text-xl`}>ingresar</Text> - </Pressable> - <Pressable - onPress={() => navigation.navigate('PasswordRecovery')} - style={tw`mb-16`} - > - <Text style={tw`text-white`}>¿olvidaste tu contraseña?</Text> - </Pressable> - <View style={tw`flex flex-row items-center`}> - <Text style={tw`text-white`}>¿no tienes una cuenta? </Text> - <Pressable onPress={() => navigation.navigate('SignUp')}> - <Text style={tw`text-red-500 font-bold`}>registrate</Text> - </Pressable> - </View> - </View> - </KeyboardAvoidingView> - </TouchableWithoutFeedback> - </SafeAreaView> - ); -}; - -export default SignIn; +import {useEffect, useState} from 'react';
+import {
+ Image,
+ Keyboard,
+ KeyboardAvoidingView,
+ Platform,
+ Pressable,
+ SafeAreaView,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
+
+import tw from 'twrnc';
+
+import {EyeIcon} from 'react-native-heroicons/outline';
+import {EyeSlashIcon} from 'react-native-heroicons/outline';
+import auth from '@react-native-firebase/auth';
+
+const SignIn = ({navigation}) => {
+
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [isValidEmail, setIsValidEmail] = useState(false);
+ const [isValidPassword, setIsValidPassword] = useState(false);
+ const [isPasswordVisible, setIsPasswordVisible] = useState(true);
+
+ useEffect(() => {
+ debounce(emailValidation());
+ }, [email]);
+
+ useEffect(() => {
+ debounce(passwordValidation());
+ }, [password]);
+
+ const emailValidation = () => {
+ const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
+ if (!email || emailRegex.test(email) === false) {
+ setIsValidEmail(false);
+ return false;
+ }
+ setIsValidEmail(true);
+ return true;
+ };
+
+ const passwordValidation = () => {
+ const passwordRegex = /^(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+])[A-Za-z\d!@#$%^&*()_+]{8,}$/i;
+
+
+ if (!password || passwordRegex.test(password) === false) {
+ setIsValidPassword(false)
+ return false
+ }
+ setIsValidPassword(true)
+ return true
+ }
+
+ // Utility FN · Mover a carpeta utils/utils.js
+ const debounce = fn => {
+ let id = null;
+
+ return (...args) => {
+ if (id) {
+ clearTimeout(id);
+ }
+ id = setTimeout(() => {
+ fn(...args);
+ id = null;
+ }, 300);
+ };
+ };
+
+ const loginUser = () => {
+ if (isValidEmail && isValidPassword) {
+ auth()
+ .signInWithEmailAndPassword(email, password)
+ .then(() => {
+ console.log('User signed in successfully!');
+ // Navigate to the home screen or other desired screen
+ })
+ .catch(error => {
+ console.error(error);
+ // Display an error message to the user
+ });
+ }
+};
+
+ return (
+ <SafeAreaView style={tw`bg-black flex-1`}>
+ <TouchableWithoutFeedback
+ onPress={() => {
+ Keyboard.dismiss();
+ }}
+ >
+ <KeyboardAvoidingView
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ style={tw`flex-1`}
+ >
+ <View style={tw`py-6 px-8 flex items-center justify-center`}>
+ <Image
+ source={require('../static/images/Vector.png')}
+ style={{ width: 140, height: 37 }}
+ />
+ </View>
+ <View style={tw`flex-1 items-center justify-center px-12`}>
+ <Text style={tw`text-white text-2xl mb-12 self-start`}>
+ ingresar
+ </Text>
+ <TextInput
+ style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${(!isValidEmail && email !== '') ? 'border border-red-500' : ''}`}
+ placeholderTextColor={tw.color('text-white/20')}
+ placeholder={'Email'}
+ value={email}
+ onChangeText={textInput => {
+ setEmail(textInput);
+ }}
+ autoCapitalize={'none'}
+ keyboardType={'email-address'}
+ />
+ <Text
+ style={tw`text-red-500 self-start mb-6 ${
+ (isValidEmail || email === '') && 'opacity-0'
+ }`}
+ >
+ email incorrecto.
+ </Text>
+ <View style={tw`relative flex flex-row`}>
+ <Pressable onPress={() => {
+ setIsPasswordVisible(!isPasswordVisible)
+ }} style={tw`absolute top-3 right-3 z-10`}>
+ {!isPasswordVisible? (
+ <EyeSlashIcon style={tw`w-6 h-6 text-white/40`} />
+ ) : (
+ <EyeIcon style={tw`w-6 h-6 text-white/40`} />
+ )}
+ </Pressable>
+ <TextInput
+ style={tw`h-11 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${(!isValidPassword && password !== '') ? 'border border-red-500' : ''}`}
+ placeholderTextColor={tw.color('text-white/20')}
+ placeholder={'Contraseña'}
+ value={password}
+ onChangeText={passwordInput => {
+ setPassword(passwordInput)
+ }}
+ secureTextEntry={!isPasswordVisible}
+ />
+ </View>
+ <Text
+ style={tw`text-red-500 self-start mb-6 ${
+ (isValidPassword || password === '') && 'opacity-0'
+ }`}
+ >
+ debe contener a-b-0-!
+ </Text>
+ <Pressable style={tw`mb-12`} onPress={loginUser}>
+ <Text style={tw`text-white/40 text-xl`}>ingresar</Text>
+ </Pressable>
+ <Pressable
+ onPress={() => navigation.navigate('PasswordRecovery')}
+ style={tw`mb-16`}
+ >
+ <Text style={tw`text-white`}>¿olvidaste tu contraseña?</Text>
+ </Pressable>
+ <View style={tw`flex flex-row items-center`}>
+ <Text style={tw`text-white`}>¿no tienes una cuenta? </Text>
+ <Pressable onPress={() => navigation.navigate('SignUp')}>
+ <Text style={tw`text-red-500 font-bold`}>registrate</Text>
+ </Pressable>
+ </View>
+ </View>
+ </KeyboardAvoidingView>
+ </TouchableWithoutFeedback>
+ </SafeAreaView>
+ );
+};
+
+export default SignIn;
diff --git a/screens/signup.js b/screens/signup.js index 73edf4f..5f531d3 100644 --- a/screens/signup.js +++ b/screens/signup.js @@ -1,201 +1,201 @@ -import {useEffect, useState} from 'react'; -import { - Keyboard, - KeyboardAvoidingView, - Platform, - Pressable, - SafeAreaView, - Text, - TextInput, - TouchableWithoutFeedback, - View, -} from 'react-native'; - -import auth from '@react-native-firebase/auth'; -import tw from 'twrnc'; -import {useToast} from 'react-native-toast-notifications'; - -import Logo from '../static/images/netflix-logo.svg'; -import {EyeIcon} from 'react-native-heroicons/outline'; -import {EyeSlashIcon} from 'react-native-heroicons/outline'; - -const SignUp = ({navigation}) => { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [isValidEmail, setIsValidEmail] = useState(false); - const [isValidPassword, setIsValidPassword] = useState(false); - const [isPasswordVisible, setIsPasswordVisible] = useState(false); - - const toast = useToast(); - - useEffect(() => { - debounce(emailValidation()); - }, [email]); - - useEffect(() => { - debounce(passwordValidation()); - }, [password]); - - const emailValidation = () => { - const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; - if (!email || emailRegex.test(email) === false) { - setIsValidEmail(false); - return false; - } - setIsValidEmail(true); - return true; - }; - - const passwordValidation = () => { - const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/i; - if (!password || passwordRegex.test(password) === false) { - setIsValidPassword(false); - return false; - } - setIsValidPassword(true); - return true; - }; - - // Utility FN · Mover a carpeta utils/utils.js - const debounce = fn => { - let id = null; - - return (...args) => { - if (id) { - clearTimeout(id); - } - id = setTimeout(() => { - fn(...args); - id = null; - }, 300); - }; - }; - - const registerUser = () => { - if (isValidEmail && isValidPassword) { - auth() - .createUserWithEmailAndPassword(email, password) - .then(() => { - console.log('User account created & signed in!'); - }) - .catch(error => { - if (error.code === 'auth/email-already-in-use') { - console.log('That email address is already in use!'); - toast.show({ - type: 'info', - text1: 'Este email ya existe.', - text2: 'Por favor prueba un diferente.' - }); - toast.show('Este email ya existe', { - type: 'info', - data: { - subtitle: 'Por favor prueba uno diferente.', - }, - }); - console.log('hello') - return error - } - - if (error.code === 'auth/invalid-email') { - console.log('That email address is invalid!'); - return error - } - - console.error(error); - }); - } - }; - - return ( - <SafeAreaView style={tw`bg-black flex-1`}> - <TouchableWithoutFeedback - onPress={() => { - Keyboard.dismiss(); - }} - > - <KeyboardAvoidingView - behavior={Platform.OS === 'ios' ? 'padding' : 'height'} - style={tw`flex-1`} - > - <View style={tw`py-6 px-8 flex items-center justify-center`}> - </View> - <View style={tw`flex-1 items-center justify-center px-12`}> - <Text style={tw`text-white text-2xl mb-12 self-start`}> - Registrate - </Text> - <TextInput - style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${ - !isValidEmail && email !== '' && 'border border-red-500' - }`} - placeholderTextColor={tw.color('text-white/20')} - placeholder={'Email'} - value={email} - onChangeText={textInput => { - setEmail(textInput); - }} - autoCorrect={false} - autoCapitalize={'none'} - keyboardType={'email-address'} - /> - <Text - style={tw`text-red-500 self-start mb-6 ${ - (isValidEmail || email === '') && 'opacity-0' - }`} - > - Email incorrecto. - </Text> - <View style={tw`relative flex flex-row`}> - <Pressable - onPress={() => { - setIsPasswordVisible(!isPasswordVisible); - }} - style={tw`absolute top-3 right-3 z-10`} - > - {!isPasswordVisible ? ( - <EyeSlashIcon style={tw`w-6 h-6 text-white/40`} /> - ) : ( - <EyeIcon style={tw`w-6 h-6 text-white/40`} /> - )} - </Pressable> - <TextInput - style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${ - !isValidPassword && password !== '' && 'border border-red-500' - }`} - placeholderTextColor={tw.color('text-white/20')} - placeholder={'Contraseña'} - value={password} - onChangeText={passwordInput => { - setPassword(passwordInput); - }} - secureTextEntry={!isPasswordVisible} - /> - </View> - <Text - style={tw`text-red-500 self-start mb-6 ${ - (isValidPassword || password === '') && 'opacity-0' - }`} - > - Debe contener A-b-0-! - </Text> - <Pressable - onPress={() => { - registerUser(); - }} - style={tw`mb-12`} - > - <Text style={tw`text-white/40 text-xl`}>Registrate</Text> - </Pressable> - <View style={tw`flex flex-row items-center`}> - <Text style={tw`text-white`}>¿Ya tienes una cuenta? </Text> - <Pressable onPress={() => navigation.navigate('SignIn')}> - <Text style={tw`text-red-500 font-bold`}>Ingresa</Text> - </Pressable> - </View> - </View> - </KeyboardAvoidingView> - </TouchableWithoutFeedback> - </SafeAreaView> - ); -}; - -export default SignUp; +import {useEffect, useState} from 'react';
+import {
+ Keyboard,
+ KeyboardAvoidingView,
+ Platform,
+ Pressable,
+ SafeAreaView,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
+
+import auth from '@react-native-firebase/auth';
+import tw from 'twrnc';
+import {useToast} from 'react-native-toast-notifications';
+
+import Logo from '../static/images/netflix-logo.svg';
+import {EyeIcon} from 'react-native-heroicons/outline';
+import {EyeSlashIcon} from 'react-native-heroicons/outline';
+
+const SignUp = ({navigation}) => {
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [isValidEmail, setIsValidEmail] = useState(false);
+ const [isValidPassword, setIsValidPassword] = useState(false);
+ const [isPasswordVisible, setIsPasswordVisible] = useState(false);
+
+ const toast = useToast();
+
+ useEffect(() => {
+ debounce(emailValidation());
+ }, [email]);
+
+ useEffect(() => {
+ debounce(passwordValidation());
+ }, [password]);
+
+ const emailValidation = () => {
+ const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
+ if (!email || emailRegex.test(email) === false) {
+ setIsValidEmail(false);
+ return false;
+ }
+ setIsValidEmail(true);
+ return true;
+ };
+
+ const passwordValidation = () => {
+ const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/i;
+ if (!password || passwordRegex.test(password) === false) {
+ setIsValidPassword(false);
+ return false;
+ }
+ setIsValidPassword(true);
+ return true;
+ };
+
+ // Utility FN · Mover a carpeta utils/utils.js
+ const debounce = fn => {
+ let id = null;
+
+ return (...args) => {
+ if (id) {
+ clearTimeout(id);
+ }
+ id = setTimeout(() => {
+ fn(...args);
+ id = null;
+ }, 300);
+ };
+ };
+
+ const registerUser = () => {
+ if (isValidEmail && isValidPassword) {
+ auth()
+ .createUserWithEmailAndPassword(email, password)
+ .then(() => {
+ console.log('User account created & signed in!');
+ })
+ .catch(error => {
+ if (error.code === 'auth/email-already-in-use') {
+ console.log('That email address is already in use!');
+ toast.show({
+ type: 'info',
+ text1: 'Este email ya existe.',
+ text2: 'Por favor prueba un diferente.'
+ });
+ toast.show('Este email ya existe', {
+ type: 'info',
+ data: {
+ subtitle: 'Por favor prueba uno diferente.',
+ },
+ });
+ console.log('hello')
+ return error
+ }
+
+ if (error.code === 'auth/invalid-email') {
+ console.log('That email address is invalid!');
+ return error
+ }
+
+ console.error(error);
+ });
+ }
+ };
+
+ return (
+ <SafeAreaView style={tw`bg-black flex-1`}>
+ <TouchableWithoutFeedback
+ onPress={() => {
+ Keyboard.dismiss();
+ }}
+ >
+ <KeyboardAvoidingView
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ style={tw`flex-1`}
+ >
+ <View style={tw`py-6 px-8 flex items-center justify-center`}>
+ </View>
+ <View style={tw`flex-1 items-center justify-center px-12`}>
+ <Text style={tw`text-white text-2xl mb-12 self-start`}>
+ Registrate
+ </Text>
+ <TextInput
+ style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${
+ !isValidEmail && email !== '' && 'border border-red-500'
+ }`}
+ placeholderTextColor={tw.color('text-white/20')}
+ placeholder={'Email'}
+ value={email}
+ onChangeText={textInput => {
+ setEmail(textInput);
+ }}
+ autoCorrect={false}
+ autoCapitalize={'none'}
+ keyboardType={'email-address'}
+ />
+ <Text
+ style={tw`text-red-500 self-start mb-6 ${
+ (isValidEmail || email === '') && 'opacity-0'
+ }`}
+ >
+ Email incorrecto.
+ </Text>
+ <View style={tw`relative flex flex-row`}>
+ <Pressable
+ onPress={() => {
+ setIsPasswordVisible(!isPasswordVisible);
+ }}
+ style={tw`absolute top-3 right-3 z-10`}
+ >
+ {!isPasswordVisible ? (
+ <EyeSlashIcon style={tw`w-6 h-6 text-white/40`} />
+ ) : (
+ <EyeIcon style={tw`w-6 h-6 text-white/40`} />
+ )}
+ </Pressable>
+ <TextInput
+ style={tw`h-12 px-4 font-medium bg-white/20 rounded w-full text-white mb-2 ${
+ !isValidPassword && password !== '' && 'border border-red-500'
+ }`}
+ placeholderTextColor={tw.color('text-white/20')}
+ placeholder={'Contraseña'}
+ value={password}
+ onChangeText={passwordInput => {
+ setPassword(passwordInput);
+ }}
+ secureTextEntry={!isPasswordVisible}
+ />
+ </View>
+ <Text
+ style={tw`text-red-500 self-start mb-6 ${
+ (isValidPassword || password === '') && 'opacity-0'
+ }`}
+ >
+ Debe contener A-b-0-!
+ </Text>
+ <Pressable
+ onPress={() => {
+ registerUser();
+ }}
+ style={tw`mb-12`}
+ >
+ <Text style={tw`text-white/40 text-xl`}>Registrate</Text>
+ </Pressable>
+ <View style={tw`flex flex-row items-center`}>
+ <Text style={tw`text-white`}>¿Ya tienes una cuenta? </Text>
+ <Pressable onPress={() => navigation.navigate('SignIn')}>
+ <Text style={tw`text-red-500 font-bold`}>Ingresa</Text>
+ </Pressable>
+ </View>
+ </View>
+ </KeyboardAvoidingView>
+ </TouchableWithoutFeedback>
+ </SafeAreaView>
+ );
+};
+
+export default SignUp;
diff --git a/screens/topRated.js b/screens/topRated.js index e4685fe..9beae37 100644 --- a/screens/topRated.js +++ b/screens/topRated.js @@ -1,6 +1,6 @@ -import {Text} from 'react-native'; -const TopRated = () => { - return <Text>Top Rated</Text>; -}; - -export default TopRated; +import {Text} from 'react-native';
+const TopRated = () => {
+ return <Text>Top Rated</Text>;
+};
+
+export default TopRated;
|