(null)
20 | const [loading, setLoading] = useState(true)
21 | console.log(user)
22 |
23 | useEffect(() => {
24 | const unsubscribe = onAuthStateChanged(auth, (user) => {
25 | if (user) {
26 | setUser({
27 | uid: user.uid,
28 | email: user.email,
29 | displayName: user.displayName,
30 | })
31 | } else {
32 | setUser(null)
33 | }
34 | setLoading(false)
35 | })
36 |
37 | return () => unsubscribe()
38 | }, [])
39 |
40 | const signup = (email: string, password: string) => {
41 | return createUserWithEmailAndPassword(auth, email, password)
42 | }
43 |
44 | const login = (email: string, password: string) => {
45 | return signInWithEmailAndPassword(auth, email, password)
46 | }
47 |
48 | const logout = async () => {
49 | setUser(null)
50 | await signOut(auth)
51 | }
52 |
53 | return (
54 |
55 | {loading ? null : children}
56 |
57 | )
58 | }
59 |
--------------------------------------------------------------------------------
/pages/signup.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import { Button, Form } from 'react-bootstrap'
3 | import { useAuth } from '../context/AuthContext'
4 |
5 | const Signup = () => {
6 | const { user, signup } = useAuth()
7 | console.log(user)
8 | const [data, setData] = useState({
9 | email: '',
10 | password: '',
11 | })
12 |
13 | const handleSignup = async (e: any) => {
14 | e.preventDefault()
15 |
16 | try {
17 | await signup(data.email, data.password)
18 | } catch (err) {
19 | console.log(err)
20 | }
21 |
22 | console.log(data)
23 | }
24 |
25 | return (
26 |
32 |
Signup
33 |
35 | Email address
36 |
41 | setData({
42 | ...data,
43 | email: e.target.value,
44 | })
45 | }
46 | value={data.email}
47 | />
48 |
49 |
50 |
51 | Password
52 |
57 | setData({
58 | ...data,
59 | password: e.target.value,
60 | })
61 | }
62 | value={data.password}
63 | />
64 |
65 |
66 |
69 |
70 |
71 | )
72 | }
73 |
74 | export default Signup
75 |
--------------------------------------------------------------------------------
/pages/login.tsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from 'next/router'
2 | import React, { useState } from 'react'
3 | import { Button, Form } from 'react-bootstrap'
4 | import { useAuth } from '../context/AuthContext'
5 |
6 | const Login = () => {
7 | const router = useRouter()
8 | const { user, login } = useAuth()
9 | const [data, setData] = useState({
10 | email: '',
11 | password: '',
12 | })
13 |
14 | const handleLogin = async (e: any) => {
15 | e.preventDefault()
16 |
17 | console.log(user)
18 | try {
19 | await login(data.email, data.password)
20 | router.push('/dashboard')
21 | } catch (err) {
22 | console.log(err)
23 | }
24 | }
25 |
26 | return (
27 |
33 |
Login
34 |
36 | Email address
37 |
39 | setData({
40 | ...data,
41 | email: e.target.value,
42 | })
43 | }
44 | value={data.email}
45 | required
46 | type="email"
47 | placeholder="Enter email"
48 | />
49 |
50 |
51 |
52 | Password
53 |
55 | setData({
56 | ...data,
57 | password: e.target.value,
58 | })
59 | }
60 | value={data.password}
61 | required
62 | type="password"
63 | placeholder="Password"
64 | />
65 |
66 |
69 |
70 |
71 | )
72 | }
73 |
74 | export default Login
75 |
--------------------------------------------------------------------------------
/styles/Home.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | padding: 0 2rem;
3 | }
4 |
5 | .main {
6 | min-height: 100vh;
7 | padding: 4rem 0;
8 | flex: 1;
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
15 | .footer {
16 | display: flex;
17 | flex: 1;
18 | padding: 2rem 0;
19 | border-top: 1px solid #eaeaea;
20 | justify-content: center;
21 | align-items: center;
22 | }
23 |
24 | .footer a {
25 | display: flex;
26 | justify-content: center;
27 | align-items: center;
28 | flex-grow: 1;
29 | }
30 |
31 | .title a {
32 | color: #0070f3;
33 | text-decoration: none;
34 | }
35 |
36 | .title a:hover,
37 | .title a:focus,
38 | .title a:active {
39 | text-decoration: underline;
40 | }
41 |
42 | .title {
43 | margin: 0;
44 | line-height: 1.15;
45 | font-size: 4rem;
46 | }
47 |
48 | .title,
49 | .description {
50 | text-align: center;
51 | }
52 |
53 | .description {
54 | margin: 4rem 0;
55 | line-height: 1.5;
56 | font-size: 1.5rem;
57 | }
58 |
59 | .code {
60 | background: #fafafa;
61 | border-radius: 5px;
62 | padding: 0.75rem;
63 | font-size: 1.1rem;
64 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
65 | Bitstream Vera Sans Mono, Courier New, monospace;
66 | }
67 |
68 | .grid {
69 | display: flex;
70 | align-items: center;
71 | justify-content: center;
72 | flex-wrap: wrap;
73 | max-width: 800px;
74 | }
75 |
76 | .card {
77 | margin: 1rem;
78 | padding: 1.5rem;
79 | text-align: left;
80 | color: inherit;
81 | text-decoration: none;
82 | border: 1px solid #eaeaea;
83 | border-radius: 10px;
84 | transition: color 0.15s ease, border-color 0.15s ease;
85 | max-width: 300px;
86 | }
87 |
88 | .card:hover,
89 | .card:focus,
90 | .card:active {
91 | color: #0070f3;
92 | border-color: #0070f3;
93 | }
94 |
95 | .card h2 {
96 | margin: 0 0 1rem 0;
97 | font-size: 1.5rem;
98 | }
99 |
100 | .card p {
101 | margin: 0;
102 | font-size: 1.25rem;
103 | line-height: 1.5;
104 | }
105 |
106 | .logo {
107 | height: 1em;
108 | margin-left: 0.5rem;
109 | }
110 |
111 | @media (max-width: 600px) {
112 | .grid {
113 | width: 100%;
114 | flex-direction: column;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------