Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 1x 1x 9x 9x 9x 5x 5x 5x 2x 2x 2x 1x 1x 3x 3x 9x 2x 2x 2x 2x 9x 1x 1x 1x 1x 9x 1x 13x 13x 9x | import React, { createContext, useState, useContext, useEffect } from "react";
/**
* @typedef {Object} AuthUser
* @property {number} id - Database row ID.
* @property {string} name - User's first name.
* @property {string} lastName - User's last name.
* @property {string} email - User's email address.
* @property {string} personType - `'PF'` (individual) or `'PJ'` (company).
*/
/**
* @typedef {Object} AuthContextValue
* @property {AuthUser|null} user - Currently authenticated user, or `null`.
* @property {string|null} accessToken - Current bearer access token.
* @property {boolean} isLoggedIn - `true` when a user session is active.
* @property {function({ user: AuthUser, accessToken: string }): void} login - Persists a user session.
* @property {function(): void} logout - Clears the current session.
*/
/** @type {React.Context<AuthContextValue>} */
const AuthContext = createContext(undefined);
/**
* Provides authentication state to the component tree.
*
* On mount the provider restores any previously persisted session from
* `localStorage` so that the user stays logged in across page reloads.
*
* @param {{ children: React.ReactNode }} props
* @returns {JSX.Element}
*/
export const AuthProvider = ({ children }) => {
/** @type {[AuthUser|null, React.Dispatch<React.SetStateAction<AuthUser|null>>]} */
const [user, setUser] = useState(null);
/** @type {[string|null, React.Dispatch<React.SetStateAction<string|null>>]} */
const [accessToken, setAccessToken] = useState(null);
// Restore session from localStorage on initial mount
useEffect(() => {
const savedUser = localStorage.getItem("auth_user");
const savedToken = localStorage.getItem("auth_token");
if (savedUser && savedToken) {
try {
setUser(JSON.parse(savedUser));
setAccessToken(savedToken);
} catch {
// Corrupt data — ignore and start with no session
localStorage.removeItem("auth_user");
localStorage.removeItem("auth_token");
}
} else {
localStorage.removeItem("auth_user");
localStorage.removeItem("auth_token");
}
}, []);
/**
* Logs a user in by storing their data in React state and localStorage.
*
* @param {{ user: AuthUser, accessToken: string }} authData - Authenticated user details and bearer token.
* @returns {void}
*/
const login = (authData) => {
setUser(authData.user);
setAccessToken(authData.accessToken);
localStorage.setItem("auth_user", JSON.stringify(authData.user));
localStorage.setItem("auth_token", authData.accessToken);
};
/**
* Logs the current user out by clearing React state and removing the
* persisted session from localStorage.
*
* @returns {void}
*/
const logout = () => {
setUser(null);
setAccessToken(null);
localStorage.removeItem("auth_user");
localStorage.removeItem("auth_token");
};
return (
<AuthContext.Provider value={{ user, accessToken, login, logout, isLoggedIn: !!user && !!accessToken }}>
{children}
</AuthContext.Provider>
);
};
/**
* Custom hook that returns the current {@link AuthContextValue}.
*
* Must be called from a component rendered inside {@link AuthProvider}.
*
* @returns {AuthContextValue}
* @throws {Error} If called outside an `AuthProvider` tree.
*
* @example
* const { isLoggedIn, user, login, logout } = useAuth();
*/
export const useAuth = () => {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("use Auth must be used within an AuthProvider");
return ctx;
};
|