+ {/*
*/}
diff --git a/src/modules/users/components/UserModal/types.ts b/src/modules/users/components/UserModal/types.ts
index a7a0c5b..710d29e 100644
--- a/src/modules/users/components/UserModal/types.ts
+++ b/src/modules/users/components/UserModal/types.ts
@@ -1,5 +1,5 @@
export type UserModalProps = {
open: boolean;
onClose: () => void;
- onSave?: () => void;
+ userId: string | null;
};
diff --git a/src/redux/store.ts b/src/redux/store.ts
index 01b2706..ff46366 100644
--- a/src/redux/store.ts
+++ b/src/redux/store.ts
@@ -4,8 +4,8 @@ import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { reducer as authReducer } from 'src/services/auth';
-import { reducer as usersReducer } from 'src/services/users';
+import usersReducer from 'src/services/users/redux/reducers';
import { State } from './types';
const persistConfig = {
diff --git a/src/services/users/hooks/use-users.ts b/src/services/users/hooks/use-users.ts
index cd5e0f6..a541955 100644
--- a/src/services/users/hooks/use-users.ts
+++ b/src/services/users/hooks/use-users.ts
@@ -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,
};
}
diff --git a/src/services/users/index.ts b/src/services/users/index.ts
index d450d39..77c62b2 100644
--- a/src/services/users/index.ts
+++ b/src/services/users/index.ts
@@ -1,6 +1,6 @@
export * from './types';
-export { reducer, fetchCurrentUser, getCurrentUser } from './redux';
+export { reducer } from './redux';
export { useUsers } from './hooks';
diff --git a/src/services/users/redux/actions.ts b/src/services/users/redux/actions.ts
index 079273c..a386b7e 100644
--- a/src/services/users/redux/actions.ts
+++ b/src/services/users/redux/actions.ts
@@ -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
) => {
+ 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(
- '/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) => {
+ dispatch({
+ type: UserActionTypes.SET_USER_MODAL_LOADING,
+ payload: isLoading,
+ });
+};
+
+export const fetchUserById = (id: string) => async (dispatch: Dispatch) => {
+ 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) => {
+ 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) => {
+ 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) => {
+ 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));
+};
diff --git a/src/services/users/redux/index.ts b/src/services/users/redux/index.ts
index d700aa8..bc41629 100644
--- a/src/services/users/redux/index.ts
+++ b/src/services/users/redux/index.ts
@@ -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';
diff --git a/src/services/users/redux/reducers.ts b/src/services/users/redux/reducers.ts
index 9b31ce4..0824955 100644
--- a/src/services/users/redux/reducers.ts
+++ b/src/services/users/redux/reducers.ts
@@ -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(
- 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;
diff --git a/src/services/users/redux/selectors.ts b/src/services/users/redux/selectors.ts
index a861e49..e076051 100644
--- a/src/services/users/redux/selectors.ts
+++ b/src/services/users/redux/selectors.ts
@@ -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;
diff --git a/src/services/users/redux/types.ts b/src/services/users/redux/types.ts
index 465d0e0..469febe 100644
--- a/src/services/users/redux/types.ts
+++ b/src/services/users/redux/types.ts
@@ -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;
+ users: User[];
+ user: User;
+ userModalLoading: boolean;
}
export interface CurrentUserUpdateAPI {
+ id: number;
phoneNumber?: string;
email?: string;
language?: string;
diff --git a/src/services/users/transformations.ts b/src/services/users/transformations.ts
index 07e7190..db77f9a 100644
--- a/src/services/users/transformations.ts
+++ b/src/services/users/transformations.ts
@@ -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,
+ };
+};
diff --git a/src/services/users/types.ts b/src/services/users/types.ts
index b106a46..1e50992 100644
--- a/src/services/users/types.ts
+++ b/src/services/users/types.ts
@@ -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;
}
diff --git a/yarn.lock b/yarn.lock
index d19b00a..11623b3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10331,10 +10331,10 @@ react-helmet@^6.1.0:
react-fast-compare "^3.1.1"
react-side-effect "^2.1.0"
-react-hook-form@^7.12.1:
- version "7.12.1"
- resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.12.1.tgz#dc6adbbd78a3c8817129672a6367d45479e9ca3e"
- integrity sha512-JBu5TZK3IXzDKw9SuNFwyQFdIx5uGZSmN9QTDsNsDSYdccU/O+43jBUh0zKG4jDc4hiNYYgDw34lLt7qLSeusA==
+react-hook-form@^7.22.0:
+ version "7.22.0"
+ resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.22.0.tgz#391f0827d487d133333789b60ad7a00e70ad1bdf"
+ integrity sha512-0gPE29N0wdd/5ZMD+TaAq5LF4NTguLnPaTqdSiWyu1QiSkB6jmWY1q0550JYu2BSgfOHecA7pxky9q+zWAwMqg==
react-hot-toast@^2.0.0:
version "2.0.0"