diff options
| author | Alberto Duarte (PWC) <alberto.duarte.delgado@pwc.com> | 2023-10-09 17:32:25 +0100 |
|---|---|---|
| committer | Alberto Duarte (PWC) <alberto.duarte.delgado@pwc.com> | 2023-10-09 17:32:25 +0100 |
| commit | 72cf36e033ba794db7982befa45f035b62fa6cd2 (patch) | |
| tree | 3a6fd91976c976afcc8bc1a7cf6fc5c1bf25a791 | |
| parent | 66412b7788f49def33fc2143f9e1bd5d25bac261 (diff) | |
Changes
| -rw-r--r-- | .env | 7 | ||||
| -rw-r--r-- | .vscode/settings.json | 4 | ||||
| -rw-r--r-- | app/browse/page.tsx (renamed from src/pages/browse/index.tsx) | 247 | ||||
| -rw-r--r-- | app/components/AuthContext.tsx | 25 | ||||
| -rw-r--r-- | app/components/Genre.tsx | 24 | ||||
| -rw-r--r-- | app/components/Modal.tsx | 66 | ||||
| -rw-r--r-- | app/components/PreviewCard.tsx | 20 | ||||
| -rw-r--r-- | app/hello/page.tsx | 99 | ||||
| -rw-r--r-- | app/layout.js | 20 | ||||
| -rw-r--r-- | app/login/page.tsx | 125 | ||||
| -rw-r--r-- | app/password-recovery/page.tsx | 44 | ||||
| -rw-r--r-- | app/profiles/page.tsx (renamed from src/pages/index.tsx) | 25 | ||||
| -rw-r--r-- | app/register/page.tsx | 123 | ||||
| -rw-r--r-- | next.config.js | 3 | ||||
| -rw-r--r-- | package-lock.json | 1028 | ||||
| -rw-r--r-- | package.json | 3 | ||||
| -rw-r--r-- | services/firebase.tsx | 25 | ||||
| -rw-r--r-- | services/requests.tsx | 15 | ||||
| -rw-r--r-- | src/components/Genre.tsx | 27 | ||||
| -rw-r--r-- | src/components/PreviewCard.tsx | 19 | ||||
| -rw-r--r-- | src/pages/_app.tsx | 2 | ||||
| -rw-r--r-- | src/styles/globals.css | 1 | ||||
| -rw-r--r-- | tailwind.config.js | 1 | ||||
| -rw-r--r-- | tsconfig.json | 30 |
24 files changed, 1774 insertions, 209 deletions
@@ -0,0 +1,7 @@ +NEXT_PUBLIC_FIREBASE_API_KEY=AIzaSyDWM4QIP4D6byd4vjmStT7hGrHlGE10mjE
+NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=reactnativeapp-12f61.firebaseapp.com
+NEXT_PUBLIC_FIREBASE_PROJECT_ID=reactnativeapp-12f61
+NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=reactnativeapp-12f61.appspot.com
+NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=588576830512
+NEXT_PUBLIC_FIREBASE_APP_ID=1:588576830512:web:b4d768e27ac4559794a9f5
+NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-J1W4WDDMQP
\ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bd3337f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "typescript.tsdk": "node_modules\\typescript\\lib", + "typescript.enablePromptUseWorkspaceTsdk": true +}
\ No newline at end of file diff --git a/src/pages/browse/index.tsx b/app/browse/page.tsx index 90c13c2..7806738 100644 --- a/src/pages/browse/index.tsx +++ b/app/browse/page.tsx @@ -1,94 +1,153 @@ -import { link } from 'fs' -import Link from 'next/link' -import { BellIcon, MagnifyingGlassIcon, PlayIcon, ArrowSmallDownIcon} from '@heroicons/react/24/solid' -import { InformationCircleIcon} from '@heroicons/react/24/outline' -import { useEffect, useState } from 'react' -import requests from '../../../services/requests' -import Image from "next/image" -import PreviewCard from '@prueba/components/PreviewCard' - -// import NetflixLogo from '../../../public/images/netflix_logo.svg' -const baseURL ='https://api.themoviedb.org/3/' -const imageURL = 'https://image.tmdb.org/t/p/original' - -export default function Home() { - const [heroMovie, setHeroMovie] = useState() - const [trendingMovies, setTrendingMovies] = useState() - useEffect(() => { - fetch(`${baseURL}${requests.fetchTopRated}`).then(res => res.json()).then((data) => { - console.log(data.results) - setHeroMovie(data.results[3]) - }) - }, []) - useEffect(() => { - fetch(`${baseURL}${requests.fetchTrending}`).then(res => res.json()).then((data) => { - setTrendingMovies(data.results) - }) - }, []) - - return ( - <div className="flex flex-col text-white justify-between gap-10 h-screen"> - <header className='flex justify-between pt-3 px-8 z-10 text-xs'> - <div className='flex items-center gap-4'> - <img className='scale-[65%] mr-4' src="../images/netflix_logo.svg" alt="SVG image"/> - <a className='text-white font-bold'>Home</a> - <a className='text-white'>TV Shows</a> - <a className='text-white'>Movies</a> - <a className='text-white'>News & Popular</a> - <a className='text-white'>My List</a> - <a className='text-white'>Browse by Language</a> - </div> - <div className='flex items-center gap-4'> - <MagnifyingGlassIcon className='h-4 w-4'/> - <a className='text-white'>Kids</a> - <BellIcon className='h-4 w-4'/> - <div className='h-8 w-8'> - <Link href='../' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white"> - <img src='https://avatars.dicebear.com/api/male/124.svg' alt=""/> - </Link> - </div> - <ArrowSmallDownIcon className='h-4 w-4'/> - </div> - </header> - <section className='w-1/3 ml-10'> - <div className='flex items-center'> - <img className='scale-[65%] mr-5' src="../images/N.svg" alt="SVG image"/> - <h1 className='text-sm font-mono tracking-[.4rem]'>MOVIES</h1> - </div> - <div className='h-fit text-[3rem]'> - {heroMovie?.original_title} - </div> - <div className='flex items-center'> - <img className='scale-[45%]' src="../images/Top10.svg" alt="SVG image"/> - <h2 className='font-bold'>#1 in TV Shows Today</h2> - </div> - <div> - <p className=' text-sm break-words text-justify'> - {heroMovie?.overview} - </p> - </div> - <div className='flex gap-4 mt-4'> - <button className='flex items-center p-4 h-10 bg-white text-black text-xl justify-center font-semibold ring-black ring-offset-10 hover:ring-4 rounded'> - <PlayIcon className='h-6 w-6 mr-2'/>Play - </button> - <button className='flex items-center p-4 h-10 bg-gray-700/80 justify-center ring-white hover:ring-4 rounded'> - <InformationCircleIcon className='h-6 w-6 mr-2'/>More Info - </button> - </div> - </section> - <section className=' ml-10 mb-10 z-10'> - <h2>Popular on Netflix</h2> - <div className='flex flex-row gap-3 overflow-x-auto mt-4 items-center p-5 pl-10 -ml-10'> - { - trendingMovies?.map((movie, index) => ( - <PreviewCard key={index} movie={movie}/> - ))} - </div> - </section> - <div className='absolute h-full w-full bg-contain bg-center -z-20 bg-right' style={{backgroundImage: `url(${imageURL}${heroMovie?.backdrop_path})`}}></div> - <div className='absolute w-full h-32 -z-10 bg-gradient-to-b from-black'></div> - <div className='absolute bottom-0 w-full h-20 -z-10 bg-gradient-to-t from-black'></div> - <div className='absolute w-2/3 h-full -z-10 bg-gradient-to-r from-black'></div> - </div> - ) -} +'use client'
+import { link } from 'fs'
+import Link from 'next/link'
+import { BellIcon, MagnifyingGlassIcon, PlayIcon, ArrowSmallDownIcon} from '@heroicons/react/24/solid'
+import { InformationCircleIcon} from '@heroicons/react/24/outline'
+import { useEffect, useState, useContext } from 'react'
+import requests from '../../services/requests'
+import Image from "next/image"
+import PreviewCard from '../components/PreviewCard'
+import Modal from '../components/Modal'
+import { auth } from '../../services/firebase';
+import { useRouter } from 'next/navigation';
+import { signOut } from 'firebase/auth';
+import { AuthContext } from '../components/AuthContext'
+
+// import NetflixLogo from '../../../public/images/netflix_logo.svg'
+const baseURL ='https://api.themoviedb.org/3/'
+const imageURL = 'https://image.tmdb.org/t/p/original'
+
+const Home = () => {
+ const router = useRouter();
+ const [heroMovie, setHeroMovie] = useState()
+ const [trendingMovies, setTrendingMovies] = useState()
+ const [trendingTv, setTrendingTv] = useState()
+ const [modalVisible, setModalVisible] = useState(false)
+ const [modalContent, setModalContent] = useState()
+ const user = useContext(AuthContext);
+
+ useEffect(() => {
+ // Check if user is authenticated
+ if (!user) {
+ // Redirect or perform any necessary action
+ router.push('/login');
+ } else {
+ // User is authenticated, continue with desired logic
+ }
+ }, [user]);
+
+ useEffect(() => {
+ const user = auth.currentUser;
+ if (!user) {
+ // User is not signed in, redirect to the login page
+ router.push('/login');
+ }
+ }, []);
+
+ const logoutUser = () => {
+ signOut(auth)
+ .then(() => {
+ console.log('User signed Out!');
+ // Navigate to the home screen or other desired screen
+ router.push('/login');
+ })
+ .catch(error => {
+ console.error(error);
+ // Display an error message to the user
+ });
+ }
+
+ useEffect(() => {
+ fetch(`${baseURL}${requests.fetchTopRated}`).then(res => res.json()).then((data) => {
+ setHeroMovie(data.results[3])
+ })
+ }, [])
+ useEffect(() => {
+ fetch(`${baseURL}${requests.fetchTrendingMovies}`).then(res => res.json()).then((data) => {
+ setTrendingMovies(data.results)
+ console.log(data.results)
+ })
+ }, [])
+ useEffect(() => {
+ fetch(`${baseURL}${requests.fetchTrendingTv}`).then(res => res.json()).then((data) => {
+ setTrendingTv(data.results)
+ })
+ }, [])
+
+ return (
+ <div className="flex flex-col text-white justify-between gap-10 h-screen">
+ <header className='flex justify-between pt-3 px-8 z-10 text-xs'>
+ <div className='flex items-center gap-4'>
+ <img className='scale-[65%] mr-4' src="../images/netflix_logo.svg" alt="SVG image"/>
+ <a className='text-white font-bold'>Home</a>
+ <a className='text-white'>TV Shows</a>
+ <a className='text-white'>Movies</a>
+ <a className='text-white'>News & Popular</a>
+ <a className='text-white'>My List</a>
+ <a className='text-white'>Browse by Language</a>
+ </div>
+ <div className='flex items-center gap-4'>
+ <MagnifyingGlassIcon className='h-4 w-4'/>
+ <a className='text-white'>Kids</a>
+ <BellIcon className='h-4 w-4'/>
+ <div className='h-8 w-8'>
+ <Link href='../' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white">
+ <img src='https://avatars.dicebear.com/api/male/124.svg' alt=""/>
+ </Link>
+ </div>
+ <ArrowSmallDownIcon className='h-4 w-4 cursor-pointer' onClick={logoutUser}/>
+ </div>
+ </header>
+ <section className='w-1/3 ml-10'>
+ <div className='flex items-center'>
+ <img className='scale-[65%] mr-5' src="../images/N.svg" alt="SVG image"/>
+ <h1 className='text-sm font-mono tracking-[.4rem]'>MOVIES</h1>
+ </div>
+ <div className='h-fit text-[3rem]'>
+ {heroMovie?.original_title}
+ </div>
+ <div className='flex items-center'>
+ <img className='scale-[45%]' src="../images/Top10.svg" alt="SVG image"/>
+ <h2 className='font-bold'>#1 in TV Shows Today</h2>
+ </div>
+ <div>
+ <p className=' text-sm break-words text-justify'>
+ {heroMovie?.overview}
+ </p>
+ </div>
+ <div className='flex gap-4 mt-4'>
+ <button className='flex items-center p-4 h-10 bg-white text-black text-xl justify-center font-semibold rounded hover:outline outline-offset-4 outline-4 outline-white'>
+ <PlayIcon className='h-6 w-6 mr-2'/>Play
+ </button>
+ <button className='flex items-center p-4 h-10 bg-gray-700/80 justify-center rounded hover:outline outline-offset-4 outline-4'>
+ <InformationCircleIcon className='h-6 w-6 mr-2'/>More Info
+ </button>
+ </div>
+ </section>
+ <section className=' ml-10 mb-10 z-10'>
+ <h2>Popular on Netflix</h2>
+ <div className='flex flex-row gap-3 overflow-x-auto mt-4 items-center p-6 pl-10 -ml-10'>
+ {
+ trendingMovies?.map((movie, index) => (
+ <PreviewCard key={index} movie={movie} setModalContentId={setModalContent} setModalVisible={setModalVisible}/>
+ ))}
+ </div>
+ </section>
+ <section className=' ml-10 mb-10 z-10'>
+ <h2>Tv Shows</h2>
+ <div className='flex flex-row gap-3 overflow-x-auto mt-4 items-center p-5 pl-10 -ml-10'>
+ {
+ trendingTv?.map((movie, index) => (
+ <PreviewCard key={index} movie={movie} setModalContentId={setModalContent} setModalVisible={setModalVisible}/>
+ ))}
+ </div>
+ </section>
+ <Modal modalContent={modalContent} setModalVisible={setModalVisible} modalVisible={modalVisible}/>
+ <div className='absolute h-full w-full bg-contain bg-right -z-20 bg-no-repeat' style={{backgroundImage: `url(${imageURL}${heroMovie?.backdrop_path})`}}></div>
+ <div className='absolute w-full h-32 -z-10 bg-gradient-to-b from-black'></div>
+ <div className='absolute bottom-0 w-full h-20 -z-10 bg-gradient-to-t from-black'></div>
+ <div className='absolute w-2/3 h-full -z-10 bg-gradient-to-r from-black'></div>
+ </div>
+ )
+}
+export default Home;
\ No newline at end of file diff --git a/app/components/AuthContext.tsx b/app/components/AuthContext.tsx new file mode 100644 index 0000000..9c83744 --- /dev/null +++ b/app/components/AuthContext.tsx @@ -0,0 +1,25 @@ +'use client'
+import { createContext, useState, useEffect } from 'react';
+import { onAuthStateChanged } from 'firebase/auth';
+import { auth } from '../../services/firebase';
+
+export const AuthContext = createContext();
+
+export const AuthProvider = ({ children }) => {
+ const [user, setUser] = useState(null);
+
+ useEffect(() => {
+ const unsubscribe = onAuthStateChanged(auth, (user) => {
+ setUser(user);
+ });
+
+ // Cleanup the subscription when the component unmounts
+ return () => unsubscribe();
+ }, []);
+
+ return (
+ <AuthContext.Provider value={user}>
+ {children}
+ </AuthContext.Provider>
+ );
+};
\ No newline at end of file diff --git a/app/components/Genre.tsx b/app/components/Genre.tsx new file mode 100644 index 0000000..13e7ed2 --- /dev/null +++ b/app/components/Genre.tsx @@ -0,0 +1,24 @@ +import { useEffect, useState } from "react"
+
+const Genres = ({id}) => {
+
+ const [genres, setGenres] = useState()
+
+ useEffect(() => {
+ fetch(`https://api.themoviedb.org/3/movie/${id}?api_key=8216fbb9997cd81a67471e6cb5a6f2df`).then((res) => res.json()).then((data) => {
+ setGenres(data?.genres)
+ })
+ }, [id])
+
+ return (
+ <div className="text-white/60 gap-x-3 text-xs flex flex-row flex-wrap relative">
+ {genres?.map((genre, index) => {
+ return (
+ <div key={index}>{genre.name}</div>
+ )
+ })}
+ </div>
+ )
+}
+
+export default Genres
\ No newline at end of file diff --git a/app/components/Modal.tsx b/app/components/Modal.tsx new file mode 100644 index 0000000..e783cfa --- /dev/null +++ b/app/components/Modal.tsx @@ -0,0 +1,66 @@ +import { useEffect, useState } from 'react'
+import { XMarkIcon } from '@heroicons/react/24/outline'
+import Genre from './Genre'
+
+const baseURL = 'https://api.themoviedb.org/3/'
+const API_KEY = '8216fbb9997cd81a67471e6cb5a6f2df'
+const Modal = ({ modalVisible, modalContent, setModalVisible, type }) => {
+ const [content, setContent] = useState()
+ const [video, setVideo] = useState()
+ const [similarMovies, setSimilarMovies] = useState()
+ useEffect(() => {
+ fetch(`${baseURL}/movie/${modalContent?.id}/similar?api_key=${API_KEY}`).then(res => res.json()).then((data) => {
+ setSimilarMovies(data.results)
+ })
+ }, [modalContent])
+ useEffect(() => {
+ if (modalContent) {
+ fetch(`${baseURL}/${modalContent.media_type}/${modalContent.id}/videos?api_key=${API_KEY}`)
+ .then((res) => res.json())
+ .then((data) => {
+ console.log('VIDEOS DATA', data.results[0].key)
+ setVideo(data.results[0].key)
+ })
+}
+ }, [modalContent])
+ return (
+ <div
+ className={`backdrop-blur-[2px] fixed inset-0 z-50 bg-black/40 flex items-center justify-center ${modalVisible ? '' : 'hidden'
+ }`} onClick={(e) => e.target === e.currentTarget && setModalVisible(false)}
+ >
+ <div className="flex flex-col bg-transparent shadow-2xl rounded-xl z-100">
+ {modalVisible && (
+ <iframe
+ className={'w-full bg-black'}
+ width="420"
+ height="315"
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
+ src={`https://www.youtube.com/embed/${video}?autoplay=1`}
+ ></iframe>
+ )}
+ <div className={'px-8 py-4 w-[600px] bg-gray-800'}>
+ <Genre id={modalContent?.id} />
+ <h3 className={'text-xl'}>{modalContent?.original_name}{modalContent?.original_title}</h3>
+ <p className='w-full break-words h-[70px] overflow-y-auto'>{modalContent?.overview}</p>
+ <hr className='my-4'/>
+ <div className='flex flex-row overflow-x-auto gap-8'>
+ {
+ similarMovies?.map((movie, index) => (
+
+
+ <div
+ className={`
+ shrink-0 bg-contain bg-no-repeat w-[150px] h-[112px] bg-center z-40 ${movie?.backdrop_path === null ? 'hidden' : '' }
+ `}
+ style={{
+ backgroundImage: `url(https://image.tmdb.org/t/p/original${movie?.backdrop_path})`,
+ }}
+ ></div>
+ ))}
+ </div>
+ </div>
+ </div>
+ </div>
+ )
+}
+export default Modal
diff --git a/app/components/PreviewCard.tsx b/app/components/PreviewCard.tsx new file mode 100644 index 0000000..132f50a --- /dev/null +++ b/app/components/PreviewCard.tsx @@ -0,0 +1,20 @@ +const imageURL = 'https://image.tmdb.org/t/p/original';
+import Genre from "./Genre";
+const baseURL ='https://api.themoviedb.org/3/'
+
+const PreviewCard = ({ movie, setModalContentId, setModalVisible }) => {
+ return (
+ <div className="hover:z-10" onClick={ () => {setModalVisible(true), setModalContentId(movie)}}>
+ <div className="shadow-black hover:outline outline-offset-4 outline-4 outline-white rounded flex-col p-1 relative bg-cover h-32 w-60 shrink-0 flex justify-end cursor-pointer hover:scale-110 transition ease-in-out" style={{backgroundImage: `url(${imageURL}${movie?.backdrop_path})`}}>
+ <div className="absolute h-full w-full inset-0 bg-gradient-to-t from-black/70"></div>
+ <h3 className={"text-white text-sm relative"}>
+ {movie.original_title}
+ {movie.original_name}
+ </h3>
+ <Genre id={movie.id}/>
+ </div>
+ </div>
+ )}
+
+
+export default PreviewCard
\ No newline at end of file diff --git a/app/hello/page.tsx b/app/hello/page.tsx new file mode 100644 index 0000000..89e730e --- /dev/null +++ b/app/hello/page.tsx @@ -0,0 +1,99 @@ +'use client'
+import { signInWithEmailAndPassword } from "firebase/auth";
+import Link from "next/link";
+import { auth } from "../../services/firebase";
+
+export default function Hello() {
+ let email = ''
+ let isValidEmail = ''
+ let setIsValidEmail = ''
+ let password = ''
+ let isValidPassword = ''
+ let setIsValidPassword = ''
+ let setIsPasswordVisible = ''
+ let se
+
+ 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
+ }
+
+ const debounce = fn => {
+ let id = null;
+
+ return (...args) => {
+ if (id) {
+ clearTimeout(id);
+ }
+ id = setTimeout(() => {
+ fn(...args);
+ id = null;
+ }, 300);
+ };
+ };
+
+ const loginUser = () => {
+ if (isValidEmail && isValidPassword) {
+ signInWithEmailAndPassword(auth, email, password)
+ .then(data => {console.log(data.user)
+
+ console.log('User signed in successfully!');
+ router.push('/browse');
+ })
+ // Navigate to the home screen or other desired screen
+ .catch(error => {
+ console.error(error);
+ // Display an error message to the user
+ });
+ }
+ };
+
+ return (
+ <div className='text-white flex flex-col items-center justify-center h-screen'>
+ <h1 className='text-2xl font-bold mb-6'>Login</h1>
+ <form className='w-64' >
+ <div className='mb-4'>
+ <label htmlFor='email' className='block font-medium mb-1'>Email:</label>
+ <input type="email" id='email' className='text-black w-full px-3 py-2 border rounded'/>
+ </div>
+ <div className='mb-4'>
+ <label htmlFor="password" className='block font-medium mb-1'>Password:</label>
+ <input type='password' id='password' className='text-black w-full px-3 py-2 border rounded'/>
+ </div>
+ <button type="submit" className='w-full py-2 bg-red-600 text-white font-medium rounded'>
+ Login
+ </button>
+ </form>
+
+ <div className="mt-4">
+ Don't have an account?{' '}
+ <Link href='../register' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white">
+ <p>Create account</p>
+ </Link>
+ </div>
+
+ <div className="mt-2">
+ Forgot your password?{' '}
+ <Link href='../password-recovery' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white">
+ <p>Recover</p>
+ </Link>
+ </div>
+ </div>
+ );
+}
diff --git a/app/layout.js b/app/layout.js new file mode 100644 index 0000000..45773fb --- /dev/null +++ b/app/layout.js @@ -0,0 +1,20 @@ +import '../src/styles/globals.css';
+import { Inter } from 'next/font/google';
+import { AuthProvider } from './components/AuthContext';
+
+const inter = Inter({
+ subsets: ['latin'],
+ variable: '--font-inter',
+});
+
+export default function RootLayout({ children }) {
+ return (
+ <html lang="en">
+ <AuthProvider>
+ <body className={`${inter.variable} font-sans bg-black h-screen`}>
+ {children}
+ </body>
+ </AuthProvider>
+ </html>
+ );
+}
\ No newline at end of file diff --git a/app/login/page.tsx b/app/login/page.tsx new file mode 100644 index 0000000..35ed0aa --- /dev/null +++ b/app/login/page.tsx @@ -0,0 +1,125 @@ +'use client';
+import { useState, useEffect, useContext } from 'react';
+import { signInWithEmailAndPassword } from 'firebase/auth';
+import { auth } from '../../services/firebase';
+import Link from 'next/link';
+import { useRouter } from 'next/navigation';
+import { AuthContext } from '../components/AuthContext'
+
+
+const Login = () => {
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [isValidEmail, setIsValidEmail] = useState(false);
+ const [isValidPassword, setIsValidPassword] = useState(false);
+ const [isPasswordVisible, setIsPasswordVisible] = useState(true);
+ const router = useRouter()
+ const user = useContext(AuthContext);
+
+ useEffect(() => {
+ // Check if user is authenticated
+ if (!user) {
+ // Redirect or perform any necessary action
+ } else {
+ // User is authenticated, continue with desired logic
+ router.push('/profiles');
+ }
+ }, [user]);
+
+ 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
+ }
+
+ const debounce = fn => {
+ let id = null;
+
+ return (...args) => {
+ if (id) {
+ clearTimeout(id);
+ }
+ id = setTimeout(() => {
+ fn(...args);
+ id = null;
+ }, 300);
+ };
+ };
+
+ const loginUser = () => {
+ if (isValidEmail && isValidPassword) {
+ signInWithEmailAndPassword(auth, email, password)
+ .then(data => {console.log(data.user)
+
+ console.log('User signed in successfully!');
+ router.push('/profiles');
+
+ })
+ // Navigate to the home screen or other desired screen
+ .catch(error => {
+ console.error(error);
+ // Display an error message to the user
+ });
+ }
+ };
+
+ return (
+ <div className='text-white flex flex-col items-center justify-center h-screen'>
+ <h1 className='text-2xl font-bold mb-6'>Login</h1>
+ <form className='w-64' onSubmit={e => {
+ e.preventDefault();
+ loginUser();
+ }}>
+ <div className='mb-4'>
+ <label htmlFor='email' className='block font-medium mb-1'>Email:</label>
+ <input type="email" id='email' className='text-black w-full px-3 py-2 border rounded' value={email} onChange={e => setEmail(e.target.value)} />
+ </div>
+ <div className='mb-4'>
+ <label htmlFor="password" className='block font-medium mb-1'>Password:</label>
+ <input type='password' id='password' className='text-black w-full px-3 py-2 border rounded' value={password} onChange={e => setPassword(e.target.value)} />
+ </div>
+ <button type="submit" className='w-full py-2 bg-red-600 text-white font-medium rounded'>
+ Login
+ </button>
+ </form>
+
+ <div className="mt-4">
+ Don't have an account?{' '}
+ <Link href='../register' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white">
+ <p>Create account</p>
+ </Link>
+ </div>
+
+ <div className="mt-2">
+ Forgot your password?{' '}
+ <Link href='../password-recovery' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white">
+ <p>Recover</p>
+ </Link>
+ </div>
+ </div>
+ );
+}
+export default Login;
\ No newline at end of file diff --git a/app/password-recovery/page.tsx b/app/password-recovery/page.tsx new file mode 100644 index 0000000..6a56d7a --- /dev/null +++ b/app/password-recovery/page.tsx @@ -0,0 +1,44 @@ +'use client'
+import { link } from 'fs'
+import Link from 'next/link'
+import { AuthContext } from '../components/AuthContext'
+import { useContext, useEffect, useState } from 'react';
+
+// import NetflixLogo from '../../../public/images/netflix_logo.svg'
+
+export default function PasswordRecovery() {
+ const user = useContext(AuthContext);
+ const [email, setEmail] = useState('');
+
+ useEffect(() => {
+ // Check if user is authenticated
+ if (!user) {
+ // Redirect or perform any necessary action
+ } else {
+ // User is authenticated, continue with desired logic
+ setEmail(user.email)
+ }
+ }, [user]);
+
+ return (
+ <div className='text-white flex flex-col items-center justify-center h-screen'>
+ <h1 className='text-2xl font-bold mb-6'>Password Recovery</h1>
+ <form className='w-64'>
+ <div className='mb-4'>
+ <label htmlFor='email' className='block font-medium mb-1'>Email:</label>
+ <input type="email" id='email' value={email} className='w-full px-3 py-2 border rounded text-black' onChange={e => setEmail(e.target.value)}/>
+ </div>
+ <button className='w-full py-2 bg-red-600 text-white font-medium rounded'>
+ Recover
+ </button>
+ </form>
+
+ <div className="mt-4">
+ Do you have an account?{' '}
+ <Link href='../login' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white">
+ <p>Login</p>
+ </Link>
+ </div>
+ </div>
+ );
+}
diff --git a/src/pages/index.tsx b/app/profiles/page.tsx index 0a21d32..fca89a5 100644 --- a/src/pages/index.tsx +++ b/app/profiles/page.tsx @@ -1,7 +1,25 @@ +'use client' import Link from "next/link" import Image from "next/image" +import { AuthContext } from '../components/AuthContext' +import { useContext, useEffect } from "react"; +import { useRouter } from 'next/navigation'; + +export default function Profiles() { + + const user = useContext(AuthContext); + const router = useRouter(); + + useEffect(() => { + // Check if user is authenticated + if (!user) { + // Redirect or perform any necessary action + router.push('/login'); + } else { + // User is authenticated, continue with desired logic + } + }, [user]); -export default function Home() { return ( <div className="bg-black w-screen h-screen flex flex-col items-center justify-center"> <h1>Netflix</h1> @@ -10,7 +28,7 @@ export default function Home() { { USERS.map((user, index) => ( <div key={index} className="flex flex-col items-center justify-center"> - <Link href={user.link} className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white"> + <Link href={'/browse'} className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white"> <Image src={user.avatar} width={128} height={128} alt=""/> </Link> <p className="text-gray-400 text-xs">{user.name}</p> @@ -24,17 +42,14 @@ export default function Home() { const USERS = [ { name:'Alberto', - link:'/browse', avatar:'https://avatars.dicebear.com/api/male/124.svg' }, { name:'Kids', - link:'/', avatar:'https://avatars.dicebear.com/api/male/122.svg' }, { name:'Add profile', - link:'/', avatar:'https://avatars.dicebear.com/api/female/12.svg' // icon:'...' } diff --git a/app/register/page.tsx b/app/register/page.tsx new file mode 100644 index 0000000..45941fd --- /dev/null +++ b/app/register/page.tsx @@ -0,0 +1,123 @@ +'use client';
+import Link from 'next/link'
+import { useContext, useEffect, useState } from 'react';
+import { auth } from '../../services/firebase';
+import { createUserWithEmailAndPassword } from 'firebase/auth';
+import { useRouter } from 'next/navigation';
+import { AuthContext } from '../components/AuthContext'
+
+// import NetflixLogo from '../../../public/images/netflix_logo.svg'
+
+const Register = () => {
+
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [isValidEmail, setIsValidEmail] = useState(false);
+ const [isValidPassword, setIsValidPassword] = useState(false);
+ const [isPasswordVisible, setIsPasswordVisible] = useState(true);
+ const router = useRouter()
+ const user = useContext(AuthContext);
+
+
+ useEffect(() => {
+ // Check if user is authenticated
+ if (!user) {
+ // Redirect or perform any necessary action
+ } else {
+ // User is authenticated, continue with desired logic
+ router.push('/profiles');
+ }
+ }, [user]);
+
+ 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 registerUser = () => {
+ if (isValidEmail && isValidPassword) {
+ createUserWithEmailAndPassword(auth, email, password)
+ .then(() => {
+ console.log('User account created & signed in!');
+ // Navigate to the home screen or other desired screen
+ router.push('/browse');
+ })
+ .catch(error => {
+ console.error(error);
+ // Display an error message to the user
+ });
+ }
+};
+
+ return (
+ <div className='text-white flex flex-col items-center justify-center h-screen'>
+ <h1 className='text-2xl font-bold mb-6'>Register</h1>
+ <form className='w-64' onSubmit={e => {
+ e.preventDefault();
+ registerUser();
+ }}>
+ <div className='mb-4'>
+ <label htmlFor='email' className='block font-medium mb-1'>Email:</label>
+ <input type="email" id='email' className='text-black w-full px-3 py-2 border rounded' value={email} onChange={e => setEmail(e.target.value)} />
+ </div>
+ <div className='mb-4'>
+ <label htmlFor="password" className='block font-medium mb-1'>Password:</label>
+ <input type='password' id='password' className='text-black w-full px-3 py-2 border rounded' value={password} onChange={e => setPassword(e.target.value)} />
+ </div>
+ <button type="submit" className='w-full py-2 bg-red-600 text-white font-medium rounded'>
+ Register
+ </button>
+ </form>
+
+ <div className="mt-4">
+ Do you have an account?{' '}
+ <Link href='../login' className="w-[128px] h-[128px] rounded-xl overflow-hidden bg-white">
+ <p>Login</p>
+ </Link>
+ </div>
+ </div>
+ );
+}
+
+export default Register;
\ No newline at end of file diff --git a/next.config.js b/next.config.js index 94c7499..13614ba 100644 --- a/next.config.js +++ b/next.config.js @@ -3,6 +3,9 @@ const { hostname } = require('os') /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, + experimental: { + appDir: true, + }, images: { remotePatterns: [ { diff --git a/package-lock.json b/package-lock.json index 12d1955..58e4c04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "autoprefixer": "10.4.14", "eslint": "8.38.0", "eslint-config-next": "13.3.0", - "next": "13.3.0", + "firebase": "^9.21.0", + "next": "13.3.1", "postcss": "8.4.23", "react": "18.2.0", "react-dom": "18.2.0", @@ -1989,6 +1990,608 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@firebase/analytics": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.0.tgz", + "integrity": "sha512-Locv8gAqx0e+GX/0SI3dzmBY5e9kjVDtD+3zCFLJ0tH2hJwuCAiL+5WkHuxKj92rqQj/rvkBUCfA1ewlX2hehg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/analytics-compat": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.6.tgz", + "integrity": "sha512-4MqpVLFkGK7NJf/5wPEEP7ePBJatwYpyjgJ+wQHQGHfzaCDgntOnl9rL2vbVGGKCnRqWtZDIWhctB86UWXaX2Q==", + "dependencies": { + "@firebase/analytics": "0.10.0", + "@firebase/analytics-types": "0.8.0", + "@firebase/component": "0.6.4", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/analytics-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz", + "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==" + }, + "node_modules/@firebase/app": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.9.tgz", + "integrity": "sha512-8jzuHtQ/t9XqK+0IAQ/lpylVYzXGKIUKm6U3v7LWor+MGIm+9Ucn+hbrd2iBjH8qfmNrjnQnmf7sWBbdSa54oA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "idb": "7.1.1", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-check": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.7.0.tgz", + "integrity": "sha512-y0raLJpEtiL+wonfInFMaSfBV/EDvr356ZHMWbpr5F7fR0/I3cC0h7U6SKpKhrbSHJ0fOYIe0xbih20KTlpcnA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/app-check-compat": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.6.tgz", + "integrity": "sha512-azHAeHi9igoaIo04E6Yfuc7aIbWoWuBXuqjyYyWbeCc8Zz/NfJvIAgmXugN4LdxsHJ7XGlZTvwJ6YaYROdSa7A==", + "dependencies": { + "@firebase/app-check": "0.7.0", + "@firebase/app-check-types": "0.5.0", + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.2.0.tgz", + "integrity": "sha512-+3PQIeX6/eiVK+x/yg8r6xTNR97fN7MahFDm+jiQmDjcyvSefoGuTTNQuuMScGyx3vYUBeZn+Cp9kC0yY/9uxQ==" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz", + "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==" + }, + "node_modules/@firebase/app-compat": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.9.tgz", + "integrity": "sha512-XdnkHNK3XdPrwChmuSJHDA6eYmo2KLAtaAG1SJLGMQ+n+S5/UcufmDkw9GvPh93H1xhPRAwd/vKdjHmE7xp3Zw==", + "dependencies": { + "@firebase/app": "0.9.9", + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" + }, + "node_modules/@firebase/auth": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.23.1.tgz", + "integrity": "sha512-QubckPA5Ad92HiY20szjdH7EnFxL8gsZzRLyNCmO2oqebVAVuh9pJp6Zb8EA+P/AuMQYMBo6rQ3oIHi9gUCstg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/auth-compat": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.4.1.tgz", + "integrity": "sha512-wCw+6Jz7zCWzMA2bN8vphqEUmxuIFxHfBJiF3rKFTCEFPPXG4ulIcmMT98uuZVVq4xDPk/hxm105xwHBFAwBng==", + "dependencies": { + "@firebase/auth": "0.23.1", + "@firebase/auth-types": "0.12.0", + "@firebase/component": "0.6.4", + "@firebase/util": "1.9.3", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", + "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" + }, + "node_modules/@firebase/auth-types": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz", + "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", + "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==", + "dependencies": { + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz", + "integrity": "sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==", + "dependencies": { + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz", + "integrity": "sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/database": "0.14.4", + "@firebase/database-types": "0.10.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz", + "integrity": "sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==", + "dependencies": { + "@firebase/app-types": "0.9.0", + "@firebase/util": "1.9.3" + } + }, + "node_modules/@firebase/firestore": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-3.11.0.tgz", + "integrity": "sha512-r9qUbjuIKOXAVYwqZaamgXuUJBuV8I2X0Kao5PUxQAPueV2mRapdIlby6awYgjknE8kq1Tlys5Nf5/TV6WtnAg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "@firebase/webchannel-wrapper": "0.10.0", + "@grpc/grpc-js": "~1.7.0", + "@grpc/proto-loader": "^0.6.13", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10.10.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/firestore-compat": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.8.tgz", + "integrity": "sha512-VrTckDEVBqFWFsHGVdQgCb0Tht/Rrg/nKFp2aat0FaIjr8A9t4Pfcuu32Py25SbiCnr98pyh3RmVYs0kbF/lCA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/firestore": "3.11.0", + "@firebase/firestore-types": "2.5.1", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.5.1.tgz", + "integrity": "sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/functions": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.9.4.tgz", + "integrity": "sha512-3H2qh6U+q+nepO5Hds+Ddl6J0pS+zisuBLqqQMRBHv9XpWfu0PnDHklNmE8rZ+ccTEXvBj6zjkPfdxt6NisvlQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.2.0", + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.4", + "@firebase/messaging-interop-types": "0.2.0", + "@firebase/util": "1.9.3", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/functions-compat": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.4.tgz", + "integrity": "sha512-kxVxTGyLV1MBR3sp3mI+eQ6JBqz0G5bk310F8eX4HzDFk4xjk5xY0KdHktMH+edM2xs1BOg0vwvvsAHczIjB+w==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/functions": "0.9.4", + "@firebase/functions-types": "0.6.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz", + "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==" + }, + "node_modules/@firebase/installations": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz", + "integrity": "sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/util": "1.9.3", + "idb": "7.0.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/installations-compat": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.4.tgz", + "integrity": "sha512-LI9dYjp0aT9Njkn9U4JRrDqQ6KXeAmFbRC0E7jI7+hxl5YmRWysq5qgQl22hcWpTk+cm3es66d/apoDU/A9n6Q==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.4", + "@firebase/installations-types": "0.5.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz", + "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/installations/node_modules/idb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", + "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==" + }, + "node_modules/@firebase/logger": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/messaging": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.4.tgz", + "integrity": "sha512-6JLZct6zUaex4g7HI3QbzeUrg9xcnmDAPTWpkoMpd/GoSVWH98zDoWXMGrcvHeCAIsLpFMe4MPoZkJbrPhaASw==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.4", + "@firebase/messaging-interop-types": "0.2.0", + "@firebase/util": "1.9.3", + "idb": "7.0.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/messaging-compat": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.4.tgz", + "integrity": "sha512-lyFjeUhIsPRYDPNIkYX1LcZMpoVbBWXX4rPl7c/rqc7G+EUea7IEtSt4MxTvh6fDfPuzLn7+FZADfscC+tNMfg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/messaging": "0.12.4", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz", + "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==" + }, + "node_modules/@firebase/messaging/node_modules/idb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", + "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==" + }, + "node_modules/@firebase/performance": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.4.tgz", + "integrity": "sha512-HfTn/bd8mfy/61vEqaBelNiNnvAbUtME2S25A67Nb34zVuCSCRIX4SseXY6zBnOFj3oLisaEqhVcJmVPAej67g==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/performance-compat": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.4.tgz", + "integrity": "sha512-nnHUb8uP9G8islzcld/k6Bg5RhX62VpbAb/Anj7IXs/hp32Eb2LqFPZK4sy3pKkBUO5wcrlRWQa6wKOxqlUqsg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/performance": "0.6.4", + "@firebase/performance-types": "0.2.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/performance-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz", + "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==" + }, + "node_modules/@firebase/remote-config": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.4.tgz", + "integrity": "sha512-x1ioTHGX8ZwDSTOVp8PBLv2/wfwKzb4pxi0gFezS5GCJwbLlloUH4YYZHHS83IPxnua8b6l0IXUaWd0RgbWwzQ==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/remote-config-compat": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.4.tgz", + "integrity": "sha512-FKiki53jZirrDFkBHglB3C07j5wBpitAaj8kLME6g8Mx+aq7u9P7qfmuSRytiOItADhWUj7O1JIv7n9q87SuwA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/remote-config": "0.4.4", + "@firebase/remote-config-types": "0.3.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz", + "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==" + }, + "node_modules/@firebase/storage": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.11.2.tgz", + "integrity": "sha512-CtvoFaBI4hGXlXbaCHf8humajkbXhs39Nbh6MbNxtwJiCqxPy9iH3D3CCfXAvP0QvAAwmJUTK3+z9a++Kc4nkA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/util": "1.9.3", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/storage-compat": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.2.tgz", + "integrity": "sha512-wvsXlLa9DVOMQJckbDNhXKKxRNNewyUhhbXev3t8kSgoCotd1v3MmqhKKz93ePhDnhHnDs7bYHy+Qa8dRY6BXw==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/storage": "0.11.2", + "@firebase/storage-types": "0.8.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz", + "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.0.tgz", + "integrity": "sha512-2I8y+vJVrPfPFJrnRGpao1Qc2Gu7wmYoo5ed2s5zK/DUGgcyY1Yr/xC0YdnKM4pi7rG3HqwW9ehAKUXoTMLdoA==" + }, + "node_modules/@grpc/grpc-js": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.7.3.tgz", + "integrity": "sha512-H9l79u4kJ2PVSxUNA08HMYAnUBLj9v6KjYQ7SQ71hOZcEXhShE/y5iQCesP8+6/Ik/7i2O0a10bPquIcYfufog==", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.7.tgz", + "integrity": "sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^7.0.0", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/grpc-js/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js/node_modules/protobufjs": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz", + "integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/protobufjs/node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/@grpc/grpc-js/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@heroicons/react": { "version": "2.0.17", "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.17.tgz", @@ -2076,9 +2679,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@next/env": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.0.tgz", - "integrity": "sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==" + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.1.tgz", + "integrity": "sha512-EDtCoedIZC7JlUQ3uaQpSc4aVmyhbLHmQVALg7pFfQgOTjgSnn7mKtA0DiCMkYvvsx6aFb5octGMtWrOtGXW9A==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.3.0", @@ -2089,9 +2692,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.0.tgz", - "integrity": "sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.1.tgz", + "integrity": "sha512-UXPtriEc/pBP8luSLSCZBcbzPeVv+SSjs9cH/KygTbhmACye8/OOXRZO13Z2Wq1G0gLmEAIHQAOuF+vafPd2lw==", "cpu": [ "arm64" ], @@ -2104,9 +2707,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.0.tgz", - "integrity": "sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.1.tgz", + "integrity": "sha512-lT36yYxosCfLtplFzJWgo0hrPu6/do8+msgM7oQkPeohDNdhjtjFUgOOwdSnPublLR6Mo2Ym4P/wl5OANuD2bw==", "cpu": [ "x64" ], @@ -2119,9 +2722,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.0.tgz", - "integrity": "sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.1.tgz", + "integrity": "sha512-wRb76nLWJhonH8s3kxC/1tFguEkeOPayIwe9mkaz1G/yeS3OrjeyKMJsb4+Kdg0zbTo53bNCOl59NNtDM7yyyw==", "cpu": [ "arm64" ], @@ -2134,9 +2737,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.0.tgz", - "integrity": "sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.1.tgz", + "integrity": "sha512-qz3BzjJRZ16Iq/jrp+pjiYOc0jTjHlfmxQmZk9x/+5uhRP6/eWQSTAPVJ33BMo6oK5O5N4644OgTAbzXzorecg==", "cpu": [ "arm64" ], @@ -2149,9 +2752,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.0.tgz", - "integrity": "sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.1.tgz", + "integrity": "sha512-6mgkLmwlyWlomQmpl21I3hxgqE5INoW4owTlcLpNsd1V4wP+J46BlI/5zV5KWWbzjfncIqzXoeGs5Eg+1GHODA==", "cpu": [ "x64" ], @@ -2164,9 +2767,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.0.tgz", - "integrity": "sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.1.tgz", + "integrity": "sha512-uqm5sielhQmKJM+qayIhgZv1KlS5pqTdQ99b+Z7hMWryXS96qE0DftTmMZowBcUL6x7s2vSXyH5wPtO1ON7LBg==", "cpu": [ "x64" ], @@ -2179,9 +2782,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.0.tgz", - "integrity": "sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.1.tgz", + "integrity": "sha512-WomIiTj/v3LevltlibNQKmvrOymNRYL+a0dp5R73IwPWN5FvXWwSELN/kiNALig/+T3luc4qHNTyvMCp9L6U5Q==", "cpu": [ "arm64" ], @@ -2194,9 +2797,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.0.tgz", - "integrity": "sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.1.tgz", + "integrity": "sha512-M+PoH+0+q658wRUbs285RIaSTYnGBSTdweH/0CdzDgA6Q4rBM0sQs4DHmO3BPP0ltCO/vViIoyG7ks66XmCA5g==", "cpu": [ "ia32" ], @@ -2209,9 +2812,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.0.tgz", - "integrity": "sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.1.tgz", + "integrity": "sha512-Sl1F4Vp5Z1rNXWZYqJwMuWRRol4bqOB6+/d7KqkgQ4AcafKPN1PZmpkCoxv4UFHtFNIB7EotnuIhtXu3zScicQ==", "cpu": [ "x64" ], @@ -2274,6 +2877,60 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "node_modules/@rushstack/eslint-patch": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", @@ -2533,9 +3190,9 @@ } }, "node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.0.tgz", + "integrity": "sha512-SjY/p4MmECVVEWspzSRpQEM3sjR17sP8PbGxELWrT+YZMBfiUyt1MRUNjMV23zohwlG2HYtCQOsCwsTHguXkyg==", "dependencies": { "tslib": "^2.4.0" } @@ -2554,6 +3211,11 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "node_modules/@types/node": { "version": "18.15.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.12.tgz", @@ -3163,6 +3825,16 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4141,6 +4813,17 @@ "reusify": "^1.0.4" } }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4178,6 +4861,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/firebase": { + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-9.21.0.tgz", + "integrity": "sha512-kQpT+YjusVhqj8feSmb+9Fpmyfy7ayGSd6GVk2k0qJjt+AwYgHZ9tuHuIgFdEHGsvqxYRZJpu067ck9ZQwbqQw==", + "dependencies": { + "@firebase/analytics": "0.10.0", + "@firebase/analytics-compat": "0.2.6", + "@firebase/app": "0.9.9", + "@firebase/app-check": "0.7.0", + "@firebase/app-check-compat": "0.3.6", + "@firebase/app-compat": "0.2.9", + "@firebase/app-types": "0.9.0", + "@firebase/auth": "0.23.1", + "@firebase/auth-compat": "0.4.1", + "@firebase/database": "0.14.4", + "@firebase/database-compat": "0.3.4", + "@firebase/firestore": "3.11.0", + "@firebase/firestore-compat": "0.3.8", + "@firebase/functions": "0.9.4", + "@firebase/functions-compat": "0.3.4", + "@firebase/installations": "0.6.4", + "@firebase/installations-compat": "0.2.4", + "@firebase/messaging": "0.12.4", + "@firebase/messaging-compat": "0.2.4", + "@firebase/performance": "0.6.4", + "@firebase/performance-compat": "0.2.4", + "@firebase/remote-config": "0.4.4", + "@firebase/remote-config-compat": "0.2.4", + "@firebase/storage": "0.11.2", + "@firebase/storage-compat": "0.3.2", + "@firebase/util": "1.9.3" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -4272,6 +4988,14 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", @@ -4490,6 +5214,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -4677,6 +5411,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -5005,6 +5747,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -5016,6 +5763,11 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -5121,12 +5873,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/next": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/next/-/next-13.3.0.tgz", - "integrity": "sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/next/-/next-13.3.1.tgz", + "integrity": "sha512-eByWRxPzKHs2oQz1yE41LX35umhz86ZSZ+mYyXBqn2IBi2hyUqxBA88avywdr4uyH+hCJczegGsDGWbzQA5Rqw==", "dependencies": { - "@next/env": "13.3.0", - "@swc/helpers": "0.4.14", + "@next/env": "13.3.1", + "@swc/helpers": "0.5.0", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", @@ -5136,18 +5888,18 @@ "next": "dist/bin/next" }, "engines": { - "node": ">=14.6.0" + "node": ">=14.18.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.3.0", - "@next/swc-darwin-x64": "13.3.0", - "@next/swc-linux-arm64-gnu": "13.3.0", - "@next/swc-linux-arm64-musl": "13.3.0", - "@next/swc-linux-x64-gnu": "13.3.0", - "@next/swc-linux-x64-musl": "13.3.0", - "@next/swc-win32-arm64-msvc": "13.3.0", - "@next/swc-win32-ia32-msvc": "13.3.0", - "@next/swc-win32-x64-msvc": "13.3.0" + "@next/swc-darwin-arm64": "13.3.1", + "@next/swc-darwin-x64": "13.3.1", + "@next/swc-linux-arm64-gnu": "13.3.1", + "@next/swc-linux-arm64-musl": "13.3.1", + "@next/swc-linux-x64-gnu": "13.3.1", + "@next/swc-linux-x64-musl": "13.3.1", + "@next/swc-win32-arm64-msvc": "13.3.1", + "@next/swc-win32-ia32-msvc": "13.3.1", + "@next/swc-win32-x64-msvc": "13.3.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -5195,6 +5947,25 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-releases": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", @@ -5629,6 +6400,31 @@ "react-is": "^16.13.1" } }, + "node_modules/protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -5800,6 +6596,14 @@ "jsesc": "bin/jsesc" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", @@ -5869,6 +6673,25 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -5971,6 +6794,24 @@ "node": ">=10.0.0" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/string.prototype.matchall": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", @@ -6329,6 +7170,11 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -6512,6 +7358,41 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6582,11 +7463,35 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -6600,6 +7505,31 @@ "node": ">= 6" } }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index b64670d..0c89190 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "autoprefixer": "10.4.14", "eslint": "8.38.0", "eslint-config-next": "13.3.0", - "next": "13.3.0", + "firebase": "^9.21.0", + "next": "13.3.1", "postcss": "8.4.23", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/services/firebase.tsx b/services/firebase.tsx new file mode 100644 index 0000000..39e72eb --- /dev/null +++ b/services/firebase.tsx @@ -0,0 +1,25 @@ +// Import the functions you need from the SDKs you need
+import { initializeApp, getApps } from "firebase/app";
+import { getAnalytics } from "firebase/analytics";
+import { getAuth } from 'firebase/auth'
+// TODO: Add SDKs for Firebase products that you want to use
+// https://firebase.google.com/docs/web/setup#available-libraries
+
+// Your web app's Firebase configuration
+// For Firebase JS SDK v7.20.0 and later, measurementId is optional
+const firebaseConfig = {
+ apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
+ authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
+ projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
+ storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
+ messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGIN_SENDER_ID,
+ appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
+ measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
+};
+
+// Initialize Firebase
+const app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];
+export const auth = getAuth(app) ;
+if (typeof window != 'undefined'){
+ const analytics = getAnalytics(app)
+}
diff --git a/services/requests.tsx b/services/requests.tsx index f77581d..b11982d 100644 --- a/services/requests.tsx +++ b/services/requests.tsx @@ -1,8 +1,9 @@ -const API_KEY = '8216fbb9997cd81a67471e6cb5a6f2df' - -const requests = { - fetchTopRated: `/movie/top_rated?api_key=${API_KEY}`, - fetchTrending: `/trending/movie/day?api_key=${API_KEY}`, -} - +const API_KEY = '8216fbb9997cd81a67471e6cb5a6f2df'
+
+const requests = {
+ fetchTopRated: `/movie/top_rated?api_key=${API_KEY}`,
+ fetchTrendingMovies: `/trending/movie/day?api_key=${API_KEY}`,
+ fetchTrendingTv: `/trending/tv/day?api_key=${API_KEY}`,
+}
+
export default requests
\ No newline at end of file diff --git a/src/components/Genre.tsx b/src/components/Genre.tsx deleted file mode 100644 index e63a26a..0000000 --- a/src/components/Genre.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useEffect, useState } from "react" - -const Genres = ({id}) => { - - const baseURL = 'https://api.themoviedb.org/3' - const API_KEY = '8216fbb9997cd81a67471e6cb5a6f2df' - const [genres, setGenres] = useState() - - useEffect(() => { - fetch(`${baseURL}/movie/${id}?api_key=${API_KEY}`).then((res) => res.json()).then((data) => { - console.log('MOVIE', data.genres) - setGenres(data.genres) - }) - }, []) - - return ( - <div className="text-white/60 gap-x-3 text-xs flex flex-row flex-wrap relative"> - {genres?.map((genre) => { - return ( - <div>{genre.name}</div> - ) - })} - </div> - ) -} - -export default Genres
\ No newline at end of file diff --git a/src/components/PreviewCard.tsx b/src/components/PreviewCard.tsx deleted file mode 100644 index 5c4129f..0000000 --- a/src/components/PreviewCard.tsx +++ /dev/null @@ -1,19 +0,0 @@ -const imageURL = 'https://image.tmdb.org/t/p/original'; -import Genre from "./Genre"; -const baseURL ='https://api.themoviedb.org/3/' - -const PreviewCard = ({ movie }) => { - return ( - <div className="hover:z-10"> - <div className="rounded ring-white hover:ring-4 flex-col p-1 relative bg-cover h-32 w-60 shrink-0 flex justify-end cursor-pointer hover:scale-125 transition ease-in-out" style={{backgroundImage: `url(${imageURL}${movie?.backdrop_path})`}}> - <div className="absolute h-full w-full inset-0 bg-gradient-to-t from-black/70"></div> - <h3 className={"text-white text-sm relative"}> - {movie.original_title} - </h3> - <Genre id={movie.id}/> - </div> - </div> - )} - - -export default PreviewCard
\ No newline at end of file diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index e57ed44..c055f25 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,4 +1,4 @@ -import '@prueba/styles/globals.css' +import '../styles/globals.css' import type { AppProps } from 'next/app' export default function App({ Component, pageProps }: AppProps) { diff --git a/src/styles/globals.css b/src/styles/globals.css index 9fbd6c7..ccea7d8 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -22,4 +22,5 @@ body { ::-webkit-scrollbar { width: 0px; + display: none; }
\ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index fba2ad6..00649fb 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -4,6 +4,7 @@ module.exports = { './src/pages/**/*.{js,ts,jsx,tsx}', './src/components/**/*.{js,ts,jsx,tsx}', './src/app/**/*.{js,ts,jsx,tsx}', + './app/**/*.{js,ts,jsx,tsx}', ], theme: { extend: { diff --git a/tsconfig.json b/tsconfig.json index c068872..0f5c44e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -15,9 +19,23 @@ "jsx": "preserve", "incremental": true, "paths": { - "@prueba/*": ["./src/*"] - } + "@prueba/*": [ + "./src/*" + ] + }, + "plugins": [ + { + "name": "next" + } + ] }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] -} + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +}
|