Last active
June 28, 2025 10:10
-
-
Save mentix02/087b2fe4d58de58c03a25b378d6c672a to your computer and use it in GitHub Desktop.
Auth
This file contains hidden or 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
import z from "zod"; | |
import { createContext } from "react"; | |
export const AuthDataSchema = z | |
.object({ | |
id: z.string().optional(), | |
name: z.string().optional(), | |
email: z.string().email().optional(), | |
token: z.string().optional(), | |
}) | |
.readonly(); | |
export type AuthData = z.infer<typeof AuthDataSchema>; | |
const AuthDataContextSchema = z.object({ | |
authData: AuthDataSchema, | |
isAuthenticated: z.boolean(), | |
logout: z.function().returns(z.void()), | |
login: z.function().args(AuthDataSchema).returns(z.void()), | |
}); | |
export type AuthContextType = z.infer<typeof AuthDataContextSchema>; | |
export const EmptyAuthData: AuthData = { | |
id: undefined, | |
name: undefined, | |
email: undefined, | |
token: undefined, | |
}; | |
const AuthContext = createContext<AuthContextType>({ | |
isAuthenticated: false, | |
authData: EmptyAuthData, | |
login: () => {}, | |
logout: () => {}, | |
}); | |
export default AuthContext; |
This file contains hidden or 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
import { useMemo, useCallback, useState, ReactNode } from "react"; | |
import AuthContext, { AuthData, AuthContextType, AuthDataSchema, EmptyAuthData } from "./context"; | |
export default function AuthProvider({ children }: { children: Readonly<ReactNode> }) { | |
// read from localStorage and set initial auth data | |
let initialAuthData: AuthData; | |
const localAuthData: string = localStorage.getItem("auth") || btoa("{}"); | |
const initialAuthDataResult = AuthDataSchema.safeParse(JSON.parse(atob(localAuthData))); | |
if (!initialAuthDataResult.success) { | |
console.error("Invalid auth data in localStorage:", initialAuthDataResult.error); | |
localStorage.removeItem("auth"); | |
initialAuthData = EmptyAuthData; | |
} else { | |
initialAuthData = initialAuthDataResult.data; | |
} | |
const [authData, setAuthData] = useState<AuthData>(initialAuthData); | |
const login = useCallback((data: AuthData) => { | |
setAuthData(data); | |
localStorage.setItem("auth", btoa(JSON.stringify(data))); | |
}, []); | |
const logout = useCallback(() => { | |
setAuthData({ | |
id: undefined, | |
name: undefined, | |
email: undefined, | |
token: undefined, | |
}); | |
}, []); | |
const isAuthenticated = useMemo<boolean>(() => { | |
return !!authData.token; | |
}, [authData.token]); | |
const contextValue = useMemo<AuthContextType>( | |
() => ({ authData, isAuthenticated, login, logout }), | |
[authData, isAuthenticated, login, logout], | |
); | |
return <AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment