diff --git a/components/Layout.tsx b/components/Layout.tsx
new file mode 100644
index 0000000..2bd6e5d
--- /dev/null
+++ b/components/Layout.tsx
@@ -0,0 +1,76 @@
+import Link from 'next/link'
+import React, { ReactNode } from 'react'
+import A from '../ui/A'
+import { useAuth } from '../hooks/useAuth'
+
+type Props = {
+ children: ReactNode
+}
+
+const Layout = ({ children }: Props) => {
+ const { user } = useAuth()
+
+ return (
+
+
+
+
+
+
+
+
+
{user ? : }
+
+
+
{children}
+
+
+ )
+}
+
+export default Layout
+
+function LoggedIn() {
+ return (
+ <>
+
+ Sign in
+
+
+ >
+ )
+}
+
+function LoggedOut() {
+ const { signout } = useAuth()
+
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/components/Login.tsx b/components/Login.tsx
new file mode 100644
index 0000000..c5e24a9
--- /dev/null
+++ b/components/Login.tsx
@@ -0,0 +1,105 @@
+import { useRouter } from 'next/router'
+import React, { FormEvent, useState } from 'react'
+import { useAuth } from '../hooks/useAuth'
+
+type LoginMode = 'signin' | 'signup'
+
+type Props = {
+ mode: LoginMode
+}
+
+const Login = ({ mode }: Props) => {
+ const router = useRouter()
+ const [formData, setFormData] = useState({
+ email: '',
+ password: '',
+ })
+ const [inProgress, setInProgress] = useState(false)
+ const [message, setMessage] = useState('')
+ const { signin, signup } = useAuth()
+
+ const onSubmit = (event: FormEvent) => {
+ event.preventDefault()
+
+ setInProgress(true)
+ setMessage('Processing...')
+
+ const method = mode === 'signin' ? signin : signup
+
+ method(formData.email, formData.password)
+ .then(() => {
+ setInProgress(false)
+ setMessage('')
+
+ router.push('/')
+ })
+ .catch((error: Error) => {
+ console.error(error)
+
+ setInProgress(false)
+ setMessage(error.message)
+ })
+ }
+
+ return (
+ <>
+
+
{mode === 'signin' ? 'Sign In' : 'Sign Up'}
+
+
+ >
+ )
+}
+
+export default Login
diff --git a/hooks/useAuth.tsx b/hooks/useAuth.tsx
new file mode 100644
index 0000000..21e8dc3
--- /dev/null
+++ b/hooks/useAuth.tsx
@@ -0,0 +1,86 @@
+import { fuego } from '@nandorojo/swr-firestore'
+import React, {
+ createContext,
+ ReactNode,
+ useContext,
+ useEffect,
+ useState,
+} from 'react'
+
+type ContextData = {
+ user: firebase.User | null
+ signin: (email: string, password: string) => Promise
+ signup: (email: string, password: string) => Promise
+ signout: () => Promise
+}
+
+const defaultContextData = {
+ user: null,
+ signin: () => Promise.resolve(null),
+ signup: () => Promise.resolve(null),
+ signout: () => Promise.resolve(void 0),
+}
+
+const AuthContext = createContext(defaultContextData)
+
+type Props = {
+ children: ReactNode
+}
+
+export function ProvideAuth({ children }: Props) {
+ const auth = useProvideAuth()
+
+ return {children}
+}
+
+export const useAuth = () => {
+ return useContext(AuthContext)
+}
+
+function useProvideAuth() {
+ const [user, setUser] = useState(null)
+
+ const signin = (email: string, password: string) => {
+ return fuego
+ .auth()
+ .signInWithEmailAndPassword(email, password)
+ .then((response) => {
+ setUser(response.user)
+ return response.user
+ })
+ }
+
+ const signup = (email: string, password: string) => {
+ return fuego
+ .auth()
+ .createUserWithEmailAndPassword(email, password)
+ .then((response) => {
+ setUser(response.user)
+ return response.user
+ })
+ }
+
+ const signout = () => {
+ return fuego
+ .auth()
+ .signOut()
+ .then(() => {
+ setUser(null)
+ })
+ }
+
+ useEffect(() => {
+ const unsubscribe = fuego.auth().onAuthStateChanged((user) => {
+ setUser(user)
+ })
+
+ return () => unsubscribe()
+ }, [])
+
+ return {
+ user,
+ signin,
+ signup,
+ signout,
+ }
+}
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 73fce5d..1117b29 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,9 +1,35 @@
+import { Fuego, FuegoProvider } from '@nandorojo/swr-firestore'
+import 'firebase/auth'
+import 'firebase/firestore'
import { AppProps } from 'next/app'
import React from 'react'
+import Layout from '../components/Layout'
+import { ProvideAuth } from '../hooks/useAuth'
import '../styles/globals.css'
+const firebaseConfig = {
+ apiKey: process.env.NEXT_PUBLIC_API_KEY,
+ authDomain: process.env.NEXT_PUBLIC_AUTH_DOMAIN,
+ databaseURL: process.env.NEXT_PUBLIC_DATABASE_URL,
+ projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
+ storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
+ messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID,
+ appId: process.env.NEXT_PUBLIC_APP_ID,
+ measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID,
+}
+
+const fuego = new Fuego(firebaseConfig)
+
const App = ({ Component, pageProps }: AppProps) => {
- return
+ return (
+
+
+
+
+
+
+
+ )
}
export default App
diff --git a/pages/_document.tsx b/pages/_document.tsx
index e7535c5..496e2b5 100644
--- a/pages/_document.tsx
+++ b/pages/_document.tsx
@@ -8,7 +8,7 @@ class MyDocument extends Document {
-
+
diff --git a/pages/index.tsx b/pages/index.tsx
index 97e513d..b6c2cc0 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -1,10 +1,8 @@
import React from 'react'
+import { useAuth } from '../hooks/useAuth'
export default function Index() {
- return (
- <>
-
- Cremona
- >
- )
+ const { user } = useAuth()
+
+ return {user ? 'Hello' : null}
}
diff --git a/pages/signin.tsx b/pages/signin.tsx
new file mode 100644
index 0000000..357aae8
--- /dev/null
+++ b/pages/signin.tsx
@@ -0,0 +1,12 @@
+import React from 'react'
+import Login from '../components/Login'
+
+const SignIn = () => {
+ return (
+ <>
+
+ >
+ )
+}
+
+export default SignIn
diff --git a/pages/signup.tsx b/pages/signup.tsx
new file mode 100644
index 0000000..99d3175
--- /dev/null
+++ b/pages/signup.tsx
@@ -0,0 +1,12 @@
+import React from 'react'
+import Login from '../components/Login'
+
+const SignUp = () => {
+ return (
+ <>
+
+ >
+ )
+}
+
+export default SignUp
diff --git a/ui/A.tsx b/ui/A.tsx
new file mode 100644
index 0000000..c4944bb
--- /dev/null
+++ b/ui/A.tsx
@@ -0,0 +1,19 @@
+import React, { AnchorHTMLAttributes, forwardRef, ReactNode, Ref } from 'react'
+
+type Props = AnchorHTMLAttributes & {
+ children: ReactNode
+}
+
+const A = forwardRef(
+ ({ children, ...rest }: Props, ref: Ref) => {
+ return (
+
+ {children}
+
+ )
+ },
+)
+
+A.displayName = 'A'
+
+export default A