summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.env4
-rw-r--r--.vscode/settings.json3
-rw-r--r--android/gradlew.bat178
-rw-r--r--components/PreviewCard.tsx38
-rw-r--r--lib/requests.js20
-rw-r--r--screens/discover.js12
-rw-r--r--screens/home.js324
-rw-r--r--screens/modal.js34
-rw-r--r--screens/passwordRecovery.js108
-rw-r--r--screens/profile.js42
-rw-r--r--screens/signin.js356
-rw-r--r--screens/signup.js402
-rw-r--r--screens/topRated.js12
-rw-r--r--stacks/AuthNavigator.tsx72
-rw-r--r--stacks/NavigatorHome.tsx152
-rw-r--r--static/images/netflix-logo.svg6
16 files changed, 883 insertions, 880 deletions
diff --git a/.env b/.env
index f3a0248..ff3cfa7 100644
--- a/.env
+++ b/.env
@@ -1,3 +1,3 @@
-BASE_URL=https://api.themoviedb.org/3
-API_KEY=f247ff737ec8062f3b5e027789eab748
+BASE_URL=https://api.themoviedb.org/3
+API_KEY=f247ff737ec8062f3b5e027789eab748
IMG_ASSETS=https://image.tmdb.org/t/p/original \ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..8274afe
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.compile.nullAnalysis.mode": "disabled"
+} \ No newline at end of file
diff --git a/android/gradlew.bat b/android/gradlew.bat
index 107acd3..ac1b06f 100644
--- a/android/gradlew.bat
+++ b/android/gradlew.bat
@@ -1,89 +1,89 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/components/PreviewCard.tsx b/components/PreviewCard.tsx
index 989ec34..5140fe2 100644
--- a/components/PreviewCard.tsx
+++ b/components/PreviewCard.tsx
@@ -1,20 +1,20 @@
-const imageURL = 'https://image.tmdb.org/t/p/original';
-import { ImageBackground, View } from "react-native";
-const baseURL ='https://api.themoviedb.org/3/'
-import tw from 'twrnc';
-
-const PreviewCard = ({ movie }) => {
- return (
- <View style={tw``}>
- <View style={tw`shadow-black rounded`}>
- <ImageBackground
- source={{uri: `https://image.tmdb.org/t/p/original${movie?.poster_path}`}}
- resizeMode={'cover'}
- style={tw`h-40 w-30 rounded-xl bg-white border border-white/30 overflow-hidden`}
- ></ImageBackground>
- </View>
- </View>
- )}
-
-
+const imageURL = 'https://image.tmdb.org/t/p/original';
+import { ImageBackground, View } from "react-native";
+const baseURL ='https://api.themoviedb.org/3/'
+import tw from 'twrnc';
+
+const PreviewCard = ({ movie }) => {
+ return (
+ <View style={tw``}>
+ <View style={tw`shadow-black rounded`}>
+ <ImageBackground
+ source={{uri: `https://image.tmdb.org/t/p/original${movie?.poster_path}`}}
+ resizeMode={'cover'}
+ style={tw`h-40 w-30 rounded-xl bg-white border border-white/30 overflow-hidden`}
+ ></ImageBackground>
+ </View>
+ </View>
+ )}
+
+
export default PreviewCard \ No newline at end of file
diff --git a/lib/requests.js b/lib/requests.js
index 84c7664..965b2ee 100644
--- a/lib/requests.js
+++ b/lib/requests.js
@@ -1,10 +1,10 @@
-import {BASE_URL, API_KEY} from '@env';
-const apiKey = process.env.API_KEY;
-const baseUrl = process.env.BASE_URL;
-const requests = {
- fetchTopRated: `${baseUrl}/movie/top_rated?api_key=${apiKey}&language=en`,
- fetchTrendingMovies: `${baseUrl}/trending/movie/day?api_key=${apiKey}&language=en`,
- fetchTrendingTv: `${baseUrl}/trending/tv/day?api_key=${apiKey}&language=en`,
-};
-
-export default requests;
+import {BASE_URL, API_KEY} from '@env';
+const apiKey = process.env.API_KEY;
+const baseUrl = process.env.BASE_URL;
+const requests = {
+ fetchTopRated: `${baseUrl}/movie/top_rated?api_key=${apiKey}&language=en`,
+ fetchTrendingMovies: `${baseUrl}/trending/movie/day?api_key=${apiKey}&language=en`,
+ fetchTrendingTv: `${baseUrl}/trending/tv/day?api_key=${apiKey}&language=en`,
+};
+
+export default requests;
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;
diff --git a/stacks/AuthNavigator.tsx b/stacks/AuthNavigator.tsx
index b796bb7..90ec6a2 100644
--- a/stacks/AuthNavigator.tsx
+++ b/stacks/AuthNavigator.tsx
@@ -1,37 +1,37 @@
-import { createNativeStackNavigator } from "@react-navigation/native-stack";
-import SignIn from "../screens/signin";
-import SignUp from "../screens/signup";
-import PasswordRecovery from "../screens/passwordRecovery";
-import Modal from "../screens/modal";
-
- const Stack = createNativeStackNavigator();
-
-const AuthNavigator = () => {
- return (
- <Stack.Navigator>
- <Stack.Screen
- name="SignIn"
- options={{
- headerShown: false,
- }}
- component={SignIn}
- />
- <Stack.Screen
- name="SignUp"
- options={{
- headerShown: false,
- }}
- component={SignUp}
- />
- <Stack.Screen
- name="PasswordRecovery"
- options={{
- headerShown: false,
- }}
- component={PasswordRecovery}
- />
- </Stack.Navigator>
- );
-};
-
+import { createNativeStackNavigator } from "@react-navigation/native-stack";
+import SignIn from "../screens/signin";
+import SignUp from "../screens/signup";
+import PasswordRecovery from "../screens/passwordRecovery";
+import Modal from "../screens/modal";
+
+ const Stack = createNativeStackNavigator();
+
+const AuthNavigator = () => {
+ return (
+ <Stack.Navigator>
+ <Stack.Screen
+ name="SignIn"
+ options={{
+ headerShown: false,
+ }}
+ component={SignIn}
+ />
+ <Stack.Screen
+ name="SignUp"
+ options={{
+ headerShown: false,
+ }}
+ component={SignUp}
+ />
+ <Stack.Screen
+ name="PasswordRecovery"
+ options={{
+ headerShown: false,
+ }}
+ component={PasswordRecovery}
+ />
+ </Stack.Navigator>
+ );
+};
+
export default AuthNavigator; \ No newline at end of file
diff --git a/stacks/NavigatorHome.tsx b/stacks/NavigatorHome.tsx
index cb972ff..dda2b96 100644
--- a/stacks/NavigatorHome.tsx
+++ b/stacks/NavigatorHome.tsx
@@ -1,77 +1,77 @@
-import {HomeIcon} from 'react-native-heroicons/outline';
-import {StarIcon} from 'react-native-heroicons/outline';
-import {HomeIcon as HomeIconSolid} from 'react-native-heroicons/solid';
-import {StarIcon as StarIconSolid} from 'react-native-heroicons/solid';
-import {RocketLaunchIcon} from 'react-native-heroicons/outline';
-import {RocketLaunchIcon as RocketLaunchIconSolid} from 'react-native-heroicons/solid';
-import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
-import tw from 'twrnc';
-import Home from '../screens/home';
-import TopRated from '../screens/topRated';
-import Discover from '../screens/discover';
-import Modal from '../screens/modal';
-
- const Tabs = createBottomTabNavigator();
-
-const NavigatorHome = () => {
- return (
- <Tabs.Navigator
- screenOptions={({route}) => ({
- tabBarIcon: ({focused}) => {
- if (route.name === 'Home') {
- return focused ? (
- <HomeIconSolid color={tw.color('blue-600')} size={20} />
- ) : (
- <HomeIcon color={tw.color('gray-400')} size={20} />
- );
- } else if (route.name === 'TopRated') {
- return focused ? (
- <StarIconSolid color={tw.color('blue-600')} size={20} />
- ) : (
- <StarIcon color={tw.color('gray-400')} size={20} />
- );
- } else if (route.name === 'Discover') {
- return focused ? (
- <RocketLaunchIconSolid color={tw.color('blue-600')} size={20} />
- ) : (
- <RocketLaunchIcon color={tw.color('gray-400')} size={20} />
- );
- }
- },
- tabBarStyle: {
- backgroundColor: tw.color('gray-950'),
- borderTopWidth: 0,
- },
- tabBarLabelStyle: {
- marginTop: -10,
- marginBottom: 7,
- },
- })}
- >
- <Tabs.Screen
- name={'Home'}
- component={Home}
- options={{
- headerShown: false,
- }}
- />
- <Tabs.Screen
- name={'TopRated'}
- component={TopRated}
- options={{
- headerShown: false,
- }}
- />
- <Tabs.Screen
- name={'Discover'}
- component={Discover}
- options={{
- headerShown: false,
- }}
- />
- <Tabs.Screen name="Modal" component={Modal} options={{ tabBarButton: () => null }}/>
- </Tabs.Navigator>
- );
-};
-
+import {HomeIcon} from 'react-native-heroicons/outline';
+import {StarIcon} from 'react-native-heroicons/outline';
+import {HomeIcon as HomeIconSolid} from 'react-native-heroicons/solid';
+import {StarIcon as StarIconSolid} from 'react-native-heroicons/solid';
+import {RocketLaunchIcon} from 'react-native-heroicons/outline';
+import {RocketLaunchIcon as RocketLaunchIconSolid} from 'react-native-heroicons/solid';
+import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
+import tw from 'twrnc';
+import Home from '../screens/home';
+import TopRated from '../screens/topRated';
+import Discover from '../screens/discover';
+import Modal from '../screens/modal';
+
+ const Tabs = createBottomTabNavigator();
+
+const NavigatorHome = () => {
+ return (
+ <Tabs.Navigator
+ screenOptions={({route}) => ({
+ tabBarIcon: ({focused}) => {
+ if (route.name === 'Home') {
+ return focused ? (
+ <HomeIconSolid color={tw.color('blue-600')} size={20} />
+ ) : (
+ <HomeIcon color={tw.color('gray-400')} size={20} />
+ );
+ } else if (route.name === 'TopRated') {
+ return focused ? (
+ <StarIconSolid color={tw.color('blue-600')} size={20} />
+ ) : (
+ <StarIcon color={tw.color('gray-400')} size={20} />
+ );
+ } else if (route.name === 'Discover') {
+ return focused ? (
+ <RocketLaunchIconSolid color={tw.color('blue-600')} size={20} />
+ ) : (
+ <RocketLaunchIcon color={tw.color('gray-400')} size={20} />
+ );
+ }
+ },
+ tabBarStyle: {
+ backgroundColor: tw.color('gray-950'),
+ borderTopWidth: 0,
+ },
+ tabBarLabelStyle: {
+ marginTop: -10,
+ marginBottom: 7,
+ },
+ })}
+ >
+ <Tabs.Screen
+ name={'Home'}
+ component={Home}
+ options={{
+ headerShown: false,
+ }}
+ />
+ <Tabs.Screen
+ name={'TopRated'}
+ component={TopRated}
+ options={{
+ headerShown: false,
+ }}
+ />
+ <Tabs.Screen
+ name={'Discover'}
+ component={Discover}
+ options={{
+ headerShown: false,
+ }}
+ />
+ <Tabs.Screen name="Modal" component={Modal} options={{ tabBarButton: () => null }}/>
+ </Tabs.Navigator>
+ );
+};
+
export default NavigatorHome; \ No newline at end of file
diff --git a/static/images/netflix-logo.svg b/static/images/netflix-logo.svg
index fa90ead..fa5c4c3 100644
--- a/static/images/netflix-logo.svg
+++ b/static/images/netflix-logo.svg
@@ -1,3 +1,3 @@
-<svg width="139" height="39" viewBox="0 0 139 39" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M19.1129 35.7153C17.0219 36.0885 14.8942 36.2004 12.6931 36.4983L5.97958 16.5157V37.356C3.88861 37.5796 1.98102 37.8778 0 38.1761V0H5.57629L13.2066 21.6608V0H19.1129V35.7153ZM30.6688 13.9805C32.9434 13.9805 36.4285 13.8686 38.5194 13.8686V19.8335C35.9147 19.8335 32.87 19.8335 30.6688 19.9454V28.8185C34.1173 28.5949 37.5657 28.2963 41.0506 28.1845V33.9255L24.799 35.2306V0H41.0506V5.96502H30.6688V13.9805ZM62.8782 5.96516H56.7886V33.4042C54.8075 33.4042 52.8265 33.4042 50.9192 33.4785V5.96516H44.8295V0H62.8785L62.8782 5.96516ZM72.4163 13.5705H80.4505V19.5354H72.4163V33.0687H66.6563V0H83.0551V5.96502H72.4163V13.5705ZM92.5931 27.8491C95.9316 27.9235 99.3064 28.1849 102.572 28.371V34.2615C97.3257 33.9257 92.0796 33.5907 86.7236 33.4785V0H92.5931V27.8491ZM107.524 34.6716C109.395 34.7836 111.376 34.8955 113.284 35.1189V0H107.524V34.6716ZM139 0L131.553 18.1561L139 38.1761C136.799 37.8778 134.598 37.4677 132.396 37.0948L128.178 26.0598L123.886 36.2004C121.758 35.8272 119.704 35.7153 117.576 35.4171L125.133 17.9322L118.31 0H124.619L128.471 10.0287L132.58 0H139V0Z" fill="#E50914"/>
-</svg>
+<svg width="139" height="39" viewBox="0 0 139 39" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.1129 35.7153C17.0219 36.0885 14.8942 36.2004 12.6931 36.4983L5.97958 16.5157V37.356C3.88861 37.5796 1.98102 37.8778 0 38.1761V0H5.57629L13.2066 21.6608V0H19.1129V35.7153ZM30.6688 13.9805C32.9434 13.9805 36.4285 13.8686 38.5194 13.8686V19.8335C35.9147 19.8335 32.87 19.8335 30.6688 19.9454V28.8185C34.1173 28.5949 37.5657 28.2963 41.0506 28.1845V33.9255L24.799 35.2306V0H41.0506V5.96502H30.6688V13.9805ZM62.8782 5.96516H56.7886V33.4042C54.8075 33.4042 52.8265 33.4042 50.9192 33.4785V5.96516H44.8295V0H62.8785L62.8782 5.96516ZM72.4163 13.5705H80.4505V19.5354H72.4163V33.0687H66.6563V0H83.0551V5.96502H72.4163V13.5705ZM92.5931 27.8491C95.9316 27.9235 99.3064 28.1849 102.572 28.371V34.2615C97.3257 33.9257 92.0796 33.5907 86.7236 33.4785V0H92.5931V27.8491ZM107.524 34.6716C109.395 34.7836 111.376 34.8955 113.284 35.1189V0H107.524V34.6716ZM139 0L131.553 18.1561L139 38.1761C136.799 37.8778 134.598 37.4677 132.396 37.0948L128.178 26.0598L123.886 36.2004C121.758 35.8272 119.704 35.7153 117.576 35.4171L125.133 17.9322L118.31 0H124.619L128.471 10.0287L132.58 0H139V0Z" fill="#E50914"/>
+</svg>