diff options
| author | s-ol <s+removethis@s-ol.nu> | 2022-01-14 15:53:47 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2022-01-14 15:53:47 +0000 |
| commit | 569d322f516ddb7271f89222f11ede68caf7fefb (patch) | |
| tree | d826b0bab30595af161f588fc4b47068ce8be3c7 /client/src/user.js | |
| parent | small fixes (diff) | |
| download | fedidag-569d322f516ddb7271f89222f11ede68caf7fefb.tar.gz fedidag-569d322f516ddb7271f89222f11ede68caf7fefb.zip | |
login/logout
Diffstat (limited to 'client/src/user.js')
| -rw-r--r-- | client/src/user.js | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/client/src/user.js b/client/src/user.js new file mode 100644 index 0000000..dfa6384 --- /dev/null +++ b/client/src/user.js @@ -0,0 +1,71 @@ +import { h, createContext } from 'preact'; +import { useRef, useState, useCallback, useEffect, useContext } from 'preact/hooks'; +import { API_PREFIX } from './config'; + +const fetchJSON = async (url, method='GET', data=undefined) => { + const res = await fetch(API_PREFIX + url, { + method, + credentials: 'include', + headers: { 'content-type': data && 'application/json' }, + body: data && JSON.stringify(data), + }); + + if (res.status !== 200) + throw new Error("wrong status"); + + return res.json(); +}; + +const initialState = { user: null, discussions: [] }; +const reducer = async (action, ref) => { + switch (action.type) { + case 'login': { + const { username, password } = action; + await fetchJSON('/discdag/login', 'POST', { username, password }); + return await reducer({ type: 'refresh' }, ref); + } + + case 'logout': { + await fetchJSON('/discdag/logout', 'POST'); + return await reducer({ type: 'refresh' }, ref); + } + + case 'refresh': { + const { user, discussions } = await fetchJSON('/discdag/list'); + return { ...ref.current, user, discussions }; + } + + default: + throw new Error('Unexpected action'); + } +}; + +const UserContext = createContext({ + state: initialState, + dispatch: () => { + throw new Error("no UserContext Provider!"); + }, +}); + +export const UserContainer = ({ children }) => { + const ref = useRef(); + const [state, setState] = useState(initialState); + ref.current = state; + + const dispatch = useCallback(async (action) => { + const nextState = await reducer(action, ref); + setState(nextState); + }, [ref]); + + useEffect(() => dispatch({ type: 'refresh' }), []); + + return ( + <UserContext.Provider value={{ state, dispatch }}> + {children} + </UserContext.Provider> + ); +}; + +export const useUser = () => useContext(UserContext).state; +export const useDispatch = () => useContext(UserContext).dispatch; +export const useUserCtx = () => useContext(UserContext); |
