@@ -7,7 +7,13 @@ import {
7
7
useSuspenseQuery ,
8
8
} from "@tanstack/react-query" ;
9
9
import { ReactQueryDevtools } from "@tanstack/react-query-devtools" ;
10
- import { ConvexProvider , ConvexReactClient } from "convex/react" ;
10
+ import {
11
+ Authenticated ,
12
+ AuthLoading ,
13
+ ConvexProvider ,
14
+ ConvexReactClient ,
15
+ Unauthenticated ,
16
+ } from "convex/react" ;
11
17
import ReactDOM from "react-dom/client" ;
12
18
import {
13
19
ConvexQueryClient ,
@@ -18,6 +24,7 @@ import {
18
24
import "./index.css" ;
19
25
import { FormEvent , useState } from "react" ;
20
26
import { api } from "../convex/_generated/api.js" ;
27
+ import { ConvexAuthProvider , useAuthActions } from "@convex-dev/auth/react" ;
21
28
22
29
// Build a global convexClient wherever you would normally create a TanStack Query client.
23
30
const convexClient = new ConvexReactClient ( import . meta. env . VITE_CONVEX_URL ) ;
@@ -38,12 +45,63 @@ convexQueryClient.connect(queryClient);
38
45
39
46
function Main ( ) {
40
47
return (
41
- < ConvexProvider client = { convexClient } >
48
+ < ConvexAuthProvider client = { convexClient } >
42
49
< QueryClientProvider client = { queryClient } >
43
- < App />
50
+ < AuthLoading >
51
+ < div > Loading...</ div >
52
+ </ AuthLoading >
53
+ < Unauthenticated >
54
+ < SignIn />
55
+ </ Unauthenticated >
56
+ < Authenticated >
57
+ < App />
58
+ </ Authenticated >
44
59
< ReactQueryDevtools initialIsOpen />
45
60
</ QueryClientProvider >
46
- </ ConvexProvider >
61
+ </ ConvexAuthProvider >
62
+ ) ;
63
+ }
64
+
65
+ function SignIn ( ) {
66
+ const { signIn } = useAuthActions ( ) ;
67
+ const [ step , setStep ] = useState < "signUp" | "signIn" > ( "signIn" ) ;
68
+ return (
69
+ < div className = "signin-container" >
70
+ < form
71
+ className = "signin-form"
72
+ onSubmit = { ( event ) => {
73
+ event . preventDefault ( ) ;
74
+ const formData = new FormData ( event . currentTarget ) ;
75
+ void signIn ( "password" , formData ) ;
76
+ } }
77
+ >
78
+ < input
79
+ name = "email"
80
+ placeholder = "Email"
81
+ type = "text"
82
+ className = "signin-input"
83
+ />
84
+ < input
85
+ name = "password"
86
+ placeholder = "Password"
87
+ type = "password"
88
+ className = "signin-input"
89
+ />
90
+ < input name = "flow" type = "hidden" value = { step } />
91
+ < button type = "submit" >
92
+ { step === "signIn" ? "Sign in" : "Sign up" }
93
+ </ button >
94
+ < button
95
+ type = "button"
96
+ className = "signin-secondary"
97
+ onClick = { ( ) => {
98
+ setStep ( step === "signIn" ? "signUp" : "signIn" ) ;
99
+ } }
100
+ >
101
+ { step === "signIn" ? "Sign up instead" : "Sign in instead" }
102
+ </ button >
103
+ </ form >
104
+ </ div >
47
105
) ;
48
106
}
49
107
@@ -90,22 +148,30 @@ function MessageCount() {
90
148
}
91
149
92
150
function App ( ) {
151
+ const { signOut } = useAuthActions ( ) ;
93
152
const { data, error, isPending } = useQuery ( {
94
153
// This query updates reactively.
95
154
...convexQuery ( api . messages . list , { } ) ,
96
155
initialData : [ ] ,
97
156
} ) ;
157
+ const {
158
+ data : user ,
159
+ error : userError ,
160
+ isPending : userIsPending ,
161
+ } = useQuery ( {
162
+ ...convexQuery ( api . user . getCurrent , { } ) ,
163
+ initialData : null ,
164
+ } ) ;
98
165
99
166
const [ newMessageText , setNewMessageText ] = useState ( "" ) ;
100
167
const { mutate, isPending : sending } = useMutation ( {
101
168
mutationFn : useConvexMutation ( api . messages . send ) ,
102
169
} ) ;
103
- const [ name ] = useState ( ( ) => "User " + Math . floor ( Math . random ( ) * 10000 ) ) ;
104
170
async function handleSendMessage ( event : FormEvent ) {
105
171
event . preventDefault ( ) ;
106
172
if ( ! sending && newMessageText ) {
107
173
mutate (
108
- { body : newMessageText , author : name } ,
174
+ { body : newMessageText , author : user ?. _id } ,
109
175
{
110
176
onSuccess : ( ) => setNewMessageText ( "" ) ,
111
177
} ,
@@ -120,16 +186,19 @@ function App() {
120
186
}
121
187
return (
122
188
< main >
189
+ < button type = "button" onClick = { ( ) => void signOut ( ) } >
190
+ Sign out
191
+ </ button >
123
192
< h1 > Convex Chat</ h1 >
124
193
< Weather />
125
194
< MessageCount />
126
195
< p className = "badge" >
127
- < span > { name } </ span >
196
+ < span > { user ?. email } </ span >
128
197
</ p >
129
198
< ul >
130
199
{ data . map ( ( message ) => (
131
200
< li key = { message . _id } >
132
- < span > { message . author } :</ span >
201
+ < span > { message . authorEmail } :</ span >
133
202
< span > { message . body } </ span >
134
203
< span > { new Date ( message . _creationTime ) . toLocaleTimeString ( ) } </ span >
135
204
</ li >
0 commit comments