-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
88ae575
commit 4497690
Showing
9 changed files
with
342 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<div className="flex flex-col min-h-screen"> | ||
<header className="p-4 shadow"> | ||
<div className="flex items-center justify-between"> | ||
<Link href="/" passHref> | ||
<A href="#!"> | ||
<img src="logo.png" alt="Cremona" className="h-12" /> | ||
</A> | ||
</Link> | ||
<div className="flex">{user ? <LoggedOut /> : <LoggedIn />}</div> | ||
</div> | ||
</header> | ||
<main className="flex-1 p-4">{children}</main> | ||
<footer className="p-4"> | ||
<p className="text-center"> | ||
<span>Created by </span> | ||
<Link href="/signin" passHref> | ||
<A | ||
href="http://twitter.com/durancristhian" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
@durancristhian | ||
</A> | ||
</Link> | ||
</p> | ||
</footer> | ||
</div> | ||
) | ||
} | ||
|
||
export default Layout | ||
|
||
function LoggedIn() { | ||
return ( | ||
<> | ||
<Link href="/signin" passHref> | ||
<A href="#!">Sign in</A> | ||
</Link> | ||
<div className="ml-4"> | ||
<Link href="/signup" passHref> | ||
<A href="#!">Sign up</A> | ||
</Link> | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
function LoggedOut() { | ||
const { signout } = useAuth() | ||
|
||
return ( | ||
<> | ||
<button | ||
onClick={() => { | ||
signout() | ||
}} | ||
className="text-blue-700" | ||
> | ||
Sing out | ||
</button> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<> | ||
<div className="mb-4"> | ||
<h1>{mode === 'signin' ? 'Sign In' : 'Sign Up'}</h1> | ||
</div> | ||
<form onSubmit={onSubmit}> | ||
<fieldset disabled={inProgress}> | ||
<div className="mb-4"> | ||
<input | ||
type="email" | ||
name="email" | ||
id="email" | ||
value={formData.email} | ||
onChange={({ target }) => { | ||
setFormData({ | ||
...formData, | ||
email: target.value, | ||
}) | ||
}} | ||
placeholder="Email" | ||
autoComplete="email" | ||
className="block px-4 py-2 shadow w-full" | ||
/> | ||
</div> | ||
<div className="mb-4"> | ||
<input | ||
type="password" | ||
name="password" | ||
id="password" | ||
value={formData.password} | ||
onChange={({ target }) => { | ||
setFormData({ | ||
...formData, | ||
password: target.value, | ||
}) | ||
}} | ||
placeholder="Password" | ||
autoComplete="current-password" | ||
className="block px-4 py-2 shadow w-full" | ||
/> | ||
</div> | ||
<div className="text-center"> | ||
<button | ||
type="submit" | ||
className="border bg-blue-200 border-blue-500 px-4 py-2 disabled:opacity-50" | ||
disabled={!formData.email || !formData.password} | ||
> | ||
{mode === 'signin' ? 'Sign In' : 'Sign Up'} | ||
</button> | ||
</div> | ||
{message && ( | ||
<div className="mt-4 text-center"> | ||
<p className="italic">{message}</p> | ||
</div> | ||
)} | ||
</fieldset> | ||
</form> | ||
</> | ||
) | ||
} | ||
|
||
export default Login |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<firebase.User | null> | ||
signup: (email: string, password: string) => Promise<firebase.User | null> | ||
signout: () => Promise<void> | ||
} | ||
|
||
const defaultContextData = { | ||
user: null, | ||
signin: () => Promise.resolve(null), | ||
signup: () => Promise.resolve(null), | ||
signout: () => Promise.resolve(void 0), | ||
} | ||
|
||
const AuthContext = createContext<ContextData>(defaultContextData) | ||
|
||
type Props = { | ||
children: ReactNode | ||
} | ||
|
||
export function ProvideAuth({ children }: Props) { | ||
const auth = useProvideAuth() | ||
|
||
return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider> | ||
} | ||
|
||
export const useAuth = () => { | ||
return useContext(AuthContext) | ||
} | ||
|
||
function useProvideAuth() { | ||
const [user, setUser] = useState<firebase.User | null>(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, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <Component {...pageProps} /> | ||
return ( | ||
<FuegoProvider fuego={fuego}> | ||
<ProvideAuth> | ||
<Layout> | ||
<Component {...pageProps} /> | ||
</Layout> | ||
</ProvideAuth> | ||
</FuegoProvider> | ||
) | ||
} | ||
|
||
export default App |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,8 @@ | ||
import React from 'react' | ||
import { useAuth } from '../hooks/useAuth' | ||
|
||
export default function Index() { | ||
return ( | ||
<> | ||
<img src="logo.png" alt="Cremona" /> | ||
<h1>Cremona</h1> | ||
</> | ||
) | ||
const { user } = useAuth() | ||
|
||
return <div className="p-4">{user ? 'Hello' : null}</div> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react' | ||
import Login from '../components/Login' | ||
|
||
const SignIn = () => { | ||
return ( | ||
<> | ||
<Login mode="signin"></Login> | ||
</> | ||
) | ||
} | ||
|
||
export default SignIn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react' | ||
import Login from '../components/Login' | ||
|
||
const SignUp = () => { | ||
return ( | ||
<> | ||
<Login mode="signup"></Login> | ||
</> | ||
) | ||
} | ||
|
||
export default SignUp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React, { AnchorHTMLAttributes, forwardRef, ReactNode, Ref } from 'react' | ||
|
||
type Props = AnchorHTMLAttributes<HTMLAnchorElement> & { | ||
children: ReactNode | ||
} | ||
|
||
const A = forwardRef( | ||
({ children, ...rest }: Props, ref: Ref<HTMLAnchorElement>) => { | ||
return ( | ||
<a ref={ref} {...rest} className="text-blue-700"> | ||
{children} | ||
</a> | ||
) | ||
}, | ||
) | ||
|
||
A.displayName = 'A' | ||
|
||
export default A |
4497690
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: