11import React , { useMemo , createContext , useContext , useState , useCallback , useEffect } from "react" ;
22
3+ import { useQuery } from "@tanstack/react-query" ;
34import { GraphQLClient } from "graphql-request" ;
45import { decodeJwt } from "jose" ;
56import { useAccount , useChainId , useSignMessage } from "wagmi" ;
67
78import { useSessionStorage } from "hooks/useSessionStorage" ;
8- import { createMessage , getNonce , loginUser } from "utils/atlas" ;
9+ import {
10+ createMessage ,
11+ getNonce ,
12+ loginUser ,
13+ addUser as addUserToAtlas ,
14+ fetchUser ,
15+ updateUser as updateUserInAtlas ,
16+ type User ,
17+ type AddUserData ,
18+ type UpdateUserData ,
19+ } from "utils/atlas" ;
20+
21+ import { isUndefined } from "src/utils" ;
922
1023interface IAtlasProvider {
1124 isVerified : boolean ;
1225 isSigningIn : boolean ;
13-
26+ isAddingUser : boolean ;
27+ isFetchingUser : boolean ;
28+ isUpdatingUser : boolean ;
29+ user : User | undefined ;
30+ userExists : boolean ;
1431 authoriseUser : ( ) => void ;
32+ addUser : ( userSettings : AddUserData ) => Promise < boolean > ;
33+ updateUser : ( userSettings : UpdateUserData ) => Promise < boolean > ;
1534}
1635
1736const Context = createContext < IAtlasProvider | undefined > ( undefined ) ;
@@ -26,13 +45,15 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
2645 const chainId = useChainId ( ) ;
2746 const [ authToken , setAuthToken ] = useSessionStorage < string | undefined > ( "authToken" , undefined ) ;
2847 const [ isSigningIn , setIsSigningIn ] = useState ( false ) ;
48+ const [ isAddingUser , setIsAddingUser ] = useState ( false ) ;
49+ const [ isUpdatingUser , setIsUpdatingUser ] = useState ( false ) ;
2950 const [ isVerified , setIsVerified ] = useState ( false ) ;
3051 const { signMessageAsync } = useSignMessage ( ) ;
3152
3253 const atlasGqlClient = useMemo ( ( ) => {
3354 const headers = authToken
3455 ? {
35- authorization : authToken ,
56+ authorization : `Bearer ${ authToken } ` ,
3657 }
3758 : undefined ;
3859 return new GraphQLClient ( atlasUri , { headers } ) ;
@@ -71,6 +92,30 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
7192 } ;
7293 } , [ authToken , verifySession ] ) ;
7394
95+ const {
96+ data : user ,
97+ isLoading : isFetchingUser ,
98+ refetch : refetchUser ,
99+ } = useQuery ( {
100+ queryKey : [ `UserSettings` ] ,
101+ enabled : isVerified && ! isUndefined ( address ) ,
102+ staleTime : Infinity ,
103+ queryFn : async ( ) => {
104+ try {
105+ if ( ! isVerified || isUndefined ( address ) ) return undefined ;
106+ return await fetchUser ( atlasGqlClient , address ) ;
107+ } catch {
108+ return undefined ;
109+ }
110+ } ,
111+ } ) ;
112+
113+ // this would change based on the fields we have and what defines a user to be existing
114+ const userExists = useMemo ( ( ) => {
115+ if ( ! user ) return false ;
116+ return user . email ? true : false ;
117+ } , [ user ] ) ;
118+
74119 /**
75120 * @description authorise user and enable authorised calls
76121 */
@@ -94,9 +139,86 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
94139 }
95140 } , [ address , chainId , setAuthToken , signMessageAsync , atlasGqlClient ] ) ;
96141
142+ /**
143+ * @description adds a new user to atlas
144+ * @param {AddUserData } userSettings - object containing data to be added
145+ * @returns {Promise<boolean> } A promise that resolves to true if the user was added successfully
146+ */
147+ const addUser = useCallback (
148+ async ( userSettings : AddUserData ) => {
149+ try {
150+ if ( ! address || ! isVerified ) return false ;
151+ setIsAddingUser ( true ) ;
152+
153+ const userAdded = await addUserToAtlas ( atlasGqlClient , { address, ...userSettings } ) ;
154+ refetchUser ( ) ;
155+
156+ return userAdded ;
157+ } catch ( err : any ) {
158+ // eslint-disable-next-line
159+ console . log ( "Add User Error : " , err ?. message ) ;
160+ return false ;
161+ } finally {
162+ setIsAddingUser ( false ) ;
163+ }
164+ } ,
165+ [ address , isVerified , setIsAddingUser , atlasGqlClient , refetchUser ]
166+ ) ;
167+
168+ /**
169+ * @description updates user settings in atlas
170+ * @param {UpdateUserData } userSettings - object containing data to be updated
171+ * @returns {Promise<boolean> } A promise that resolves to true if settings were updated successfully
172+ */
173+ const updateUser = useCallback (
174+ async ( userSettings : UpdateUserData ) => {
175+ try {
176+ if ( ! address || ! isVerified ) return false ;
177+ setIsUpdatingUser ( true ) ;
178+
179+ const userUpdated = await updateUserInAtlas ( atlasGqlClient , userSettings ) ;
180+ refetchUser ( ) ;
181+
182+ return userUpdated ;
183+ } catch ( err : any ) {
184+ // eslint-disable-next-line
185+ console . log ( "Update User Error : " , err ?. message ) ;
186+ return false ;
187+ } finally {
188+ setIsUpdatingUser ( false ) ;
189+ }
190+ } ,
191+ [ address , isVerified , setIsUpdatingUser , atlasGqlClient , refetchUser ]
192+ ) ;
193+
97194 return (
98195 < Context . Provider
99- value = { useMemo ( ( ) => ( { isVerified, isSigningIn, authoriseUser } ) , [ isVerified , isSigningIn , authoriseUser ] ) }
196+ value = { useMemo (
197+ ( ) => ( {
198+ isVerified,
199+ isSigningIn,
200+ isAddingUser,
201+ authoriseUser,
202+ addUser,
203+ user,
204+ isFetchingUser,
205+ updateUser,
206+ isUpdatingUser,
207+ userExists,
208+ } ) ,
209+ [
210+ isVerified ,
211+ isSigningIn ,
212+ isAddingUser ,
213+ authoriseUser ,
214+ addUser ,
215+ user ,
216+ isFetchingUser ,
217+ updateUser ,
218+ isUpdatingUser ,
219+ userExists ,
220+ ]
221+ ) }
100222 >
101223 { children }
102224 </ Context . Provider >
0 commit comments