Connected users with Kratos
This commit is contained in:
parent
b0af0de05b
commit
8da937d0c5
22 changed files with 479 additions and 228 deletions
|
|
@ -1,16 +1,41 @@
|
|||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getUsers, fetchUsers } from '../redux';
|
||||
import { getUsers, fetchUsers, fetchUserById, updateUserById, createUser, deleteUser } from '../redux';
|
||||
import { getUserById, getUserModalLoading } from '../redux/selectors';
|
||||
|
||||
export function useUsers() {
|
||||
const dispatch = useDispatch();
|
||||
const users = useSelector(getUsers);
|
||||
const user = useSelector(getUserById);
|
||||
const userModalLoading = useSelector(getUserModalLoading);
|
||||
|
||||
function loadUsers() {
|
||||
return dispatch(fetchUsers());
|
||||
}
|
||||
|
||||
function loadUser(id: string) {
|
||||
return dispatch(fetchUserById(id));
|
||||
}
|
||||
|
||||
function editUserById(data: any) {
|
||||
return dispatch(updateUserById(data));
|
||||
}
|
||||
|
||||
function createNewUser(data: any) {
|
||||
return dispatch(createUser(data));
|
||||
}
|
||||
|
||||
function deleteUserById(id: string) {
|
||||
return dispatch(deleteUser(id));
|
||||
}
|
||||
|
||||
return {
|
||||
users,
|
||||
user,
|
||||
loadUser,
|
||||
loadUsers,
|
||||
editUserById,
|
||||
userModalLoading,
|
||||
createNewUser,
|
||||
deleteUserById,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export * from './types';
|
||||
|
||||
export { reducer, fetchCurrentUser, getCurrentUser } from './redux';
|
||||
export { reducer } from './redux';
|
||||
|
||||
export { useUsers } from './hooks';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,64 +1,132 @@
|
|||
import { createApiAction, createCrudApiActions } from 'src/services/api';
|
||||
import { transformUserForApi } from '../transformations';
|
||||
|
||||
import { User } from '../types';
|
||||
import { CurrentUserUpdateAPI } from './types';
|
||||
import { Dispatch } from 'redux';
|
||||
import { showToast, ToastType } from 'src/common/util/show-toast';
|
||||
import { performApiCall } from 'src/services/api';
|
||||
import { transformRequestUser, transformResponseUser } from '../transformations';
|
||||
|
||||
export enum UserActionTypes {
|
||||
CHANGE_CURRENT_USER_START = 'users/fetch_current_user_start',
|
||||
CHANGE_CURRENT_USER_FAILURE = 'users/fetch_current_user_failure',
|
||||
FETCH_CURRENT_USER_SUCCESS = 'users/fetch_current_user_success',
|
||||
UPDATE_CURRENT_USER_SUCCESS = 'users/update_current_user_success',
|
||||
|
||||
CHANGE_USERS_START = 'users/change_users_start',
|
||||
CHANGE_USERS_FAILURE = 'users/change_users_failure',
|
||||
FETCH_USERS_SUCCESS = 'users/fetch_users_success',
|
||||
ADD_ACCOUNT_USER_SUCCESS = 'users/add_account_user_success',
|
||||
UPDATE_ACCOUNT_USER_SUCCESS = 'users/update_account_user_success',
|
||||
DELETE_ACCOUNT_USER_SUCCESS = 'users/delete_account_user_success',
|
||||
|
||||
CHANGE_USER_ROLES_START = 'users/change_user_roles_start',
|
||||
CHANGE_USER_ROLES_FAILURE = 'users/change_user_roles_failure',
|
||||
FETCH_USER_ROLES_SUCCESS = 'users/fetch_user_roles_success',
|
||||
ADD_USER_ROLE_SUCCESS = 'users/add_user_role_success',
|
||||
UPDATE_USER_ROLE_SUCCESS = 'users/update_user_role_success',
|
||||
DELETE_USER_ROLE_SUCCESS = 'users/delete_user_role_success',
|
||||
FETCH_USERS = 'users/fetch_users',
|
||||
FETCH_USER = 'users/fetch_user',
|
||||
UPDATE_USER = 'users/update_user',
|
||||
CREATE_USER = 'users/create_user',
|
||||
DELETE_USER = 'users/delete_user',
|
||||
SET_USER_MODAL_LOADING = 'users/user_modal_loading',
|
||||
}
|
||||
|
||||
export const fetchCurrentUser = () =>
|
||||
createApiAction(
|
||||
{
|
||||
path: '/users/me',
|
||||
export const fetchUsers = () => async (dispatch: Dispatch<any>) => {
|
||||
try {
|
||||
const { data } = await performApiCall({
|
||||
path: '/users',
|
||||
method: 'GET',
|
||||
},
|
||||
[
|
||||
UserActionTypes.CHANGE_CURRENT_USER_START,
|
||||
UserActionTypes.FETCH_CURRENT_USER_SUCCESS,
|
||||
UserActionTypes.CHANGE_CURRENT_USER_FAILURE,
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
export const updateCurrentUser = (data: CurrentUserUpdateAPI) =>
|
||||
createApiAction(
|
||||
{
|
||||
path: '/users/me',
|
||||
method: 'PATCH',
|
||||
body: data,
|
||||
},
|
||||
[
|
||||
UserActionTypes.CHANGE_CURRENT_USER_START,
|
||||
UserActionTypes.UPDATE_CURRENT_USER_SUCCESS,
|
||||
UserActionTypes.CHANGE_CURRENT_USER_FAILURE,
|
||||
],
|
||||
);
|
||||
dispatch({
|
||||
type: UserActionTypes.FETCH_USERS,
|
||||
payload: data.map(transformResponseUser),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
export const [fetchUsers, addUser, updateUser, deleteUser] = createCrudApiActions<User>(
|
||||
'/users',
|
||||
UserActionTypes.CHANGE_USERS_START,
|
||||
UserActionTypes.CHANGE_USERS_FAILURE,
|
||||
UserActionTypes.FETCH_USERS_SUCCESS,
|
||||
UserActionTypes.ADD_ACCOUNT_USER_SUCCESS,
|
||||
UserActionTypes.UPDATE_ACCOUNT_USER_SUCCESS,
|
||||
UserActionTypes.DELETE_ACCOUNT_USER_SUCCESS,
|
||||
transformUserForApi,
|
||||
);
|
||||
export const setUserModalLoading = (isLoading: boolean) => (dispatch: Dispatch<any>) => {
|
||||
dispatch({
|
||||
type: UserActionTypes.SET_USER_MODAL_LOADING,
|
||||
payload: isLoading,
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchUserById = (id: string) => async (dispatch: Dispatch<any>) => {
|
||||
dispatch(setUserModalLoading(true));
|
||||
|
||||
try {
|
||||
const { data } = await performApiCall({
|
||||
path: `/users/${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: UserActionTypes.FETCH_USER,
|
||||
payload: transformResponseUser(data),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
dispatch(setUserModalLoading(false));
|
||||
};
|
||||
|
||||
export const updateUserById = (user: any) => async (dispatch: Dispatch<any>) => {
|
||||
dispatch(setUserModalLoading(true));
|
||||
|
||||
try {
|
||||
const { data } = await performApiCall({
|
||||
path: `/users/${user.id}`,
|
||||
method: 'PUT',
|
||||
body: transformRequestUser(user),
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: UserActionTypes.UPDATE_USER,
|
||||
payload: transformResponseUser(data),
|
||||
});
|
||||
|
||||
showToast('User updated sucessfully.', ToastType.Success);
|
||||
|
||||
dispatch(fetchUsers());
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
dispatch(setUserModalLoading(false));
|
||||
};
|
||||
|
||||
export const createUser = (user: any) => async (dispatch: Dispatch<any>) => {
|
||||
dispatch(setUserModalLoading(true));
|
||||
|
||||
try {
|
||||
const { data } = await performApiCall({
|
||||
path: '/users',
|
||||
method: 'POST',
|
||||
body: transformRequestUser(user),
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: UserActionTypes.CREATE_USER,
|
||||
payload: transformResponseUser(data),
|
||||
});
|
||||
|
||||
showToast('User created sucessfully.', ToastType.Success);
|
||||
|
||||
dispatch(fetchUsers());
|
||||
} catch (err: any) {
|
||||
dispatch(setUserModalLoading(false));
|
||||
showToast(`${err}`, ToastType.Error);
|
||||
throw err;
|
||||
}
|
||||
|
||||
dispatch(setUserModalLoading(false));
|
||||
};
|
||||
|
||||
export const deleteUser = (id: string) => async (dispatch: Dispatch<any>) => {
|
||||
dispatch(setUserModalLoading(true));
|
||||
|
||||
try {
|
||||
await performApiCall({
|
||||
path: `/users/${id}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: UserActionTypes.DELETE_USER,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
showToast('User deleted sucessfully.', ToastType.Success);
|
||||
|
||||
dispatch(fetchUsers());
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
dispatch(setUserModalLoading(false));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export * from './actions';
|
||||
export { default as reducer } from './reducers';
|
||||
export { getCurrentUser, getUsers } from './selectors';
|
||||
export { getUsers } from './selectors';
|
||||
export * from './types';
|
||||
|
|
|
|||
|
|
@ -1,61 +1,39 @@
|
|||
import { combineReducers } from 'redux';
|
||||
|
||||
import { createApiReducer, chainReducers, INITIAL_API_STATE, createCrudApiReducer } from 'src/services/api';
|
||||
import { AuthActionTypes } from 'src/services/auth/redux/actions';
|
||||
|
||||
import { transformUser } from '../transformations';
|
||||
import { User } from '../types';
|
||||
import { UserActionTypes } from './actions';
|
||||
|
||||
const signInReducer = createApiReducer(
|
||||
[AuthActionTypes.SIGN_IN_START, AuthActionTypes.SIGN_IN_SUCCESS, AuthActionTypes.SIGN_IN_FAILURE],
|
||||
transformUser,
|
||||
(data) => data,
|
||||
);
|
||||
const initialUsersState: any = {
|
||||
users: [],
|
||||
user: {},
|
||||
userModalLoading: false,
|
||||
};
|
||||
|
||||
const fetchCurrentUserReducer = createApiReducer(
|
||||
[
|
||||
UserActionTypes.CHANGE_CURRENT_USER_START,
|
||||
UserActionTypes.FETCH_CURRENT_USER_SUCCESS,
|
||||
UserActionTypes.CHANGE_CURRENT_USER_FAILURE,
|
||||
],
|
||||
transformUser,
|
||||
(data) => data,
|
||||
);
|
||||
const usersReducer = (state: any = initialUsersState, action: any) => {
|
||||
switch (action.type) {
|
||||
case UserActionTypes.FETCH_USERS:
|
||||
return {
|
||||
...state,
|
||||
users: action.payload,
|
||||
};
|
||||
case UserActionTypes.SET_USER_MODAL_LOADING:
|
||||
return {
|
||||
...state,
|
||||
userModalLoading: action.payload,
|
||||
};
|
||||
case UserActionTypes.FETCH_USER:
|
||||
case UserActionTypes.UPDATE_USER:
|
||||
case UserActionTypes.CREATE_USER:
|
||||
return {
|
||||
...state,
|
||||
isModalVisible: false,
|
||||
user: action.payload,
|
||||
};
|
||||
case UserActionTypes.DELETE_USER:
|
||||
return {
|
||||
...state,
|
||||
user: {},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const updateCurrentUserReducer = createApiReducer(
|
||||
[
|
||||
UserActionTypes.CHANGE_CURRENT_USER_START,
|
||||
UserActionTypes.UPDATE_CURRENT_USER_SUCCESS,
|
||||
UserActionTypes.CHANGE_CURRENT_USER_FAILURE,
|
||||
],
|
||||
transformUser,
|
||||
(data) => data,
|
||||
);
|
||||
|
||||
const signOutReducer = createApiReducer(
|
||||
['', AuthActionTypes.SIGN_OUT, ''],
|
||||
() => INITIAL_API_STATE,
|
||||
() => INITIAL_API_STATE,
|
||||
);
|
||||
|
||||
const usersReducer = createCrudApiReducer<User>(
|
||||
UserActionTypes.CHANGE_USERS_START,
|
||||
UserActionTypes.CHANGE_USERS_FAILURE,
|
||||
UserActionTypes.FETCH_USERS_SUCCESS,
|
||||
UserActionTypes.ADD_ACCOUNT_USER_SUCCESS,
|
||||
UserActionTypes.UPDATE_ACCOUNT_USER_SUCCESS,
|
||||
UserActionTypes.DELETE_ACCOUNT_USER_SUCCESS,
|
||||
transformUser,
|
||||
);
|
||||
|
||||
export default combineReducers({
|
||||
currentUser: chainReducers(
|
||||
INITIAL_API_STATE,
|
||||
signInReducer,
|
||||
fetchCurrentUserReducer,
|
||||
updateCurrentUserReducer,
|
||||
signOutReducer,
|
||||
),
|
||||
users: usersReducer,
|
||||
});
|
||||
export default usersReducer;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { State } from 'src/redux';
|
||||
|
||||
export const getCurrentUser = (state: State) => state.users.currentUser;
|
||||
export const getUsers = (state: State) => state.users.users;
|
||||
export const getUserById = (state: State) => state.users.user;
|
||||
export const getUserModalLoading = (state: State) => state.users.userModalLoading;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ApiState, ApiStatus } from 'src/services/api/redux';
|
||||
import { ApiStatus } from 'src/services/api/redux';
|
||||
|
||||
import { User } from '../types';
|
||||
|
||||
|
|
@ -8,10 +8,13 @@ export interface CurrentUserState extends User {
|
|||
|
||||
export interface UsersState {
|
||||
currentUser: CurrentUserState;
|
||||
users: ApiState<User>;
|
||||
users: User[];
|
||||
user: User;
|
||||
userModalLoading: boolean;
|
||||
}
|
||||
|
||||
export interface CurrentUserUpdateAPI {
|
||||
id: number;
|
||||
phoneNumber?: string;
|
||||
email?: string;
|
||||
language?: string;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
import _ from 'lodash';
|
||||
|
||||
import { FormUser, User, UserApiRequest } from './types';
|
||||
import { User } from './types';
|
||||
|
||||
export const transformUserForApi = (user: FormUser): UserApiRequest => ({
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
status: user.status,
|
||||
last_login: user.last_login,
|
||||
});
|
||||
export const transformResponseUser = (response: any): User => {
|
||||
const userResponse = _.get(response, 'user', response);
|
||||
|
||||
return {
|
||||
id: userResponse.id,
|
||||
email: userResponse.traits.email,
|
||||
name: userResponse.traits.name ?? null,
|
||||
status: userResponse.state,
|
||||
};
|
||||
};
|
||||
|
||||
export const transformUser = (response: any): User => {
|
||||
const userResponse = _.get(response, 'user', response);
|
||||
|
|
@ -17,7 +20,13 @@ export const transformUser = (response: any): User => {
|
|||
id: userResponse.id,
|
||||
email: userResponse.email,
|
||||
name: userResponse.name,
|
||||
last_login: userResponse.last_login,
|
||||
status: userResponse.status,
|
||||
};
|
||||
};
|
||||
|
||||
export const transformRequestUser = (data: any) => {
|
||||
return {
|
||||
email: data.email,
|
||||
name: data.name,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
export interface User {
|
||||
id: number | null;
|
||||
email: string;
|
||||
name: string;
|
||||
last_login: string;
|
||||
status: string;
|
||||
email: string | null;
|
||||
name: string | null;
|
||||
status: string | null;
|
||||
}
|
||||
|
||||
export interface FormUser extends User {
|
||||
|
|
@ -21,6 +20,5 @@ export interface UserApiRequest {
|
|||
id: number | null;
|
||||
email: string;
|
||||
name: string;
|
||||
last_login: string;
|
||||
status: string;
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue