import { createSelector, createSlice, PayloadAction } from '@reduxjs/toolkit'; import api from 'api/api'; import { availableRoles } from 'api/configuration'; import { RootState } from 'app/rootReducer'; import { AppThunk } from 'app/store'; import { WithSnackbarProps } from 'notistack'; export type Role = typeof availableRoles[number]; type UserProfile = { email: string; name: string; image: string; }; type UserPreferences = { roles: Role[]; }; export interface User { loading: boolean; token: string; id: string; ref: number; profile: UserProfile; preferences: UserPreferences; } type UserState = Partial; const initialState: UserState = { loading: true, }; const userSlice = createSlice({ name: 'user', initialState, reducers: { logIn(_, { payload }: PayloadAction>) { return { loading: false, ...payload }; }, logOut(state) { return { loading: false }; }, setLoading(state) { state.loading = true; }, }, }); export const { logIn, logOut, setLoading } = userSlice.actions; export const makeSignedInChange = ( enqueueSnackbar: WithSnackbarProps['enqueueSnackbar'], ) => (isSignedIn: boolean): AppThunk => async dispatch => { if (!isSignedIn) { dispatch(logOut()); } else { if (api.validDomain) { dispatch(setLoading()); const userData = await api.getUserData(); dispatch(logIn(userData)); enqueueSnackbar('You have been logged in', { key: 'user-logged-in', variant: 'success', }); } else { enqueueSnackbar( 'Your google account is not authorized to access this application', { variant: 'warning', key: 'domain-not-allowed' }, ); api.signOut(); } } }; const selectStateUser = ({ user }: RootState) => user; export const selectLoading = createSelector( selectStateUser, ({ loading }) => loading, ); export const selectToken = createSelector( selectStateUser, ({ token }) => token, ); export const selectIsSignedIn = createSelector(selectToken, token => !!token); export const selectProfile = createSelector( selectStateUser, ({ profile }) => profile, ); const selectUserPreferences = createSelector( selectStateUser, ({ preferences }) => preferences, ); export const selectUserRoles = createSelector( selectUserPreferences, preferences => preferences?.roles, ); export default userSlice.reducer;