diff options
Diffstat (limited to 'src/hooks')
-rw-r--r-- | src/hooks/useAuth.tsx | 77 | ||||
-rw-r--r-- | src/hooks/useNavigate.tsx | 41 |
2 files changed, 118 insertions, 0 deletions
diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx new file mode 100644 index 0000000..55e142c --- /dev/null +++ b/src/hooks/useAuth.tsx @@ -0,0 +1,77 @@ +import React, { + useState, useEffect, useContext, createContext +} from 'react'; +import { User } from 'which-types'; +import { post, get } from '../requests'; + + +interface ContextType { + user: User | null, + setUser: (user: User) => void; + login: (username: string, password: string, remember?: boolean) => Promise<boolean>; + logout: () => void; + isAuthenticated: () => boolean; +} + +const authContext = createContext<ContextType>({ + user: null, + setUser: () => {}, + login: async () => false, + logout: () => {}, + isAuthenticated: () => false +}); + +const useProvideAuth = () => { + const [user, setUser] = useState<User | null>(null); + + const login: ContextType['login'] = (username, password, remember = true) => { + return post('/authentication', { + strategy: 'local', + username, + password + }).then(response => { + const me = response.data.user; + const token = response.data.accessToken; + setUser(me); + localStorage.setItem('userId', me._id); + localStorage.setItem('token', token); + if (!remember) localStorage.setItem('shouldClear', 'true'); + return true; + }).catch(() => false); + }; + + const logout = () => { + setUser(null); + localStorage.removeItem('userId'); + localStorage.removeItem('token'); + }; + + const isAuthenticated = () => Boolean(user); + + useEffect(() => { + if (localStorage.getItem('shouldClear')) { + localStorage.clear(); + } + const userId = localStorage.getItem('userId'); + if (userId) { + get(`/users/${userId}`).then(response => { + setUser(response.data); + }); + } + }, []); + + return { + user, setUser, login, logout, isAuthenticated + }; +}; + +export const AuthProvider: React.FC = ({ children }) => { + const auth = useProvideAuth(); + const { Provider } = authContext; + return <Provider value={auth}>{children}</Provider>; +}; + +export const useAuth = (): ContextType => { + return useContext(authContext); +}; + diff --git a/src/hooks/useNavigate.tsx b/src/hooks/useNavigate.tsx new file mode 100644 index 0000000..befc529 --- /dev/null +++ b/src/hooks/useNavigate.tsx @@ -0,0 +1,41 @@ +import React, { useState, useContext, createContext } from 'react'; + +export interface Page { + prefix: string; + id?: string; +} + +interface ContextType { + page: Page; + setPage: (page: Page) => void; + navigate: (prefix: string, id?: string) => void; +} + +const landingPage = { prefix: 'feed' }; + +const context = createContext<ContextType>({ + page: landingPage, + setPage: () => {}, + navigate: () => {} +}); + +const useProvideNavigation = () => { + const [page, setPage] = useState<Page>(landingPage); + + const navigate: ContextType['navigate'] = (prefix, id?) => { + setPage({ prefix, id }); + }; + + return { page, setPage, navigate }; +}; + +export const NavigationProvider: React.FC = ({ children }) => { + const navigation = useProvideNavigation(); + const { Provider } = context; + return <Provider value={navigation}>{children}</Provider>; +}; + +export const useNavigate = (): ContextType => { + return useContext(context); +}; + |