From 3a35a342662b7b2044050908fcea68aa3b8f558e Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Wed, 15 May 2024 20:22:33 +0100 Subject: [PATCH 1/4] initial commit --- .../process/components/UserApprovedList.tsx | 38 +- .../process/components/UserPendingList.tsx | 38 +- .../process/components/UserReadyList.tsx | 38 +- .../process/components/UserRejectedList.tsx | 38 +- .../process/components/UserStartedList.tsx | 38 +- .../process/user-approved/UsersList.tsx | 37 ++ .../process/user-approved/UsersPage.tsx | 39 -- .../components/header/UserListToolbar.tsx | 23 +- .../components/header/UsersListFilter.tsx | 136 ++++++ .../components/header/UsersListGrouping.tsx | 38 ++ .../components/header/UsersListHeader.tsx | 0 .../header/UsersListSearchComponent.tsx | 49 ++ .../components/loading/UsersListLoading.tsx | 0 .../pagination/UsersListPagination.tsx | 179 ++++++++ .../user-approved/core/ListViewProvider.tsx | 62 +++ .../core/QueryRequestProvider.tsx | 29 ++ .../core/QueryResponseProvider.tsx | 87 ++++ .../process/user-approved/core/_models.ts | 42 ++ .../core/_requests.ts | 7 +- .../user-approved/table/UsersTable.tsx | 66 +++ .../user-approved/table/columns/AddedCell.tsx | 14 + .../table/columns/AgentCell.tsx | 0 .../table/columns/CustomHeaderColumn.tsx | 0 .../table/columns/CustomRow.tsx | 0 .../table/columns/UserActionsCell.tsx | 75 +++ .../table/columns/UserCustomHeader.tsx | 61 +++ .../table/columns/UserInfoCell.tsx | 46 ++ .../table/columns/UserLastLoginCell.tsx | 0 .../table/columns/UserSelectionCell.tsx | 26 ++ .../table/columns/UserSelectionHeader.tsx | 0 .../table/columns/_columns.tsx | 0 .../user-edit-modal/UserEditModal.tsx | 0 .../user-edit-modal/UserEditModalForm.tsx | 433 ++++++++++++++++++ .../UserEditModalFormWrapper.tsx | 42 ++ .../user-edit-modal/UserEditModalHeader.tsx | 27 ++ .../user-approved/users-list/UsersList.tsx | 37 -- .../components/header/UsersListFilter.tsx | 133 ------ .../components/header/UsersListGrouping.tsx | 38 -- .../header/UsersListSearchComponent.tsx | 45 -- .../users-list/table/UsersTable.tsx | 62 --- .../table/columns/UserActionsCell.tsx | 76 --- .../table/columns/UserCustomHeader.tsx | 61 --- .../users-list/table/columns/UserInfoCell.tsx | 42 -- .../table/columns/UserSelectionCell.tsx | 26 -- .../process/user-pending/UsersList.tsx | 40 ++ .../process/user-pending/UsersPage.tsx | 39 -- .../components/header/UserListToolbar.tsx | 23 +- .../components/header/UsersListFilter.tsx | 136 ++++++ .../components/header/UsersListGrouping.tsx | 38 ++ .../components/header/UsersListHeader.tsx | 0 .../header/UsersListSearchComponent.tsx | 49 ++ .../components/loading/UsersListLoading.tsx | 0 .../pagination/UsersListPagination.tsx | 179 ++++++++ .../user-pending/core/ListViewProvider.tsx | 62 +++ .../core/QueryRequestProvider.tsx | 29 ++ .../core/QueryResponseProvider.tsx | 68 +-- .../process/user-pending/core/_models.ts | 42 ++ .../core/_requests.ts | 7 +- .../process/user-pending/table/UsersTable.tsx | 66 +++ .../user-pending/table/columns/AddedCell.tsx | 14 + .../table/columns/AgentCell.tsx | 0 .../table/columns/CustomHeaderColumn.tsx | 0 .../table/columns/CustomRow.tsx | 0 .../table/columns/UserActionsCell.tsx | 75 +++ .../table/columns/UserCustomHeader.tsx | 61 +++ .../table/columns/UserInfoCell.tsx | 46 ++ .../table/columns/UserLastLoginCell.tsx | 0 .../table/columns/UserSelectionCell.tsx | 26 ++ .../table/columns/UserSelectionHeader.tsx | 0 .../table/columns/_columns.tsx | 0 .../user-edit-modal/UserEditModal.tsx | 0 .../user-edit-modal/UserEditModalForm.tsx | 433 ++++++++++++++++++ .../UserEditModalFormWrapper.tsx | 42 ++ .../user-edit-modal/UserEditModalHeader.tsx | 27 ++ .../user-pending/users-list/UsersList.tsx | 37 -- .../components/header/UsersListFilter.tsx | 133 ------ .../header/UsersListSearchComponent.tsx | 45 -- .../pagination/UsersListPagination.tsx | 156 ------- .../users-list/core/ListViewProvider.tsx | 51 --- .../users-list/core/QueryRequestProvider.tsx | 28 -- .../user-pending/users-list/core/_models.ts | 42 -- .../users-list/table/columns/AddedCell.tsx | 12 - .../table/columns/UserActionsCell.tsx | 76 --- .../table/columns/UserCustomHeader.tsx | 61 --- .../users-list/table/columns/UserInfoCell.tsx | 42 -- .../table/columns/UserSelectionCell.tsx | 26 -- .../user-edit-modal/UserEditModalForm.tsx | 407 ---------------- .../UserEditModalFormWrapper.tsx | 40 -- .../user-edit-modal/UserEditModalHeader.tsx | 27 -- .../modules/process/user-ready/UsersList.tsx | 37 ++ .../modules/process/user-ready/UsersPage.tsx | 39 -- .../components/header/UserListToolbar.tsx | 23 +- .../components/header/UsersListFilter.tsx | 136 ++++++ .../components/header/UsersListGrouping.tsx | 38 ++ .../components/header/UsersListHeader.tsx | 0 .../header/UsersListSearchComponent.tsx | 49 ++ .../components/loading/UsersListLoading.tsx | 0 .../pagination/UsersListPagination.tsx | 179 ++++++++ .../user-ready/core/ListViewProvider.tsx | 62 +++ .../user-ready/core/QueryRequestProvider.tsx | 29 ++ .../core/QueryResponseProvider.tsx | 68 +-- .../process/user-ready/core/_models.ts | 42 ++ .../core/_requests.ts | 7 +- .../process/user-ready/table/UsersTable.tsx | 66 +++ .../user-ready/table/columns/AddedCell.tsx | 14 + .../table/columns/AgentCell.tsx | 0 .../table/columns/CustomHeaderColumn.tsx | 0 .../table/columns/CustomRow.tsx | 0 .../table/columns/UserActionsCell.tsx | 75 +++ .../table/columns/UserCustomHeader.tsx | 61 +++ .../user-ready/table/columns/UserInfoCell.tsx | 46 ++ .../table/columns/UserLastLoginCell.tsx | 0 .../table/columns/UserSelectionCell.tsx | 26 ++ .../table/columns/UserSelectionHeader.tsx | 0 .../table/columns/_columns.tsx | 0 .../user-edit-modal/UserEditModal.tsx | 0 .../user-edit-modal/UserEditModalForm.tsx | 433 ++++++++++++++++++ .../UserEditModalFormWrapper.tsx | 42 ++ .../user-edit-modal/UserEditModalHeader.tsx | 27 ++ .../user-ready/users-list/UsersList.tsx | 37 -- .../components/header/UsersListGrouping.tsx | 38 -- .../pagination/UsersListPagination.tsx | 156 ------- .../users-list/core/ListViewProvider.tsx | 51 --- .../users-list/core/QueryRequestProvider.tsx | 28 -- .../user-ready/users-list/core/_models.ts | 42 -- .../users-list/table/UsersTable.tsx | 62 --- .../users-list/table/columns/AddedCell.tsx | 12 - .../user-edit-modal/UserEditModalForm.tsx | 407 ---------------- .../UserEditModalFormWrapper.tsx | 40 -- .../user-edit-modal/UserEditModalHeader.tsx | 27 -- .../process/user-rejected/UsersList.tsx | 37 ++ .../process/user-rejected/UsersPage.tsx | 39 -- .../components/header/UserListToolbar.tsx | 2 +- .../components/header/UsersListFilter.tsx | 4 +- .../components/header/UsersListGrouping.tsx | 2 +- .../components/header/UsersListHeader.tsx | 0 .../header/UsersListSearchComponent.tsx | 2 +- .../components/loading/UsersListLoading.tsx | 0 .../pagination/UsersListPagination.tsx | 2 +- .../core/ListViewProvider.tsx | 2 +- .../core/QueryRequestProvider.tsx | 2 +- .../core/QueryResponseProvider.tsx | 6 +- .../core/_models.ts | 0 .../core/_requests.ts | 0 .../table/UsersTable.tsx | 4 +- .../table/columns/AddedCell.tsx | 2 +- .../table/columns/AgentCell.tsx | 0 .../table/columns/CustomHeaderColumn.tsx | 0 .../table/columns/CustomRow.tsx | 0 .../table/columns/UserActionsCell.tsx | 4 +- .../table/columns/UserCustomHeader.tsx | 2 +- .../table/columns/UserInfoCell.tsx | 2 +- .../table/columns/UserLastLoginCell.tsx | 0 .../table/columns/UserSelectionCell.tsx | 2 +- .../table/columns/UserSelectionHeader.tsx | 0 .../table/columns/_columns.tsx | 0 .../user-edit-modal/UserEditModal.tsx | 0 .../user-edit-modal/UserEditModalForm.tsx | 2 +- .../UserEditModalFormWrapper.tsx | 2 +- .../user-edit-modal/UserEditModalHeader.tsx | 2 +- .../user-rejected/users-list/UsersList.tsx | 37 -- .../components/header/UsersListFilter.tsx | 133 ------ .../components/header/UsersListGrouping.tsx | 38 -- .../header/UsersListSearchComponent.tsx | 45 -- .../pagination/UsersListPagination.tsx | 156 ------- .../users-list/core/ListViewProvider.tsx | 51 --- .../users-list/core/QueryRequestProvider.tsx | 28 -- .../user-rejected/users-list/core/_models.ts | 42 -- .../users-list/table/UsersTable.tsx | 62 --- .../users-list/table/columns/AddedCell.tsx | 12 - .../table/columns/UserActionsCell.tsx | 76 --- .../table/columns/UserCustomHeader.tsx | 61 --- .../users-list/table/columns/UserInfoCell.tsx | 42 -- .../table/columns/UserSelectionCell.tsx | 26 -- .../user-edit-modal/UserEditModalForm.tsx | 407 ---------------- .../UserEditModalFormWrapper.tsx | 40 -- .../user-edit-modal/UserEditModalHeader.tsx | 27 -- .../process/user-started/UsersList.tsx | 37 ++ .../process/user-started/UsersPage.tsx | 39 -- .../components/header/UserListToolbar.tsx | 35 ++ .../components/header/UsersListFilter.tsx | 136 ++++++ .../components/header/UsersListGrouping.tsx | 38 ++ .../components/header/UsersListHeader.tsx | 0 .../header/UsersListSearchComponent.tsx | 49 ++ .../components/loading/UsersListLoading.tsx | 0 .../pagination/UsersListPagination.tsx | 179 ++++++++ .../user-started/core/ListViewProvider.tsx | 62 +++ .../core/QueryRequestProvider.tsx | 29 ++ .../core/QueryResponseProvider.tsx | 68 +-- .../process/user-started/core/_models.ts | 42 ++ .../core/_requests.ts | 7 +- .../process/user-started/table/UsersTable.tsx | 67 +++ .../user-started/table/columns/AddedCell.tsx | 14 + .../table/columns/AgentCell.tsx | 0 .../table/columns/CustomHeaderColumn.tsx | 0 .../table/columns/CustomRow.tsx | 0 .../table/columns/UserActionsCell.tsx | 75 +++ .../table/columns/UserCustomHeader.tsx | 61 +++ .../table/columns/UserInfoCell.tsx | 46 ++ .../table/columns/UserLastLoginCell.tsx | 0 .../table/columns/UserSelectionCell.tsx | 26 ++ .../table/columns/UserSelectionHeader.tsx | 0 .../table/columns/_columns.tsx | 0 .../user-edit-modal/UserEditModal.tsx | 0 .../user-edit-modal/UserEditModalForm.tsx | 433 ++++++++++++++++++ .../UserEditModalFormWrapper.tsx | 42 ++ .../user-edit-modal/UserEditModalHeader.tsx | 27 ++ .../user-started/users-list/UsersList.tsx | 37 -- .../components/header/UserListToolbar.tsx | 32 -- .../components/header/UsersListFilter.tsx | 133 ------ .../components/header/UsersListGrouping.tsx | 38 -- .../header/UsersListSearchComponent.tsx | 45 -- .../pagination/UsersListPagination.tsx | 156 ------- .../users-list/core/ListViewProvider.tsx | 51 --- .../users-list/core/QueryRequestProvider.tsx | 28 -- .../users-list/core/QueryResponseProvider.tsx | 85 ---- .../user-started/users-list/core/_models.ts | 42 -- .../users-list/table/UsersTable.tsx | 62 --- .../users-list/table/columns/AddedCell.tsx | 12 - .../table/columns/UserActionsCell.tsx | 76 --- .../table/columns/UserCustomHeader.tsx | 61 --- .../users-list/table/columns/UserInfoCell.tsx | 42 -- .../table/columns/UserSelectionCell.tsx | 26 -- .../user-edit-modal/UserEditModalForm.tsx | 407 ---------------- .../UserEditModalFormWrapper.tsx | 40 -- .../user-edit-modal/UserEditModalHeader.tsx | 27 -- 226 files changed, 5808 insertions(+), 5819 deletions(-) create mode 100644 src/app/modules/process/user-approved/UsersList.tsx delete mode 100644 src/app/modules/process/user-approved/UsersPage.tsx rename src/app/modules/process/{user-rejected/users-list => user-approved}/components/header/UserListToolbar.tsx (59%) create mode 100644 src/app/modules/process/user-approved/components/header/UsersListFilter.tsx create mode 100644 src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx rename src/app/modules/process/user-approved/{users-list => }/components/header/UsersListHeader.tsx (100%) create mode 100644 src/app/modules/process/user-approved/components/header/UsersListSearchComponent.tsx rename src/app/modules/process/user-approved/{users-list => }/components/loading/UsersListLoading.tsx (100%) create mode 100644 src/app/modules/process/user-approved/components/pagination/UsersListPagination.tsx create mode 100644 src/app/modules/process/user-approved/core/ListViewProvider.tsx create mode 100644 src/app/modules/process/user-approved/core/QueryRequestProvider.tsx create mode 100644 src/app/modules/process/user-approved/core/QueryResponseProvider.tsx create mode 100644 src/app/modules/process/user-approved/core/_models.ts rename src/app/modules/process/{user-ready/users-list => user-approved}/core/_requests.ts (93%) create mode 100644 src/app/modules/process/user-approved/table/UsersTable.tsx create mode 100644 src/app/modules/process/user-approved/table/columns/AddedCell.tsx rename src/app/modules/process/user-approved/{users-list => }/table/columns/AgentCell.tsx (100%) rename src/app/modules/process/user-approved/{users-list => }/table/columns/CustomHeaderColumn.tsx (100%) rename src/app/modules/process/user-approved/{users-list => }/table/columns/CustomRow.tsx (100%) create mode 100644 src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx create mode 100644 src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx create mode 100644 src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx rename src/app/modules/process/user-approved/{users-list => }/table/columns/UserLastLoginCell.tsx (100%) create mode 100644 src/app/modules/process/user-approved/table/columns/UserSelectionCell.tsx rename src/app/modules/process/user-approved/{users-list => }/table/columns/UserSelectionHeader.tsx (100%) rename src/app/modules/process/user-approved/{users-list => }/table/columns/_columns.tsx (100%) rename src/app/modules/process/user-approved/{users-list => }/user-edit-modal/UserEditModal.tsx (100%) create mode 100644 src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx create mode 100644 src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx create mode 100644 src/app/modules/process/user-approved/user-edit-modal/UserEditModalHeader.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/UsersList.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/components/header/UsersListFilter.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/components/header/UsersListGrouping.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/components/header/UsersListSearchComponent.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/table/UsersTable.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/table/columns/UserActionsCell.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/table/columns/UserCustomHeader.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/table/columns/UserInfoCell.tsx delete mode 100644 src/app/modules/process/user-approved/users-list/table/columns/UserSelectionCell.tsx create mode 100644 src/app/modules/process/user-pending/UsersList.tsx delete mode 100644 src/app/modules/process/user-pending/UsersPage.tsx rename src/app/modules/process/{user-approved/users-list => user-pending}/components/header/UserListToolbar.tsx (59%) create mode 100644 src/app/modules/process/user-pending/components/header/UsersListFilter.tsx create mode 100644 src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx rename src/app/modules/process/user-pending/{users-list => }/components/header/UsersListHeader.tsx (100%) create mode 100644 src/app/modules/process/user-pending/components/header/UsersListSearchComponent.tsx rename src/app/modules/process/user-pending/{users-list => }/components/loading/UsersListLoading.tsx (100%) create mode 100644 src/app/modules/process/user-pending/components/pagination/UsersListPagination.tsx create mode 100644 src/app/modules/process/user-pending/core/ListViewProvider.tsx create mode 100644 src/app/modules/process/user-pending/core/QueryRequestProvider.tsx rename src/app/modules/process/{user-approved/users-list => user-pending}/core/QueryResponseProvider.tsx (51%) create mode 100644 src/app/modules/process/user-pending/core/_models.ts rename src/app/modules/process/{user-rejected/users-list => user-pending}/core/_requests.ts (93%) create mode 100644 src/app/modules/process/user-pending/table/UsersTable.tsx create mode 100644 src/app/modules/process/user-pending/table/columns/AddedCell.tsx rename src/app/modules/process/user-pending/{users-list => }/table/columns/AgentCell.tsx (100%) rename src/app/modules/process/user-pending/{users-list => }/table/columns/CustomHeaderColumn.tsx (100%) rename src/app/modules/process/user-pending/{users-list => }/table/columns/CustomRow.tsx (100%) create mode 100644 src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx create mode 100644 src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx create mode 100644 src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx rename src/app/modules/process/user-pending/{users-list => }/table/columns/UserLastLoginCell.tsx (100%) create mode 100644 src/app/modules/process/user-pending/table/columns/UserSelectionCell.tsx rename src/app/modules/process/user-pending/{users-list => }/table/columns/UserSelectionHeader.tsx (100%) rename src/app/modules/process/user-pending/{users-list => }/table/columns/_columns.tsx (100%) rename src/app/modules/process/user-pending/{users-list => }/user-edit-modal/UserEditModal.tsx (100%) create mode 100644 src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx create mode 100644 src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx create mode 100644 src/app/modules/process/user-pending/user-edit-modal/UserEditModalHeader.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/UsersList.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/components/header/UsersListFilter.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/components/header/UsersListSearchComponent.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/components/pagination/UsersListPagination.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/core/ListViewProvider.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/core/QueryRequestProvider.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/core/_models.ts delete mode 100644 src/app/modules/process/user-pending/users-list/table/columns/AddedCell.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/table/columns/UserActionsCell.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/table/columns/UserCustomHeader.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/table/columns/UserInfoCell.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/table/columns/UserSelectionCell.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalForm.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalFormWrapper.tsx delete mode 100644 src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalHeader.tsx create mode 100644 src/app/modules/process/user-ready/UsersList.tsx delete mode 100644 src/app/modules/process/user-ready/UsersPage.tsx rename src/app/modules/process/{user-pending/users-list => user-ready}/components/header/UserListToolbar.tsx (59%) create mode 100644 src/app/modules/process/user-ready/components/header/UsersListFilter.tsx create mode 100644 src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx rename src/app/modules/process/user-ready/{users-list => }/components/header/UsersListHeader.tsx (100%) create mode 100644 src/app/modules/process/user-ready/components/header/UsersListSearchComponent.tsx rename src/app/modules/process/user-ready/{users-list => }/components/loading/UsersListLoading.tsx (100%) create mode 100644 src/app/modules/process/user-ready/components/pagination/UsersListPagination.tsx create mode 100644 src/app/modules/process/user-ready/core/ListViewProvider.tsx create mode 100644 src/app/modules/process/user-ready/core/QueryRequestProvider.tsx rename src/app/modules/process/user-ready/{users-list => }/core/QueryResponseProvider.tsx (51%) create mode 100644 src/app/modules/process/user-ready/core/_models.ts rename src/app/modules/process/{user-started/users-list => user-ready}/core/_requests.ts (93%) create mode 100644 src/app/modules/process/user-ready/table/UsersTable.tsx create mode 100644 src/app/modules/process/user-ready/table/columns/AddedCell.tsx rename src/app/modules/process/user-ready/{users-list => }/table/columns/AgentCell.tsx (100%) rename src/app/modules/process/user-ready/{users-list => }/table/columns/CustomHeaderColumn.tsx (100%) rename src/app/modules/process/user-ready/{users-list => }/table/columns/CustomRow.tsx (100%) create mode 100644 src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx create mode 100644 src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx create mode 100644 src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx rename src/app/modules/process/user-ready/{users-list => }/table/columns/UserLastLoginCell.tsx (100%) create mode 100644 src/app/modules/process/user-ready/table/columns/UserSelectionCell.tsx rename src/app/modules/process/user-ready/{users-list => }/table/columns/UserSelectionHeader.tsx (100%) rename src/app/modules/process/user-ready/{users-list => }/table/columns/_columns.tsx (100%) rename src/app/modules/process/user-ready/{users-list => }/user-edit-modal/UserEditModal.tsx (100%) create mode 100644 src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx create mode 100644 src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx create mode 100644 src/app/modules/process/user-ready/user-edit-modal/UserEditModalHeader.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/UsersList.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/components/header/UsersListGrouping.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/components/pagination/UsersListPagination.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/core/ListViewProvider.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/core/QueryRequestProvider.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/core/_models.ts delete mode 100644 src/app/modules/process/user-ready/users-list/table/UsersTable.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/table/columns/AddedCell.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalForm.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalFormWrapper.tsx delete mode 100644 src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalHeader.tsx create mode 100644 src/app/modules/process/user-rejected/UsersList.tsx delete mode 100644 src/app/modules/process/user-rejected/UsersPage.tsx rename src/app/modules/process/{user-ready/users-list => user-rejected}/components/header/UserListToolbar.tsx (93%) rename src/app/modules/process/{user-ready/users-list => user-rejected}/components/header/UsersListFilter.tsx (96%) rename src/app/modules/process/{user-pending/users-list => user-rejected}/components/header/UsersListGrouping.tsx (94%) rename src/app/modules/process/user-rejected/{users-list => }/components/header/UsersListHeader.tsx (100%) rename src/app/modules/process/{user-ready/users-list => user-rejected}/components/header/UsersListSearchComponent.tsx (98%) rename src/app/modules/process/user-rejected/{users-list => }/components/loading/UsersListLoading.tsx (100%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/components/pagination/UsersListPagination.tsx (98%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/core/ListViewProvider.tsx (97%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/core/QueryRequestProvider.tsx (95%) rename src/app/modules/process/user-rejected/{users-list => }/core/QueryResponseProvider.tsx (93%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/core/_models.ts (100%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/core/_requests.ts (100%) rename src/app/modules/process/{user-pending/users-list => user-rejected}/table/UsersTable.tsx (95%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/table/columns/AddedCell.tsx (63%) rename src/app/modules/process/user-rejected/{users-list => }/table/columns/AgentCell.tsx (100%) rename src/app/modules/process/user-rejected/{users-list => }/table/columns/CustomHeaderColumn.tsx (100%) rename src/app/modules/process/user-rejected/{users-list => }/table/columns/CustomRow.tsx (100%) rename src/app/modules/process/{user-ready/users-list => user-rejected}/table/columns/UserActionsCell.tsx (92%) rename src/app/modules/process/{user-ready/users-list => user-rejected}/table/columns/UserCustomHeader.tsx (95%) rename src/app/modules/process/{user-ready/users-list => user-rejected}/table/columns/UserInfoCell.tsx (94%) rename src/app/modules/process/user-rejected/{users-list => }/table/columns/UserLastLoginCell.tsx (100%) rename src/app/modules/process/{user-ready/users-list => user-rejected}/table/columns/UserSelectionCell.tsx (92%) rename src/app/modules/process/user-rejected/{users-list => }/table/columns/UserSelectionHeader.tsx (100%) rename src/app/modules/process/user-rejected/{users-list => }/table/columns/_columns.tsx (100%) rename src/app/modules/process/user-rejected/{users-list => }/user-edit-modal/UserEditModal.tsx (100%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/user-edit-modal/UserEditModalForm.tsx (99%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/user-edit-modal/UserEditModalFormWrapper.tsx (93%) rename src/app/modules/process/{user-approved/users-list => user-rejected}/user-edit-modal/UserEditModalHeader.tsx (92%) delete mode 100644 src/app/modules/process/user-rejected/users-list/UsersList.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/components/header/UsersListFilter.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/components/header/UsersListGrouping.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/components/header/UsersListSearchComponent.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/components/pagination/UsersListPagination.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/core/ListViewProvider.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/core/QueryRequestProvider.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/core/_models.ts delete mode 100644 src/app/modules/process/user-rejected/users-list/table/UsersTable.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/table/columns/AddedCell.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/table/columns/UserActionsCell.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/table/columns/UserCustomHeader.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/table/columns/UserInfoCell.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/table/columns/UserSelectionCell.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalForm.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalFormWrapper.tsx delete mode 100644 src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalHeader.tsx create mode 100644 src/app/modules/process/user-started/UsersList.tsx delete mode 100644 src/app/modules/process/user-started/UsersPage.tsx create mode 100644 src/app/modules/process/user-started/components/header/UserListToolbar.tsx create mode 100644 src/app/modules/process/user-started/components/header/UsersListFilter.tsx create mode 100644 src/app/modules/process/user-started/components/header/UsersListGrouping.tsx rename src/app/modules/process/user-started/{users-list => }/components/header/UsersListHeader.tsx (100%) create mode 100644 src/app/modules/process/user-started/components/header/UsersListSearchComponent.tsx rename src/app/modules/process/user-started/{users-list => }/components/loading/UsersListLoading.tsx (100%) create mode 100644 src/app/modules/process/user-started/components/pagination/UsersListPagination.tsx create mode 100644 src/app/modules/process/user-started/core/ListViewProvider.tsx create mode 100644 src/app/modules/process/user-started/core/QueryRequestProvider.tsx rename src/app/modules/process/{user-pending/users-list => user-started}/core/QueryResponseProvider.tsx (51%) create mode 100644 src/app/modules/process/user-started/core/_models.ts rename src/app/modules/process/{user-pending/users-list => user-started}/core/_requests.ts (93%) create mode 100644 src/app/modules/process/user-started/table/UsersTable.tsx create mode 100644 src/app/modules/process/user-started/table/columns/AddedCell.tsx rename src/app/modules/process/user-started/{users-list => }/table/columns/AgentCell.tsx (100%) rename src/app/modules/process/user-started/{users-list => }/table/columns/CustomHeaderColumn.tsx (100%) rename src/app/modules/process/user-started/{users-list => }/table/columns/CustomRow.tsx (100%) create mode 100644 src/app/modules/process/user-started/table/columns/UserActionsCell.tsx create mode 100644 src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx create mode 100644 src/app/modules/process/user-started/table/columns/UserInfoCell.tsx rename src/app/modules/process/user-started/{users-list => }/table/columns/UserLastLoginCell.tsx (100%) create mode 100644 src/app/modules/process/user-started/table/columns/UserSelectionCell.tsx rename src/app/modules/process/user-started/{users-list => }/table/columns/UserSelectionHeader.tsx (100%) rename src/app/modules/process/user-started/{users-list => }/table/columns/_columns.tsx (100%) rename src/app/modules/process/user-started/{users-list => }/user-edit-modal/UserEditModal.tsx (100%) create mode 100644 src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx create mode 100644 src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx create mode 100644 src/app/modules/process/user-started/user-edit-modal/UserEditModalHeader.tsx delete mode 100644 src/app/modules/process/user-started/users-list/UsersList.tsx delete mode 100644 src/app/modules/process/user-started/users-list/components/header/UserListToolbar.tsx delete mode 100644 src/app/modules/process/user-started/users-list/components/header/UsersListFilter.tsx delete mode 100644 src/app/modules/process/user-started/users-list/components/header/UsersListGrouping.tsx delete mode 100644 src/app/modules/process/user-started/users-list/components/header/UsersListSearchComponent.tsx delete mode 100644 src/app/modules/process/user-started/users-list/components/pagination/UsersListPagination.tsx delete mode 100644 src/app/modules/process/user-started/users-list/core/ListViewProvider.tsx delete mode 100644 src/app/modules/process/user-started/users-list/core/QueryRequestProvider.tsx delete mode 100644 src/app/modules/process/user-started/users-list/core/QueryResponseProvider.tsx delete mode 100644 src/app/modules/process/user-started/users-list/core/_models.ts delete mode 100644 src/app/modules/process/user-started/users-list/table/UsersTable.tsx delete mode 100644 src/app/modules/process/user-started/users-list/table/columns/AddedCell.tsx delete mode 100644 src/app/modules/process/user-started/users-list/table/columns/UserActionsCell.tsx delete mode 100644 src/app/modules/process/user-started/users-list/table/columns/UserCustomHeader.tsx delete mode 100644 src/app/modules/process/user-started/users-list/table/columns/UserInfoCell.tsx delete mode 100644 src/app/modules/process/user-started/users-list/table/columns/UserSelectionCell.tsx delete mode 100644 src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalForm.tsx delete mode 100644 src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalFormWrapper.tsx delete mode 100644 src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalHeader.tsx diff --git a/src/app/modules/process/components/UserApprovedList.tsx b/src/app/modules/process/components/UserApprovedList.tsx index 8fc4cbf..6727ff8 100644 --- a/src/app/modules/process/components/UserApprovedList.tsx +++ b/src/app/modules/process/components/UserApprovedList.tsx @@ -1,37 +1,5 @@ -import { KTCard } from "../../../../_digifi/helpers" -import { Content } from "../../../../_digifi/layout/components/content" -import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar" -import { UsersListHeader } from "../user-approved/users-list/components/header/UsersListHeader" -import { ListViewProvider, useListView } from "../user-approved/users-list/core/ListViewProvider" -import { QueryRequestProvider } from "../user-approved/users-list/core/QueryRequestProvider" -import { QueryResponseProvider } from "../user-approved/users-list/core/QueryResponseProvider" -import { UsersTable } from "../user-approved/users-list/table/UsersTable" -import { UserEditModal } from "../user-approved/users-list/user-edit-modal/UserEditModal" +import { UsersListWrapper } from "../user-approved/UsersList"; -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} +const UserApprovedList = () => ; -const UserApprovedList = () => ( - - - - - - - - - - -) - -export {UserApprovedList} +export { UserApprovedList }; diff --git a/src/app/modules/process/components/UserPendingList.tsx b/src/app/modules/process/components/UserPendingList.tsx index 8a2ff75..77be63b 100644 --- a/src/app/modules/process/components/UserPendingList.tsx +++ b/src/app/modules/process/components/UserPendingList.tsx @@ -1,37 +1,5 @@ -import { KTCard } from "../../../../_digifi/helpers" -import { Content } from "../../../../_digifi/layout/components/content" -import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar" -import { UsersListHeader } from "../user-pending/users-list/components/header/UsersListHeader" -import { ListViewProvider, useListView } from "../user-pending/users-list/core/ListViewProvider" -import { QueryRequestProvider } from "../user-pending/users-list/core/QueryRequestProvider" -import { QueryResponseProvider } from "../user-pending/users-list/core/QueryResponseProvider" -import { UsersTable } from "../user-pending/users-list/table/UsersTable" -import { UserEditModal } from "../user-pending/users-list/user-edit-modal/UserEditModal" +import { UsersListWrapper } from "../user-pending/UsersList"; -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} +const UserPendingList = () => ; -const UserPendingList = () => ( - - - - - - - - - - -) - -export {UserPendingList} +export { UserPendingList }; diff --git a/src/app/modules/process/components/UserReadyList.tsx b/src/app/modules/process/components/UserReadyList.tsx index fae4d05..9d76b42 100644 --- a/src/app/modules/process/components/UserReadyList.tsx +++ b/src/app/modules/process/components/UserReadyList.tsx @@ -1,37 +1,5 @@ -import { KTCard } from "../../../../_digifi/helpers" -import { Content } from "../../../../_digifi/layout/components/content" -import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar" -import { UsersListHeader } from "../user-ready/users-list/components/header/UsersListHeader" -import { ListViewProvider, useListView } from "../user-ready/users-list/core/ListViewProvider" -import { QueryRequestProvider } from "../user-ready/users-list/core/QueryRequestProvider" -import { QueryResponseProvider } from "../user-ready/users-list/core/QueryResponseProvider" -import { UsersTable } from "../user-ready/users-list/table/UsersTable" -import { UserEditModal } from "../user-ready/users-list/user-edit-modal/UserEditModal" +import { UsersListWrapper } from "../user-ready/UsersList"; -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} +const UserReadyList = () => ; -const UserReadyList = () => ( - - - - - - - - - - -) - -export {UserReadyList} +export { UserReadyList }; diff --git a/src/app/modules/process/components/UserRejectedList.tsx b/src/app/modules/process/components/UserRejectedList.tsx index 9f41d7b..4d60f03 100644 --- a/src/app/modules/process/components/UserRejectedList.tsx +++ b/src/app/modules/process/components/UserRejectedList.tsx @@ -1,37 +1,5 @@ -import { KTCard } from "../../../../_digifi/helpers" -import { Content } from "../../../../_digifi/layout/components/content" -import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar" -import { UsersListHeader } from "../user-rejected/users-list/components/header/UsersListHeader" -import { ListViewProvider, useListView } from "../user-rejected/users-list/core/ListViewProvider" -import { QueryRequestProvider } from "../user-rejected/users-list/core/QueryRequestProvider" -import { QueryResponseProvider } from "../user-rejected/users-list/core/QueryResponseProvider" -import { UsersTable } from "../user-rejected/users-list/table/UsersTable" -import { UserEditModal } from "../user-rejected/users-list/user-edit-modal/UserEditModal" +import { UsersListWrapper } from "../user-rejected/UsersList"; -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} +const UserRejectedList = () => ; -const UserRejectedList = () => ( - - - - - - - - - - -) - -export {UserRejectedList} +export { UserRejectedList }; diff --git a/src/app/modules/process/components/UserStartedList.tsx b/src/app/modules/process/components/UserStartedList.tsx index c7fbc85..302985f 100644 --- a/src/app/modules/process/components/UserStartedList.tsx +++ b/src/app/modules/process/components/UserStartedList.tsx @@ -1,37 +1,5 @@ -import { KTCard } from "../../../../_digifi/helpers" -import { Content } from "../../../../_digifi/layout/components/content" -import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar" -import { UsersListHeader } from "../user-started/users-list/components/header/UsersListHeader" -import { ListViewProvider, useListView } from "../user-started/users-list/core/ListViewProvider" -import { QueryRequestProvider } from "../user-started/users-list/core/QueryRequestProvider" -import { QueryResponseProvider } from "../user-started/users-list/core/QueryResponseProvider" -import { UsersTable } from "../user-started/users-list/table/UsersTable" -import { UserEditModal } from "../user-started/users-list/user-edit-modal/UserEditModal" +import { UsersListWrapper } from "../user-started/UsersList"; -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} +const UserStartedList = () => ; -const UserStartedList = () => ( - - - - - - - - - - -) - -export {UserStartedList} +export { UserStartedList }; diff --git a/src/app/modules/process/user-approved/UsersList.tsx b/src/app/modules/process/user-approved/UsersList.tsx new file mode 100644 index 0000000..10546aa --- /dev/null +++ b/src/app/modules/process/user-approved/UsersList.tsx @@ -0,0 +1,37 @@ +import { ListViewProvider, useListView } from "./core/ListViewProvider"; +import { QueryRequestProvider } from "./core/QueryRequestProvider"; +import { QueryResponseProvider } from "./core/QueryResponseProvider"; +import { UsersListHeader } from "./components/header/UsersListHeader"; +import { UsersTable } from "./table/UsersTable"; +import { UserEditModal } from "./user-edit-modal/UserEditModal"; +import { KTCard } from "../../../../_digifi/helpers"; +import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar"; +import { Content } from "../../../../_digifi/layout/components/content"; + +const UsersList = () => { + const { itemIdForUpdate } = useListView(); + return ( + <> + + + + + {itemIdForUpdate !== undefined && } + + ); +}; + +const UsersListWrapper = () => ( + + + + + + + + + + +); + +export { UsersListWrapper }; diff --git a/src/app/modules/process/user-approved/UsersPage.tsx b/src/app/modules/process/user-approved/UsersPage.tsx deleted file mode 100644 index ec70d89..0000000 --- a/src/app/modules/process/user-approved/UsersPage.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {Route, Routes, Outlet, Navigate} from 'react-router-dom' -import {PageLink, PageTitle} from '../../../../_digifi/layout/core' -import {UsersListWrapper} from './users-list/UsersList' - -const usersBreadcrumbs: Array = [ - { - title: 'User Management', - path: '/apps/user-management/users', - isSeparator: false, - isActive: false, - }, - { - title: '', - path: '', - isSeparator: true, - isActive: false, - }, -] - -const UsersPage = () => { - return ( - - }> - - Users list - - - } - /> - - } /> - - ) -} - -export default UsersPage diff --git a/src/app/modules/process/user-rejected/users-list/components/header/UserListToolbar.tsx b/src/app/modules/process/user-approved/components/header/UserListToolbar.tsx similarity index 59% rename from src/app/modules/process/user-rejected/users-list/components/header/UserListToolbar.tsx rename to src/app/modules/process/user-approved/components/header/UserListToolbar.tsx index e86343b..10974f5 100644 --- a/src/app/modules/process/user-rejected/users-list/components/header/UserListToolbar.tsx +++ b/src/app/modules/process/user-approved/components/header/UserListToolbar.tsx @@ -1,15 +1,18 @@ -import {KTIcon} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {UsersListFilter} from './UsersListFilter' +import { KTIcon } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { UsersListFilter } from "./UsersListFilter"; const UsersListToolbar = () => { - const {setItemIdForUpdate} = useListView() + const { setItemIdForUpdate } = useListView(); const openAddUserModal = () => { - setItemIdForUpdate(null) - } + setItemIdForUpdate(null); + }; return ( -
+
{/* begin::Export */} @@ -26,7 +29,7 @@ const UsersListToolbar = () => { */} {/* end::Add user */}
- ) -} + ); +}; -export {UsersListToolbar} +export { UsersListToolbar }; diff --git a/src/app/modules/process/user-approved/components/header/UsersListFilter.tsx b/src/app/modules/process/user-approved/components/header/UsersListFilter.tsx new file mode 100644 index 0000000..b0fea79 --- /dev/null +++ b/src/app/modules/process/user-approved/components/header/UsersListFilter.tsx @@ -0,0 +1,136 @@ +import { useEffect, useState } from "react"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { initialQueryState, KTIcon } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; + +const UsersListFilter = () => { + const { updateState } = useQueryRequest(); + const { isLoading } = useQueryResponse(); + const [role, setRole] = useState(); + const [lastLogin, setLastLogin] = useState(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const resetData = () => { + updateState({ filter: undefined, ...initialQueryState }); + }; + + const filterData = () => { + updateState({ + filter: { role, last_login: lastLogin }, + ...initialQueryState, + }); + }; + + return ( + <> + {/* begin::Filter Button */} + + {/* end::Filter Button */} + {/* begin::SubMenu */} +
+ {/* begin::Header */} +
+
Filter Options
+
+ {/* end::Header */} + + {/* begin::Separator */} +
+ {/* end::Separator */} + + {/* begin::Content */} +
+ {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Actions */} +
+ + +
+ {/* end::Actions */} +
+ {/* end::Content */} +
+ {/* end::SubMenu */} + + ); +}; + +export { UsersListFilter }; diff --git a/src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx new file mode 100644 index 0000000..7f31f93 --- /dev/null +++ b/src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx @@ -0,0 +1,38 @@ +import { useQueryClient, useMutation } from "react-query"; +import { QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteSelectedUsers } from "../../core/_requests"; + +const UsersListGrouping = () => { + const { selected, clearSelected } = useListView(); + const queryClient = useQueryClient(); + const { query } = useQueryResponse(); + + const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + clearSelected(); + }, + }); + + return ( +
+
+ {selected.length} Selected +
+ + +
+ ); +}; + +export { UsersListGrouping }; diff --git a/src/app/modules/process/user-approved/users-list/components/header/UsersListHeader.tsx b/src/app/modules/process/user-approved/components/header/UsersListHeader.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/components/header/UsersListHeader.tsx rename to src/app/modules/process/user-approved/components/header/UsersListHeader.tsx diff --git a/src/app/modules/process/user-approved/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-approved/components/header/UsersListSearchComponent.tsx new file mode 100644 index 0000000..e25b9ed --- /dev/null +++ b/src/app/modules/process/user-approved/components/header/UsersListSearchComponent.tsx @@ -0,0 +1,49 @@ +/* eslint-disable react-hooks/exhaustive-deps */ + +import { useEffect, useState } from "react"; +import { + initialQueryState, + KTIcon, + useDebounce, +} from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; + +const UsersListSearchComponent = () => { + const { updateState } = useQueryRequest(); + const [searchTerm, setSearchTerm] = useState(""); + // Debounce search term so that it only gives us latest value ... + // ... if searchTerm has not been updated within last 500ms. + // The goal is to only have the API call fire when user stops typing ... + // ... so that we aren't hitting our API rapidly. + const debouncedSearchTerm = useDebounce(searchTerm, 150); + // Effect for API call + useEffect( + () => { + if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { + updateState({ search: debouncedSearchTerm, ...initialQueryState }); + } + }, + [debouncedSearchTerm] // Only call effect if debounced search term changes + // More details about useDebounce: https://usehooks.com/useDebounce/ + ); + + return ( +
+ {/* begin::Search */} +
+ + setSearchTerm(e.target.value)} + /> +
+ {/* end::Search */} +
+ ); +}; + +export { UsersListSearchComponent }; diff --git a/src/app/modules/process/user-approved/users-list/components/loading/UsersListLoading.tsx b/src/app/modules/process/user-approved/components/loading/UsersListLoading.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/components/loading/UsersListLoading.tsx rename to src/app/modules/process/user-approved/components/loading/UsersListLoading.tsx diff --git a/src/app/modules/process/user-approved/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-approved/components/pagination/UsersListPagination.tsx new file mode 100644 index 0000000..346131c --- /dev/null +++ b/src/app/modules/process/user-approved/components/pagination/UsersListPagination.tsx @@ -0,0 +1,179 @@ +import clsx from "clsx"; +import { + useQueryResponseLoading, + useQueryResponsePagination, +} from "../../core/QueryResponseProvider"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { PaginationState } from "../../../../../../_digifi/helpers"; +import { useMemo } from "react"; + +const mappedLabel = (label: string): string => { + if (label === "« Previous") { + return "Previous"; + } + + if (label === "Next »") { + return "Next"; + } + + return label; +}; + +const UsersListPagination = () => { + const pagination = useQueryResponsePagination(); + const isLoading = useQueryResponseLoading(); + const { updateState } = useQueryRequest(); + const updatePage = (page: number | undefined | null) => { + if (!page || isLoading || pagination.page === page) { + return; + } + + updateState({ page, items_per_page: pagination.items_per_page || 10 }); + }; + + const PAGINATION_PAGES_COUNT = 5; + const sliceLinks = (pagination?: PaginationState) => { + if (!pagination?.links?.length) { + return []; + } + + const scopedLinks = [...pagination.links]; + + let pageLinks: Array<{ + label: string; + active: boolean; + url: string | null; + page: number | null; + }> = []; + const previousLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.shift()!; + const nextLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.pop()!; + + const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2); + + pageLinks.push(previousLink); + + if ( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT), + ]; + } + + if ( + pagination.page > scopedLinks.length - halfOfPagesCount && + scopedLinks.length > PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + scopedLinks.length - PAGINATION_PAGES_COUNT, + scopedLinks.length + ), + ]; + } + + if ( + !( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) && + !(pagination.page > scopedLinks.length - halfOfPagesCount) + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + pagination.page - 1 - halfOfPagesCount, + pagination.page + halfOfPagesCount + ), + ]; + } + + pageLinks.push(nextLink); + + return pageLinks; + }; + + const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]); + + return ( + + ); +}; + +export { UsersListPagination }; diff --git a/src/app/modules/process/user-approved/core/ListViewProvider.tsx b/src/app/modules/process/user-approved/core/ListViewProvider.tsx new file mode 100644 index 0000000..d72ff1c --- /dev/null +++ b/src/app/modules/process/user-approved/core/ListViewProvider.tsx @@ -0,0 +1,62 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext, useMemo } from "react"; +import { + ID, + calculatedGroupingIsDisabled, + calculateIsAllDataSelected, + groupingOnSelect, + initialListView, + ListViewContextProps, + groupingOnSelectAll, + WithChildren, +} from "../../../../../_digifi/helpers"; +import { + useQueryResponse, + useQueryResponseData, +} from "./QueryResponseProvider"; + +const ListViewContext = createContext(initialListView); + +const ListViewProvider: FC = ({ children }) => { + const [selected, setSelected] = useState>(initialListView.selected); + const [itemIdForUpdate, setItemIdForUpdate] = useState( + initialListView.itemIdForUpdate + ); + const { isLoading } = useQueryResponse(); + const data = useQueryResponseData(); + const disabled = useMemo( + () => calculatedGroupingIsDisabled(isLoading, data), + [isLoading, data] + ); + const isAllSelected = useMemo( + () => calculateIsAllDataSelected(data, selected), + [data, selected] + ); + + return ( + { + groupingOnSelect(id, selected, setSelected); + }, + onSelectAll: () => { + groupingOnSelectAll(isAllSelected, setSelected, data); + }, + clearSelected: () => { + setSelected([]); + }, + }} + > + {children} + + ); +}; + +const useListView = () => useContext(ListViewContext); + +export { ListViewProvider, useListView }; diff --git a/src/app/modules/process/user-approved/core/QueryRequestProvider.tsx b/src/app/modules/process/user-approved/core/QueryRequestProvider.tsx new file mode 100644 index 0000000..2fb7824 --- /dev/null +++ b/src/app/modules/process/user-approved/core/QueryRequestProvider.tsx @@ -0,0 +1,29 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext } from "react"; +import { + QueryState, + QueryRequestContextProps, + initialQueryRequest, + WithChildren, +} from "../../../../../_digifi/helpers"; + +const QueryRequestContext = + createContext(initialQueryRequest); + +const QueryRequestProvider: FC = ({ children }) => { + const [state, setState] = useState(initialQueryRequest.state); + + const updateState = (updates: Partial) => { + const updatedState = { ...state, ...updates } as QueryState; + setState(updatedState); + }; + + return ( + + {children} + + ); +}; + +const useQueryRequest = () => useContext(QueryRequestContext); +export { QueryRequestProvider, useQueryRequest }; diff --git a/src/app/modules/process/user-approved/core/QueryResponseProvider.tsx b/src/app/modules/process/user-approved/core/QueryResponseProvider.tsx new file mode 100644 index 0000000..d07d67f --- /dev/null +++ b/src/app/modules/process/user-approved/core/QueryResponseProvider.tsx @@ -0,0 +1,87 @@ +/* eslint-disable react-refresh/only-export-components */ +/* eslint-disable react-hooks/exhaustive-deps */ +import { FC, useContext, useState, useEffect, useMemo } from "react"; +import { useQuery } from "react-query"; +import { + createResponseContext, + initialQueryResponse, + initialQueryState, + PaginationState, + QUERIES, + stringifyRequestQuery, + WithChildren, +} from "../../../../../_digifi/helpers"; +import { getApprovedUsers } from "../../core/_requests"; +import { User } from "../../core/_models"; +import { useQueryRequest } from "./QueryRequestProvider"; + +const QueryResponseContext = createResponseContext(initialQueryResponse); +const QueryResponseProvider: FC = ({ children }) => { + const { state } = useQueryRequest(); + const [query, setQuery] = useState(stringifyRequestQuery(state)); + const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]); + + useEffect(() => { + if (query !== updatedQuery) { + setQuery(updatedQuery); + } + }, [updatedQuery]); + + const { + isFetching, + refetch, + data: response, + } = useQuery( + `${QUERIES.USERS_LIST}-${query}`, + () => { + return getApprovedUsers(query); + }, + { cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false } + ); + + return ( + + {children} + + ); +}; + +const useQueryResponse = () => useContext(QueryResponseContext); + +const useQueryResponseData = () => { + const { response } = useQueryResponse(); + if (!response) { + return []; + } + + return response?.records || []; +}; + +const useQueryResponsePagination = () => { + const defaultPaginationState: PaginationState = { + links: [], + ...initialQueryState, + }; + + const { response } = useQueryResponse(); + if (!response || !response.payload || !response.payload.pagination) { + return defaultPaginationState; + } + + return response.payload.pagination; +}; + +const useQueryResponseLoading = (): boolean => { + const { isLoading } = useQueryResponse(); + return isLoading; +}; + +export { + QueryResponseProvider, + useQueryResponse, + useQueryResponseData, + useQueryResponsePagination, + useQueryResponseLoading, +}; diff --git a/src/app/modules/process/user-approved/core/_models.ts b/src/app/modules/process/user-approved/core/_models.ts new file mode 100644 index 0000000..bc84896 --- /dev/null +++ b/src/app/modules/process/user-approved/core/_models.ts @@ -0,0 +1,42 @@ +import { ID, Response } from "../../../../../_digifi/helpers"; +export type User = { + id?: ID; + name?: string; + avatar?: string; + // email?: string + position?: string; + role?: string; + last_login?: string; + two_steps?: boolean; + joined_day?: string; + online?: boolean; + initials?: { + label: string; + state: string; + }; + firstname?: string; + lastname?: string; + uid?: string; + loan_amount?: string; + payment_month?: string; + sales_agent?: string; + gender?: string | null; + marital_status?: string; + email?: string; + address?: string; + state?: string; + country?: string; + status?: string; + added?: string; + updated?: string; +}; + +export type UsersQueryResponse = Response>; + +export const initialUser: User = { + avatar: "avatars/300-6.jpg", + position: "Art Director", + role: "Administrator", + name: "", + email: "", +}; diff --git a/src/app/modules/process/user-ready/users-list/core/_requests.ts b/src/app/modules/process/user-approved/core/_requests.ts similarity index 93% rename from src/app/modules/process/user-ready/users-list/core/_requests.ts rename to src/app/modules/process/user-approved/core/_requests.ts index a585521..ccf71ba 100644 --- a/src/app/modules/process/user-ready/users-list/core/_requests.ts +++ b/src/app/modules/process/user-approved/core/_requests.ts @@ -1,19 +1,20 @@ import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../../_digifi/helpers"; +import { ID, Response } from "../../../../../_digifi/helpers"; import { User, UsersQueryResponse } from "./_models"; const API_URL = import.meta.env.VITE_APP_THEME_API_URL; const USER_URL = `${API_URL}/user`; // const GET_USERS_URL = `${API_URL}/users/query`; -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT +const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; // const getStartedUsers = (query: string): Promise => { // return axios // .get(`${GET_USERS_URL}?${query}`) // .then((d: AxiosResponse) => d.data); // }; -const getStartedUsers = (query: string): Promise => { // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION +const getStartedUsers = (query: string): Promise => { + // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION return axios .get(`${NEW_USER_ENDPOINT}/loan/started`) .then((d: AxiosResponse) => d.data); diff --git a/src/app/modules/process/user-approved/table/UsersTable.tsx b/src/app/modules/process/user-approved/table/UsersTable.tsx new file mode 100644 index 0000000..8f7a3bb --- /dev/null +++ b/src/app/modules/process/user-approved/table/UsersTable.tsx @@ -0,0 +1,66 @@ +import { useMemo } from "react"; +import { useTable, ColumnInstance, Row } from "react-table"; +import { CustomHeaderColumn } from "./columns/CustomHeaderColumn"; +import { CustomRow } from "./columns/CustomRow"; +import { + useQueryResponseData, + useQueryResponseLoading, +} from "../core/QueryResponseProvider"; +import { usersColumns } from "./columns/_columns"; +import { User } from "../../core/_models"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { UsersListPagination } from "../components/pagination/UsersListPagination"; +import { KTCardBody } from "../../../../../_digifi/helpers"; + +const UsersTable = () => { + const users = useQueryResponseData(); + // console.log('users', users) + const isLoading = useQueryResponseLoading(); + const data = useMemo(() => users, [users]); + const columns = useMemo(() => usersColumns, []); + const { getTableProps, getTableBodyProps, headers, rows, prepareRow } = + useTable({ + columns, + data, + }); + + return ( + +
+ + + + {headers.map((column: ColumnInstance) => ( + + ))} + + + + {rows.length > 0 ? ( + rows.map((row: Row, i) => { + prepareRow(row); + return ; + }) + ) : ( + + + + )} + +
+
+ No matching records found +
+
+
+ + {isLoading && } +
+ ); +}; + +export { UsersTable }; diff --git a/src/app/modules/process/user-approved/table/columns/AddedCell.tsx b/src/app/modules/process/user-approved/table/columns/AddedCell.tsx new file mode 100644 index 0000000..2e18bad --- /dev/null +++ b/src/app/modules/process/user-approved/table/columns/AddedCell.tsx @@ -0,0 +1,14 @@ +import { FC } from "react"; +import { NewDateTimeFormatter } from "../../../../../../_digifi/lib/NewDateTimeFormatter"; + +type Props = { + added?: string; +}; + +const AddedCell: FC = ({ added }) => ( +
+ {NewDateTimeFormatter(added)} +
+); + +export { AddedCell }; diff --git a/src/app/modules/process/user-approved/users-list/table/columns/AgentCell.tsx b/src/app/modules/process/user-approved/table/columns/AgentCell.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/table/columns/AgentCell.tsx rename to src/app/modules/process/user-approved/table/columns/AgentCell.tsx diff --git a/src/app/modules/process/user-approved/users-list/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-approved/table/columns/CustomHeaderColumn.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/table/columns/CustomHeaderColumn.tsx rename to src/app/modules/process/user-approved/table/columns/CustomHeaderColumn.tsx diff --git a/src/app/modules/process/user-approved/users-list/table/columns/CustomRow.tsx b/src/app/modules/process/user-approved/table/columns/CustomRow.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/table/columns/CustomRow.tsx rename to src/app/modules/process/user-approved/table/columns/CustomRow.tsx diff --git a/src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx new file mode 100644 index 0000000..4843e41 --- /dev/null +++ b/src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx @@ -0,0 +1,75 @@ +import { FC, useEffect } from "react"; +import { useMutation, useQueryClient } from "react-query"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteUser } from "../../core/_requests"; + +type Props = { + id: ID; +}; + +const UserActionsCell: FC = ({ id }) => { + const { setItemIdForUpdate } = useListView(); + const { query } = useQueryResponse(); + const queryClient = useQueryClient(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const openEditModal = () => { + setItemIdForUpdate(id); + }; + + const deleteItem = useMutation(() => deleteUser(id), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + }, + }); + + return ( + <> + + Actions + + + {/* begin::Menu */} +
+ {/* begin::Menu item */} + + {/* end::Menu item */} + + {/* begin::Menu item */} + + {/* end::Menu item */} +
+ {/* end::Menu */} + + ); +}; + +export { UserActionsCell }; diff --git a/src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx new file mode 100644 index 0000000..76ea930 --- /dev/null +++ b/src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx @@ -0,0 +1,61 @@ +import clsx from "clsx"; +import { FC, PropsWithChildren, useMemo } from "react"; +import { HeaderProps } from "react-table"; +import { initialQueryState } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { User } from "../../core/_models"; + +type Props = { + className?: string; + title?: string; + tableProps: PropsWithChildren>; +}; +const UserCustomHeader: FC = ({ className, title, tableProps }) => { + const id = tableProps.column.id; + const { state, updateState } = useQueryRequest(); + + const isSelectedForSorting = useMemo(() => { + return state.sort && state.sort === id; + }, [state, id]); + const order: "asc" | "desc" | undefined = useMemo(() => state.order, [state]); + + const sortColumn = () => { + // avoid sorting for these columns + if (id === "actions" || id === "selection") { + return; + } + + if (!isSelectedForSorting) { + // enable sort asc + updateState({ sort: id, order: "asc", ...initialQueryState }); + return; + } + + if (isSelectedForSorting && order !== undefined) { + if (order === "asc") { + // enable sort desc + updateState({ sort: id, order: "desc", ...initialQueryState }); + return; + } + + // disable sort + updateState({ sort: undefined, order: undefined, ...initialQueryState }); + } + }; + + return ( + + {title} + + ); +}; + +export { UserCustomHeader }; diff --git a/src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx new file mode 100644 index 0000000..6b45b58 --- /dev/null +++ b/src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx @@ -0,0 +1,46 @@ +import clsx from "clsx"; +import { FC } from "react"; +import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; +import { User } from "../../core/_models"; + +type Props = { + user: User; +}; + +const UserInfoCell: FC = ({ user }) => ( + +); + +export { UserInfoCell }; diff --git a/src/app/modules/process/user-approved/users-list/table/columns/UserLastLoginCell.tsx b/src/app/modules/process/user-approved/table/columns/UserLastLoginCell.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/table/columns/UserLastLoginCell.tsx rename to src/app/modules/process/user-approved/table/columns/UserLastLoginCell.tsx diff --git a/src/app/modules/process/user-approved/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-approved/table/columns/UserSelectionCell.tsx new file mode 100644 index 0000000..ee8d295 --- /dev/null +++ b/src/app/modules/process/user-approved/table/columns/UserSelectionCell.tsx @@ -0,0 +1,26 @@ +import { FC, useMemo } from "react"; +import { ID } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; + +type Props = { + id: ID; +}; + +const UserSelectionCell: FC = ({ id }) => { + const { selected, onSelect } = useListView(); + const isSelected = useMemo(() => selected.includes(id), [id, selected]); + return ( +
+ onSelect(id)} + /> +
+ ); +}; + +export { UserSelectionCell }; diff --git a/src/app/modules/process/user-approved/users-list/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-approved/table/columns/UserSelectionHeader.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/table/columns/UserSelectionHeader.tsx rename to src/app/modules/process/user-approved/table/columns/UserSelectionHeader.tsx diff --git a/src/app/modules/process/user-approved/users-list/table/columns/_columns.tsx b/src/app/modules/process/user-approved/table/columns/_columns.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/table/columns/_columns.tsx rename to src/app/modules/process/user-approved/table/columns/_columns.tsx diff --git a/src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModal.tsx b/src/app/modules/process/user-approved/user-edit-modal/UserEditModal.tsx similarity index 100% rename from src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModal.tsx rename to src/app/modules/process/user-approved/user-edit-modal/UserEditModal.tsx diff --git a/src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx new file mode 100644 index 0000000..ff35559 --- /dev/null +++ b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx @@ -0,0 +1,433 @@ +import { FC, useState } from "react"; +import * as Yup from "yup"; +import { useFormik } from "formik"; +import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; +import { initialUser, User } from "../core/_models"; +import clsx from "clsx"; +import { useListView } from "../core/ListViewProvider"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { createUser, updateUser } from "../core/_requests"; +import { useQueryResponse } from "../core/QueryResponseProvider"; + +type Props = { + isUserLoading: boolean; + user: User; +}; + +const editUserSchema = Yup.object().shape({ + email: Yup.string() + .email("Wrong email format") + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Email is required"), + name: Yup.string() + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Name is required"), +}); + +const UserEditModalForm: FC = ({ user, isUserLoading }) => { + const { setItemIdForUpdate } = useListView(); + const { refetch } = useQueryResponse(); + + const [userForEdit] = useState({ + ...user, + avatar: user.avatar || initialUser.avatar, + role: user.role || initialUser.role, + position: user.position || initialUser.position, + name: user.name || initialUser.name, + email: user.email || initialUser.email, + }); + + const cancel = (withRefresh?: boolean) => { + if (withRefresh) { + refetch(); + } + setItemIdForUpdate(undefined); + }; + + const blankImg = toAbsoluteUrl("media/svg/avatars/blank.svg"); + const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`); + + const formik = useFormik({ + initialValues: userForEdit, + validationSchema: editUserSchema, + onSubmit: async (values, { setSubmitting }) => { + setSubmitting(true); + try { + if (isNotEmpty(values.id)) { + await updateUser(values); + } else { + await createUser(values); + } + } catch (ex) { + console.error(ex); + } finally { + setSubmitting(true); + cancel(true); + } + }, + }); + + return ( + <> +
+ {/* begin::Scroll */} +
+ {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Image input */} +
+ {/* begin::Preview existing avatar */} +
+ {/* end::Preview existing avatar */} + + {/* begin::Label */} + {/* */} + {/* end::Label */} + + {/* begin::Cancel */} + {/* + + */} + {/* end::Cancel */} + + {/* begin::Remove */} + {/* + + */} + {/* end::Remove */} +
+ {/* end::Image input */} + + {/* begin::Hint */} + {/*
Allowed file types: png, jpg, jpeg.
*/} + {/* end::Hint */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {formik.touched.name && formik.errors.name && ( +
+
+ {formik.errors.name} +
+
+ )} + {/* end::Input */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {/* end::Input */} + {formik.touched.email && formik.errors.email && ( +
+ {formik.errors.email} +
+ )} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + {/* begin::Roles */} + {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} + {/* end::Roles */} +
+ {/* end::Input group */} +
+ {/* end::Scroll */} + + {/* begin::Actions */} +
+ + + +
+ {/* end::Actions */} +
+ {(formik.isSubmitting || isUserLoading) && } + + ); +}; + +export { UserEditModalForm }; diff --git a/src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx new file mode 100644 index 0000000..c3caa7f --- /dev/null +++ b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx @@ -0,0 +1,42 @@ +import { useQuery } from "react-query"; +import { UserEditModalForm } from "./UserEditModalForm"; +import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; +import { getUserById } from "../core/_requests"; + +const UserEditModalFormWrapper = () => { + const { itemIdForUpdate, setItemIdForUpdate } = useListView(); + const enabledQuery: boolean = isNotEmpty(itemIdForUpdate); + const { + isLoading, + data: user, + error, + } = useQuery( + `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, + () => { + return getUserById(itemIdForUpdate); + }, + { + cacheTime: 0, + enabled: enabledQuery, + onError: (err) => { + setItemIdForUpdate(undefined); + console.error(err); + }, + } + ); + + if (!itemIdForUpdate) { + return ( + + ); + } + + if (!isLoading && !error && user) { + return ; + } + + return null; +}; + +export { UserEditModalFormWrapper }; diff --git a/src/app/modules/process/user-approved/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalHeader.tsx new file mode 100644 index 0000000..7fc6d55 --- /dev/null +++ b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalHeader.tsx @@ -0,0 +1,27 @@ +import { KTIcon } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; + +const UserEditModalHeader = () => { + const { setItemIdForUpdate } = useListView(); + + return ( +
+ {/* begin::Modal title */} +

Add User

+ {/* end::Modal title */} + + {/* begin::Close */} +
setItemIdForUpdate(undefined)} + style={{ cursor: "pointer" }} + > + +
+ {/* end::Close */} +
+ ); +}; + +export { UserEditModalHeader }; diff --git a/src/app/modules/process/user-approved/users-list/UsersList.tsx b/src/app/modules/process/user-approved/users-list/UsersList.tsx deleted file mode 100644 index d8f1f10..0000000 --- a/src/app/modules/process/user-approved/users-list/UsersList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import {ListViewProvider, useListView} from './core/ListViewProvider' -import {QueryRequestProvider} from './core/QueryRequestProvider' -import {QueryResponseProvider} from './core/QueryResponseProvider' -import {UsersListHeader} from './components/header/UsersListHeader' -import {UsersTable} from './table/UsersTable' -import {UserEditModal} from './user-edit-modal/UserEditModal' -import {KTCard} from '../../../../../_digifi/helpers' -import { ToolbarWrapper } from '../../../../../_digifi/layout/components/toolbar' -import { Content } from '../../../../../_digifi/layout/components/content' - -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} - -const UsersListWrapper = () => ( - - - - - - - - - - -) - -export {UsersListWrapper} diff --git a/src/app/modules/process/user-approved/users-list/components/header/UsersListFilter.tsx b/src/app/modules/process/user-approved/users-list/components/header/UsersListFilter.tsx deleted file mode 100644 index 4ac79a9..0000000 --- a/src/app/modules/process/user-approved/users-list/components/header/UsersListFilter.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import {useEffect, useState} from 'react' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {initialQueryState, KTIcon} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' - -const UsersListFilter = () => { - const {updateState} = useQueryRequest() - const {isLoading} = useQueryResponse() - const [role, setRole] = useState() - const [lastLogin, setLastLogin] = useState() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const resetData = () => { - updateState({filter: undefined, ...initialQueryState}) - } - - const filterData = () => { - updateState({ - filter: {role, last_login: lastLogin}, - ...initialQueryState, - }) - } - - return ( - <> - {/* begin::Filter Button */} - - {/* end::Filter Button */} - {/* begin::SubMenu */} -
- {/* begin::Header */} -
-
Filter Options
-
- {/* end::Header */} - - {/* begin::Separator */} -
- {/* end::Separator */} - - {/* begin::Content */} -
- {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Actions */} -
- - -
- {/* end::Actions */} -
- {/* end::Content */} -
- {/* end::SubMenu */} - - ) -} - -export {UsersListFilter} diff --git a/src/app/modules/process/user-approved/users-list/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-approved/users-list/components/header/UsersListGrouping.tsx deleted file mode 100644 index 6400fd7..0000000 --- a/src/app/modules/process/user-approved/users-list/components/header/UsersListGrouping.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import {useQueryClient, useMutation} from 'react-query' -import {QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteSelectedUsers} from '../../core/_requests' - -const UsersListGrouping = () => { - const {selected, clearSelected} = useListView() - const queryClient = useQueryClient() - const {query} = useQueryResponse() - - const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - clearSelected() - }, - }) - - return ( -
-
- {selected.length} Selected -
- - -
- ) -} - -export {UsersListGrouping} diff --git a/src/app/modules/process/user-approved/users-list/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-approved/users-list/components/header/UsersListSearchComponent.tsx deleted file mode 100644 index 75cba1c..0000000 --- a/src/app/modules/process/user-approved/users-list/components/header/UsersListSearchComponent.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ - -import {useEffect, useState} from 'react' -import {initialQueryState, KTIcon, useDebounce} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' - -const UsersListSearchComponent = () => { - const {updateState} = useQueryRequest() - const [searchTerm, setSearchTerm] = useState('') - // Debounce search term so that it only gives us latest value ... - // ... if searchTerm has not been updated within last 500ms. - // The goal is to only have the API call fire when user stops typing ... - // ... so that we aren't hitting our API rapidly. - const debouncedSearchTerm = useDebounce(searchTerm, 150) - // Effect for API call - useEffect( - () => { - if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { - updateState({search: debouncedSearchTerm, ...initialQueryState}) - } - }, - [debouncedSearchTerm] // Only call effect if debounced search term changes - // More details about useDebounce: https://usehooks.com/useDebounce/ - ) - - return ( -
- {/* begin::Search */} -
- - setSearchTerm(e.target.value)} - /> -
- {/* end::Search */} -
- ) -} - -export {UsersListSearchComponent} diff --git a/src/app/modules/process/user-approved/users-list/table/UsersTable.tsx b/src/app/modules/process/user-approved/users-list/table/UsersTable.tsx deleted file mode 100644 index e803da9..0000000 --- a/src/app/modules/process/user-approved/users-list/table/UsersTable.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import {useMemo} from 'react' -import {useTable, ColumnInstance, Row} from 'react-table' -import {CustomHeaderColumn} from './columns/CustomHeaderColumn' -import {CustomRow} from './columns/CustomRow' -import {useQueryResponseData, useQueryResponseLoading} from '../core/QueryResponseProvider' -import {usersColumns} from './columns/_columns' -import {User} from '../../../core/_models' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {UsersListPagination} from '../components/pagination/UsersListPagination' -import {KTCardBody} from '../../../../../../_digifi/helpers' - -const UsersTable = () => { - const users = useQueryResponseData() - // console.log('users', users) - const isLoading = useQueryResponseLoading() - const data = useMemo(() => users, [users]) - const columns = useMemo(() => usersColumns, []) - const {getTableProps, getTableBodyProps, headers, rows, prepareRow} = useTable({ - columns, - data, - }) - - return ( - -
- - - - {headers.map((column: ColumnInstance) => ( - - ))} - - - - {rows.length > 0 ? ( - rows.map((row: Row, i) => { - prepareRow(row) - return - }) - ) : ( - - - - )} - -
-
- No matching records found -
-
-
- - {isLoading && } -
- ) -} - -export {UsersTable} diff --git a/src/app/modules/process/user-approved/users-list/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-approved/users-list/table/columns/UserActionsCell.tsx deleted file mode 100644 index 9a91389..0000000 --- a/src/app/modules/process/user-approved/users-list/table/columns/UserActionsCell.tsx +++ /dev/null @@ -1,76 +0,0 @@ - -import {FC, useEffect} from 'react' -import {useMutation, useQueryClient} from 'react-query' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {ID, KTIcon, QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteUser} from '../../core/_requests' - -type Props = { - id: ID -} - -const UserActionsCell: FC = ({id}) => { - const {setItemIdForUpdate} = useListView() - const {query} = useQueryResponse() - const queryClient = useQueryClient() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const openEditModal = () => { - setItemIdForUpdate(id) - } - - const deleteItem = useMutation(() => deleteUser(id), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - }, - }) - - return ( - <> - - Actions - - - {/* begin::Menu */} -
- {/* begin::Menu item */} - - {/* end::Menu item */} - - {/* begin::Menu item */} - - {/* end::Menu item */} -
- {/* end::Menu */} - - ) -} - -export {UserActionsCell} diff --git a/src/app/modules/process/user-approved/users-list/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-approved/users-list/table/columns/UserCustomHeader.tsx deleted file mode 100644 index 3d0b58a..0000000 --- a/src/app/modules/process/user-approved/users-list/table/columns/UserCustomHeader.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import clsx from 'clsx' -import {FC, PropsWithChildren, useMemo} from 'react' -import {HeaderProps} from 'react-table' -import {initialQueryState} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {User} from '../../core/_models' - -type Props = { - className?: string - title?: string - tableProps: PropsWithChildren> -} -const UserCustomHeader: FC = ({className, title, tableProps}) => { - const id = tableProps.column.id - const {state, updateState} = useQueryRequest() - - const isSelectedForSorting = useMemo(() => { - return state.sort && state.sort === id - }, [state, id]) - const order: 'asc' | 'desc' | undefined = useMemo(() => state.order, [state]) - - const sortColumn = () => { - // avoid sorting for these columns - if (id === 'actions' || id === 'selection') { - return - } - - if (!isSelectedForSorting) { - // enable sort asc - updateState({sort: id, order: 'asc', ...initialQueryState}) - return - } - - if (isSelectedForSorting && order !== undefined) { - if (order === 'asc') { - // enable sort desc - updateState({sort: id, order: 'desc', ...initialQueryState}) - return - } - - // disable sort - updateState({sort: undefined, order: undefined, ...initialQueryState}) - } - } - - return ( - - {title} - - ) -} - -export {UserCustomHeader} diff --git a/src/app/modules/process/user-approved/users-list/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-approved/users-list/table/columns/UserInfoCell.tsx deleted file mode 100644 index 1840fef..0000000 --- a/src/app/modules/process/user-approved/users-list/table/columns/UserInfoCell.tsx +++ /dev/null @@ -1,42 +0,0 @@ - -import clsx from 'clsx' -import {FC} from 'react' -import {toAbsoluteUrl} from '../../../../../../../_digifi/helpers' -import {User} from '../../core/_models' - -type Props = { - user: User -} - -const UserInfoCell: FC = ({user}) => ( - -) - -export {UserInfoCell} diff --git a/src/app/modules/process/user-approved/users-list/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-approved/users-list/table/columns/UserSelectionCell.tsx deleted file mode 100644 index dcd2bfb..0000000 --- a/src/app/modules/process/user-approved/users-list/table/columns/UserSelectionCell.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import {FC, useMemo} from 'react' -import {ID} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' - -type Props = { - id: ID -} - -const UserSelectionCell: FC = ({id}) => { - const {selected, onSelect} = useListView() - const isSelected = useMemo(() => selected.includes(id), [id, selected]) - return ( -
- onSelect(id)} - /> -
- ) -} - -export {UserSelectionCell} diff --git a/src/app/modules/process/user-pending/UsersList.tsx b/src/app/modules/process/user-pending/UsersList.tsx new file mode 100644 index 0000000..a4ddb17 --- /dev/null +++ b/src/app/modules/process/user-pending/UsersList.tsx @@ -0,0 +1,40 @@ +import { + ListViewProvider, + useListView, +} from "./core/ListViewProvider"; +import { QueryRequestProvider } from "./core/QueryRequestProvider"; +import { QueryResponseProvider } from "./core/QueryResponseProvider"; +import { UsersListHeader } from "./components/header/UsersListHeader"; +import { UsersTable } from "./table/UsersTable"; +import { UserEditModal } from "./user-edit-modal/UserEditModal"; +import { KTCard } from "../../../../_digifi/helpers"; +import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar"; +import { Content } from "../../../../_digifi/layout/components/content"; + +const UsersList = () => { + const { itemIdForUpdate } = useListView(); + return ( + <> + + + + + {itemIdForUpdate !== undefined && } + + ); +}; + +const UsersListWrapper = () => ( + + + + + + + + + + +); + +export { UsersListWrapper }; diff --git a/src/app/modules/process/user-pending/UsersPage.tsx b/src/app/modules/process/user-pending/UsersPage.tsx deleted file mode 100644 index ec70d89..0000000 --- a/src/app/modules/process/user-pending/UsersPage.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {Route, Routes, Outlet, Navigate} from 'react-router-dom' -import {PageLink, PageTitle} from '../../../../_digifi/layout/core' -import {UsersListWrapper} from './users-list/UsersList' - -const usersBreadcrumbs: Array = [ - { - title: 'User Management', - path: '/apps/user-management/users', - isSeparator: false, - isActive: false, - }, - { - title: '', - path: '', - isSeparator: true, - isActive: false, - }, -] - -const UsersPage = () => { - return ( - - }> - - Users list - - - } - /> - - } /> - - ) -} - -export default UsersPage diff --git a/src/app/modules/process/user-approved/users-list/components/header/UserListToolbar.tsx b/src/app/modules/process/user-pending/components/header/UserListToolbar.tsx similarity index 59% rename from src/app/modules/process/user-approved/users-list/components/header/UserListToolbar.tsx rename to src/app/modules/process/user-pending/components/header/UserListToolbar.tsx index e86343b..10974f5 100644 --- a/src/app/modules/process/user-approved/users-list/components/header/UserListToolbar.tsx +++ b/src/app/modules/process/user-pending/components/header/UserListToolbar.tsx @@ -1,15 +1,18 @@ -import {KTIcon} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {UsersListFilter} from './UsersListFilter' +import { KTIcon } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { UsersListFilter } from "./UsersListFilter"; const UsersListToolbar = () => { - const {setItemIdForUpdate} = useListView() + const { setItemIdForUpdate } = useListView(); const openAddUserModal = () => { - setItemIdForUpdate(null) - } + setItemIdForUpdate(null); + }; return ( -
+
{/* begin::Export */} @@ -26,7 +29,7 @@ const UsersListToolbar = () => { */} {/* end::Add user */}
- ) -} + ); +}; -export {UsersListToolbar} +export { UsersListToolbar }; diff --git a/src/app/modules/process/user-pending/components/header/UsersListFilter.tsx b/src/app/modules/process/user-pending/components/header/UsersListFilter.tsx new file mode 100644 index 0000000..b0fea79 --- /dev/null +++ b/src/app/modules/process/user-pending/components/header/UsersListFilter.tsx @@ -0,0 +1,136 @@ +import { useEffect, useState } from "react"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { initialQueryState, KTIcon } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; + +const UsersListFilter = () => { + const { updateState } = useQueryRequest(); + const { isLoading } = useQueryResponse(); + const [role, setRole] = useState(); + const [lastLogin, setLastLogin] = useState(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const resetData = () => { + updateState({ filter: undefined, ...initialQueryState }); + }; + + const filterData = () => { + updateState({ + filter: { role, last_login: lastLogin }, + ...initialQueryState, + }); + }; + + return ( + <> + {/* begin::Filter Button */} + + {/* end::Filter Button */} + {/* begin::SubMenu */} +
+ {/* begin::Header */} +
+
Filter Options
+
+ {/* end::Header */} + + {/* begin::Separator */} +
+ {/* end::Separator */} + + {/* begin::Content */} +
+ {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Actions */} +
+ + +
+ {/* end::Actions */} +
+ {/* end::Content */} +
+ {/* end::SubMenu */} + + ); +}; + +export { UsersListFilter }; diff --git a/src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx new file mode 100644 index 0000000..7f31f93 --- /dev/null +++ b/src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx @@ -0,0 +1,38 @@ +import { useQueryClient, useMutation } from "react-query"; +import { QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteSelectedUsers } from "../../core/_requests"; + +const UsersListGrouping = () => { + const { selected, clearSelected } = useListView(); + const queryClient = useQueryClient(); + const { query } = useQueryResponse(); + + const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + clearSelected(); + }, + }); + + return ( +
+
+ {selected.length} Selected +
+ + +
+ ); +}; + +export { UsersListGrouping }; diff --git a/src/app/modules/process/user-pending/users-list/components/header/UsersListHeader.tsx b/src/app/modules/process/user-pending/components/header/UsersListHeader.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/components/header/UsersListHeader.tsx rename to src/app/modules/process/user-pending/components/header/UsersListHeader.tsx diff --git a/src/app/modules/process/user-pending/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-pending/components/header/UsersListSearchComponent.tsx new file mode 100644 index 0000000..e25b9ed --- /dev/null +++ b/src/app/modules/process/user-pending/components/header/UsersListSearchComponent.tsx @@ -0,0 +1,49 @@ +/* eslint-disable react-hooks/exhaustive-deps */ + +import { useEffect, useState } from "react"; +import { + initialQueryState, + KTIcon, + useDebounce, +} from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; + +const UsersListSearchComponent = () => { + const { updateState } = useQueryRequest(); + const [searchTerm, setSearchTerm] = useState(""); + // Debounce search term so that it only gives us latest value ... + // ... if searchTerm has not been updated within last 500ms. + // The goal is to only have the API call fire when user stops typing ... + // ... so that we aren't hitting our API rapidly. + const debouncedSearchTerm = useDebounce(searchTerm, 150); + // Effect for API call + useEffect( + () => { + if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { + updateState({ search: debouncedSearchTerm, ...initialQueryState }); + } + }, + [debouncedSearchTerm] // Only call effect if debounced search term changes + // More details about useDebounce: https://usehooks.com/useDebounce/ + ); + + return ( +
+ {/* begin::Search */} +
+ + setSearchTerm(e.target.value)} + /> +
+ {/* end::Search */} +
+ ); +}; + +export { UsersListSearchComponent }; diff --git a/src/app/modules/process/user-pending/users-list/components/loading/UsersListLoading.tsx b/src/app/modules/process/user-pending/components/loading/UsersListLoading.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/components/loading/UsersListLoading.tsx rename to src/app/modules/process/user-pending/components/loading/UsersListLoading.tsx diff --git a/src/app/modules/process/user-pending/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-pending/components/pagination/UsersListPagination.tsx new file mode 100644 index 0000000..346131c --- /dev/null +++ b/src/app/modules/process/user-pending/components/pagination/UsersListPagination.tsx @@ -0,0 +1,179 @@ +import clsx from "clsx"; +import { + useQueryResponseLoading, + useQueryResponsePagination, +} from "../../core/QueryResponseProvider"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { PaginationState } from "../../../../../../_digifi/helpers"; +import { useMemo } from "react"; + +const mappedLabel = (label: string): string => { + if (label === "« Previous") { + return "Previous"; + } + + if (label === "Next »") { + return "Next"; + } + + return label; +}; + +const UsersListPagination = () => { + const pagination = useQueryResponsePagination(); + const isLoading = useQueryResponseLoading(); + const { updateState } = useQueryRequest(); + const updatePage = (page: number | undefined | null) => { + if (!page || isLoading || pagination.page === page) { + return; + } + + updateState({ page, items_per_page: pagination.items_per_page || 10 }); + }; + + const PAGINATION_PAGES_COUNT = 5; + const sliceLinks = (pagination?: PaginationState) => { + if (!pagination?.links?.length) { + return []; + } + + const scopedLinks = [...pagination.links]; + + let pageLinks: Array<{ + label: string; + active: boolean; + url: string | null; + page: number | null; + }> = []; + const previousLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.shift()!; + const nextLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.pop()!; + + const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2); + + pageLinks.push(previousLink); + + if ( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT), + ]; + } + + if ( + pagination.page > scopedLinks.length - halfOfPagesCount && + scopedLinks.length > PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + scopedLinks.length - PAGINATION_PAGES_COUNT, + scopedLinks.length + ), + ]; + } + + if ( + !( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) && + !(pagination.page > scopedLinks.length - halfOfPagesCount) + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + pagination.page - 1 - halfOfPagesCount, + pagination.page + halfOfPagesCount + ), + ]; + } + + pageLinks.push(nextLink); + + return pageLinks; + }; + + const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]); + + return ( + + ); +}; + +export { UsersListPagination }; diff --git a/src/app/modules/process/user-pending/core/ListViewProvider.tsx b/src/app/modules/process/user-pending/core/ListViewProvider.tsx new file mode 100644 index 0000000..d72ff1c --- /dev/null +++ b/src/app/modules/process/user-pending/core/ListViewProvider.tsx @@ -0,0 +1,62 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext, useMemo } from "react"; +import { + ID, + calculatedGroupingIsDisabled, + calculateIsAllDataSelected, + groupingOnSelect, + initialListView, + ListViewContextProps, + groupingOnSelectAll, + WithChildren, +} from "../../../../../_digifi/helpers"; +import { + useQueryResponse, + useQueryResponseData, +} from "./QueryResponseProvider"; + +const ListViewContext = createContext(initialListView); + +const ListViewProvider: FC = ({ children }) => { + const [selected, setSelected] = useState>(initialListView.selected); + const [itemIdForUpdate, setItemIdForUpdate] = useState( + initialListView.itemIdForUpdate + ); + const { isLoading } = useQueryResponse(); + const data = useQueryResponseData(); + const disabled = useMemo( + () => calculatedGroupingIsDisabled(isLoading, data), + [isLoading, data] + ); + const isAllSelected = useMemo( + () => calculateIsAllDataSelected(data, selected), + [data, selected] + ); + + return ( + { + groupingOnSelect(id, selected, setSelected); + }, + onSelectAll: () => { + groupingOnSelectAll(isAllSelected, setSelected, data); + }, + clearSelected: () => { + setSelected([]); + }, + }} + > + {children} + + ); +}; + +const useListView = () => useContext(ListViewContext); + +export { ListViewProvider, useListView }; diff --git a/src/app/modules/process/user-pending/core/QueryRequestProvider.tsx b/src/app/modules/process/user-pending/core/QueryRequestProvider.tsx new file mode 100644 index 0000000..2fb7824 --- /dev/null +++ b/src/app/modules/process/user-pending/core/QueryRequestProvider.tsx @@ -0,0 +1,29 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext } from "react"; +import { + QueryState, + QueryRequestContextProps, + initialQueryRequest, + WithChildren, +} from "../../../../../_digifi/helpers"; + +const QueryRequestContext = + createContext(initialQueryRequest); + +const QueryRequestProvider: FC = ({ children }) => { + const [state, setState] = useState(initialQueryRequest.state); + + const updateState = (updates: Partial) => { + const updatedState = { ...state, ...updates } as QueryState; + setState(updatedState); + }; + + return ( + + {children} + + ); +}; + +const useQueryRequest = () => useContext(QueryRequestContext); +export { QueryRequestProvider, useQueryRequest }; diff --git a/src/app/modules/process/user-approved/users-list/core/QueryResponseProvider.tsx b/src/app/modules/process/user-pending/core/QueryResponseProvider.tsx similarity index 51% rename from src/app/modules/process/user-approved/users-list/core/QueryResponseProvider.tsx rename to src/app/modules/process/user-pending/core/QueryResponseProvider.tsx index f451987..ee07a21 100644 --- a/src/app/modules/process/user-approved/users-list/core/QueryResponseProvider.tsx +++ b/src/app/modules/process/user-pending/core/QueryResponseProvider.tsx @@ -1,7 +1,7 @@ /* eslint-disable react-refresh/only-export-components */ /* eslint-disable react-hooks/exhaustive-deps */ -import {FC, useContext, useState, useEffect, useMemo} from 'react' -import {useQuery} from 'react-query' +import { FC, useContext, useState, useEffect, useMemo } from "react"; +import { useQuery } from "react-query"; import { createResponseContext, initialQueryResponse, @@ -10,22 +10,22 @@ import { QUERIES, stringifyRequestQuery, WithChildren, -} from '../../../../../../_digifi/helpers' -import {getApprovedUsers} from '../../../core/_requests' -import {User} from '../../../core/_models' -import {useQueryRequest} from './QueryRequestProvider' +} from "../../../../../_digifi/helpers"; +import { getPendingUsers } from "../../core/_requests"; +import { User } from "../../core/_models"; +import { useQueryRequest } from "./QueryRequestProvider"; -const QueryResponseContext = createResponseContext(initialQueryResponse) -const QueryResponseProvider: FC = ({children}) => { - const {state} = useQueryRequest() - const [query, setQuery] = useState(stringifyRequestQuery(state)) - const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]) +const QueryResponseContext = createResponseContext(initialQueryResponse); +const QueryResponseProvider: FC = ({ children }) => { + const { state } = useQueryRequest(); + const [query, setQuery] = useState(stringifyRequestQuery(state)); + const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]); useEffect(() => { if (query !== updatedQuery) { - setQuery(updatedQuery) + setQuery(updatedQuery); } - }, [updatedQuery]) + }, [updatedQuery]); const { isFetching, @@ -34,47 +34,49 @@ const QueryResponseProvider: FC = ({children}) => { } = useQuery( `${QUERIES.USERS_LIST}-${query}`, () => { - return getApprovedUsers(query) + return getPendingUsers(query); }, - {cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false} - ) + { cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false } + ); return ( - + {children} - ) -} + ); +}; -const useQueryResponse = () => useContext(QueryResponseContext) +const useQueryResponse = () => useContext(QueryResponseContext); const useQueryResponseData = () => { - const {response} = useQueryResponse() + const { response } = useQueryResponse(); if (!response) { - return [] + return []; } - return response?.records || [] -} + return response?.records || []; +}; const useQueryResponsePagination = () => { const defaultPaginationState: PaginationState = { links: [], ...initialQueryState, - } + }; - const {response} = useQueryResponse() + const { response } = useQueryResponse(); if (!response || !response.payload || !response.payload.pagination) { - return defaultPaginationState + return defaultPaginationState; } - return response.payload.pagination -} + return response.payload.pagination; +}; const useQueryResponseLoading = (): boolean => { - const {isLoading} = useQueryResponse() - return isLoading -} + const { isLoading } = useQueryResponse(); + return isLoading; +}; export { QueryResponseProvider, @@ -82,4 +84,4 @@ export { useQueryResponseData, useQueryResponsePagination, useQueryResponseLoading, -} +}; diff --git a/src/app/modules/process/user-pending/core/_models.ts b/src/app/modules/process/user-pending/core/_models.ts new file mode 100644 index 0000000..bc84896 --- /dev/null +++ b/src/app/modules/process/user-pending/core/_models.ts @@ -0,0 +1,42 @@ +import { ID, Response } from "../../../../../_digifi/helpers"; +export type User = { + id?: ID; + name?: string; + avatar?: string; + // email?: string + position?: string; + role?: string; + last_login?: string; + two_steps?: boolean; + joined_day?: string; + online?: boolean; + initials?: { + label: string; + state: string; + }; + firstname?: string; + lastname?: string; + uid?: string; + loan_amount?: string; + payment_month?: string; + sales_agent?: string; + gender?: string | null; + marital_status?: string; + email?: string; + address?: string; + state?: string; + country?: string; + status?: string; + added?: string; + updated?: string; +}; + +export type UsersQueryResponse = Response>; + +export const initialUser: User = { + avatar: "avatars/300-6.jpg", + position: "Art Director", + role: "Administrator", + name: "", + email: "", +}; diff --git a/src/app/modules/process/user-rejected/users-list/core/_requests.ts b/src/app/modules/process/user-pending/core/_requests.ts similarity index 93% rename from src/app/modules/process/user-rejected/users-list/core/_requests.ts rename to src/app/modules/process/user-pending/core/_requests.ts index a585521..ccf71ba 100644 --- a/src/app/modules/process/user-rejected/users-list/core/_requests.ts +++ b/src/app/modules/process/user-pending/core/_requests.ts @@ -1,19 +1,20 @@ import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../../_digifi/helpers"; +import { ID, Response } from "../../../../../_digifi/helpers"; import { User, UsersQueryResponse } from "./_models"; const API_URL = import.meta.env.VITE_APP_THEME_API_URL; const USER_URL = `${API_URL}/user`; // const GET_USERS_URL = `${API_URL}/users/query`; -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT +const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; // const getStartedUsers = (query: string): Promise => { // return axios // .get(`${GET_USERS_URL}?${query}`) // .then((d: AxiosResponse) => d.data); // }; -const getStartedUsers = (query: string): Promise => { // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION +const getStartedUsers = (query: string): Promise => { + // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION return axios .get(`${NEW_USER_ENDPOINT}/loan/started`) .then((d: AxiosResponse) => d.data); diff --git a/src/app/modules/process/user-pending/table/UsersTable.tsx b/src/app/modules/process/user-pending/table/UsersTable.tsx new file mode 100644 index 0000000..8f7a3bb --- /dev/null +++ b/src/app/modules/process/user-pending/table/UsersTable.tsx @@ -0,0 +1,66 @@ +import { useMemo } from "react"; +import { useTable, ColumnInstance, Row } from "react-table"; +import { CustomHeaderColumn } from "./columns/CustomHeaderColumn"; +import { CustomRow } from "./columns/CustomRow"; +import { + useQueryResponseData, + useQueryResponseLoading, +} from "../core/QueryResponseProvider"; +import { usersColumns } from "./columns/_columns"; +import { User } from "../../core/_models"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { UsersListPagination } from "../components/pagination/UsersListPagination"; +import { KTCardBody } from "../../../../../_digifi/helpers"; + +const UsersTable = () => { + const users = useQueryResponseData(); + // console.log('users', users) + const isLoading = useQueryResponseLoading(); + const data = useMemo(() => users, [users]); + const columns = useMemo(() => usersColumns, []); + const { getTableProps, getTableBodyProps, headers, rows, prepareRow } = + useTable({ + columns, + data, + }); + + return ( + +
+ + + + {headers.map((column: ColumnInstance) => ( + + ))} + + + + {rows.length > 0 ? ( + rows.map((row: Row, i) => { + prepareRow(row); + return ; + }) + ) : ( + + + + )} + +
+
+ No matching records found +
+
+
+ + {isLoading && } +
+ ); +}; + +export { UsersTable }; diff --git a/src/app/modules/process/user-pending/table/columns/AddedCell.tsx b/src/app/modules/process/user-pending/table/columns/AddedCell.tsx new file mode 100644 index 0000000..2e18bad --- /dev/null +++ b/src/app/modules/process/user-pending/table/columns/AddedCell.tsx @@ -0,0 +1,14 @@ +import { FC } from "react"; +import { NewDateTimeFormatter } from "../../../../../../_digifi/lib/NewDateTimeFormatter"; + +type Props = { + added?: string; +}; + +const AddedCell: FC = ({ added }) => ( +
+ {NewDateTimeFormatter(added)} +
+); + +export { AddedCell }; diff --git a/src/app/modules/process/user-pending/users-list/table/columns/AgentCell.tsx b/src/app/modules/process/user-pending/table/columns/AgentCell.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/table/columns/AgentCell.tsx rename to src/app/modules/process/user-pending/table/columns/AgentCell.tsx diff --git a/src/app/modules/process/user-pending/users-list/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-pending/table/columns/CustomHeaderColumn.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/table/columns/CustomHeaderColumn.tsx rename to src/app/modules/process/user-pending/table/columns/CustomHeaderColumn.tsx diff --git a/src/app/modules/process/user-pending/users-list/table/columns/CustomRow.tsx b/src/app/modules/process/user-pending/table/columns/CustomRow.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/table/columns/CustomRow.tsx rename to src/app/modules/process/user-pending/table/columns/CustomRow.tsx diff --git a/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx new file mode 100644 index 0000000..4843e41 --- /dev/null +++ b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx @@ -0,0 +1,75 @@ +import { FC, useEffect } from "react"; +import { useMutation, useQueryClient } from "react-query"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteUser } from "../../core/_requests"; + +type Props = { + id: ID; +}; + +const UserActionsCell: FC = ({ id }) => { + const { setItemIdForUpdate } = useListView(); + const { query } = useQueryResponse(); + const queryClient = useQueryClient(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const openEditModal = () => { + setItemIdForUpdate(id); + }; + + const deleteItem = useMutation(() => deleteUser(id), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + }, + }); + + return ( + <> + + Actions + + + {/* begin::Menu */} +
+ {/* begin::Menu item */} + + {/* end::Menu item */} + + {/* begin::Menu item */} + + {/* end::Menu item */} +
+ {/* end::Menu */} + + ); +}; + +export { UserActionsCell }; diff --git a/src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx new file mode 100644 index 0000000..76ea930 --- /dev/null +++ b/src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx @@ -0,0 +1,61 @@ +import clsx from "clsx"; +import { FC, PropsWithChildren, useMemo } from "react"; +import { HeaderProps } from "react-table"; +import { initialQueryState } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { User } from "../../core/_models"; + +type Props = { + className?: string; + title?: string; + tableProps: PropsWithChildren>; +}; +const UserCustomHeader: FC = ({ className, title, tableProps }) => { + const id = tableProps.column.id; + const { state, updateState } = useQueryRequest(); + + const isSelectedForSorting = useMemo(() => { + return state.sort && state.sort === id; + }, [state, id]); + const order: "asc" | "desc" | undefined = useMemo(() => state.order, [state]); + + const sortColumn = () => { + // avoid sorting for these columns + if (id === "actions" || id === "selection") { + return; + } + + if (!isSelectedForSorting) { + // enable sort asc + updateState({ sort: id, order: "asc", ...initialQueryState }); + return; + } + + if (isSelectedForSorting && order !== undefined) { + if (order === "asc") { + // enable sort desc + updateState({ sort: id, order: "desc", ...initialQueryState }); + return; + } + + // disable sort + updateState({ sort: undefined, order: undefined, ...initialQueryState }); + } + }; + + return ( + + {title} + + ); +}; + +export { UserCustomHeader }; diff --git a/src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx new file mode 100644 index 0000000..6b45b58 --- /dev/null +++ b/src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx @@ -0,0 +1,46 @@ +import clsx from "clsx"; +import { FC } from "react"; +import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; +import { User } from "../../core/_models"; + +type Props = { + user: User; +}; + +const UserInfoCell: FC = ({ user }) => ( + +); + +export { UserInfoCell }; diff --git a/src/app/modules/process/user-pending/users-list/table/columns/UserLastLoginCell.tsx b/src/app/modules/process/user-pending/table/columns/UserLastLoginCell.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/table/columns/UserLastLoginCell.tsx rename to src/app/modules/process/user-pending/table/columns/UserLastLoginCell.tsx diff --git a/src/app/modules/process/user-pending/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-pending/table/columns/UserSelectionCell.tsx new file mode 100644 index 0000000..ee8d295 --- /dev/null +++ b/src/app/modules/process/user-pending/table/columns/UserSelectionCell.tsx @@ -0,0 +1,26 @@ +import { FC, useMemo } from "react"; +import { ID } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; + +type Props = { + id: ID; +}; + +const UserSelectionCell: FC = ({ id }) => { + const { selected, onSelect } = useListView(); + const isSelected = useMemo(() => selected.includes(id), [id, selected]); + return ( +
+ onSelect(id)} + /> +
+ ); +}; + +export { UserSelectionCell }; diff --git a/src/app/modules/process/user-pending/users-list/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-pending/table/columns/UserSelectionHeader.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/table/columns/UserSelectionHeader.tsx rename to src/app/modules/process/user-pending/table/columns/UserSelectionHeader.tsx diff --git a/src/app/modules/process/user-pending/users-list/table/columns/_columns.tsx b/src/app/modules/process/user-pending/table/columns/_columns.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/table/columns/_columns.tsx rename to src/app/modules/process/user-pending/table/columns/_columns.tsx diff --git a/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModal.tsx b/src/app/modules/process/user-pending/user-edit-modal/UserEditModal.tsx similarity index 100% rename from src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModal.tsx rename to src/app/modules/process/user-pending/user-edit-modal/UserEditModal.tsx diff --git a/src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx new file mode 100644 index 0000000..ff35559 --- /dev/null +++ b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx @@ -0,0 +1,433 @@ +import { FC, useState } from "react"; +import * as Yup from "yup"; +import { useFormik } from "formik"; +import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; +import { initialUser, User } from "../core/_models"; +import clsx from "clsx"; +import { useListView } from "../core/ListViewProvider"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { createUser, updateUser } from "../core/_requests"; +import { useQueryResponse } from "../core/QueryResponseProvider"; + +type Props = { + isUserLoading: boolean; + user: User; +}; + +const editUserSchema = Yup.object().shape({ + email: Yup.string() + .email("Wrong email format") + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Email is required"), + name: Yup.string() + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Name is required"), +}); + +const UserEditModalForm: FC = ({ user, isUserLoading }) => { + const { setItemIdForUpdate } = useListView(); + const { refetch } = useQueryResponse(); + + const [userForEdit] = useState({ + ...user, + avatar: user.avatar || initialUser.avatar, + role: user.role || initialUser.role, + position: user.position || initialUser.position, + name: user.name || initialUser.name, + email: user.email || initialUser.email, + }); + + const cancel = (withRefresh?: boolean) => { + if (withRefresh) { + refetch(); + } + setItemIdForUpdate(undefined); + }; + + const blankImg = toAbsoluteUrl("media/svg/avatars/blank.svg"); + const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`); + + const formik = useFormik({ + initialValues: userForEdit, + validationSchema: editUserSchema, + onSubmit: async (values, { setSubmitting }) => { + setSubmitting(true); + try { + if (isNotEmpty(values.id)) { + await updateUser(values); + } else { + await createUser(values); + } + } catch (ex) { + console.error(ex); + } finally { + setSubmitting(true); + cancel(true); + } + }, + }); + + return ( + <> +
+ {/* begin::Scroll */} +
+ {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Image input */} +
+ {/* begin::Preview existing avatar */} +
+ {/* end::Preview existing avatar */} + + {/* begin::Label */} + {/* */} + {/* end::Label */} + + {/* begin::Cancel */} + {/* + + */} + {/* end::Cancel */} + + {/* begin::Remove */} + {/* + + */} + {/* end::Remove */} +
+ {/* end::Image input */} + + {/* begin::Hint */} + {/*
Allowed file types: png, jpg, jpeg.
*/} + {/* end::Hint */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {formik.touched.name && formik.errors.name && ( +
+
+ {formik.errors.name} +
+
+ )} + {/* end::Input */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {/* end::Input */} + {formik.touched.email && formik.errors.email && ( +
+ {formik.errors.email} +
+ )} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + {/* begin::Roles */} + {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} + {/* end::Roles */} +
+ {/* end::Input group */} +
+ {/* end::Scroll */} + + {/* begin::Actions */} +
+ + + +
+ {/* end::Actions */} +
+ {(formik.isSubmitting || isUserLoading) && } + + ); +}; + +export { UserEditModalForm }; diff --git a/src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx new file mode 100644 index 0000000..c3caa7f --- /dev/null +++ b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx @@ -0,0 +1,42 @@ +import { useQuery } from "react-query"; +import { UserEditModalForm } from "./UserEditModalForm"; +import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; +import { getUserById } from "../core/_requests"; + +const UserEditModalFormWrapper = () => { + const { itemIdForUpdate, setItemIdForUpdate } = useListView(); + const enabledQuery: boolean = isNotEmpty(itemIdForUpdate); + const { + isLoading, + data: user, + error, + } = useQuery( + `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, + () => { + return getUserById(itemIdForUpdate); + }, + { + cacheTime: 0, + enabled: enabledQuery, + onError: (err) => { + setItemIdForUpdate(undefined); + console.error(err); + }, + } + ); + + if (!itemIdForUpdate) { + return ( + + ); + } + + if (!isLoading && !error && user) { + return ; + } + + return null; +}; + +export { UserEditModalFormWrapper }; diff --git a/src/app/modules/process/user-pending/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalHeader.tsx new file mode 100644 index 0000000..7fc6d55 --- /dev/null +++ b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalHeader.tsx @@ -0,0 +1,27 @@ +import { KTIcon } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; + +const UserEditModalHeader = () => { + const { setItemIdForUpdate } = useListView(); + + return ( +
+ {/* begin::Modal title */} +

Add User

+ {/* end::Modal title */} + + {/* begin::Close */} +
setItemIdForUpdate(undefined)} + style={{ cursor: "pointer" }} + > + +
+ {/* end::Close */} +
+ ); +}; + +export { UserEditModalHeader }; diff --git a/src/app/modules/process/user-pending/users-list/UsersList.tsx b/src/app/modules/process/user-pending/users-list/UsersList.tsx deleted file mode 100644 index d8f1f10..0000000 --- a/src/app/modules/process/user-pending/users-list/UsersList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import {ListViewProvider, useListView} from './core/ListViewProvider' -import {QueryRequestProvider} from './core/QueryRequestProvider' -import {QueryResponseProvider} from './core/QueryResponseProvider' -import {UsersListHeader} from './components/header/UsersListHeader' -import {UsersTable} from './table/UsersTable' -import {UserEditModal} from './user-edit-modal/UserEditModal' -import {KTCard} from '../../../../../_digifi/helpers' -import { ToolbarWrapper } from '../../../../../_digifi/layout/components/toolbar' -import { Content } from '../../../../../_digifi/layout/components/content' - -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} - -const UsersListWrapper = () => ( - - - - - - - - - - -) - -export {UsersListWrapper} diff --git a/src/app/modules/process/user-pending/users-list/components/header/UsersListFilter.tsx b/src/app/modules/process/user-pending/users-list/components/header/UsersListFilter.tsx deleted file mode 100644 index 4ac79a9..0000000 --- a/src/app/modules/process/user-pending/users-list/components/header/UsersListFilter.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import {useEffect, useState} from 'react' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {initialQueryState, KTIcon} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' - -const UsersListFilter = () => { - const {updateState} = useQueryRequest() - const {isLoading} = useQueryResponse() - const [role, setRole] = useState() - const [lastLogin, setLastLogin] = useState() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const resetData = () => { - updateState({filter: undefined, ...initialQueryState}) - } - - const filterData = () => { - updateState({ - filter: {role, last_login: lastLogin}, - ...initialQueryState, - }) - } - - return ( - <> - {/* begin::Filter Button */} - - {/* end::Filter Button */} - {/* begin::SubMenu */} -
- {/* begin::Header */} -
-
Filter Options
-
- {/* end::Header */} - - {/* begin::Separator */} -
- {/* end::Separator */} - - {/* begin::Content */} -
- {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Actions */} -
- - -
- {/* end::Actions */} -
- {/* end::Content */} -
- {/* end::SubMenu */} - - ) -} - -export {UsersListFilter} diff --git a/src/app/modules/process/user-pending/users-list/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-pending/users-list/components/header/UsersListSearchComponent.tsx deleted file mode 100644 index 75cba1c..0000000 --- a/src/app/modules/process/user-pending/users-list/components/header/UsersListSearchComponent.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ - -import {useEffect, useState} from 'react' -import {initialQueryState, KTIcon, useDebounce} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' - -const UsersListSearchComponent = () => { - const {updateState} = useQueryRequest() - const [searchTerm, setSearchTerm] = useState('') - // Debounce search term so that it only gives us latest value ... - // ... if searchTerm has not been updated within last 500ms. - // The goal is to only have the API call fire when user stops typing ... - // ... so that we aren't hitting our API rapidly. - const debouncedSearchTerm = useDebounce(searchTerm, 150) - // Effect for API call - useEffect( - () => { - if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { - updateState({search: debouncedSearchTerm, ...initialQueryState}) - } - }, - [debouncedSearchTerm] // Only call effect if debounced search term changes - // More details about useDebounce: https://usehooks.com/useDebounce/ - ) - - return ( -
- {/* begin::Search */} -
- - setSearchTerm(e.target.value)} - /> -
- {/* end::Search */} -
- ) -} - -export {UsersListSearchComponent} diff --git a/src/app/modules/process/user-pending/users-list/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-pending/users-list/components/pagination/UsersListPagination.tsx deleted file mode 100644 index 2879f48..0000000 --- a/src/app/modules/process/user-pending/users-list/components/pagination/UsersListPagination.tsx +++ /dev/null @@ -1,156 +0,0 @@ - -import clsx from 'clsx' -import {useQueryResponseLoading, useQueryResponsePagination} from '../../core/QueryResponseProvider' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {PaginationState} from '../../../../../../../_digifi/helpers' -import {useMemo} from 'react' - -const mappedLabel = (label: string): string => { - if (label === '« Previous') { - return 'Previous' - } - - if (label === 'Next »') { - return 'Next' - } - - return label -} - -const UsersListPagination = () => { - const pagination = useQueryResponsePagination() - const isLoading = useQueryResponseLoading() - const {updateState} = useQueryRequest() - const updatePage = (page: number | undefined | null) => { - if (!page || isLoading || pagination.page === page) { - return - } - - updateState({page, items_per_page: pagination.items_per_page || 10}) - } - - const PAGINATION_PAGES_COUNT = 5 - const sliceLinks = (pagination?: PaginationState) => { - if (!pagination?.links?.length) { - return [] - } - - const scopedLinks = [...pagination.links] - - let pageLinks: Array<{ - label: string - active: boolean - url: string | null - page: number | null - }> = [] - const previousLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.shift()! - const nextLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.pop()! - - const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2) - - pageLinks.push(previousLink) - - if ( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) { - pageLinks = [...pageLinks, ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT)] - } - - if ( - pagination.page > scopedLinks.length - halfOfPagesCount && - scopedLinks.length > PAGINATION_PAGES_COUNT - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice(scopedLinks.length - PAGINATION_PAGES_COUNT, scopedLinks.length), - ] - } - - if ( - !( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) && - !(pagination.page > scopedLinks.length - halfOfPagesCount) - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice( - pagination.page - 1 - halfOfPagesCount, - pagination.page + halfOfPagesCount - ), - ] - } - - pageLinks.push(nextLink) - - return pageLinks - } - - const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]) - - return ( - - ) -} - -export {UsersListPagination} diff --git a/src/app/modules/process/user-pending/users-list/core/ListViewProvider.tsx b/src/app/modules/process/user-pending/users-list/core/ListViewProvider.tsx deleted file mode 100644 index 91cc2cf..0000000 --- a/src/app/modules/process/user-pending/users-list/core/ListViewProvider.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext, useMemo} from 'react' -import { - ID, - calculatedGroupingIsDisabled, - calculateIsAllDataSelected, - groupingOnSelect, - initialListView, - ListViewContextProps, - groupingOnSelectAll, - WithChildren, -} from '../../../../../../_digifi/helpers' -import {useQueryResponse, useQueryResponseData} from './QueryResponseProvider' - -const ListViewContext = createContext(initialListView) - -const ListViewProvider: FC = ({children}) => { - const [selected, setSelected] = useState>(initialListView.selected) - const [itemIdForUpdate, setItemIdForUpdate] = useState(initialListView.itemIdForUpdate) - const {isLoading} = useQueryResponse() - const data = useQueryResponseData() - const disabled = useMemo(() => calculatedGroupingIsDisabled(isLoading, data), [isLoading, data]) - const isAllSelected = useMemo(() => calculateIsAllDataSelected(data, selected), [data, selected]) - - return ( - { - groupingOnSelect(id, selected, setSelected) - }, - onSelectAll: () => { - groupingOnSelectAll(isAllSelected, setSelected, data) - }, - clearSelected: () => { - setSelected([]) - }, - }} - > - {children} - - ) -} - -const useListView = () => useContext(ListViewContext) - -export {ListViewProvider, useListView} diff --git a/src/app/modules/process/user-pending/users-list/core/QueryRequestProvider.tsx b/src/app/modules/process/user-pending/users-list/core/QueryRequestProvider.tsx deleted file mode 100644 index 95f31cf..0000000 --- a/src/app/modules/process/user-pending/users-list/core/QueryRequestProvider.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext} from 'react' -import { - QueryState, - QueryRequestContextProps, - initialQueryRequest, - WithChildren, -} from '../../../../../../_digifi/helpers' - -const QueryRequestContext = createContext(initialQueryRequest) - -const QueryRequestProvider: FC = ({children}) => { - const [state, setState] = useState(initialQueryRequest.state) - - const updateState = (updates: Partial) => { - const updatedState = {...state, ...updates} as QueryState - setState(updatedState) - } - - return ( - - {children} - - ) -} - -const useQueryRequest = () => useContext(QueryRequestContext) -export {QueryRequestProvider, useQueryRequest} diff --git a/src/app/modules/process/user-pending/users-list/core/_models.ts b/src/app/modules/process/user-pending/users-list/core/_models.ts deleted file mode 100644 index b9b06ec..0000000 --- a/src/app/modules/process/user-pending/users-list/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {ID, Response} from '../../../../../../_digifi/helpers' -export type User = { - id?: ID - name?: string - avatar?: string - // email?: string - position?: string - role?: string - last_login?: string - two_steps?: boolean - joined_day?: string - online?: boolean - initials?: { - label: string - state: string - } - firstname?: string, - lastname?: string - uid?: string - loan_amount?: string - payment_month?: string - sales_agent?: string - gender?: string | null - marital_status?: string - email?: string - address?: string - state?: string - country?: string - status?: string - added?: string - updated?: string -} - -export type UsersQueryResponse = Response> - -export const initialUser: User = { - avatar: 'avatars/300-6.jpg', - position: 'Art Director', - role: 'Administrator', - name: '', - email: '', -} diff --git a/src/app/modules/process/user-pending/users-list/table/columns/AddedCell.tsx b/src/app/modules/process/user-pending/users-list/table/columns/AddedCell.tsx deleted file mode 100644 index 6f5bc2b..0000000 --- a/src/app/modules/process/user-pending/users-list/table/columns/AddedCell.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import {FC} from 'react' -import { NewDateTimeFormatter } from '../../../../../../../_digifi/lib/NewDateTimeFormatter' - -type Props = { - added?: string -} - -const AddedCell: FC = ({added}) => ( -
{NewDateTimeFormatter((added))}
-) - -export {AddedCell} \ No newline at end of file diff --git a/src/app/modules/process/user-pending/users-list/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-pending/users-list/table/columns/UserActionsCell.tsx deleted file mode 100644 index 9a91389..0000000 --- a/src/app/modules/process/user-pending/users-list/table/columns/UserActionsCell.tsx +++ /dev/null @@ -1,76 +0,0 @@ - -import {FC, useEffect} from 'react' -import {useMutation, useQueryClient} from 'react-query' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {ID, KTIcon, QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteUser} from '../../core/_requests' - -type Props = { - id: ID -} - -const UserActionsCell: FC = ({id}) => { - const {setItemIdForUpdate} = useListView() - const {query} = useQueryResponse() - const queryClient = useQueryClient() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const openEditModal = () => { - setItemIdForUpdate(id) - } - - const deleteItem = useMutation(() => deleteUser(id), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - }, - }) - - return ( - <> - - Actions - - - {/* begin::Menu */} -
- {/* begin::Menu item */} - - {/* end::Menu item */} - - {/* begin::Menu item */} - - {/* end::Menu item */} -
- {/* end::Menu */} - - ) -} - -export {UserActionsCell} diff --git a/src/app/modules/process/user-pending/users-list/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-pending/users-list/table/columns/UserCustomHeader.tsx deleted file mode 100644 index 3d0b58a..0000000 --- a/src/app/modules/process/user-pending/users-list/table/columns/UserCustomHeader.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import clsx from 'clsx' -import {FC, PropsWithChildren, useMemo} from 'react' -import {HeaderProps} from 'react-table' -import {initialQueryState} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {User} from '../../core/_models' - -type Props = { - className?: string - title?: string - tableProps: PropsWithChildren> -} -const UserCustomHeader: FC = ({className, title, tableProps}) => { - const id = tableProps.column.id - const {state, updateState} = useQueryRequest() - - const isSelectedForSorting = useMemo(() => { - return state.sort && state.sort === id - }, [state, id]) - const order: 'asc' | 'desc' | undefined = useMemo(() => state.order, [state]) - - const sortColumn = () => { - // avoid sorting for these columns - if (id === 'actions' || id === 'selection') { - return - } - - if (!isSelectedForSorting) { - // enable sort asc - updateState({sort: id, order: 'asc', ...initialQueryState}) - return - } - - if (isSelectedForSorting && order !== undefined) { - if (order === 'asc') { - // enable sort desc - updateState({sort: id, order: 'desc', ...initialQueryState}) - return - } - - // disable sort - updateState({sort: undefined, order: undefined, ...initialQueryState}) - } - } - - return ( - - {title} - - ) -} - -export {UserCustomHeader} diff --git a/src/app/modules/process/user-pending/users-list/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-pending/users-list/table/columns/UserInfoCell.tsx deleted file mode 100644 index 1840fef..0000000 --- a/src/app/modules/process/user-pending/users-list/table/columns/UserInfoCell.tsx +++ /dev/null @@ -1,42 +0,0 @@ - -import clsx from 'clsx' -import {FC} from 'react' -import {toAbsoluteUrl} from '../../../../../../../_digifi/helpers' -import {User} from '../../core/_models' - -type Props = { - user: User -} - -const UserInfoCell: FC = ({user}) => ( - -) - -export {UserInfoCell} diff --git a/src/app/modules/process/user-pending/users-list/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-pending/users-list/table/columns/UserSelectionCell.tsx deleted file mode 100644 index dcd2bfb..0000000 --- a/src/app/modules/process/user-pending/users-list/table/columns/UserSelectionCell.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import {FC, useMemo} from 'react' -import {ID} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' - -type Props = { - id: ID -} - -const UserSelectionCell: FC = ({id}) => { - const {selected, onSelect} = useListView() - const isSelected = useMemo(() => selected.includes(id), [id, selected]) - return ( -
- onSelect(id)} - /> -
- ) -} - -export {UserSelectionCell} diff --git a/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalForm.tsx deleted file mode 100644 index 6e8b0ec..0000000 --- a/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalForm.tsx +++ /dev/null @@ -1,407 +0,0 @@ -import {FC, useState} from 'react' -import * as Yup from 'yup' -import {useFormik} from 'formik' -import {isNotEmpty, toAbsoluteUrl} from '../../../../../../_digifi/helpers' -import {initialUser, User} from '../core/_models' -import clsx from 'clsx' -import {useListView} from '../core/ListViewProvider' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {createUser, updateUser} from '../core/_requests' -import {useQueryResponse} from '../core/QueryResponseProvider' - -type Props = { - isUserLoading: boolean - user: User -} - -const editUserSchema = Yup.object().shape({ - email: Yup.string() - .email('Wrong email format') - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Email is required'), - name: Yup.string() - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Name is required'), -}) - -const UserEditModalForm: FC = ({user, isUserLoading}) => { - const {setItemIdForUpdate} = useListView() - const {refetch} = useQueryResponse() - - const [userForEdit] = useState({ - ...user, - avatar: user.avatar || initialUser.avatar, - role: user.role || initialUser.role, - position: user.position || initialUser.position, - name: user.name || initialUser.name, - email: user.email || initialUser.email, - }) - - const cancel = (withRefresh?: boolean) => { - if (withRefresh) { - refetch() - } - setItemIdForUpdate(undefined) - } - - const blankImg = toAbsoluteUrl('media/svg/avatars/blank.svg') - const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`) - - const formik = useFormik({ - initialValues: userForEdit, - validationSchema: editUserSchema, - onSubmit: async (values, {setSubmitting}) => { - setSubmitting(true) - try { - if (isNotEmpty(values.id)) { - await updateUser(values) - } else { - await createUser(values) - } - } catch (ex) { - console.error(ex) - } finally { - setSubmitting(true) - cancel(true) - } - }, - }) - - return ( - <> -
- {/* begin::Scroll */} -
- {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Image input */} -
- {/* begin::Preview existing avatar */} -
- {/* end::Preview existing avatar */} - - {/* begin::Label */} - {/* */} - {/* end::Label */} - - {/* begin::Cancel */} - {/* - - */} - {/* end::Cancel */} - - {/* begin::Remove */} - {/* - - */} - {/* end::Remove */} -
- {/* end::Image input */} - - {/* begin::Hint */} - {/*
Allowed file types: png, jpg, jpeg.
*/} - {/* end::Hint */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {formik.touched.name && formik.errors.name && ( -
-
- {formik.errors.name} -
-
- )} - {/* end::Input */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {/* end::Input */} - {formik.touched.email && formik.errors.email && ( -
- {formik.errors.email} -
- )} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - {/* begin::Roles */} - {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} - {/* end::Roles */} -
- {/* end::Input group */} -
- {/* end::Scroll */} - - {/* begin::Actions */} -
- - - -
- {/* end::Actions */} -
- {(formik.isSubmitting || isUserLoading) && } - - ) -} - -export {UserEditModalForm} diff --git a/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalFormWrapper.tsx deleted file mode 100644 index d60d7e3..0000000 --- a/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalFormWrapper.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import {useQuery} from 'react-query' -import {UserEditModalForm} from './UserEditModalForm' -import {isNotEmpty, QUERIES} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' -import {getUserById} from '../core/_requests' - -const UserEditModalFormWrapper = () => { - const {itemIdForUpdate, setItemIdForUpdate} = useListView() - const enabledQuery: boolean = isNotEmpty(itemIdForUpdate) - const { - isLoading, - data: user, - error, - } = useQuery( - `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, - () => { - return getUserById(itemIdForUpdate) - }, - { - cacheTime: 0, - enabled: enabledQuery, - onError: (err) => { - setItemIdForUpdate(undefined) - console.error(err) - }, - } - ) - - if (!itemIdForUpdate) { - return - } - - if (!isLoading && !error && user) { - return - } - - return null -} - -export {UserEditModalFormWrapper} diff --git a/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalHeader.tsx deleted file mode 100644 index cb0f5b6..0000000 --- a/src/app/modules/process/user-pending/users-list/user-edit-modal/UserEditModalHeader.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import {KTIcon} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' - -const UserEditModalHeader = () => { - const {setItemIdForUpdate} = useListView() - - return ( -
- {/* begin::Modal title */} -

Add User

- {/* end::Modal title */} - - {/* begin::Close */} -
setItemIdForUpdate(undefined)} - style={{cursor: 'pointer'}} - > - -
- {/* end::Close */} -
- ) -} - -export {UserEditModalHeader} diff --git a/src/app/modules/process/user-ready/UsersList.tsx b/src/app/modules/process/user-ready/UsersList.tsx new file mode 100644 index 0000000..10546aa --- /dev/null +++ b/src/app/modules/process/user-ready/UsersList.tsx @@ -0,0 +1,37 @@ +import { ListViewProvider, useListView } from "./core/ListViewProvider"; +import { QueryRequestProvider } from "./core/QueryRequestProvider"; +import { QueryResponseProvider } from "./core/QueryResponseProvider"; +import { UsersListHeader } from "./components/header/UsersListHeader"; +import { UsersTable } from "./table/UsersTable"; +import { UserEditModal } from "./user-edit-modal/UserEditModal"; +import { KTCard } from "../../../../_digifi/helpers"; +import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar"; +import { Content } from "../../../../_digifi/layout/components/content"; + +const UsersList = () => { + const { itemIdForUpdate } = useListView(); + return ( + <> + + + + + {itemIdForUpdate !== undefined && } + + ); +}; + +const UsersListWrapper = () => ( + + + + + + + + + + +); + +export { UsersListWrapper }; diff --git a/src/app/modules/process/user-ready/UsersPage.tsx b/src/app/modules/process/user-ready/UsersPage.tsx deleted file mode 100644 index ec70d89..0000000 --- a/src/app/modules/process/user-ready/UsersPage.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {Route, Routes, Outlet, Navigate} from 'react-router-dom' -import {PageLink, PageTitle} from '../../../../_digifi/layout/core' -import {UsersListWrapper} from './users-list/UsersList' - -const usersBreadcrumbs: Array = [ - { - title: 'User Management', - path: '/apps/user-management/users', - isSeparator: false, - isActive: false, - }, - { - title: '', - path: '', - isSeparator: true, - isActive: false, - }, -] - -const UsersPage = () => { - return ( - - }> - - Users list - - - } - /> - - } /> - - ) -} - -export default UsersPage diff --git a/src/app/modules/process/user-pending/users-list/components/header/UserListToolbar.tsx b/src/app/modules/process/user-ready/components/header/UserListToolbar.tsx similarity index 59% rename from src/app/modules/process/user-pending/users-list/components/header/UserListToolbar.tsx rename to src/app/modules/process/user-ready/components/header/UserListToolbar.tsx index e86343b..10974f5 100644 --- a/src/app/modules/process/user-pending/users-list/components/header/UserListToolbar.tsx +++ b/src/app/modules/process/user-ready/components/header/UserListToolbar.tsx @@ -1,15 +1,18 @@ -import {KTIcon} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {UsersListFilter} from './UsersListFilter' +import { KTIcon } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { UsersListFilter } from "./UsersListFilter"; const UsersListToolbar = () => { - const {setItemIdForUpdate} = useListView() + const { setItemIdForUpdate } = useListView(); const openAddUserModal = () => { - setItemIdForUpdate(null) - } + setItemIdForUpdate(null); + }; return ( -
+
{/* begin::Export */} @@ -26,7 +29,7 @@ const UsersListToolbar = () => { */} {/* end::Add user */}
- ) -} + ); +}; -export {UsersListToolbar} +export { UsersListToolbar }; diff --git a/src/app/modules/process/user-ready/components/header/UsersListFilter.tsx b/src/app/modules/process/user-ready/components/header/UsersListFilter.tsx new file mode 100644 index 0000000..b0fea79 --- /dev/null +++ b/src/app/modules/process/user-ready/components/header/UsersListFilter.tsx @@ -0,0 +1,136 @@ +import { useEffect, useState } from "react"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { initialQueryState, KTIcon } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; + +const UsersListFilter = () => { + const { updateState } = useQueryRequest(); + const { isLoading } = useQueryResponse(); + const [role, setRole] = useState(); + const [lastLogin, setLastLogin] = useState(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const resetData = () => { + updateState({ filter: undefined, ...initialQueryState }); + }; + + const filterData = () => { + updateState({ + filter: { role, last_login: lastLogin }, + ...initialQueryState, + }); + }; + + return ( + <> + {/* begin::Filter Button */} + + {/* end::Filter Button */} + {/* begin::SubMenu */} +
+ {/* begin::Header */} +
+
Filter Options
+
+ {/* end::Header */} + + {/* begin::Separator */} +
+ {/* end::Separator */} + + {/* begin::Content */} +
+ {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Actions */} +
+ + +
+ {/* end::Actions */} +
+ {/* end::Content */} +
+ {/* end::SubMenu */} + + ); +}; + +export { UsersListFilter }; diff --git a/src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx new file mode 100644 index 0000000..7f31f93 --- /dev/null +++ b/src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx @@ -0,0 +1,38 @@ +import { useQueryClient, useMutation } from "react-query"; +import { QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteSelectedUsers } from "../../core/_requests"; + +const UsersListGrouping = () => { + const { selected, clearSelected } = useListView(); + const queryClient = useQueryClient(); + const { query } = useQueryResponse(); + + const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + clearSelected(); + }, + }); + + return ( +
+
+ {selected.length} Selected +
+ + +
+ ); +}; + +export { UsersListGrouping }; diff --git a/src/app/modules/process/user-ready/users-list/components/header/UsersListHeader.tsx b/src/app/modules/process/user-ready/components/header/UsersListHeader.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/components/header/UsersListHeader.tsx rename to src/app/modules/process/user-ready/components/header/UsersListHeader.tsx diff --git a/src/app/modules/process/user-ready/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-ready/components/header/UsersListSearchComponent.tsx new file mode 100644 index 0000000..e25b9ed --- /dev/null +++ b/src/app/modules/process/user-ready/components/header/UsersListSearchComponent.tsx @@ -0,0 +1,49 @@ +/* eslint-disable react-hooks/exhaustive-deps */ + +import { useEffect, useState } from "react"; +import { + initialQueryState, + KTIcon, + useDebounce, +} from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; + +const UsersListSearchComponent = () => { + const { updateState } = useQueryRequest(); + const [searchTerm, setSearchTerm] = useState(""); + // Debounce search term so that it only gives us latest value ... + // ... if searchTerm has not been updated within last 500ms. + // The goal is to only have the API call fire when user stops typing ... + // ... so that we aren't hitting our API rapidly. + const debouncedSearchTerm = useDebounce(searchTerm, 150); + // Effect for API call + useEffect( + () => { + if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { + updateState({ search: debouncedSearchTerm, ...initialQueryState }); + } + }, + [debouncedSearchTerm] // Only call effect if debounced search term changes + // More details about useDebounce: https://usehooks.com/useDebounce/ + ); + + return ( +
+ {/* begin::Search */} +
+ + setSearchTerm(e.target.value)} + /> +
+ {/* end::Search */} +
+ ); +}; + +export { UsersListSearchComponent }; diff --git a/src/app/modules/process/user-ready/users-list/components/loading/UsersListLoading.tsx b/src/app/modules/process/user-ready/components/loading/UsersListLoading.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/components/loading/UsersListLoading.tsx rename to src/app/modules/process/user-ready/components/loading/UsersListLoading.tsx diff --git a/src/app/modules/process/user-ready/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-ready/components/pagination/UsersListPagination.tsx new file mode 100644 index 0000000..346131c --- /dev/null +++ b/src/app/modules/process/user-ready/components/pagination/UsersListPagination.tsx @@ -0,0 +1,179 @@ +import clsx from "clsx"; +import { + useQueryResponseLoading, + useQueryResponsePagination, +} from "../../core/QueryResponseProvider"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { PaginationState } from "../../../../../../_digifi/helpers"; +import { useMemo } from "react"; + +const mappedLabel = (label: string): string => { + if (label === "« Previous") { + return "Previous"; + } + + if (label === "Next »") { + return "Next"; + } + + return label; +}; + +const UsersListPagination = () => { + const pagination = useQueryResponsePagination(); + const isLoading = useQueryResponseLoading(); + const { updateState } = useQueryRequest(); + const updatePage = (page: number | undefined | null) => { + if (!page || isLoading || pagination.page === page) { + return; + } + + updateState({ page, items_per_page: pagination.items_per_page || 10 }); + }; + + const PAGINATION_PAGES_COUNT = 5; + const sliceLinks = (pagination?: PaginationState) => { + if (!pagination?.links?.length) { + return []; + } + + const scopedLinks = [...pagination.links]; + + let pageLinks: Array<{ + label: string; + active: boolean; + url: string | null; + page: number | null; + }> = []; + const previousLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.shift()!; + const nextLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.pop()!; + + const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2); + + pageLinks.push(previousLink); + + if ( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT), + ]; + } + + if ( + pagination.page > scopedLinks.length - halfOfPagesCount && + scopedLinks.length > PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + scopedLinks.length - PAGINATION_PAGES_COUNT, + scopedLinks.length + ), + ]; + } + + if ( + !( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) && + !(pagination.page > scopedLinks.length - halfOfPagesCount) + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + pagination.page - 1 - halfOfPagesCount, + pagination.page + halfOfPagesCount + ), + ]; + } + + pageLinks.push(nextLink); + + return pageLinks; + }; + + const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]); + + return ( + + ); +}; + +export { UsersListPagination }; diff --git a/src/app/modules/process/user-ready/core/ListViewProvider.tsx b/src/app/modules/process/user-ready/core/ListViewProvider.tsx new file mode 100644 index 0000000..d72ff1c --- /dev/null +++ b/src/app/modules/process/user-ready/core/ListViewProvider.tsx @@ -0,0 +1,62 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext, useMemo } from "react"; +import { + ID, + calculatedGroupingIsDisabled, + calculateIsAllDataSelected, + groupingOnSelect, + initialListView, + ListViewContextProps, + groupingOnSelectAll, + WithChildren, +} from "../../../../../_digifi/helpers"; +import { + useQueryResponse, + useQueryResponseData, +} from "./QueryResponseProvider"; + +const ListViewContext = createContext(initialListView); + +const ListViewProvider: FC = ({ children }) => { + const [selected, setSelected] = useState>(initialListView.selected); + const [itemIdForUpdate, setItemIdForUpdate] = useState( + initialListView.itemIdForUpdate + ); + const { isLoading } = useQueryResponse(); + const data = useQueryResponseData(); + const disabled = useMemo( + () => calculatedGroupingIsDisabled(isLoading, data), + [isLoading, data] + ); + const isAllSelected = useMemo( + () => calculateIsAllDataSelected(data, selected), + [data, selected] + ); + + return ( + { + groupingOnSelect(id, selected, setSelected); + }, + onSelectAll: () => { + groupingOnSelectAll(isAllSelected, setSelected, data); + }, + clearSelected: () => { + setSelected([]); + }, + }} + > + {children} + + ); +}; + +const useListView = () => useContext(ListViewContext); + +export { ListViewProvider, useListView }; diff --git a/src/app/modules/process/user-ready/core/QueryRequestProvider.tsx b/src/app/modules/process/user-ready/core/QueryRequestProvider.tsx new file mode 100644 index 0000000..2fb7824 --- /dev/null +++ b/src/app/modules/process/user-ready/core/QueryRequestProvider.tsx @@ -0,0 +1,29 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext } from "react"; +import { + QueryState, + QueryRequestContextProps, + initialQueryRequest, + WithChildren, +} from "../../../../../_digifi/helpers"; + +const QueryRequestContext = + createContext(initialQueryRequest); + +const QueryRequestProvider: FC = ({ children }) => { + const [state, setState] = useState(initialQueryRequest.state); + + const updateState = (updates: Partial) => { + const updatedState = { ...state, ...updates } as QueryState; + setState(updatedState); + }; + + return ( + + {children} + + ); +}; + +const useQueryRequest = () => useContext(QueryRequestContext); +export { QueryRequestProvider, useQueryRequest }; diff --git a/src/app/modules/process/user-ready/users-list/core/QueryResponseProvider.tsx b/src/app/modules/process/user-ready/core/QueryResponseProvider.tsx similarity index 51% rename from src/app/modules/process/user-ready/users-list/core/QueryResponseProvider.tsx rename to src/app/modules/process/user-ready/core/QueryResponseProvider.tsx index 9f9e490..efc16f4 100644 --- a/src/app/modules/process/user-ready/users-list/core/QueryResponseProvider.tsx +++ b/src/app/modules/process/user-ready/core/QueryResponseProvider.tsx @@ -1,7 +1,7 @@ /* eslint-disable react-refresh/only-export-components */ /* eslint-disable react-hooks/exhaustive-deps */ -import {FC, useContext, useState, useEffect, useMemo} from 'react' -import {useQuery} from 'react-query' +import { FC, useContext, useState, useEffect, useMemo } from "react"; +import { useQuery } from "react-query"; import { createResponseContext, initialQueryResponse, @@ -10,22 +10,22 @@ import { QUERIES, stringifyRequestQuery, WithChildren, -} from '../../../../../../_digifi/helpers' -import {getReadyUsers} from '../../../core/_requests' -import {User} from '../../../core/_models' -import {useQueryRequest} from './QueryRequestProvider' +} from "../../../../../_digifi/helpers"; +import { getReadyUsers } from "../../core/_requests"; +import { User } from "../../core/_models"; +import { useQueryRequest } from "./QueryRequestProvider"; -const QueryResponseContext = createResponseContext(initialQueryResponse) -const QueryResponseProvider: FC = ({children}) => { - const {state} = useQueryRequest() - const [query, setQuery] = useState(stringifyRequestQuery(state)) - const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]) +const QueryResponseContext = createResponseContext(initialQueryResponse); +const QueryResponseProvider: FC = ({ children }) => { + const { state } = useQueryRequest(); + const [query, setQuery] = useState(stringifyRequestQuery(state)); + const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]); useEffect(() => { if (query !== updatedQuery) { - setQuery(updatedQuery) + setQuery(updatedQuery); } - }, [updatedQuery]) + }, [updatedQuery]); const { isFetching, @@ -34,47 +34,49 @@ const QueryResponseProvider: FC = ({children}) => { } = useQuery( `${QUERIES.USERS_LIST}-${query}`, () => { - return getReadyUsers(query) + return getReadyUsers(query); }, - {cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false} - ) + { cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false } + ); return ( - + {children} - ) -} + ); +}; -const useQueryResponse = () => useContext(QueryResponseContext) +const useQueryResponse = () => useContext(QueryResponseContext); const useQueryResponseData = () => { - const {response} = useQueryResponse() + const { response } = useQueryResponse(); if (!response) { - return [] + return []; } - return response?.records || [] -} + return response?.records || []; +}; const useQueryResponsePagination = () => { const defaultPaginationState: PaginationState = { links: [], ...initialQueryState, - } + }; - const {response} = useQueryResponse() + const { response } = useQueryResponse(); if (!response || !response.payload || !response.payload.pagination) { - return defaultPaginationState + return defaultPaginationState; } - return response.payload.pagination -} + return response.payload.pagination; +}; const useQueryResponseLoading = (): boolean => { - const {isLoading} = useQueryResponse() - return isLoading -} + const { isLoading } = useQueryResponse(); + return isLoading; +}; export { QueryResponseProvider, @@ -82,4 +84,4 @@ export { useQueryResponseData, useQueryResponsePagination, useQueryResponseLoading, -} +}; diff --git a/src/app/modules/process/user-ready/core/_models.ts b/src/app/modules/process/user-ready/core/_models.ts new file mode 100644 index 0000000..bc84896 --- /dev/null +++ b/src/app/modules/process/user-ready/core/_models.ts @@ -0,0 +1,42 @@ +import { ID, Response } from "../../../../../_digifi/helpers"; +export type User = { + id?: ID; + name?: string; + avatar?: string; + // email?: string + position?: string; + role?: string; + last_login?: string; + two_steps?: boolean; + joined_day?: string; + online?: boolean; + initials?: { + label: string; + state: string; + }; + firstname?: string; + lastname?: string; + uid?: string; + loan_amount?: string; + payment_month?: string; + sales_agent?: string; + gender?: string | null; + marital_status?: string; + email?: string; + address?: string; + state?: string; + country?: string; + status?: string; + added?: string; + updated?: string; +}; + +export type UsersQueryResponse = Response>; + +export const initialUser: User = { + avatar: "avatars/300-6.jpg", + position: "Art Director", + role: "Administrator", + name: "", + email: "", +}; diff --git a/src/app/modules/process/user-started/users-list/core/_requests.ts b/src/app/modules/process/user-ready/core/_requests.ts similarity index 93% rename from src/app/modules/process/user-started/users-list/core/_requests.ts rename to src/app/modules/process/user-ready/core/_requests.ts index a585521..ccf71ba 100644 --- a/src/app/modules/process/user-started/users-list/core/_requests.ts +++ b/src/app/modules/process/user-ready/core/_requests.ts @@ -1,19 +1,20 @@ import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../../_digifi/helpers"; +import { ID, Response } from "../../../../../_digifi/helpers"; import { User, UsersQueryResponse } from "./_models"; const API_URL = import.meta.env.VITE_APP_THEME_API_URL; const USER_URL = `${API_URL}/user`; // const GET_USERS_URL = `${API_URL}/users/query`; -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT +const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; // const getStartedUsers = (query: string): Promise => { // return axios // .get(`${GET_USERS_URL}?${query}`) // .then((d: AxiosResponse) => d.data); // }; -const getStartedUsers = (query: string): Promise => { // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION +const getStartedUsers = (query: string): Promise => { + // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION return axios .get(`${NEW_USER_ENDPOINT}/loan/started`) .then((d: AxiosResponse) => d.data); diff --git a/src/app/modules/process/user-ready/table/UsersTable.tsx b/src/app/modules/process/user-ready/table/UsersTable.tsx new file mode 100644 index 0000000..8f7a3bb --- /dev/null +++ b/src/app/modules/process/user-ready/table/UsersTable.tsx @@ -0,0 +1,66 @@ +import { useMemo } from "react"; +import { useTable, ColumnInstance, Row } from "react-table"; +import { CustomHeaderColumn } from "./columns/CustomHeaderColumn"; +import { CustomRow } from "./columns/CustomRow"; +import { + useQueryResponseData, + useQueryResponseLoading, +} from "../core/QueryResponseProvider"; +import { usersColumns } from "./columns/_columns"; +import { User } from "../../core/_models"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { UsersListPagination } from "../components/pagination/UsersListPagination"; +import { KTCardBody } from "../../../../../_digifi/helpers"; + +const UsersTable = () => { + const users = useQueryResponseData(); + // console.log('users', users) + const isLoading = useQueryResponseLoading(); + const data = useMemo(() => users, [users]); + const columns = useMemo(() => usersColumns, []); + const { getTableProps, getTableBodyProps, headers, rows, prepareRow } = + useTable({ + columns, + data, + }); + + return ( + +
+ + + + {headers.map((column: ColumnInstance) => ( + + ))} + + + + {rows.length > 0 ? ( + rows.map((row: Row, i) => { + prepareRow(row); + return ; + }) + ) : ( + + + + )} + +
+
+ No matching records found +
+
+
+ + {isLoading && } +
+ ); +}; + +export { UsersTable }; diff --git a/src/app/modules/process/user-ready/table/columns/AddedCell.tsx b/src/app/modules/process/user-ready/table/columns/AddedCell.tsx new file mode 100644 index 0000000..2e18bad --- /dev/null +++ b/src/app/modules/process/user-ready/table/columns/AddedCell.tsx @@ -0,0 +1,14 @@ +import { FC } from "react"; +import { NewDateTimeFormatter } from "../../../../../../_digifi/lib/NewDateTimeFormatter"; + +type Props = { + added?: string; +}; + +const AddedCell: FC = ({ added }) => ( +
+ {NewDateTimeFormatter(added)} +
+); + +export { AddedCell }; diff --git a/src/app/modules/process/user-ready/users-list/table/columns/AgentCell.tsx b/src/app/modules/process/user-ready/table/columns/AgentCell.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/table/columns/AgentCell.tsx rename to src/app/modules/process/user-ready/table/columns/AgentCell.tsx diff --git a/src/app/modules/process/user-ready/users-list/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-ready/table/columns/CustomHeaderColumn.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/table/columns/CustomHeaderColumn.tsx rename to src/app/modules/process/user-ready/table/columns/CustomHeaderColumn.tsx diff --git a/src/app/modules/process/user-ready/users-list/table/columns/CustomRow.tsx b/src/app/modules/process/user-ready/table/columns/CustomRow.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/table/columns/CustomRow.tsx rename to src/app/modules/process/user-ready/table/columns/CustomRow.tsx diff --git a/src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx new file mode 100644 index 0000000..4843e41 --- /dev/null +++ b/src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx @@ -0,0 +1,75 @@ +import { FC, useEffect } from "react"; +import { useMutation, useQueryClient } from "react-query"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteUser } from "../../core/_requests"; + +type Props = { + id: ID; +}; + +const UserActionsCell: FC = ({ id }) => { + const { setItemIdForUpdate } = useListView(); + const { query } = useQueryResponse(); + const queryClient = useQueryClient(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const openEditModal = () => { + setItemIdForUpdate(id); + }; + + const deleteItem = useMutation(() => deleteUser(id), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + }, + }); + + return ( + <> + + Actions + + + {/* begin::Menu */} +
+ {/* begin::Menu item */} + + {/* end::Menu item */} + + {/* begin::Menu item */} + + {/* end::Menu item */} +
+ {/* end::Menu */} + + ); +}; + +export { UserActionsCell }; diff --git a/src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx new file mode 100644 index 0000000..76ea930 --- /dev/null +++ b/src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx @@ -0,0 +1,61 @@ +import clsx from "clsx"; +import { FC, PropsWithChildren, useMemo } from "react"; +import { HeaderProps } from "react-table"; +import { initialQueryState } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { User } from "../../core/_models"; + +type Props = { + className?: string; + title?: string; + tableProps: PropsWithChildren>; +}; +const UserCustomHeader: FC = ({ className, title, tableProps }) => { + const id = tableProps.column.id; + const { state, updateState } = useQueryRequest(); + + const isSelectedForSorting = useMemo(() => { + return state.sort && state.sort === id; + }, [state, id]); + const order: "asc" | "desc" | undefined = useMemo(() => state.order, [state]); + + const sortColumn = () => { + // avoid sorting for these columns + if (id === "actions" || id === "selection") { + return; + } + + if (!isSelectedForSorting) { + // enable sort asc + updateState({ sort: id, order: "asc", ...initialQueryState }); + return; + } + + if (isSelectedForSorting && order !== undefined) { + if (order === "asc") { + // enable sort desc + updateState({ sort: id, order: "desc", ...initialQueryState }); + return; + } + + // disable sort + updateState({ sort: undefined, order: undefined, ...initialQueryState }); + } + }; + + return ( + + {title} + + ); +}; + +export { UserCustomHeader }; diff --git a/src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx new file mode 100644 index 0000000..6b45b58 --- /dev/null +++ b/src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx @@ -0,0 +1,46 @@ +import clsx from "clsx"; +import { FC } from "react"; +import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; +import { User } from "../../core/_models"; + +type Props = { + user: User; +}; + +const UserInfoCell: FC = ({ user }) => ( + +); + +export { UserInfoCell }; diff --git a/src/app/modules/process/user-ready/users-list/table/columns/UserLastLoginCell.tsx b/src/app/modules/process/user-ready/table/columns/UserLastLoginCell.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/table/columns/UserLastLoginCell.tsx rename to src/app/modules/process/user-ready/table/columns/UserLastLoginCell.tsx diff --git a/src/app/modules/process/user-ready/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-ready/table/columns/UserSelectionCell.tsx new file mode 100644 index 0000000..ee8d295 --- /dev/null +++ b/src/app/modules/process/user-ready/table/columns/UserSelectionCell.tsx @@ -0,0 +1,26 @@ +import { FC, useMemo } from "react"; +import { ID } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; + +type Props = { + id: ID; +}; + +const UserSelectionCell: FC = ({ id }) => { + const { selected, onSelect } = useListView(); + const isSelected = useMemo(() => selected.includes(id), [id, selected]); + return ( +
+ onSelect(id)} + /> +
+ ); +}; + +export { UserSelectionCell }; diff --git a/src/app/modules/process/user-ready/users-list/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-ready/table/columns/UserSelectionHeader.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/table/columns/UserSelectionHeader.tsx rename to src/app/modules/process/user-ready/table/columns/UserSelectionHeader.tsx diff --git a/src/app/modules/process/user-ready/users-list/table/columns/_columns.tsx b/src/app/modules/process/user-ready/table/columns/_columns.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/table/columns/_columns.tsx rename to src/app/modules/process/user-ready/table/columns/_columns.tsx diff --git a/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModal.tsx b/src/app/modules/process/user-ready/user-edit-modal/UserEditModal.tsx similarity index 100% rename from src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModal.tsx rename to src/app/modules/process/user-ready/user-edit-modal/UserEditModal.tsx diff --git a/src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx new file mode 100644 index 0000000..ff35559 --- /dev/null +++ b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx @@ -0,0 +1,433 @@ +import { FC, useState } from "react"; +import * as Yup from "yup"; +import { useFormik } from "formik"; +import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; +import { initialUser, User } from "../core/_models"; +import clsx from "clsx"; +import { useListView } from "../core/ListViewProvider"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { createUser, updateUser } from "../core/_requests"; +import { useQueryResponse } from "../core/QueryResponseProvider"; + +type Props = { + isUserLoading: boolean; + user: User; +}; + +const editUserSchema = Yup.object().shape({ + email: Yup.string() + .email("Wrong email format") + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Email is required"), + name: Yup.string() + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Name is required"), +}); + +const UserEditModalForm: FC = ({ user, isUserLoading }) => { + const { setItemIdForUpdate } = useListView(); + const { refetch } = useQueryResponse(); + + const [userForEdit] = useState({ + ...user, + avatar: user.avatar || initialUser.avatar, + role: user.role || initialUser.role, + position: user.position || initialUser.position, + name: user.name || initialUser.name, + email: user.email || initialUser.email, + }); + + const cancel = (withRefresh?: boolean) => { + if (withRefresh) { + refetch(); + } + setItemIdForUpdate(undefined); + }; + + const blankImg = toAbsoluteUrl("media/svg/avatars/blank.svg"); + const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`); + + const formik = useFormik({ + initialValues: userForEdit, + validationSchema: editUserSchema, + onSubmit: async (values, { setSubmitting }) => { + setSubmitting(true); + try { + if (isNotEmpty(values.id)) { + await updateUser(values); + } else { + await createUser(values); + } + } catch (ex) { + console.error(ex); + } finally { + setSubmitting(true); + cancel(true); + } + }, + }); + + return ( + <> +
+ {/* begin::Scroll */} +
+ {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Image input */} +
+ {/* begin::Preview existing avatar */} +
+ {/* end::Preview existing avatar */} + + {/* begin::Label */} + {/* */} + {/* end::Label */} + + {/* begin::Cancel */} + {/* + + */} + {/* end::Cancel */} + + {/* begin::Remove */} + {/* + + */} + {/* end::Remove */} +
+ {/* end::Image input */} + + {/* begin::Hint */} + {/*
Allowed file types: png, jpg, jpeg.
*/} + {/* end::Hint */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {formik.touched.name && formik.errors.name && ( +
+
+ {formik.errors.name} +
+
+ )} + {/* end::Input */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {/* end::Input */} + {formik.touched.email && formik.errors.email && ( +
+ {formik.errors.email} +
+ )} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + {/* begin::Roles */} + {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} + {/* end::Roles */} +
+ {/* end::Input group */} +
+ {/* end::Scroll */} + + {/* begin::Actions */} +
+ + + +
+ {/* end::Actions */} +
+ {(formik.isSubmitting || isUserLoading) && } + + ); +}; + +export { UserEditModalForm }; diff --git a/src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx new file mode 100644 index 0000000..c3caa7f --- /dev/null +++ b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx @@ -0,0 +1,42 @@ +import { useQuery } from "react-query"; +import { UserEditModalForm } from "./UserEditModalForm"; +import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; +import { getUserById } from "../core/_requests"; + +const UserEditModalFormWrapper = () => { + const { itemIdForUpdate, setItemIdForUpdate } = useListView(); + const enabledQuery: boolean = isNotEmpty(itemIdForUpdate); + const { + isLoading, + data: user, + error, + } = useQuery( + `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, + () => { + return getUserById(itemIdForUpdate); + }, + { + cacheTime: 0, + enabled: enabledQuery, + onError: (err) => { + setItemIdForUpdate(undefined); + console.error(err); + }, + } + ); + + if (!itemIdForUpdate) { + return ( + + ); + } + + if (!isLoading && !error && user) { + return ; + } + + return null; +}; + +export { UserEditModalFormWrapper }; diff --git a/src/app/modules/process/user-ready/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalHeader.tsx new file mode 100644 index 0000000..7fc6d55 --- /dev/null +++ b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalHeader.tsx @@ -0,0 +1,27 @@ +import { KTIcon } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; + +const UserEditModalHeader = () => { + const { setItemIdForUpdate } = useListView(); + + return ( +
+ {/* begin::Modal title */} +

Add User

+ {/* end::Modal title */} + + {/* begin::Close */} +
setItemIdForUpdate(undefined)} + style={{ cursor: "pointer" }} + > + +
+ {/* end::Close */} +
+ ); +}; + +export { UserEditModalHeader }; diff --git a/src/app/modules/process/user-ready/users-list/UsersList.tsx b/src/app/modules/process/user-ready/users-list/UsersList.tsx deleted file mode 100644 index d8f1f10..0000000 --- a/src/app/modules/process/user-ready/users-list/UsersList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import {ListViewProvider, useListView} from './core/ListViewProvider' -import {QueryRequestProvider} from './core/QueryRequestProvider' -import {QueryResponseProvider} from './core/QueryResponseProvider' -import {UsersListHeader} from './components/header/UsersListHeader' -import {UsersTable} from './table/UsersTable' -import {UserEditModal} from './user-edit-modal/UserEditModal' -import {KTCard} from '../../../../../_digifi/helpers' -import { ToolbarWrapper } from '../../../../../_digifi/layout/components/toolbar' -import { Content } from '../../../../../_digifi/layout/components/content' - -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} - -const UsersListWrapper = () => ( - - - - - - - - - - -) - -export {UsersListWrapper} diff --git a/src/app/modules/process/user-ready/users-list/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-ready/users-list/components/header/UsersListGrouping.tsx deleted file mode 100644 index 6400fd7..0000000 --- a/src/app/modules/process/user-ready/users-list/components/header/UsersListGrouping.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import {useQueryClient, useMutation} from 'react-query' -import {QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteSelectedUsers} from '../../core/_requests' - -const UsersListGrouping = () => { - const {selected, clearSelected} = useListView() - const queryClient = useQueryClient() - const {query} = useQueryResponse() - - const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - clearSelected() - }, - }) - - return ( -
-
- {selected.length} Selected -
- - -
- ) -} - -export {UsersListGrouping} diff --git a/src/app/modules/process/user-ready/users-list/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-ready/users-list/components/pagination/UsersListPagination.tsx deleted file mode 100644 index 2879f48..0000000 --- a/src/app/modules/process/user-ready/users-list/components/pagination/UsersListPagination.tsx +++ /dev/null @@ -1,156 +0,0 @@ - -import clsx from 'clsx' -import {useQueryResponseLoading, useQueryResponsePagination} from '../../core/QueryResponseProvider' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {PaginationState} from '../../../../../../../_digifi/helpers' -import {useMemo} from 'react' - -const mappedLabel = (label: string): string => { - if (label === '« Previous') { - return 'Previous' - } - - if (label === 'Next »') { - return 'Next' - } - - return label -} - -const UsersListPagination = () => { - const pagination = useQueryResponsePagination() - const isLoading = useQueryResponseLoading() - const {updateState} = useQueryRequest() - const updatePage = (page: number | undefined | null) => { - if (!page || isLoading || pagination.page === page) { - return - } - - updateState({page, items_per_page: pagination.items_per_page || 10}) - } - - const PAGINATION_PAGES_COUNT = 5 - const sliceLinks = (pagination?: PaginationState) => { - if (!pagination?.links?.length) { - return [] - } - - const scopedLinks = [...pagination.links] - - let pageLinks: Array<{ - label: string - active: boolean - url: string | null - page: number | null - }> = [] - const previousLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.shift()! - const nextLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.pop()! - - const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2) - - pageLinks.push(previousLink) - - if ( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) { - pageLinks = [...pageLinks, ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT)] - } - - if ( - pagination.page > scopedLinks.length - halfOfPagesCount && - scopedLinks.length > PAGINATION_PAGES_COUNT - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice(scopedLinks.length - PAGINATION_PAGES_COUNT, scopedLinks.length), - ] - } - - if ( - !( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) && - !(pagination.page > scopedLinks.length - halfOfPagesCount) - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice( - pagination.page - 1 - halfOfPagesCount, - pagination.page + halfOfPagesCount - ), - ] - } - - pageLinks.push(nextLink) - - return pageLinks - } - - const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]) - - return ( - - ) -} - -export {UsersListPagination} diff --git a/src/app/modules/process/user-ready/users-list/core/ListViewProvider.tsx b/src/app/modules/process/user-ready/users-list/core/ListViewProvider.tsx deleted file mode 100644 index 91cc2cf..0000000 --- a/src/app/modules/process/user-ready/users-list/core/ListViewProvider.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext, useMemo} from 'react' -import { - ID, - calculatedGroupingIsDisabled, - calculateIsAllDataSelected, - groupingOnSelect, - initialListView, - ListViewContextProps, - groupingOnSelectAll, - WithChildren, -} from '../../../../../../_digifi/helpers' -import {useQueryResponse, useQueryResponseData} from './QueryResponseProvider' - -const ListViewContext = createContext(initialListView) - -const ListViewProvider: FC = ({children}) => { - const [selected, setSelected] = useState>(initialListView.selected) - const [itemIdForUpdate, setItemIdForUpdate] = useState(initialListView.itemIdForUpdate) - const {isLoading} = useQueryResponse() - const data = useQueryResponseData() - const disabled = useMemo(() => calculatedGroupingIsDisabled(isLoading, data), [isLoading, data]) - const isAllSelected = useMemo(() => calculateIsAllDataSelected(data, selected), [data, selected]) - - return ( - { - groupingOnSelect(id, selected, setSelected) - }, - onSelectAll: () => { - groupingOnSelectAll(isAllSelected, setSelected, data) - }, - clearSelected: () => { - setSelected([]) - }, - }} - > - {children} - - ) -} - -const useListView = () => useContext(ListViewContext) - -export {ListViewProvider, useListView} diff --git a/src/app/modules/process/user-ready/users-list/core/QueryRequestProvider.tsx b/src/app/modules/process/user-ready/users-list/core/QueryRequestProvider.tsx deleted file mode 100644 index 95f31cf..0000000 --- a/src/app/modules/process/user-ready/users-list/core/QueryRequestProvider.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext} from 'react' -import { - QueryState, - QueryRequestContextProps, - initialQueryRequest, - WithChildren, -} from '../../../../../../_digifi/helpers' - -const QueryRequestContext = createContext(initialQueryRequest) - -const QueryRequestProvider: FC = ({children}) => { - const [state, setState] = useState(initialQueryRequest.state) - - const updateState = (updates: Partial) => { - const updatedState = {...state, ...updates} as QueryState - setState(updatedState) - } - - return ( - - {children} - - ) -} - -const useQueryRequest = () => useContext(QueryRequestContext) -export {QueryRequestProvider, useQueryRequest} diff --git a/src/app/modules/process/user-ready/users-list/core/_models.ts b/src/app/modules/process/user-ready/users-list/core/_models.ts deleted file mode 100644 index b9b06ec..0000000 --- a/src/app/modules/process/user-ready/users-list/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {ID, Response} from '../../../../../../_digifi/helpers' -export type User = { - id?: ID - name?: string - avatar?: string - // email?: string - position?: string - role?: string - last_login?: string - two_steps?: boolean - joined_day?: string - online?: boolean - initials?: { - label: string - state: string - } - firstname?: string, - lastname?: string - uid?: string - loan_amount?: string - payment_month?: string - sales_agent?: string - gender?: string | null - marital_status?: string - email?: string - address?: string - state?: string - country?: string - status?: string - added?: string - updated?: string -} - -export type UsersQueryResponse = Response> - -export const initialUser: User = { - avatar: 'avatars/300-6.jpg', - position: 'Art Director', - role: 'Administrator', - name: '', - email: '', -} diff --git a/src/app/modules/process/user-ready/users-list/table/UsersTable.tsx b/src/app/modules/process/user-ready/users-list/table/UsersTable.tsx deleted file mode 100644 index e803da9..0000000 --- a/src/app/modules/process/user-ready/users-list/table/UsersTable.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import {useMemo} from 'react' -import {useTable, ColumnInstance, Row} from 'react-table' -import {CustomHeaderColumn} from './columns/CustomHeaderColumn' -import {CustomRow} from './columns/CustomRow' -import {useQueryResponseData, useQueryResponseLoading} from '../core/QueryResponseProvider' -import {usersColumns} from './columns/_columns' -import {User} from '../../../core/_models' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {UsersListPagination} from '../components/pagination/UsersListPagination' -import {KTCardBody} from '../../../../../../_digifi/helpers' - -const UsersTable = () => { - const users = useQueryResponseData() - // console.log('users', users) - const isLoading = useQueryResponseLoading() - const data = useMemo(() => users, [users]) - const columns = useMemo(() => usersColumns, []) - const {getTableProps, getTableBodyProps, headers, rows, prepareRow} = useTable({ - columns, - data, - }) - - return ( - -
- - - - {headers.map((column: ColumnInstance) => ( - - ))} - - - - {rows.length > 0 ? ( - rows.map((row: Row, i) => { - prepareRow(row) - return - }) - ) : ( - - - - )} - -
-
- No matching records found -
-
-
- - {isLoading && } -
- ) -} - -export {UsersTable} diff --git a/src/app/modules/process/user-ready/users-list/table/columns/AddedCell.tsx b/src/app/modules/process/user-ready/users-list/table/columns/AddedCell.tsx deleted file mode 100644 index 6f5bc2b..0000000 --- a/src/app/modules/process/user-ready/users-list/table/columns/AddedCell.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import {FC} from 'react' -import { NewDateTimeFormatter } from '../../../../../../../_digifi/lib/NewDateTimeFormatter' - -type Props = { - added?: string -} - -const AddedCell: FC = ({added}) => ( -
{NewDateTimeFormatter((added))}
-) - -export {AddedCell} \ No newline at end of file diff --git a/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalForm.tsx deleted file mode 100644 index 6e8b0ec..0000000 --- a/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalForm.tsx +++ /dev/null @@ -1,407 +0,0 @@ -import {FC, useState} from 'react' -import * as Yup from 'yup' -import {useFormik} from 'formik' -import {isNotEmpty, toAbsoluteUrl} from '../../../../../../_digifi/helpers' -import {initialUser, User} from '../core/_models' -import clsx from 'clsx' -import {useListView} from '../core/ListViewProvider' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {createUser, updateUser} from '../core/_requests' -import {useQueryResponse} from '../core/QueryResponseProvider' - -type Props = { - isUserLoading: boolean - user: User -} - -const editUserSchema = Yup.object().shape({ - email: Yup.string() - .email('Wrong email format') - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Email is required'), - name: Yup.string() - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Name is required'), -}) - -const UserEditModalForm: FC = ({user, isUserLoading}) => { - const {setItemIdForUpdate} = useListView() - const {refetch} = useQueryResponse() - - const [userForEdit] = useState({ - ...user, - avatar: user.avatar || initialUser.avatar, - role: user.role || initialUser.role, - position: user.position || initialUser.position, - name: user.name || initialUser.name, - email: user.email || initialUser.email, - }) - - const cancel = (withRefresh?: boolean) => { - if (withRefresh) { - refetch() - } - setItemIdForUpdate(undefined) - } - - const blankImg = toAbsoluteUrl('media/svg/avatars/blank.svg') - const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`) - - const formik = useFormik({ - initialValues: userForEdit, - validationSchema: editUserSchema, - onSubmit: async (values, {setSubmitting}) => { - setSubmitting(true) - try { - if (isNotEmpty(values.id)) { - await updateUser(values) - } else { - await createUser(values) - } - } catch (ex) { - console.error(ex) - } finally { - setSubmitting(true) - cancel(true) - } - }, - }) - - return ( - <> -
- {/* begin::Scroll */} -
- {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Image input */} -
- {/* begin::Preview existing avatar */} -
- {/* end::Preview existing avatar */} - - {/* begin::Label */} - {/* */} - {/* end::Label */} - - {/* begin::Cancel */} - {/* - - */} - {/* end::Cancel */} - - {/* begin::Remove */} - {/* - - */} - {/* end::Remove */} -
- {/* end::Image input */} - - {/* begin::Hint */} - {/*
Allowed file types: png, jpg, jpeg.
*/} - {/* end::Hint */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {formik.touched.name && formik.errors.name && ( -
-
- {formik.errors.name} -
-
- )} - {/* end::Input */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {/* end::Input */} - {formik.touched.email && formik.errors.email && ( -
- {formik.errors.email} -
- )} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - {/* begin::Roles */} - {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} - {/* end::Roles */} -
- {/* end::Input group */} -
- {/* end::Scroll */} - - {/* begin::Actions */} -
- - - -
- {/* end::Actions */} -
- {(formik.isSubmitting || isUserLoading) && } - - ) -} - -export {UserEditModalForm} diff --git a/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalFormWrapper.tsx deleted file mode 100644 index d60d7e3..0000000 --- a/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalFormWrapper.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import {useQuery} from 'react-query' -import {UserEditModalForm} from './UserEditModalForm' -import {isNotEmpty, QUERIES} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' -import {getUserById} from '../core/_requests' - -const UserEditModalFormWrapper = () => { - const {itemIdForUpdate, setItemIdForUpdate} = useListView() - const enabledQuery: boolean = isNotEmpty(itemIdForUpdate) - const { - isLoading, - data: user, - error, - } = useQuery( - `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, - () => { - return getUserById(itemIdForUpdate) - }, - { - cacheTime: 0, - enabled: enabledQuery, - onError: (err) => { - setItemIdForUpdate(undefined) - console.error(err) - }, - } - ) - - if (!itemIdForUpdate) { - return - } - - if (!isLoading && !error && user) { - return - } - - return null -} - -export {UserEditModalFormWrapper} diff --git a/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalHeader.tsx deleted file mode 100644 index cb0f5b6..0000000 --- a/src/app/modules/process/user-ready/users-list/user-edit-modal/UserEditModalHeader.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import {KTIcon} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' - -const UserEditModalHeader = () => { - const {setItemIdForUpdate} = useListView() - - return ( -
- {/* begin::Modal title */} -

Add User

- {/* end::Modal title */} - - {/* begin::Close */} -
setItemIdForUpdate(undefined)} - style={{cursor: 'pointer'}} - > - -
- {/* end::Close */} -
- ) -} - -export {UserEditModalHeader} diff --git a/src/app/modules/process/user-rejected/UsersList.tsx b/src/app/modules/process/user-rejected/UsersList.tsx new file mode 100644 index 0000000..10546aa --- /dev/null +++ b/src/app/modules/process/user-rejected/UsersList.tsx @@ -0,0 +1,37 @@ +import { ListViewProvider, useListView } from "./core/ListViewProvider"; +import { QueryRequestProvider } from "./core/QueryRequestProvider"; +import { QueryResponseProvider } from "./core/QueryResponseProvider"; +import { UsersListHeader } from "./components/header/UsersListHeader"; +import { UsersTable } from "./table/UsersTable"; +import { UserEditModal } from "./user-edit-modal/UserEditModal"; +import { KTCard } from "../../../../_digifi/helpers"; +import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar"; +import { Content } from "../../../../_digifi/layout/components/content"; + +const UsersList = () => { + const { itemIdForUpdate } = useListView(); + return ( + <> + + + + + {itemIdForUpdate !== undefined && } + + ); +}; + +const UsersListWrapper = () => ( + + + + + + + + + + +); + +export { UsersListWrapper }; diff --git a/src/app/modules/process/user-rejected/UsersPage.tsx b/src/app/modules/process/user-rejected/UsersPage.tsx deleted file mode 100644 index ec70d89..0000000 --- a/src/app/modules/process/user-rejected/UsersPage.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {Route, Routes, Outlet, Navigate} from 'react-router-dom' -import {PageLink, PageTitle} from '../../../../_digifi/layout/core' -import {UsersListWrapper} from './users-list/UsersList' - -const usersBreadcrumbs: Array = [ - { - title: 'User Management', - path: '/apps/user-management/users', - isSeparator: false, - isActive: false, - }, - { - title: '', - path: '', - isSeparator: true, - isActive: false, - }, -] - -const UsersPage = () => { - return ( - - }> - - Users list - - - } - /> - - } /> - - ) -} - -export default UsersPage diff --git a/src/app/modules/process/user-ready/users-list/components/header/UserListToolbar.tsx b/src/app/modules/process/user-rejected/components/header/UserListToolbar.tsx similarity index 93% rename from src/app/modules/process/user-ready/users-list/components/header/UserListToolbar.tsx rename to src/app/modules/process/user-rejected/components/header/UserListToolbar.tsx index e86343b..20c5bbc 100644 --- a/src/app/modules/process/user-ready/users-list/components/header/UserListToolbar.tsx +++ b/src/app/modules/process/user-rejected/components/header/UserListToolbar.tsx @@ -1,4 +1,4 @@ -import {KTIcon} from '../../../../../../../_digifi/helpers' +import {KTIcon} from '../../../../../../_digifi/helpers' import {useListView} from '../../core/ListViewProvider' import {UsersListFilter} from './UsersListFilter' diff --git a/src/app/modules/process/user-ready/users-list/components/header/UsersListFilter.tsx b/src/app/modules/process/user-rejected/components/header/UsersListFilter.tsx similarity index 96% rename from src/app/modules/process/user-ready/users-list/components/header/UsersListFilter.tsx rename to src/app/modules/process/user-rejected/components/header/UsersListFilter.tsx index 4ac79a9..136161c 100644 --- a/src/app/modules/process/user-ready/users-list/components/header/UsersListFilter.tsx +++ b/src/app/modules/process/user-rejected/components/header/UsersListFilter.tsx @@ -1,6 +1,6 @@ import {useEffect, useState} from 'react' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {initialQueryState, KTIcon} from '../../../../../../../_digifi/helpers' +import {MenuComponent} from '../../../../../../_digifi/assets/ts/components' +import {initialQueryState, KTIcon} from '../../../../../../_digifi/helpers' import {useQueryRequest} from '../../core/QueryRequestProvider' import {useQueryResponse} from '../../core/QueryResponseProvider' diff --git a/src/app/modules/process/user-pending/users-list/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-rejected/components/header/UsersListGrouping.tsx similarity index 94% rename from src/app/modules/process/user-pending/users-list/components/header/UsersListGrouping.tsx rename to src/app/modules/process/user-rejected/components/header/UsersListGrouping.tsx index 6400fd7..0a5df5a 100644 --- a/src/app/modules/process/user-pending/users-list/components/header/UsersListGrouping.tsx +++ b/src/app/modules/process/user-rejected/components/header/UsersListGrouping.tsx @@ -1,5 +1,5 @@ import {useQueryClient, useMutation} from 'react-query' -import {QUERIES} from '../../../../../../../_digifi/helpers' +import {QUERIES} from '../../../../../../_digifi/helpers' import {useListView} from '../../core/ListViewProvider' import {useQueryResponse} from '../../core/QueryResponseProvider' import {deleteSelectedUsers} from '../../core/_requests' diff --git a/src/app/modules/process/user-rejected/users-list/components/header/UsersListHeader.tsx b/src/app/modules/process/user-rejected/components/header/UsersListHeader.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/components/header/UsersListHeader.tsx rename to src/app/modules/process/user-rejected/components/header/UsersListHeader.tsx diff --git a/src/app/modules/process/user-ready/users-list/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-rejected/components/header/UsersListSearchComponent.tsx similarity index 98% rename from src/app/modules/process/user-ready/users-list/components/header/UsersListSearchComponent.tsx rename to src/app/modules/process/user-rejected/components/header/UsersListSearchComponent.tsx index 75cba1c..7ae4f4f 100644 --- a/src/app/modules/process/user-ready/users-list/components/header/UsersListSearchComponent.tsx +++ b/src/app/modules/process/user-rejected/components/header/UsersListSearchComponent.tsx @@ -1,7 +1,7 @@ /* eslint-disable react-hooks/exhaustive-deps */ import {useEffect, useState} from 'react' -import {initialQueryState, KTIcon, useDebounce} from '../../../../../../../_digifi/helpers' +import {initialQueryState, KTIcon, useDebounce} from '../../../../../../_digifi/helpers' import {useQueryRequest} from '../../core/QueryRequestProvider' const UsersListSearchComponent = () => { diff --git a/src/app/modules/process/user-rejected/users-list/components/loading/UsersListLoading.tsx b/src/app/modules/process/user-rejected/components/loading/UsersListLoading.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/components/loading/UsersListLoading.tsx rename to src/app/modules/process/user-rejected/components/loading/UsersListLoading.tsx diff --git a/src/app/modules/process/user-approved/users-list/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-rejected/components/pagination/UsersListPagination.tsx similarity index 98% rename from src/app/modules/process/user-approved/users-list/components/pagination/UsersListPagination.tsx rename to src/app/modules/process/user-rejected/components/pagination/UsersListPagination.tsx index 2879f48..a5e68a7 100644 --- a/src/app/modules/process/user-approved/users-list/components/pagination/UsersListPagination.tsx +++ b/src/app/modules/process/user-rejected/components/pagination/UsersListPagination.tsx @@ -2,7 +2,7 @@ import clsx from 'clsx' import {useQueryResponseLoading, useQueryResponsePagination} from '../../core/QueryResponseProvider' import {useQueryRequest} from '../../core/QueryRequestProvider' -import {PaginationState} from '../../../../../../../_digifi/helpers' +import {PaginationState} from '../../../../../../_digifi/helpers' import {useMemo} from 'react' const mappedLabel = (label: string): string => { diff --git a/src/app/modules/process/user-approved/users-list/core/ListViewProvider.tsx b/src/app/modules/process/user-rejected/core/ListViewProvider.tsx similarity index 97% rename from src/app/modules/process/user-approved/users-list/core/ListViewProvider.tsx rename to src/app/modules/process/user-rejected/core/ListViewProvider.tsx index 91cc2cf..e5a66f0 100644 --- a/src/app/modules/process/user-approved/users-list/core/ListViewProvider.tsx +++ b/src/app/modules/process/user-rejected/core/ListViewProvider.tsx @@ -9,7 +9,7 @@ import { ListViewContextProps, groupingOnSelectAll, WithChildren, -} from '../../../../../../_digifi/helpers' +} from '../../../../../_digifi/helpers' import {useQueryResponse, useQueryResponseData} from './QueryResponseProvider' const ListViewContext = createContext(initialListView) diff --git a/src/app/modules/process/user-approved/users-list/core/QueryRequestProvider.tsx b/src/app/modules/process/user-rejected/core/QueryRequestProvider.tsx similarity index 95% rename from src/app/modules/process/user-approved/users-list/core/QueryRequestProvider.tsx rename to src/app/modules/process/user-rejected/core/QueryRequestProvider.tsx index 95f31cf..8362146 100644 --- a/src/app/modules/process/user-approved/users-list/core/QueryRequestProvider.tsx +++ b/src/app/modules/process/user-rejected/core/QueryRequestProvider.tsx @@ -5,7 +5,7 @@ import { QueryRequestContextProps, initialQueryRequest, WithChildren, -} from '../../../../../../_digifi/helpers' +} from '../../../../../_digifi/helpers' const QueryRequestContext = createContext(initialQueryRequest) diff --git a/src/app/modules/process/user-rejected/users-list/core/QueryResponseProvider.tsx b/src/app/modules/process/user-rejected/core/QueryResponseProvider.tsx similarity index 93% rename from src/app/modules/process/user-rejected/users-list/core/QueryResponseProvider.tsx rename to src/app/modules/process/user-rejected/core/QueryResponseProvider.tsx index 11422e7..cbc9b76 100644 --- a/src/app/modules/process/user-rejected/users-list/core/QueryResponseProvider.tsx +++ b/src/app/modules/process/user-rejected/core/QueryResponseProvider.tsx @@ -10,9 +10,9 @@ import { QUERIES, stringifyRequestQuery, WithChildren, -} from '../../../../../../_digifi/helpers' -import {getRejectedUsers} from '../../../core/_requests' -import {User} from '../../../core/_models' +} from '../../../../../_digifi/helpers' +import {getRejectedUsers} from '../../core/_requests' +import {User} from '../../core/_models' import {useQueryRequest} from './QueryRequestProvider' const QueryResponseContext = createResponseContext(initialQueryResponse) diff --git a/src/app/modules/process/user-approved/users-list/core/_models.ts b/src/app/modules/process/user-rejected/core/_models.ts similarity index 100% rename from src/app/modules/process/user-approved/users-list/core/_models.ts rename to src/app/modules/process/user-rejected/core/_models.ts diff --git a/src/app/modules/process/user-approved/users-list/core/_requests.ts b/src/app/modules/process/user-rejected/core/_requests.ts similarity index 100% rename from src/app/modules/process/user-approved/users-list/core/_requests.ts rename to src/app/modules/process/user-rejected/core/_requests.ts diff --git a/src/app/modules/process/user-pending/users-list/table/UsersTable.tsx b/src/app/modules/process/user-rejected/table/UsersTable.tsx similarity index 95% rename from src/app/modules/process/user-pending/users-list/table/UsersTable.tsx rename to src/app/modules/process/user-rejected/table/UsersTable.tsx index e803da9..7f18d2a 100644 --- a/src/app/modules/process/user-pending/users-list/table/UsersTable.tsx +++ b/src/app/modules/process/user-rejected/table/UsersTable.tsx @@ -4,10 +4,10 @@ import {CustomHeaderColumn} from './columns/CustomHeaderColumn' import {CustomRow} from './columns/CustomRow' import {useQueryResponseData, useQueryResponseLoading} from '../core/QueryResponseProvider' import {usersColumns} from './columns/_columns' -import {User} from '../../../core/_models' +import { User } from '../../core/_models' import {UsersListLoading} from '../components/loading/UsersListLoading' import {UsersListPagination} from '../components/pagination/UsersListPagination' -import {KTCardBody} from '../../../../../../_digifi/helpers' +import { KTCardBody } from "../../../../../_digifi/helpers"; const UsersTable = () => { const users = useQueryResponseData() diff --git a/src/app/modules/process/user-approved/users-list/table/columns/AddedCell.tsx b/src/app/modules/process/user-rejected/table/columns/AddedCell.tsx similarity index 63% rename from src/app/modules/process/user-approved/users-list/table/columns/AddedCell.tsx rename to src/app/modules/process/user-rejected/table/columns/AddedCell.tsx index 6f5bc2b..10cf3d6 100644 --- a/src/app/modules/process/user-approved/users-list/table/columns/AddedCell.tsx +++ b/src/app/modules/process/user-rejected/table/columns/AddedCell.tsx @@ -1,5 +1,5 @@ import {FC} from 'react' -import { NewDateTimeFormatter } from '../../../../../../../_digifi/lib/NewDateTimeFormatter' +import { NewDateTimeFormatter } from '../../../../../../_digifi/lib/NewDateTimeFormatter' type Props = { added?: string diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/AgentCell.tsx b/src/app/modules/process/user-rejected/table/columns/AgentCell.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/table/columns/AgentCell.tsx rename to src/app/modules/process/user-rejected/table/columns/AgentCell.tsx diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-rejected/table/columns/CustomHeaderColumn.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/table/columns/CustomHeaderColumn.tsx rename to src/app/modules/process/user-rejected/table/columns/CustomHeaderColumn.tsx diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/CustomRow.tsx b/src/app/modules/process/user-rejected/table/columns/CustomRow.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/table/columns/CustomRow.tsx rename to src/app/modules/process/user-rejected/table/columns/CustomRow.tsx diff --git a/src/app/modules/process/user-ready/users-list/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-rejected/table/columns/UserActionsCell.tsx similarity index 92% rename from src/app/modules/process/user-ready/users-list/table/columns/UserActionsCell.tsx rename to src/app/modules/process/user-rejected/table/columns/UserActionsCell.tsx index 9a91389..a5bd83b 100644 --- a/src/app/modules/process/user-ready/users-list/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserActionsCell.tsx @@ -1,8 +1,8 @@ import {FC, useEffect} from 'react' import {useMutation, useQueryClient} from 'react-query' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {ID, KTIcon, QUERIES} from '../../../../../../../_digifi/helpers' +import {MenuComponent} from '../../../../../../_digifi/assets/ts/components' +import {ID, KTIcon, QUERIES} from '../../../../../../_digifi/helpers' import {useListView} from '../../core/ListViewProvider' import {useQueryResponse} from '../../core/QueryResponseProvider' import {deleteUser} from '../../core/_requests' diff --git a/src/app/modules/process/user-ready/users-list/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-rejected/table/columns/UserCustomHeader.tsx similarity index 95% rename from src/app/modules/process/user-ready/users-list/table/columns/UserCustomHeader.tsx rename to src/app/modules/process/user-rejected/table/columns/UserCustomHeader.tsx index 3d0b58a..cb40449 100644 --- a/src/app/modules/process/user-ready/users-list/table/columns/UserCustomHeader.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserCustomHeader.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import {FC, PropsWithChildren, useMemo} from 'react' import {HeaderProps} from 'react-table' -import {initialQueryState} from '../../../../../../../_digifi/helpers' +import {initialQueryState} from '../../../../../../_digifi/helpers' import {useQueryRequest} from '../../core/QueryRequestProvider' import {User} from '../../core/_models' diff --git a/src/app/modules/process/user-ready/users-list/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-rejected/table/columns/UserInfoCell.tsx similarity index 94% rename from src/app/modules/process/user-ready/users-list/table/columns/UserInfoCell.tsx rename to src/app/modules/process/user-rejected/table/columns/UserInfoCell.tsx index 1840fef..215efd1 100644 --- a/src/app/modules/process/user-ready/users-list/table/columns/UserInfoCell.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserInfoCell.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import {FC} from 'react' -import {toAbsoluteUrl} from '../../../../../../../_digifi/helpers' +import {toAbsoluteUrl} from '../../../../../../_digifi/helpers' import {User} from '../../core/_models' type Props = { diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/UserLastLoginCell.tsx b/src/app/modules/process/user-rejected/table/columns/UserLastLoginCell.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/table/columns/UserLastLoginCell.tsx rename to src/app/modules/process/user-rejected/table/columns/UserLastLoginCell.tsx diff --git a/src/app/modules/process/user-ready/users-list/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-rejected/table/columns/UserSelectionCell.tsx similarity index 92% rename from src/app/modules/process/user-ready/users-list/table/columns/UserSelectionCell.tsx rename to src/app/modules/process/user-rejected/table/columns/UserSelectionCell.tsx index dcd2bfb..6fa1988 100644 --- a/src/app/modules/process/user-ready/users-list/table/columns/UserSelectionCell.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserSelectionCell.tsx @@ -1,5 +1,5 @@ import {FC, useMemo} from 'react' -import {ID} from '../../../../../../../_digifi/helpers' +import {ID} from '../../../../../../_digifi/helpers' import {useListView} from '../../core/ListViewProvider' type Props = { diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-rejected/table/columns/UserSelectionHeader.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/table/columns/UserSelectionHeader.tsx rename to src/app/modules/process/user-rejected/table/columns/UserSelectionHeader.tsx diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/_columns.tsx b/src/app/modules/process/user-rejected/table/columns/_columns.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/table/columns/_columns.tsx rename to src/app/modules/process/user-rejected/table/columns/_columns.tsx diff --git a/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModal.tsx b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModal.tsx similarity index 100% rename from src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModal.tsx rename to src/app/modules/process/user-rejected/user-edit-modal/UserEditModal.tsx diff --git a/src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalForm.tsx similarity index 99% rename from src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalForm.tsx rename to src/app/modules/process/user-rejected/user-edit-modal/UserEditModalForm.tsx index 6e8b0ec..2136452 100644 --- a/src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalForm.tsx +++ b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalForm.tsx @@ -1,7 +1,7 @@ import {FC, useState} from 'react' import * as Yup from 'yup' import {useFormik} from 'formik' -import {isNotEmpty, toAbsoluteUrl} from '../../../../../../_digifi/helpers' +import {isNotEmpty, toAbsoluteUrl} from '../../../../../_digifi/helpers' import {initialUser, User} from '../core/_models' import clsx from 'clsx' import {useListView} from '../core/ListViewProvider' diff --git a/src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalFormWrapper.tsx similarity index 93% rename from src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalFormWrapper.tsx rename to src/app/modules/process/user-rejected/user-edit-modal/UserEditModalFormWrapper.tsx index d60d7e3..a60b730 100644 --- a/src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalFormWrapper.tsx +++ b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalFormWrapper.tsx @@ -1,6 +1,6 @@ import {useQuery} from 'react-query' import {UserEditModalForm} from './UserEditModalForm' -import {isNotEmpty, QUERIES} from '../../../../../../_digifi/helpers' +import {isNotEmpty, QUERIES} from '../../../../../_digifi/helpers' import {useListView} from '../core/ListViewProvider' import {getUserById} from '../core/_requests' diff --git a/src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalHeader.tsx similarity index 92% rename from src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalHeader.tsx rename to src/app/modules/process/user-rejected/user-edit-modal/UserEditModalHeader.tsx index cb0f5b6..0327eb0 100644 --- a/src/app/modules/process/user-approved/users-list/user-edit-modal/UserEditModalHeader.tsx +++ b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalHeader.tsx @@ -1,4 +1,4 @@ -import {KTIcon} from '../../../../../../_digifi/helpers' +import {KTIcon} from '../../../../../_digifi/helpers' import {useListView} from '../core/ListViewProvider' const UserEditModalHeader = () => { diff --git a/src/app/modules/process/user-rejected/users-list/UsersList.tsx b/src/app/modules/process/user-rejected/users-list/UsersList.tsx deleted file mode 100644 index d8f1f10..0000000 --- a/src/app/modules/process/user-rejected/users-list/UsersList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import {ListViewProvider, useListView} from './core/ListViewProvider' -import {QueryRequestProvider} from './core/QueryRequestProvider' -import {QueryResponseProvider} from './core/QueryResponseProvider' -import {UsersListHeader} from './components/header/UsersListHeader' -import {UsersTable} from './table/UsersTable' -import {UserEditModal} from './user-edit-modal/UserEditModal' -import {KTCard} from '../../../../../_digifi/helpers' -import { ToolbarWrapper } from '../../../../../_digifi/layout/components/toolbar' -import { Content } from '../../../../../_digifi/layout/components/content' - -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} - -const UsersListWrapper = () => ( - - - - - - - - - - -) - -export {UsersListWrapper} diff --git a/src/app/modules/process/user-rejected/users-list/components/header/UsersListFilter.tsx b/src/app/modules/process/user-rejected/users-list/components/header/UsersListFilter.tsx deleted file mode 100644 index 4ac79a9..0000000 --- a/src/app/modules/process/user-rejected/users-list/components/header/UsersListFilter.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import {useEffect, useState} from 'react' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {initialQueryState, KTIcon} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' - -const UsersListFilter = () => { - const {updateState} = useQueryRequest() - const {isLoading} = useQueryResponse() - const [role, setRole] = useState() - const [lastLogin, setLastLogin] = useState() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const resetData = () => { - updateState({filter: undefined, ...initialQueryState}) - } - - const filterData = () => { - updateState({ - filter: {role, last_login: lastLogin}, - ...initialQueryState, - }) - } - - return ( - <> - {/* begin::Filter Button */} - - {/* end::Filter Button */} - {/* begin::SubMenu */} -
- {/* begin::Header */} -
-
Filter Options
-
- {/* end::Header */} - - {/* begin::Separator */} -
- {/* end::Separator */} - - {/* begin::Content */} -
- {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Actions */} -
- - -
- {/* end::Actions */} -
- {/* end::Content */} -
- {/* end::SubMenu */} - - ) -} - -export {UsersListFilter} diff --git a/src/app/modules/process/user-rejected/users-list/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-rejected/users-list/components/header/UsersListGrouping.tsx deleted file mode 100644 index 6400fd7..0000000 --- a/src/app/modules/process/user-rejected/users-list/components/header/UsersListGrouping.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import {useQueryClient, useMutation} from 'react-query' -import {QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteSelectedUsers} from '../../core/_requests' - -const UsersListGrouping = () => { - const {selected, clearSelected} = useListView() - const queryClient = useQueryClient() - const {query} = useQueryResponse() - - const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - clearSelected() - }, - }) - - return ( -
-
- {selected.length} Selected -
- - -
- ) -} - -export {UsersListGrouping} diff --git a/src/app/modules/process/user-rejected/users-list/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-rejected/users-list/components/header/UsersListSearchComponent.tsx deleted file mode 100644 index 75cba1c..0000000 --- a/src/app/modules/process/user-rejected/users-list/components/header/UsersListSearchComponent.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ - -import {useEffect, useState} from 'react' -import {initialQueryState, KTIcon, useDebounce} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' - -const UsersListSearchComponent = () => { - const {updateState} = useQueryRequest() - const [searchTerm, setSearchTerm] = useState('') - // Debounce search term so that it only gives us latest value ... - // ... if searchTerm has not been updated within last 500ms. - // The goal is to only have the API call fire when user stops typing ... - // ... so that we aren't hitting our API rapidly. - const debouncedSearchTerm = useDebounce(searchTerm, 150) - // Effect for API call - useEffect( - () => { - if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { - updateState({search: debouncedSearchTerm, ...initialQueryState}) - } - }, - [debouncedSearchTerm] // Only call effect if debounced search term changes - // More details about useDebounce: https://usehooks.com/useDebounce/ - ) - - return ( -
- {/* begin::Search */} -
- - setSearchTerm(e.target.value)} - /> -
- {/* end::Search */} -
- ) -} - -export {UsersListSearchComponent} diff --git a/src/app/modules/process/user-rejected/users-list/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-rejected/users-list/components/pagination/UsersListPagination.tsx deleted file mode 100644 index 2879f48..0000000 --- a/src/app/modules/process/user-rejected/users-list/components/pagination/UsersListPagination.tsx +++ /dev/null @@ -1,156 +0,0 @@ - -import clsx from 'clsx' -import {useQueryResponseLoading, useQueryResponsePagination} from '../../core/QueryResponseProvider' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {PaginationState} from '../../../../../../../_digifi/helpers' -import {useMemo} from 'react' - -const mappedLabel = (label: string): string => { - if (label === '« Previous') { - return 'Previous' - } - - if (label === 'Next »') { - return 'Next' - } - - return label -} - -const UsersListPagination = () => { - const pagination = useQueryResponsePagination() - const isLoading = useQueryResponseLoading() - const {updateState} = useQueryRequest() - const updatePage = (page: number | undefined | null) => { - if (!page || isLoading || pagination.page === page) { - return - } - - updateState({page, items_per_page: pagination.items_per_page || 10}) - } - - const PAGINATION_PAGES_COUNT = 5 - const sliceLinks = (pagination?: PaginationState) => { - if (!pagination?.links?.length) { - return [] - } - - const scopedLinks = [...pagination.links] - - let pageLinks: Array<{ - label: string - active: boolean - url: string | null - page: number | null - }> = [] - const previousLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.shift()! - const nextLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.pop()! - - const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2) - - pageLinks.push(previousLink) - - if ( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) { - pageLinks = [...pageLinks, ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT)] - } - - if ( - pagination.page > scopedLinks.length - halfOfPagesCount && - scopedLinks.length > PAGINATION_PAGES_COUNT - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice(scopedLinks.length - PAGINATION_PAGES_COUNT, scopedLinks.length), - ] - } - - if ( - !( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) && - !(pagination.page > scopedLinks.length - halfOfPagesCount) - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice( - pagination.page - 1 - halfOfPagesCount, - pagination.page + halfOfPagesCount - ), - ] - } - - pageLinks.push(nextLink) - - return pageLinks - } - - const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]) - - return ( - - ) -} - -export {UsersListPagination} diff --git a/src/app/modules/process/user-rejected/users-list/core/ListViewProvider.tsx b/src/app/modules/process/user-rejected/users-list/core/ListViewProvider.tsx deleted file mode 100644 index 91cc2cf..0000000 --- a/src/app/modules/process/user-rejected/users-list/core/ListViewProvider.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext, useMemo} from 'react' -import { - ID, - calculatedGroupingIsDisabled, - calculateIsAllDataSelected, - groupingOnSelect, - initialListView, - ListViewContextProps, - groupingOnSelectAll, - WithChildren, -} from '../../../../../../_digifi/helpers' -import {useQueryResponse, useQueryResponseData} from './QueryResponseProvider' - -const ListViewContext = createContext(initialListView) - -const ListViewProvider: FC = ({children}) => { - const [selected, setSelected] = useState>(initialListView.selected) - const [itemIdForUpdate, setItemIdForUpdate] = useState(initialListView.itemIdForUpdate) - const {isLoading} = useQueryResponse() - const data = useQueryResponseData() - const disabled = useMemo(() => calculatedGroupingIsDisabled(isLoading, data), [isLoading, data]) - const isAllSelected = useMemo(() => calculateIsAllDataSelected(data, selected), [data, selected]) - - return ( - { - groupingOnSelect(id, selected, setSelected) - }, - onSelectAll: () => { - groupingOnSelectAll(isAllSelected, setSelected, data) - }, - clearSelected: () => { - setSelected([]) - }, - }} - > - {children} - - ) -} - -const useListView = () => useContext(ListViewContext) - -export {ListViewProvider, useListView} diff --git a/src/app/modules/process/user-rejected/users-list/core/QueryRequestProvider.tsx b/src/app/modules/process/user-rejected/users-list/core/QueryRequestProvider.tsx deleted file mode 100644 index 95f31cf..0000000 --- a/src/app/modules/process/user-rejected/users-list/core/QueryRequestProvider.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext} from 'react' -import { - QueryState, - QueryRequestContextProps, - initialQueryRequest, - WithChildren, -} from '../../../../../../_digifi/helpers' - -const QueryRequestContext = createContext(initialQueryRequest) - -const QueryRequestProvider: FC = ({children}) => { - const [state, setState] = useState(initialQueryRequest.state) - - const updateState = (updates: Partial) => { - const updatedState = {...state, ...updates} as QueryState - setState(updatedState) - } - - return ( - - {children} - - ) -} - -const useQueryRequest = () => useContext(QueryRequestContext) -export {QueryRequestProvider, useQueryRequest} diff --git a/src/app/modules/process/user-rejected/users-list/core/_models.ts b/src/app/modules/process/user-rejected/users-list/core/_models.ts deleted file mode 100644 index b9b06ec..0000000 --- a/src/app/modules/process/user-rejected/users-list/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {ID, Response} from '../../../../../../_digifi/helpers' -export type User = { - id?: ID - name?: string - avatar?: string - // email?: string - position?: string - role?: string - last_login?: string - two_steps?: boolean - joined_day?: string - online?: boolean - initials?: { - label: string - state: string - } - firstname?: string, - lastname?: string - uid?: string - loan_amount?: string - payment_month?: string - sales_agent?: string - gender?: string | null - marital_status?: string - email?: string - address?: string - state?: string - country?: string - status?: string - added?: string - updated?: string -} - -export type UsersQueryResponse = Response> - -export const initialUser: User = { - avatar: 'avatars/300-6.jpg', - position: 'Art Director', - role: 'Administrator', - name: '', - email: '', -} diff --git a/src/app/modules/process/user-rejected/users-list/table/UsersTable.tsx b/src/app/modules/process/user-rejected/users-list/table/UsersTable.tsx deleted file mode 100644 index e803da9..0000000 --- a/src/app/modules/process/user-rejected/users-list/table/UsersTable.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import {useMemo} from 'react' -import {useTable, ColumnInstance, Row} from 'react-table' -import {CustomHeaderColumn} from './columns/CustomHeaderColumn' -import {CustomRow} from './columns/CustomRow' -import {useQueryResponseData, useQueryResponseLoading} from '../core/QueryResponseProvider' -import {usersColumns} from './columns/_columns' -import {User} from '../../../core/_models' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {UsersListPagination} from '../components/pagination/UsersListPagination' -import {KTCardBody} from '../../../../../../_digifi/helpers' - -const UsersTable = () => { - const users = useQueryResponseData() - // console.log('users', users) - const isLoading = useQueryResponseLoading() - const data = useMemo(() => users, [users]) - const columns = useMemo(() => usersColumns, []) - const {getTableProps, getTableBodyProps, headers, rows, prepareRow} = useTable({ - columns, - data, - }) - - return ( - -
- - - - {headers.map((column: ColumnInstance) => ( - - ))} - - - - {rows.length > 0 ? ( - rows.map((row: Row, i) => { - prepareRow(row) - return - }) - ) : ( - - - - )} - -
-
- No matching records found -
-
-
- - {isLoading && } -
- ) -} - -export {UsersTable} diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/AddedCell.tsx b/src/app/modules/process/user-rejected/users-list/table/columns/AddedCell.tsx deleted file mode 100644 index 6f5bc2b..0000000 --- a/src/app/modules/process/user-rejected/users-list/table/columns/AddedCell.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import {FC} from 'react' -import { NewDateTimeFormatter } from '../../../../../../../_digifi/lib/NewDateTimeFormatter' - -type Props = { - added?: string -} - -const AddedCell: FC = ({added}) => ( -
{NewDateTimeFormatter((added))}
-) - -export {AddedCell} \ No newline at end of file diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-rejected/users-list/table/columns/UserActionsCell.tsx deleted file mode 100644 index 9a91389..0000000 --- a/src/app/modules/process/user-rejected/users-list/table/columns/UserActionsCell.tsx +++ /dev/null @@ -1,76 +0,0 @@ - -import {FC, useEffect} from 'react' -import {useMutation, useQueryClient} from 'react-query' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {ID, KTIcon, QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteUser} from '../../core/_requests' - -type Props = { - id: ID -} - -const UserActionsCell: FC = ({id}) => { - const {setItemIdForUpdate} = useListView() - const {query} = useQueryResponse() - const queryClient = useQueryClient() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const openEditModal = () => { - setItemIdForUpdate(id) - } - - const deleteItem = useMutation(() => deleteUser(id), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - }, - }) - - return ( - <> - - Actions - - - {/* begin::Menu */} -
- {/* begin::Menu item */} - - {/* end::Menu item */} - - {/* begin::Menu item */} - - {/* end::Menu item */} -
- {/* end::Menu */} - - ) -} - -export {UserActionsCell} diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-rejected/users-list/table/columns/UserCustomHeader.tsx deleted file mode 100644 index 3d0b58a..0000000 --- a/src/app/modules/process/user-rejected/users-list/table/columns/UserCustomHeader.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import clsx from 'clsx' -import {FC, PropsWithChildren, useMemo} from 'react' -import {HeaderProps} from 'react-table' -import {initialQueryState} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {User} from '../../core/_models' - -type Props = { - className?: string - title?: string - tableProps: PropsWithChildren> -} -const UserCustomHeader: FC = ({className, title, tableProps}) => { - const id = tableProps.column.id - const {state, updateState} = useQueryRequest() - - const isSelectedForSorting = useMemo(() => { - return state.sort && state.sort === id - }, [state, id]) - const order: 'asc' | 'desc' | undefined = useMemo(() => state.order, [state]) - - const sortColumn = () => { - // avoid sorting for these columns - if (id === 'actions' || id === 'selection') { - return - } - - if (!isSelectedForSorting) { - // enable sort asc - updateState({sort: id, order: 'asc', ...initialQueryState}) - return - } - - if (isSelectedForSorting && order !== undefined) { - if (order === 'asc') { - // enable sort desc - updateState({sort: id, order: 'desc', ...initialQueryState}) - return - } - - // disable sort - updateState({sort: undefined, order: undefined, ...initialQueryState}) - } - } - - return ( - - {title} - - ) -} - -export {UserCustomHeader} diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-rejected/users-list/table/columns/UserInfoCell.tsx deleted file mode 100644 index 1840fef..0000000 --- a/src/app/modules/process/user-rejected/users-list/table/columns/UserInfoCell.tsx +++ /dev/null @@ -1,42 +0,0 @@ - -import clsx from 'clsx' -import {FC} from 'react' -import {toAbsoluteUrl} from '../../../../../../../_digifi/helpers' -import {User} from '../../core/_models' - -type Props = { - user: User -} - -const UserInfoCell: FC = ({user}) => ( - -) - -export {UserInfoCell} diff --git a/src/app/modules/process/user-rejected/users-list/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-rejected/users-list/table/columns/UserSelectionCell.tsx deleted file mode 100644 index dcd2bfb..0000000 --- a/src/app/modules/process/user-rejected/users-list/table/columns/UserSelectionCell.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import {FC, useMemo} from 'react' -import {ID} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' - -type Props = { - id: ID -} - -const UserSelectionCell: FC = ({id}) => { - const {selected, onSelect} = useListView() - const isSelected = useMemo(() => selected.includes(id), [id, selected]) - return ( -
- onSelect(id)} - /> -
- ) -} - -export {UserSelectionCell} diff --git a/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalForm.tsx deleted file mode 100644 index 6e8b0ec..0000000 --- a/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalForm.tsx +++ /dev/null @@ -1,407 +0,0 @@ -import {FC, useState} from 'react' -import * as Yup from 'yup' -import {useFormik} from 'formik' -import {isNotEmpty, toAbsoluteUrl} from '../../../../../../_digifi/helpers' -import {initialUser, User} from '../core/_models' -import clsx from 'clsx' -import {useListView} from '../core/ListViewProvider' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {createUser, updateUser} from '../core/_requests' -import {useQueryResponse} from '../core/QueryResponseProvider' - -type Props = { - isUserLoading: boolean - user: User -} - -const editUserSchema = Yup.object().shape({ - email: Yup.string() - .email('Wrong email format') - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Email is required'), - name: Yup.string() - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Name is required'), -}) - -const UserEditModalForm: FC = ({user, isUserLoading}) => { - const {setItemIdForUpdate} = useListView() - const {refetch} = useQueryResponse() - - const [userForEdit] = useState({ - ...user, - avatar: user.avatar || initialUser.avatar, - role: user.role || initialUser.role, - position: user.position || initialUser.position, - name: user.name || initialUser.name, - email: user.email || initialUser.email, - }) - - const cancel = (withRefresh?: boolean) => { - if (withRefresh) { - refetch() - } - setItemIdForUpdate(undefined) - } - - const blankImg = toAbsoluteUrl('media/svg/avatars/blank.svg') - const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`) - - const formik = useFormik({ - initialValues: userForEdit, - validationSchema: editUserSchema, - onSubmit: async (values, {setSubmitting}) => { - setSubmitting(true) - try { - if (isNotEmpty(values.id)) { - await updateUser(values) - } else { - await createUser(values) - } - } catch (ex) { - console.error(ex) - } finally { - setSubmitting(true) - cancel(true) - } - }, - }) - - return ( - <> -
- {/* begin::Scroll */} -
- {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Image input */} -
- {/* begin::Preview existing avatar */} -
- {/* end::Preview existing avatar */} - - {/* begin::Label */} - {/* */} - {/* end::Label */} - - {/* begin::Cancel */} - {/* - - */} - {/* end::Cancel */} - - {/* begin::Remove */} - {/* - - */} - {/* end::Remove */} -
- {/* end::Image input */} - - {/* begin::Hint */} - {/*
Allowed file types: png, jpg, jpeg.
*/} - {/* end::Hint */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {formik.touched.name && formik.errors.name && ( -
-
- {formik.errors.name} -
-
- )} - {/* end::Input */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {/* end::Input */} - {formik.touched.email && formik.errors.email && ( -
- {formik.errors.email} -
- )} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - {/* begin::Roles */} - {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} - {/* end::Roles */} -
- {/* end::Input group */} -
- {/* end::Scroll */} - - {/* begin::Actions */} -
- - - -
- {/* end::Actions */} -
- {(formik.isSubmitting || isUserLoading) && } - - ) -} - -export {UserEditModalForm} diff --git a/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalFormWrapper.tsx deleted file mode 100644 index d60d7e3..0000000 --- a/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalFormWrapper.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import {useQuery} from 'react-query' -import {UserEditModalForm} from './UserEditModalForm' -import {isNotEmpty, QUERIES} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' -import {getUserById} from '../core/_requests' - -const UserEditModalFormWrapper = () => { - const {itemIdForUpdate, setItemIdForUpdate} = useListView() - const enabledQuery: boolean = isNotEmpty(itemIdForUpdate) - const { - isLoading, - data: user, - error, - } = useQuery( - `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, - () => { - return getUserById(itemIdForUpdate) - }, - { - cacheTime: 0, - enabled: enabledQuery, - onError: (err) => { - setItemIdForUpdate(undefined) - console.error(err) - }, - } - ) - - if (!itemIdForUpdate) { - return - } - - if (!isLoading && !error && user) { - return - } - - return null -} - -export {UserEditModalFormWrapper} diff --git a/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalHeader.tsx deleted file mode 100644 index cb0f5b6..0000000 --- a/src/app/modules/process/user-rejected/users-list/user-edit-modal/UserEditModalHeader.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import {KTIcon} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' - -const UserEditModalHeader = () => { - const {setItemIdForUpdate} = useListView() - - return ( -
- {/* begin::Modal title */} -

Add User

- {/* end::Modal title */} - - {/* begin::Close */} -
setItemIdForUpdate(undefined)} - style={{cursor: 'pointer'}} - > - -
- {/* end::Close */} -
- ) -} - -export {UserEditModalHeader} diff --git a/src/app/modules/process/user-started/UsersList.tsx b/src/app/modules/process/user-started/UsersList.tsx new file mode 100644 index 0000000..10546aa --- /dev/null +++ b/src/app/modules/process/user-started/UsersList.tsx @@ -0,0 +1,37 @@ +import { ListViewProvider, useListView } from "./core/ListViewProvider"; +import { QueryRequestProvider } from "./core/QueryRequestProvider"; +import { QueryResponseProvider } from "./core/QueryResponseProvider"; +import { UsersListHeader } from "./components/header/UsersListHeader"; +import { UsersTable } from "./table/UsersTable"; +import { UserEditModal } from "./user-edit-modal/UserEditModal"; +import { KTCard } from "../../../../_digifi/helpers"; +import { ToolbarWrapper } from "../../../../_digifi/layout/components/toolbar"; +import { Content } from "../../../../_digifi/layout/components/content"; + +const UsersList = () => { + const { itemIdForUpdate } = useListView(); + return ( + <> + + + + + {itemIdForUpdate !== undefined && } + + ); +}; + +const UsersListWrapper = () => ( + + + + + + + + + + +); + +export { UsersListWrapper }; diff --git a/src/app/modules/process/user-started/UsersPage.tsx b/src/app/modules/process/user-started/UsersPage.tsx deleted file mode 100644 index ec70d89..0000000 --- a/src/app/modules/process/user-started/UsersPage.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {Route, Routes, Outlet, Navigate} from 'react-router-dom' -import {PageLink, PageTitle} from '../../../../_digifi/layout/core' -import {UsersListWrapper} from './users-list/UsersList' - -const usersBreadcrumbs: Array = [ - { - title: 'User Management', - path: '/apps/user-management/users', - isSeparator: false, - isActive: false, - }, - { - title: '', - path: '', - isSeparator: true, - isActive: false, - }, -] - -const UsersPage = () => { - return ( - - }> - - Users list - - - } - /> - - } /> - - ) -} - -export default UsersPage diff --git a/src/app/modules/process/user-started/components/header/UserListToolbar.tsx b/src/app/modules/process/user-started/components/header/UserListToolbar.tsx new file mode 100644 index 0000000..10974f5 --- /dev/null +++ b/src/app/modules/process/user-started/components/header/UserListToolbar.tsx @@ -0,0 +1,35 @@ +import { KTIcon } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { UsersListFilter } from "./UsersListFilter"; + +const UsersListToolbar = () => { + const { setItemIdForUpdate } = useListView(); + const openAddUserModal = () => { + setItemIdForUpdate(null); + }; + + return ( +
+ + + {/* begin::Export */} + {/* */} + {/* end::Export */} + + {/* begin::Add user */} + {/* */} + {/* end::Add user */} +
+ ); +}; + +export { UsersListToolbar }; diff --git a/src/app/modules/process/user-started/components/header/UsersListFilter.tsx b/src/app/modules/process/user-started/components/header/UsersListFilter.tsx new file mode 100644 index 0000000..b0fea79 --- /dev/null +++ b/src/app/modules/process/user-started/components/header/UsersListFilter.tsx @@ -0,0 +1,136 @@ +import { useEffect, useState } from "react"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { initialQueryState, KTIcon } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; + +const UsersListFilter = () => { + const { updateState } = useQueryRequest(); + const { isLoading } = useQueryResponse(); + const [role, setRole] = useState(); + const [lastLogin, setLastLogin] = useState(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const resetData = () => { + updateState({ filter: undefined, ...initialQueryState }); + }; + + const filterData = () => { + updateState({ + filter: { role, last_login: lastLogin }, + ...initialQueryState, + }); + }; + + return ( + <> + {/* begin::Filter Button */} + + {/* end::Filter Button */} + {/* begin::SubMenu */} +
+ {/* begin::Header */} +
+
Filter Options
+
+ {/* end::Header */} + + {/* begin::Separator */} +
+ {/* end::Separator */} + + {/* begin::Content */} +
+ {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ + +
+ {/* end::Input group */} + + {/* begin::Actions */} +
+ + +
+ {/* end::Actions */} +
+ {/* end::Content */} +
+ {/* end::SubMenu */} + + ); +}; + +export { UsersListFilter }; diff --git a/src/app/modules/process/user-started/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-started/components/header/UsersListGrouping.tsx new file mode 100644 index 0000000..7f31f93 --- /dev/null +++ b/src/app/modules/process/user-started/components/header/UsersListGrouping.tsx @@ -0,0 +1,38 @@ +import { useQueryClient, useMutation } from "react-query"; +import { QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteSelectedUsers } from "../../core/_requests"; + +const UsersListGrouping = () => { + const { selected, clearSelected } = useListView(); + const queryClient = useQueryClient(); + const { query } = useQueryResponse(); + + const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + clearSelected(); + }, + }); + + return ( +
+
+ {selected.length} Selected +
+ + +
+ ); +}; + +export { UsersListGrouping }; diff --git a/src/app/modules/process/user-started/users-list/components/header/UsersListHeader.tsx b/src/app/modules/process/user-started/components/header/UsersListHeader.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/components/header/UsersListHeader.tsx rename to src/app/modules/process/user-started/components/header/UsersListHeader.tsx diff --git a/src/app/modules/process/user-started/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-started/components/header/UsersListSearchComponent.tsx new file mode 100644 index 0000000..e25b9ed --- /dev/null +++ b/src/app/modules/process/user-started/components/header/UsersListSearchComponent.tsx @@ -0,0 +1,49 @@ +/* eslint-disable react-hooks/exhaustive-deps */ + +import { useEffect, useState } from "react"; +import { + initialQueryState, + KTIcon, + useDebounce, +} from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; + +const UsersListSearchComponent = () => { + const { updateState } = useQueryRequest(); + const [searchTerm, setSearchTerm] = useState(""); + // Debounce search term so that it only gives us latest value ... + // ... if searchTerm has not been updated within last 500ms. + // The goal is to only have the API call fire when user stops typing ... + // ... so that we aren't hitting our API rapidly. + const debouncedSearchTerm = useDebounce(searchTerm, 150); + // Effect for API call + useEffect( + () => { + if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { + updateState({ search: debouncedSearchTerm, ...initialQueryState }); + } + }, + [debouncedSearchTerm] // Only call effect if debounced search term changes + // More details about useDebounce: https://usehooks.com/useDebounce/ + ); + + return ( +
+ {/* begin::Search */} +
+ + setSearchTerm(e.target.value)} + /> +
+ {/* end::Search */} +
+ ); +}; + +export { UsersListSearchComponent }; diff --git a/src/app/modules/process/user-started/users-list/components/loading/UsersListLoading.tsx b/src/app/modules/process/user-started/components/loading/UsersListLoading.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/components/loading/UsersListLoading.tsx rename to src/app/modules/process/user-started/components/loading/UsersListLoading.tsx diff --git a/src/app/modules/process/user-started/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-started/components/pagination/UsersListPagination.tsx new file mode 100644 index 0000000..346131c --- /dev/null +++ b/src/app/modules/process/user-started/components/pagination/UsersListPagination.tsx @@ -0,0 +1,179 @@ +import clsx from "clsx"; +import { + useQueryResponseLoading, + useQueryResponsePagination, +} from "../../core/QueryResponseProvider"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { PaginationState } from "../../../../../../_digifi/helpers"; +import { useMemo } from "react"; + +const mappedLabel = (label: string): string => { + if (label === "« Previous") { + return "Previous"; + } + + if (label === "Next »") { + return "Next"; + } + + return label; +}; + +const UsersListPagination = () => { + const pagination = useQueryResponsePagination(); + const isLoading = useQueryResponseLoading(); + const { updateState } = useQueryRequest(); + const updatePage = (page: number | undefined | null) => { + if (!page || isLoading || pagination.page === page) { + return; + } + + updateState({ page, items_per_page: pagination.items_per_page || 10 }); + }; + + const PAGINATION_PAGES_COUNT = 5; + const sliceLinks = (pagination?: PaginationState) => { + if (!pagination?.links?.length) { + return []; + } + + const scopedLinks = [...pagination.links]; + + let pageLinks: Array<{ + label: string; + active: boolean; + url: string | null; + page: number | null; + }> = []; + const previousLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.shift()!; + const nextLink: { + label: string; + active: boolean; + url: string | null; + page: number | null; + } = scopedLinks.pop()!; + + const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2); + + pageLinks.push(previousLink); + + if ( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT), + ]; + } + + if ( + pagination.page > scopedLinks.length - halfOfPagesCount && + scopedLinks.length > PAGINATION_PAGES_COUNT + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + scopedLinks.length - PAGINATION_PAGES_COUNT, + scopedLinks.length + ), + ]; + } + + if ( + !( + pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || + scopedLinks.length <= PAGINATION_PAGES_COUNT + ) && + !(pagination.page > scopedLinks.length - halfOfPagesCount) + ) { + pageLinks = [ + ...pageLinks, + ...scopedLinks.slice( + pagination.page - 1 - halfOfPagesCount, + pagination.page + halfOfPagesCount + ), + ]; + } + + pageLinks.push(nextLink); + + return pageLinks; + }; + + const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]); + + return ( + + ); +}; + +export { UsersListPagination }; diff --git a/src/app/modules/process/user-started/core/ListViewProvider.tsx b/src/app/modules/process/user-started/core/ListViewProvider.tsx new file mode 100644 index 0000000..d72ff1c --- /dev/null +++ b/src/app/modules/process/user-started/core/ListViewProvider.tsx @@ -0,0 +1,62 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext, useMemo } from "react"; +import { + ID, + calculatedGroupingIsDisabled, + calculateIsAllDataSelected, + groupingOnSelect, + initialListView, + ListViewContextProps, + groupingOnSelectAll, + WithChildren, +} from "../../../../../_digifi/helpers"; +import { + useQueryResponse, + useQueryResponseData, +} from "./QueryResponseProvider"; + +const ListViewContext = createContext(initialListView); + +const ListViewProvider: FC = ({ children }) => { + const [selected, setSelected] = useState>(initialListView.selected); + const [itemIdForUpdate, setItemIdForUpdate] = useState( + initialListView.itemIdForUpdate + ); + const { isLoading } = useQueryResponse(); + const data = useQueryResponseData(); + const disabled = useMemo( + () => calculatedGroupingIsDisabled(isLoading, data), + [isLoading, data] + ); + const isAllSelected = useMemo( + () => calculateIsAllDataSelected(data, selected), + [data, selected] + ); + + return ( + { + groupingOnSelect(id, selected, setSelected); + }, + onSelectAll: () => { + groupingOnSelectAll(isAllSelected, setSelected, data); + }, + clearSelected: () => { + setSelected([]); + }, + }} + > + {children} + + ); +}; + +const useListView = () => useContext(ListViewContext); + +export { ListViewProvider, useListView }; diff --git a/src/app/modules/process/user-started/core/QueryRequestProvider.tsx b/src/app/modules/process/user-started/core/QueryRequestProvider.tsx new file mode 100644 index 0000000..2fb7824 --- /dev/null +++ b/src/app/modules/process/user-started/core/QueryRequestProvider.tsx @@ -0,0 +1,29 @@ +/* eslint-disable react-refresh/only-export-components */ +import { FC, useState, createContext, useContext } from "react"; +import { + QueryState, + QueryRequestContextProps, + initialQueryRequest, + WithChildren, +} from "../../../../../_digifi/helpers"; + +const QueryRequestContext = + createContext(initialQueryRequest); + +const QueryRequestProvider: FC = ({ children }) => { + const [state, setState] = useState(initialQueryRequest.state); + + const updateState = (updates: Partial) => { + const updatedState = { ...state, ...updates } as QueryState; + setState(updatedState); + }; + + return ( + + {children} + + ); +}; + +const useQueryRequest = () => useContext(QueryRequestContext); +export { QueryRequestProvider, useQueryRequest }; diff --git a/src/app/modules/process/user-pending/users-list/core/QueryResponseProvider.tsx b/src/app/modules/process/user-started/core/QueryResponseProvider.tsx similarity index 51% rename from src/app/modules/process/user-pending/users-list/core/QueryResponseProvider.tsx rename to src/app/modules/process/user-started/core/QueryResponseProvider.tsx index b3520a2..61554c5 100644 --- a/src/app/modules/process/user-pending/users-list/core/QueryResponseProvider.tsx +++ b/src/app/modules/process/user-started/core/QueryResponseProvider.tsx @@ -1,7 +1,7 @@ /* eslint-disable react-refresh/only-export-components */ /* eslint-disable react-hooks/exhaustive-deps */ -import {FC, useContext, useState, useEffect, useMemo} from 'react' -import {useQuery} from 'react-query' +import { FC, useContext, useState, useEffect, useMemo } from "react"; +import { useQuery } from "react-query"; import { createResponseContext, initialQueryResponse, @@ -10,22 +10,22 @@ import { QUERIES, stringifyRequestQuery, WithChildren, -} from '../../../../../../_digifi/helpers' -import {getPendingUsers} from '../../../core/_requests' -import {User} from '../../../core/_models' -import {useQueryRequest} from './QueryRequestProvider' +} from "../../../../../_digifi/helpers"; +import { getStartedUsers } from "../../core/_requests"; +import { User } from "../../core/_models"; +import { useQueryRequest } from "./QueryRequestProvider"; -const QueryResponseContext = createResponseContext(initialQueryResponse) -const QueryResponseProvider: FC = ({children}) => { - const {state} = useQueryRequest() - const [query, setQuery] = useState(stringifyRequestQuery(state)) - const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]) +const QueryResponseContext = createResponseContext(initialQueryResponse); +const QueryResponseProvider: FC = ({ children }) => { + const { state } = useQueryRequest(); + const [query, setQuery] = useState(stringifyRequestQuery(state)); + const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]); useEffect(() => { if (query !== updatedQuery) { - setQuery(updatedQuery) + setQuery(updatedQuery); } - }, [updatedQuery]) + }, [updatedQuery]); const { isFetching, @@ -34,47 +34,49 @@ const QueryResponseProvider: FC = ({children}) => { } = useQuery( `${QUERIES.USERS_LIST}-${query}`, () => { - return getPendingUsers(query) + return getStartedUsers(query); }, - {cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false} - ) + { cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false } + ); return ( - + {children} - ) -} + ); +}; -const useQueryResponse = () => useContext(QueryResponseContext) +const useQueryResponse = () => useContext(QueryResponseContext); const useQueryResponseData = () => { - const {response} = useQueryResponse() + const { response } = useQueryResponse(); if (!response) { - return [] + return []; } - return response?.records || [] -} + return response?.records || []; +}; const useQueryResponsePagination = () => { const defaultPaginationState: PaginationState = { links: [], ...initialQueryState, - } + }; - const {response} = useQueryResponse() + const { response } = useQueryResponse(); if (!response || !response.payload || !response.payload.pagination) { - return defaultPaginationState + return defaultPaginationState; } - return response.payload.pagination -} + return response.payload.pagination; +}; const useQueryResponseLoading = (): boolean => { - const {isLoading} = useQueryResponse() - return isLoading -} + const { isLoading } = useQueryResponse(); + return isLoading; +}; export { QueryResponseProvider, @@ -82,4 +84,4 @@ export { useQueryResponseData, useQueryResponsePagination, useQueryResponseLoading, -} +}; diff --git a/src/app/modules/process/user-started/core/_models.ts b/src/app/modules/process/user-started/core/_models.ts new file mode 100644 index 0000000..bc84896 --- /dev/null +++ b/src/app/modules/process/user-started/core/_models.ts @@ -0,0 +1,42 @@ +import { ID, Response } from "../../../../../_digifi/helpers"; +export type User = { + id?: ID; + name?: string; + avatar?: string; + // email?: string + position?: string; + role?: string; + last_login?: string; + two_steps?: boolean; + joined_day?: string; + online?: boolean; + initials?: { + label: string; + state: string; + }; + firstname?: string; + lastname?: string; + uid?: string; + loan_amount?: string; + payment_month?: string; + sales_agent?: string; + gender?: string | null; + marital_status?: string; + email?: string; + address?: string; + state?: string; + country?: string; + status?: string; + added?: string; + updated?: string; +}; + +export type UsersQueryResponse = Response>; + +export const initialUser: User = { + avatar: "avatars/300-6.jpg", + position: "Art Director", + role: "Administrator", + name: "", + email: "", +}; diff --git a/src/app/modules/process/user-pending/users-list/core/_requests.ts b/src/app/modules/process/user-started/core/_requests.ts similarity index 93% rename from src/app/modules/process/user-pending/users-list/core/_requests.ts rename to src/app/modules/process/user-started/core/_requests.ts index a585521..ccf71ba 100644 --- a/src/app/modules/process/user-pending/users-list/core/_requests.ts +++ b/src/app/modules/process/user-started/core/_requests.ts @@ -1,19 +1,20 @@ import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../../_digifi/helpers"; +import { ID, Response } from "../../../../../_digifi/helpers"; import { User, UsersQueryResponse } from "./_models"; const API_URL = import.meta.env.VITE_APP_THEME_API_URL; const USER_URL = `${API_URL}/user`; // const GET_USERS_URL = `${API_URL}/users/query`; -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT +const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; // const getStartedUsers = (query: string): Promise => { // return axios // .get(`${GET_USERS_URL}?${query}`) // .then((d: AxiosResponse) => d.data); // }; -const getStartedUsers = (query: string): Promise => { // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION +const getStartedUsers = (query: string): Promise => { + // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION return axios .get(`${NEW_USER_ENDPOINT}/loan/started`) .then((d: AxiosResponse) => d.data); diff --git a/src/app/modules/process/user-started/table/UsersTable.tsx b/src/app/modules/process/user-started/table/UsersTable.tsx new file mode 100644 index 0000000..82cb1c2 --- /dev/null +++ b/src/app/modules/process/user-started/table/UsersTable.tsx @@ -0,0 +1,67 @@ +import { useMemo } from "react"; +import { useTable, ColumnInstance, Row } from "react-table"; +import { CustomHeaderColumn } from "./columns/CustomHeaderColumn"; +import { CustomRow } from "./columns/CustomRow"; +import { + useQueryResponseData, + useQueryResponseLoading, +} from "../core/QueryResponseProvider"; +import { usersColumns } from "./columns/_columns"; +import { User } from "../../core/_models"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { UsersListPagination } from "../components/pagination/UsersListPagination"; +import { KTCardBody } from "../../../../../_digifi/helpers"; + + +const UsersTable = () => { + const users = useQueryResponseData(); + // console.log('users', users) + const isLoading = useQueryResponseLoading(); + const data = useMemo(() => users, [users]); + const columns = useMemo(() => usersColumns, []); + const { getTableProps, getTableBodyProps, headers, rows, prepareRow } = + useTable({ + columns, + data, + }); + + return ( + +
+ + + + {headers.map((column: ColumnInstance) => ( + + ))} + + + + {rows.length > 0 ? ( + rows.map((row: Row, i) => { + prepareRow(row); + return ; + }) + ) : ( + + + + )} + +
+
+ No matching records found +
+
+
+ + {isLoading && } +
+ ); +}; + +export { UsersTable }; diff --git a/src/app/modules/process/user-started/table/columns/AddedCell.tsx b/src/app/modules/process/user-started/table/columns/AddedCell.tsx new file mode 100644 index 0000000..2e18bad --- /dev/null +++ b/src/app/modules/process/user-started/table/columns/AddedCell.tsx @@ -0,0 +1,14 @@ +import { FC } from "react"; +import { NewDateTimeFormatter } from "../../../../../../_digifi/lib/NewDateTimeFormatter"; + +type Props = { + added?: string; +}; + +const AddedCell: FC = ({ added }) => ( +
+ {NewDateTimeFormatter(added)} +
+); + +export { AddedCell }; diff --git a/src/app/modules/process/user-started/users-list/table/columns/AgentCell.tsx b/src/app/modules/process/user-started/table/columns/AgentCell.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/table/columns/AgentCell.tsx rename to src/app/modules/process/user-started/table/columns/AgentCell.tsx diff --git a/src/app/modules/process/user-started/users-list/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-started/table/columns/CustomHeaderColumn.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/table/columns/CustomHeaderColumn.tsx rename to src/app/modules/process/user-started/table/columns/CustomHeaderColumn.tsx diff --git a/src/app/modules/process/user-started/users-list/table/columns/CustomRow.tsx b/src/app/modules/process/user-started/table/columns/CustomRow.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/table/columns/CustomRow.tsx rename to src/app/modules/process/user-started/table/columns/CustomRow.tsx diff --git a/src/app/modules/process/user-started/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-started/table/columns/UserActionsCell.tsx new file mode 100644 index 0000000..4843e41 --- /dev/null +++ b/src/app/modules/process/user-started/table/columns/UserActionsCell.tsx @@ -0,0 +1,75 @@ +import { FC, useEffect } from "react"; +import { useMutation, useQueryClient } from "react-query"; +import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; +import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; +import { useQueryResponse } from "../../core/QueryResponseProvider"; +import { deleteUser } from "../../core/_requests"; + +type Props = { + id: ID; +}; + +const UserActionsCell: FC = ({ id }) => { + const { setItemIdForUpdate } = useListView(); + const { query } = useQueryResponse(); + const queryClient = useQueryClient(); + + useEffect(() => { + MenuComponent.reinitialization(); + }, []); + + const openEditModal = () => { + setItemIdForUpdate(id); + }; + + const deleteItem = useMutation(() => deleteUser(id), { + // 💡 response of the mutation is passed to onSuccess + onSuccess: () => { + // ✅ update detail view directly + queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]); + }, + }); + + return ( + <> + + Actions + + + {/* begin::Menu */} +
+ {/* begin::Menu item */} + + {/* end::Menu item */} + + {/* begin::Menu item */} + + {/* end::Menu item */} +
+ {/* end::Menu */} + + ); +}; + +export { UserActionsCell }; diff --git a/src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx new file mode 100644 index 0000000..76ea930 --- /dev/null +++ b/src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx @@ -0,0 +1,61 @@ +import clsx from "clsx"; +import { FC, PropsWithChildren, useMemo } from "react"; +import { HeaderProps } from "react-table"; +import { initialQueryState } from "../../../../../../_digifi/helpers"; +import { useQueryRequest } from "../../core/QueryRequestProvider"; +import { User } from "../../core/_models"; + +type Props = { + className?: string; + title?: string; + tableProps: PropsWithChildren>; +}; +const UserCustomHeader: FC = ({ className, title, tableProps }) => { + const id = tableProps.column.id; + const { state, updateState } = useQueryRequest(); + + const isSelectedForSorting = useMemo(() => { + return state.sort && state.sort === id; + }, [state, id]); + const order: "asc" | "desc" | undefined = useMemo(() => state.order, [state]); + + const sortColumn = () => { + // avoid sorting for these columns + if (id === "actions" || id === "selection") { + return; + } + + if (!isSelectedForSorting) { + // enable sort asc + updateState({ sort: id, order: "asc", ...initialQueryState }); + return; + } + + if (isSelectedForSorting && order !== undefined) { + if (order === "asc") { + // enable sort desc + updateState({ sort: id, order: "desc", ...initialQueryState }); + return; + } + + // disable sort + updateState({ sort: undefined, order: undefined, ...initialQueryState }); + } + }; + + return ( + + {title} + + ); +}; + +export { UserCustomHeader }; diff --git a/src/app/modules/process/user-started/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-started/table/columns/UserInfoCell.tsx new file mode 100644 index 0000000..6b45b58 --- /dev/null +++ b/src/app/modules/process/user-started/table/columns/UserInfoCell.tsx @@ -0,0 +1,46 @@ +import clsx from "clsx"; +import { FC } from "react"; +import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; +import { User } from "../../core/_models"; + +type Props = { + user: User; +}; + +const UserInfoCell: FC = ({ user }) => ( + +); + +export { UserInfoCell }; diff --git a/src/app/modules/process/user-started/users-list/table/columns/UserLastLoginCell.tsx b/src/app/modules/process/user-started/table/columns/UserLastLoginCell.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/table/columns/UserLastLoginCell.tsx rename to src/app/modules/process/user-started/table/columns/UserLastLoginCell.tsx diff --git a/src/app/modules/process/user-started/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-started/table/columns/UserSelectionCell.tsx new file mode 100644 index 0000000..ee8d295 --- /dev/null +++ b/src/app/modules/process/user-started/table/columns/UserSelectionCell.tsx @@ -0,0 +1,26 @@ +import { FC, useMemo } from "react"; +import { ID } from "../../../../../../_digifi/helpers"; +import { useListView } from "../../core/ListViewProvider"; + +type Props = { + id: ID; +}; + +const UserSelectionCell: FC = ({ id }) => { + const { selected, onSelect } = useListView(); + const isSelected = useMemo(() => selected.includes(id), [id, selected]); + return ( +
+ onSelect(id)} + /> +
+ ); +}; + +export { UserSelectionCell }; diff --git a/src/app/modules/process/user-started/users-list/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-started/table/columns/UserSelectionHeader.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/table/columns/UserSelectionHeader.tsx rename to src/app/modules/process/user-started/table/columns/UserSelectionHeader.tsx diff --git a/src/app/modules/process/user-started/users-list/table/columns/_columns.tsx b/src/app/modules/process/user-started/table/columns/_columns.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/table/columns/_columns.tsx rename to src/app/modules/process/user-started/table/columns/_columns.tsx diff --git a/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModal.tsx b/src/app/modules/process/user-started/user-edit-modal/UserEditModal.tsx similarity index 100% rename from src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModal.tsx rename to src/app/modules/process/user-started/user-edit-modal/UserEditModal.tsx diff --git a/src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx new file mode 100644 index 0000000..ff35559 --- /dev/null +++ b/src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx @@ -0,0 +1,433 @@ +import { FC, useState } from "react"; +import * as Yup from "yup"; +import { useFormik } from "formik"; +import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; +import { initialUser, User } from "../core/_models"; +import clsx from "clsx"; +import { useListView } from "../core/ListViewProvider"; +import { UsersListLoading } from "../components/loading/UsersListLoading"; +import { createUser, updateUser } from "../core/_requests"; +import { useQueryResponse } from "../core/QueryResponseProvider"; + +type Props = { + isUserLoading: boolean; + user: User; +}; + +const editUserSchema = Yup.object().shape({ + email: Yup.string() + .email("Wrong email format") + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Email is required"), + name: Yup.string() + .min(3, "Minimum 3 symbols") + .max(50, "Maximum 50 symbols") + .required("Name is required"), +}); + +const UserEditModalForm: FC = ({ user, isUserLoading }) => { + const { setItemIdForUpdate } = useListView(); + const { refetch } = useQueryResponse(); + + const [userForEdit] = useState({ + ...user, + avatar: user.avatar || initialUser.avatar, + role: user.role || initialUser.role, + position: user.position || initialUser.position, + name: user.name || initialUser.name, + email: user.email || initialUser.email, + }); + + const cancel = (withRefresh?: boolean) => { + if (withRefresh) { + refetch(); + } + setItemIdForUpdate(undefined); + }; + + const blankImg = toAbsoluteUrl("media/svg/avatars/blank.svg"); + const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`); + + const formik = useFormik({ + initialValues: userForEdit, + validationSchema: editUserSchema, + onSubmit: async (values, { setSubmitting }) => { + setSubmitting(true); + try { + if (isNotEmpty(values.id)) { + await updateUser(values); + } else { + await createUser(values); + } + } catch (ex) { + console.error(ex); + } finally { + setSubmitting(true); + cancel(true); + } + }, + }); + + return ( + <> +
+ {/* begin::Scroll */} +
+ {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Image input */} +
+ {/* begin::Preview existing avatar */} +
+ {/* end::Preview existing avatar */} + + {/* begin::Label */} + {/* */} + {/* end::Label */} + + {/* begin::Cancel */} + {/* + + */} + {/* end::Cancel */} + + {/* begin::Remove */} + {/* + + */} + {/* end::Remove */} +
+ {/* end::Image input */} + + {/* begin::Hint */} + {/*
Allowed file types: png, jpg, jpeg.
*/} + {/* end::Hint */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {formik.touched.name && formik.errors.name && ( +
+
+ {formik.errors.name} +
+
+ )} + {/* end::Input */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + + {/* begin::Input */} + + {/* end::Input */} + {formik.touched.email && formik.errors.email && ( +
+ {formik.errors.email} +
+ )} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Label */} + + {/* end::Label */} + {/* begin::Roles */} + {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} +
+ {/* begin::Input row */} +
+ {/* begin::Radio */} +
+ {/* begin::Input */} + + {/* end::Input */} + {/* begin::Label */} + + {/* end::Label */} +
+ {/* end::Radio */} +
+ {/* end::Input row */} + {/* end::Roles */} +
+ {/* end::Input group */} +
+ {/* end::Scroll */} + + {/* begin::Actions */} +
+ + + +
+ {/* end::Actions */} +
+ {(formik.isSubmitting || isUserLoading) && } + + ); +}; + +export { UserEditModalForm }; diff --git a/src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx new file mode 100644 index 0000000..c3caa7f --- /dev/null +++ b/src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx @@ -0,0 +1,42 @@ +import { useQuery } from "react-query"; +import { UserEditModalForm } from "./UserEditModalForm"; +import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; +import { getUserById } from "../core/_requests"; + +const UserEditModalFormWrapper = () => { + const { itemIdForUpdate, setItemIdForUpdate } = useListView(); + const enabledQuery: boolean = isNotEmpty(itemIdForUpdate); + const { + isLoading, + data: user, + error, + } = useQuery( + `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, + () => { + return getUserById(itemIdForUpdate); + }, + { + cacheTime: 0, + enabled: enabledQuery, + onError: (err) => { + setItemIdForUpdate(undefined); + console.error(err); + }, + } + ); + + if (!itemIdForUpdate) { + return ( + + ); + } + + if (!isLoading && !error && user) { + return ; + } + + return null; +}; + +export { UserEditModalFormWrapper }; diff --git a/src/app/modules/process/user-started/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-started/user-edit-modal/UserEditModalHeader.tsx new file mode 100644 index 0000000..7fc6d55 --- /dev/null +++ b/src/app/modules/process/user-started/user-edit-modal/UserEditModalHeader.tsx @@ -0,0 +1,27 @@ +import { KTIcon } from "../../../../../_digifi/helpers"; +import { useListView } from "../core/ListViewProvider"; + +const UserEditModalHeader = () => { + const { setItemIdForUpdate } = useListView(); + + return ( +
+ {/* begin::Modal title */} +

Add User

+ {/* end::Modal title */} + + {/* begin::Close */} +
setItemIdForUpdate(undefined)} + style={{ cursor: "pointer" }} + > + +
+ {/* end::Close */} +
+ ); +}; + +export { UserEditModalHeader }; diff --git a/src/app/modules/process/user-started/users-list/UsersList.tsx b/src/app/modules/process/user-started/users-list/UsersList.tsx deleted file mode 100644 index d8f1f10..0000000 --- a/src/app/modules/process/user-started/users-list/UsersList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import {ListViewProvider, useListView} from './core/ListViewProvider' -import {QueryRequestProvider} from './core/QueryRequestProvider' -import {QueryResponseProvider} from './core/QueryResponseProvider' -import {UsersListHeader} from './components/header/UsersListHeader' -import {UsersTable} from './table/UsersTable' -import {UserEditModal} from './user-edit-modal/UserEditModal' -import {KTCard} from '../../../../../_digifi/helpers' -import { ToolbarWrapper } from '../../../../../_digifi/layout/components/toolbar' -import { Content } from '../../../../../_digifi/layout/components/content' - -const UsersList = () => { - const {itemIdForUpdate} = useListView() - return ( - <> - - - - - {itemIdForUpdate !== undefined && } - - ) -} - -const UsersListWrapper = () => ( - - - - - - - - - - -) - -export {UsersListWrapper} diff --git a/src/app/modules/process/user-started/users-list/components/header/UserListToolbar.tsx b/src/app/modules/process/user-started/users-list/components/header/UserListToolbar.tsx deleted file mode 100644 index e86343b..0000000 --- a/src/app/modules/process/user-started/users-list/components/header/UserListToolbar.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import {KTIcon} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {UsersListFilter} from './UsersListFilter' - -const UsersListToolbar = () => { - const {setItemIdForUpdate} = useListView() - const openAddUserModal = () => { - setItemIdForUpdate(null) - } - - return ( -
- - - {/* begin::Export */} - {/* */} - {/* end::Export */} - - {/* begin::Add user */} - {/* */} - {/* end::Add user */} -
- ) -} - -export {UsersListToolbar} diff --git a/src/app/modules/process/user-started/users-list/components/header/UsersListFilter.tsx b/src/app/modules/process/user-started/users-list/components/header/UsersListFilter.tsx deleted file mode 100644 index 4ac79a9..0000000 --- a/src/app/modules/process/user-started/users-list/components/header/UsersListFilter.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import {useEffect, useState} from 'react' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {initialQueryState, KTIcon} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' - -const UsersListFilter = () => { - const {updateState} = useQueryRequest() - const {isLoading} = useQueryResponse() - const [role, setRole] = useState() - const [lastLogin, setLastLogin] = useState() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const resetData = () => { - updateState({filter: undefined, ...initialQueryState}) - } - - const filterData = () => { - updateState({ - filter: {role, last_login: lastLogin}, - ...initialQueryState, - }) - } - - return ( - <> - {/* begin::Filter Button */} - - {/* end::Filter Button */} - {/* begin::SubMenu */} -
- {/* begin::Header */} -
-
Filter Options
-
- {/* end::Header */} - - {/* begin::Separator */} -
- {/* end::Separator */} - - {/* begin::Content */} -
- {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Input group */} -
- - -
- {/* end::Input group */} - - {/* begin::Actions */} -
- - -
- {/* end::Actions */} -
- {/* end::Content */} -
- {/* end::SubMenu */} - - ) -} - -export {UsersListFilter} diff --git a/src/app/modules/process/user-started/users-list/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-started/users-list/components/header/UsersListGrouping.tsx deleted file mode 100644 index 6400fd7..0000000 --- a/src/app/modules/process/user-started/users-list/components/header/UsersListGrouping.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import {useQueryClient, useMutation} from 'react-query' -import {QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteSelectedUsers} from '../../core/_requests' - -const UsersListGrouping = () => { - const {selected, clearSelected} = useListView() - const queryClient = useQueryClient() - const {query} = useQueryResponse() - - const deleteSelectedItems = useMutation(() => deleteSelectedUsers(selected), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - clearSelected() - }, - }) - - return ( -
-
- {selected.length} Selected -
- - -
- ) -} - -export {UsersListGrouping} diff --git a/src/app/modules/process/user-started/users-list/components/header/UsersListSearchComponent.tsx b/src/app/modules/process/user-started/users-list/components/header/UsersListSearchComponent.tsx deleted file mode 100644 index 75cba1c..0000000 --- a/src/app/modules/process/user-started/users-list/components/header/UsersListSearchComponent.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ - -import {useEffect, useState} from 'react' -import {initialQueryState, KTIcon, useDebounce} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' - -const UsersListSearchComponent = () => { - const {updateState} = useQueryRequest() - const [searchTerm, setSearchTerm] = useState('') - // Debounce search term so that it only gives us latest value ... - // ... if searchTerm has not been updated within last 500ms. - // The goal is to only have the API call fire when user stops typing ... - // ... so that we aren't hitting our API rapidly. - const debouncedSearchTerm = useDebounce(searchTerm, 150) - // Effect for API call - useEffect( - () => { - if (debouncedSearchTerm !== undefined && searchTerm !== undefined) { - updateState({search: debouncedSearchTerm, ...initialQueryState}) - } - }, - [debouncedSearchTerm] // Only call effect if debounced search term changes - // More details about useDebounce: https://usehooks.com/useDebounce/ - ) - - return ( -
- {/* begin::Search */} -
- - setSearchTerm(e.target.value)} - /> -
- {/* end::Search */} -
- ) -} - -export {UsersListSearchComponent} diff --git a/src/app/modules/process/user-started/users-list/components/pagination/UsersListPagination.tsx b/src/app/modules/process/user-started/users-list/components/pagination/UsersListPagination.tsx deleted file mode 100644 index 2879f48..0000000 --- a/src/app/modules/process/user-started/users-list/components/pagination/UsersListPagination.tsx +++ /dev/null @@ -1,156 +0,0 @@ - -import clsx from 'clsx' -import {useQueryResponseLoading, useQueryResponsePagination} from '../../core/QueryResponseProvider' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {PaginationState} from '../../../../../../../_digifi/helpers' -import {useMemo} from 'react' - -const mappedLabel = (label: string): string => { - if (label === '« Previous') { - return 'Previous' - } - - if (label === 'Next »') { - return 'Next' - } - - return label -} - -const UsersListPagination = () => { - const pagination = useQueryResponsePagination() - const isLoading = useQueryResponseLoading() - const {updateState} = useQueryRequest() - const updatePage = (page: number | undefined | null) => { - if (!page || isLoading || pagination.page === page) { - return - } - - updateState({page, items_per_page: pagination.items_per_page || 10}) - } - - const PAGINATION_PAGES_COUNT = 5 - const sliceLinks = (pagination?: PaginationState) => { - if (!pagination?.links?.length) { - return [] - } - - const scopedLinks = [...pagination.links] - - let pageLinks: Array<{ - label: string - active: boolean - url: string | null - page: number | null - }> = [] - const previousLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.shift()! - const nextLink: {label: string; active: boolean; url: string | null; page: number | null} = - scopedLinks.pop()! - - const halfOfPagesCount = Math.floor(PAGINATION_PAGES_COUNT / 2) - - pageLinks.push(previousLink) - - if ( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) { - pageLinks = [...pageLinks, ...scopedLinks.slice(0, PAGINATION_PAGES_COUNT)] - } - - if ( - pagination.page > scopedLinks.length - halfOfPagesCount && - scopedLinks.length > PAGINATION_PAGES_COUNT - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice(scopedLinks.length - PAGINATION_PAGES_COUNT, scopedLinks.length), - ] - } - - if ( - !( - pagination.page <= Math.round(PAGINATION_PAGES_COUNT / 2) || - scopedLinks.length <= PAGINATION_PAGES_COUNT - ) && - !(pagination.page > scopedLinks.length - halfOfPagesCount) - ) { - pageLinks = [ - ...pageLinks, - ...scopedLinks.slice( - pagination.page - 1 - halfOfPagesCount, - pagination.page + halfOfPagesCount - ), - ] - } - - pageLinks.push(nextLink) - - return pageLinks - } - - const paginationLinks = useMemo(() => sliceLinks(pagination), [pagination]) - - return ( - - ) -} - -export {UsersListPagination} diff --git a/src/app/modules/process/user-started/users-list/core/ListViewProvider.tsx b/src/app/modules/process/user-started/users-list/core/ListViewProvider.tsx deleted file mode 100644 index 91cc2cf..0000000 --- a/src/app/modules/process/user-started/users-list/core/ListViewProvider.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext, useMemo} from 'react' -import { - ID, - calculatedGroupingIsDisabled, - calculateIsAllDataSelected, - groupingOnSelect, - initialListView, - ListViewContextProps, - groupingOnSelectAll, - WithChildren, -} from '../../../../../../_digifi/helpers' -import {useQueryResponse, useQueryResponseData} from './QueryResponseProvider' - -const ListViewContext = createContext(initialListView) - -const ListViewProvider: FC = ({children}) => { - const [selected, setSelected] = useState>(initialListView.selected) - const [itemIdForUpdate, setItemIdForUpdate] = useState(initialListView.itemIdForUpdate) - const {isLoading} = useQueryResponse() - const data = useQueryResponseData() - const disabled = useMemo(() => calculatedGroupingIsDisabled(isLoading, data), [isLoading, data]) - const isAllSelected = useMemo(() => calculateIsAllDataSelected(data, selected), [data, selected]) - - return ( - { - groupingOnSelect(id, selected, setSelected) - }, - onSelectAll: () => { - groupingOnSelectAll(isAllSelected, setSelected, data) - }, - clearSelected: () => { - setSelected([]) - }, - }} - > - {children} - - ) -} - -const useListView = () => useContext(ListViewContext) - -export {ListViewProvider, useListView} diff --git a/src/app/modules/process/user-started/users-list/core/QueryRequestProvider.tsx b/src/app/modules/process/user-started/users-list/core/QueryRequestProvider.tsx deleted file mode 100644 index 95f31cf..0000000 --- a/src/app/modules/process/user-started/users-list/core/QueryRequestProvider.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -import {FC, useState, createContext, useContext} from 'react' -import { - QueryState, - QueryRequestContextProps, - initialQueryRequest, - WithChildren, -} from '../../../../../../_digifi/helpers' - -const QueryRequestContext = createContext(initialQueryRequest) - -const QueryRequestProvider: FC = ({children}) => { - const [state, setState] = useState(initialQueryRequest.state) - - const updateState = (updates: Partial) => { - const updatedState = {...state, ...updates} as QueryState - setState(updatedState) - } - - return ( - - {children} - - ) -} - -const useQueryRequest = () => useContext(QueryRequestContext) -export {QueryRequestProvider, useQueryRequest} diff --git a/src/app/modules/process/user-started/users-list/core/QueryResponseProvider.tsx b/src/app/modules/process/user-started/users-list/core/QueryResponseProvider.tsx deleted file mode 100644 index 6ed3089..0000000 --- a/src/app/modules/process/user-started/users-list/core/QueryResponseProvider.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/* eslint-disable react-refresh/only-export-components */ -/* eslint-disable react-hooks/exhaustive-deps */ -import {FC, useContext, useState, useEffect, useMemo} from 'react' -import {useQuery} from 'react-query' -import { - createResponseContext, - initialQueryResponse, - initialQueryState, - PaginationState, - QUERIES, - stringifyRequestQuery, - WithChildren, -} from '../../../../../../_digifi/helpers' -import {getStartedUsers} from '../../../core/_requests' -import {User} from '../../../core/_models' -import {useQueryRequest} from './QueryRequestProvider' - -const QueryResponseContext = createResponseContext(initialQueryResponse) -const QueryResponseProvider: FC = ({children}) => { - const {state} = useQueryRequest() - const [query, setQuery] = useState(stringifyRequestQuery(state)) - const updatedQuery = useMemo(() => stringifyRequestQuery(state), [state]) - - useEffect(() => { - if (query !== updatedQuery) { - setQuery(updatedQuery) - } - }, [updatedQuery]) - - const { - isFetching, - refetch, - data: response, - } = useQuery( - `${QUERIES.USERS_LIST}-${query}`, - () => { - return getStartedUsers(query) - }, - {cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false} - ) - - return ( - - {children} - - ) -} - -const useQueryResponse = () => useContext(QueryResponseContext) - -const useQueryResponseData = () => { - const {response} = useQueryResponse() - if (!response) { - return [] - } - - return response?.records || [] -} - -const useQueryResponsePagination = () => { - const defaultPaginationState: PaginationState = { - links: [], - ...initialQueryState, - } - - const {response} = useQueryResponse() - if (!response || !response.payload || !response.payload.pagination) { - return defaultPaginationState - } - - return response.payload.pagination -} - -const useQueryResponseLoading = (): boolean => { - const {isLoading} = useQueryResponse() - return isLoading -} - -export { - QueryResponseProvider, - useQueryResponse, - useQueryResponseData, - useQueryResponsePagination, - useQueryResponseLoading, -} diff --git a/src/app/modules/process/user-started/users-list/core/_models.ts b/src/app/modules/process/user-started/users-list/core/_models.ts deleted file mode 100644 index b9b06ec..0000000 --- a/src/app/modules/process/user-started/users-list/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {ID, Response} from '../../../../../../_digifi/helpers' -export type User = { - id?: ID - name?: string - avatar?: string - // email?: string - position?: string - role?: string - last_login?: string - two_steps?: boolean - joined_day?: string - online?: boolean - initials?: { - label: string - state: string - } - firstname?: string, - lastname?: string - uid?: string - loan_amount?: string - payment_month?: string - sales_agent?: string - gender?: string | null - marital_status?: string - email?: string - address?: string - state?: string - country?: string - status?: string - added?: string - updated?: string -} - -export type UsersQueryResponse = Response> - -export const initialUser: User = { - avatar: 'avatars/300-6.jpg', - position: 'Art Director', - role: 'Administrator', - name: '', - email: '', -} diff --git a/src/app/modules/process/user-started/users-list/table/UsersTable.tsx b/src/app/modules/process/user-started/users-list/table/UsersTable.tsx deleted file mode 100644 index e803da9..0000000 --- a/src/app/modules/process/user-started/users-list/table/UsersTable.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import {useMemo} from 'react' -import {useTable, ColumnInstance, Row} from 'react-table' -import {CustomHeaderColumn} from './columns/CustomHeaderColumn' -import {CustomRow} from './columns/CustomRow' -import {useQueryResponseData, useQueryResponseLoading} from '../core/QueryResponseProvider' -import {usersColumns} from './columns/_columns' -import {User} from '../../../core/_models' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {UsersListPagination} from '../components/pagination/UsersListPagination' -import {KTCardBody} from '../../../../../../_digifi/helpers' - -const UsersTable = () => { - const users = useQueryResponseData() - // console.log('users', users) - const isLoading = useQueryResponseLoading() - const data = useMemo(() => users, [users]) - const columns = useMemo(() => usersColumns, []) - const {getTableProps, getTableBodyProps, headers, rows, prepareRow} = useTable({ - columns, - data, - }) - - return ( - -
- - - - {headers.map((column: ColumnInstance) => ( - - ))} - - - - {rows.length > 0 ? ( - rows.map((row: Row, i) => { - prepareRow(row) - return - }) - ) : ( - - - - )} - -
-
- No matching records found -
-
-
- - {isLoading && } -
- ) -} - -export {UsersTable} diff --git a/src/app/modules/process/user-started/users-list/table/columns/AddedCell.tsx b/src/app/modules/process/user-started/users-list/table/columns/AddedCell.tsx deleted file mode 100644 index 6f5bc2b..0000000 --- a/src/app/modules/process/user-started/users-list/table/columns/AddedCell.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import {FC} from 'react' -import { NewDateTimeFormatter } from '../../../../../../../_digifi/lib/NewDateTimeFormatter' - -type Props = { - added?: string -} - -const AddedCell: FC = ({added}) => ( -
{NewDateTimeFormatter((added))}
-) - -export {AddedCell} \ No newline at end of file diff --git a/src/app/modules/process/user-started/users-list/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-started/users-list/table/columns/UserActionsCell.tsx deleted file mode 100644 index 9a91389..0000000 --- a/src/app/modules/process/user-started/users-list/table/columns/UserActionsCell.tsx +++ /dev/null @@ -1,76 +0,0 @@ - -import {FC, useEffect} from 'react' -import {useMutation, useQueryClient} from 'react-query' -import {MenuComponent} from '../../../../../../../_digifi/assets/ts/components' -import {ID, KTIcon, QUERIES} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' -import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteUser} from '../../core/_requests' - -type Props = { - id: ID -} - -const UserActionsCell: FC = ({id}) => { - const {setItemIdForUpdate} = useListView() - const {query} = useQueryResponse() - const queryClient = useQueryClient() - - useEffect(() => { - MenuComponent.reinitialization() - }, []) - - const openEditModal = () => { - setItemIdForUpdate(id) - } - - const deleteItem = useMutation(() => deleteUser(id), { - // 💡 response of the mutation is passed to onSuccess - onSuccess: () => { - // ✅ update detail view directly - queryClient.invalidateQueries([`${QUERIES.USERS_LIST}-${query}`]) - }, - }) - - return ( - <> - - Actions - - - {/* begin::Menu */} -
- {/* begin::Menu item */} - - {/* end::Menu item */} - - {/* begin::Menu item */} - - {/* end::Menu item */} -
- {/* end::Menu */} - - ) -} - -export {UserActionsCell} diff --git a/src/app/modules/process/user-started/users-list/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-started/users-list/table/columns/UserCustomHeader.tsx deleted file mode 100644 index 3d0b58a..0000000 --- a/src/app/modules/process/user-started/users-list/table/columns/UserCustomHeader.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import clsx from 'clsx' -import {FC, PropsWithChildren, useMemo} from 'react' -import {HeaderProps} from 'react-table' -import {initialQueryState} from '../../../../../../../_digifi/helpers' -import {useQueryRequest} from '../../core/QueryRequestProvider' -import {User} from '../../core/_models' - -type Props = { - className?: string - title?: string - tableProps: PropsWithChildren> -} -const UserCustomHeader: FC = ({className, title, tableProps}) => { - const id = tableProps.column.id - const {state, updateState} = useQueryRequest() - - const isSelectedForSorting = useMemo(() => { - return state.sort && state.sort === id - }, [state, id]) - const order: 'asc' | 'desc' | undefined = useMemo(() => state.order, [state]) - - const sortColumn = () => { - // avoid sorting for these columns - if (id === 'actions' || id === 'selection') { - return - } - - if (!isSelectedForSorting) { - // enable sort asc - updateState({sort: id, order: 'asc', ...initialQueryState}) - return - } - - if (isSelectedForSorting && order !== undefined) { - if (order === 'asc') { - // enable sort desc - updateState({sort: id, order: 'desc', ...initialQueryState}) - return - } - - // disable sort - updateState({sort: undefined, order: undefined, ...initialQueryState}) - } - } - - return ( - - {title} - - ) -} - -export {UserCustomHeader} diff --git a/src/app/modules/process/user-started/users-list/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-started/users-list/table/columns/UserInfoCell.tsx deleted file mode 100644 index 1840fef..0000000 --- a/src/app/modules/process/user-started/users-list/table/columns/UserInfoCell.tsx +++ /dev/null @@ -1,42 +0,0 @@ - -import clsx from 'clsx' -import {FC} from 'react' -import {toAbsoluteUrl} from '../../../../../../../_digifi/helpers' -import {User} from '../../core/_models' - -type Props = { - user: User -} - -const UserInfoCell: FC = ({user}) => ( - -) - -export {UserInfoCell} diff --git a/src/app/modules/process/user-started/users-list/table/columns/UserSelectionCell.tsx b/src/app/modules/process/user-started/users-list/table/columns/UserSelectionCell.tsx deleted file mode 100644 index dcd2bfb..0000000 --- a/src/app/modules/process/user-started/users-list/table/columns/UserSelectionCell.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import {FC, useMemo} from 'react' -import {ID} from '../../../../../../../_digifi/helpers' -import {useListView} from '../../core/ListViewProvider' - -type Props = { - id: ID -} - -const UserSelectionCell: FC = ({id}) => { - const {selected, onSelect} = useListView() - const isSelected = useMemo(() => selected.includes(id), [id, selected]) - return ( -
- onSelect(id)} - /> -
- ) -} - -export {UserSelectionCell} diff --git a/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalForm.tsx deleted file mode 100644 index 6e8b0ec..0000000 --- a/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalForm.tsx +++ /dev/null @@ -1,407 +0,0 @@ -import {FC, useState} from 'react' -import * as Yup from 'yup' -import {useFormik} from 'formik' -import {isNotEmpty, toAbsoluteUrl} from '../../../../../../_digifi/helpers' -import {initialUser, User} from '../core/_models' -import clsx from 'clsx' -import {useListView} from '../core/ListViewProvider' -import {UsersListLoading} from '../components/loading/UsersListLoading' -import {createUser, updateUser} from '../core/_requests' -import {useQueryResponse} from '../core/QueryResponseProvider' - -type Props = { - isUserLoading: boolean - user: User -} - -const editUserSchema = Yup.object().shape({ - email: Yup.string() - .email('Wrong email format') - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Email is required'), - name: Yup.string() - .min(3, 'Minimum 3 symbols') - .max(50, 'Maximum 50 symbols') - .required('Name is required'), -}) - -const UserEditModalForm: FC = ({user, isUserLoading}) => { - const {setItemIdForUpdate} = useListView() - const {refetch} = useQueryResponse() - - const [userForEdit] = useState({ - ...user, - avatar: user.avatar || initialUser.avatar, - role: user.role || initialUser.role, - position: user.position || initialUser.position, - name: user.name || initialUser.name, - email: user.email || initialUser.email, - }) - - const cancel = (withRefresh?: boolean) => { - if (withRefresh) { - refetch() - } - setItemIdForUpdate(undefined) - } - - const blankImg = toAbsoluteUrl('media/svg/avatars/blank.svg') - const userAvatarImg = toAbsoluteUrl(`media/${userForEdit.avatar}`) - - const formik = useFormik({ - initialValues: userForEdit, - validationSchema: editUserSchema, - onSubmit: async (values, {setSubmitting}) => { - setSubmitting(true) - try { - if (isNotEmpty(values.id)) { - await updateUser(values) - } else { - await createUser(values) - } - } catch (ex) { - console.error(ex) - } finally { - setSubmitting(true) - cancel(true) - } - }, - }) - - return ( - <> -
- {/* begin::Scroll */} -
- {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Image input */} -
- {/* begin::Preview existing avatar */} -
- {/* end::Preview existing avatar */} - - {/* begin::Label */} - {/* */} - {/* end::Label */} - - {/* begin::Cancel */} - {/* - - */} - {/* end::Cancel */} - - {/* begin::Remove */} - {/* - - */} - {/* end::Remove */} -
- {/* end::Image input */} - - {/* begin::Hint */} - {/*
Allowed file types: png, jpg, jpeg.
*/} - {/* end::Hint */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {formik.touched.name && formik.errors.name && ( -
-
- {formik.errors.name} -
-
- )} - {/* end::Input */} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - - {/* begin::Input */} - - {/* end::Input */} - {formik.touched.email && formik.errors.email && ( -
- {formik.errors.email} -
- )} -
- {/* end::Input group */} - - {/* begin::Input group */} -
- {/* begin::Label */} - - {/* end::Label */} - {/* begin::Roles */} - {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} -
- {/* begin::Input row */} -
- {/* begin::Radio */} -
- {/* begin::Input */} - - {/* end::Input */} - {/* begin::Label */} - - {/* end::Label */} -
- {/* end::Radio */} -
- {/* end::Input row */} - {/* end::Roles */} -
- {/* end::Input group */} -
- {/* end::Scroll */} - - {/* begin::Actions */} -
- - - -
- {/* end::Actions */} -
- {(formik.isSubmitting || isUserLoading) && } - - ) -} - -export {UserEditModalForm} diff --git a/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalFormWrapper.tsx deleted file mode 100644 index d60d7e3..0000000 --- a/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalFormWrapper.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import {useQuery} from 'react-query' -import {UserEditModalForm} from './UserEditModalForm' -import {isNotEmpty, QUERIES} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' -import {getUserById} from '../core/_requests' - -const UserEditModalFormWrapper = () => { - const {itemIdForUpdate, setItemIdForUpdate} = useListView() - const enabledQuery: boolean = isNotEmpty(itemIdForUpdate) - const { - isLoading, - data: user, - error, - } = useQuery( - `${QUERIES.USERS_LIST}-user-${itemIdForUpdate}`, - () => { - return getUserById(itemIdForUpdate) - }, - { - cacheTime: 0, - enabled: enabledQuery, - onError: (err) => { - setItemIdForUpdate(undefined) - console.error(err) - }, - } - ) - - if (!itemIdForUpdate) { - return - } - - if (!isLoading && !error && user) { - return - } - - return null -} - -export {UserEditModalFormWrapper} diff --git a/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalHeader.tsx b/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalHeader.tsx deleted file mode 100644 index cb0f5b6..0000000 --- a/src/app/modules/process/user-started/users-list/user-edit-modal/UserEditModalHeader.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import {KTIcon} from '../../../../../../_digifi/helpers' -import {useListView} from '../core/ListViewProvider' - -const UserEditModalHeader = () => { - const {setItemIdForUpdate} = useListView() - - return ( -
- {/* begin::Modal title */} -

Add User

- {/* end::Modal title */} - - {/* begin::Close */} -
setItemIdForUpdate(undefined)} - style={{cursor: 'pointer'}} - > - -
- {/* end::Close */} -
- ) -} - -export {UserEditModalHeader} From 5eb07b2057214896996906c40ed649cd5c3baf6c Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Wed, 15 May 2024 20:47:29 +0100 Subject: [PATCH 2/4] removal of redundant pages --- .../components/header/UsersListGrouping.tsx | 2 +- .../process/user-approved/core/_models.ts | 42 ------------- .../process/user-approved/core/_requests.ts | 60 ------------------- .../table/columns/CustomHeaderColumn.tsx | 2 +- .../user-approved/table/columns/CustomRow.tsx | 2 +- .../table/columns/UserActionsCell.tsx | 2 +- .../table/columns/UserCustomHeader.tsx | 2 +- .../table/columns/UserInfoCell.tsx | 2 +- .../table/columns/UserSelectionHeader.tsx | 2 +- .../user-approved/table/columns/_columns.tsx | 2 +- .../user-edit-modal/UserEditModalForm.tsx | 4 +- .../UserEditModalFormWrapper.tsx | 2 +- .../components/header/UsersListGrouping.tsx | 2 +- .../process/user-pending/core/_models.ts | 42 ------------- .../process/user-pending/core/_requests.ts | 60 ------------------- .../table/columns/CustomHeaderColumn.tsx | 2 +- .../user-pending/table/columns/CustomRow.tsx | 2 +- .../table/columns/UserActionsCell.tsx | 3 +- .../table/columns/UserCustomHeader.tsx | 2 +- .../table/columns/UserInfoCell.tsx | 2 +- .../table/columns/UserSelectionHeader.tsx | 2 +- .../user-pending/table/columns/_columns.tsx | 2 +- .../user-edit-modal/UserEditModalForm.tsx | 4 +- .../UserEditModalFormWrapper.tsx | 2 +- .../components/header/UsersListGrouping.tsx | 2 +- .../process/user-ready/core/_models.ts | 42 ------------- .../process/user-ready/core/_requests.ts | 60 ------------------- .../table/columns/CustomHeaderColumn.tsx | 2 +- .../user-ready/table/columns/CustomRow.tsx | 2 +- .../table/columns/UserActionsCell.tsx | 2 +- .../table/columns/UserCustomHeader.tsx | 2 +- .../user-ready/table/columns/UserInfoCell.tsx | 2 +- .../table/columns/UserSelectionHeader.tsx | 2 +- .../user-ready/table/columns/_columns.tsx | 2 +- .../user-edit-modal/UserEditModalForm.tsx | 4 +- .../UserEditModalFormWrapper.tsx | 2 +- .../components/header/UsersListGrouping.tsx | 2 +- .../process/user-rejected/core/_models.ts | 42 ------------- .../process/user-rejected/core/_requests.ts | 59 ------------------ .../table/columns/CustomHeaderColumn.tsx | 2 +- .../user-rejected/table/columns/CustomRow.tsx | 2 +- .../table/columns/UserActionsCell.tsx | 2 +- .../table/columns/UserCustomHeader.tsx | 2 +- .../table/columns/UserInfoCell.tsx | 2 +- .../table/columns/UserSelectionHeader.tsx | 2 +- .../user-rejected/table/columns/_columns.tsx | 2 +- .../user-edit-modal/UserEditModalForm.tsx | 4 +- .../UserEditModalFormWrapper.tsx | 2 +- .../components/header/UsersListGrouping.tsx | 2 +- .../process/user-started/core/_models.ts | 42 ------------- .../process/user-started/core/_requests.ts | 60 ------------------- .../table/columns/CustomHeaderColumn.tsx | 2 +- .../user-started/table/columns/CustomRow.tsx | 2 +- .../table/columns/UserActionsCell.tsx | 2 +- .../table/columns/UserCustomHeader.tsx | 2 +- .../table/columns/UserInfoCell.tsx | 2 +- .../table/columns/UserSelectionHeader.tsx | 2 +- .../user-started/table/columns/_columns.tsx | 2 +- .../user-edit-modal/UserEditModalForm.tsx | 4 +- .../UserEditModalFormWrapper.tsx | 2 +- 60 files changed, 56 insertions(+), 564 deletions(-) delete mode 100644 src/app/modules/process/user-approved/core/_models.ts delete mode 100644 src/app/modules/process/user-approved/core/_requests.ts delete mode 100644 src/app/modules/process/user-pending/core/_models.ts delete mode 100644 src/app/modules/process/user-pending/core/_requests.ts delete mode 100644 src/app/modules/process/user-ready/core/_models.ts delete mode 100644 src/app/modules/process/user-ready/core/_requests.ts delete mode 100644 src/app/modules/process/user-rejected/core/_models.ts delete mode 100644 src/app/modules/process/user-rejected/core/_requests.ts delete mode 100644 src/app/modules/process/user-started/core/_models.ts delete mode 100644 src/app/modules/process/user-started/core/_requests.ts diff --git a/src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx index 7f31f93..6c5df5b 100644 --- a/src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx +++ b/src/app/modules/process/user-approved/components/header/UsersListGrouping.tsx @@ -2,7 +2,7 @@ import { useQueryClient, useMutation } from "react-query"; import { QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteSelectedUsers } from "../../core/_requests"; +import { deleteSelectedUsers } from "../../../core/_requests"; const UsersListGrouping = () => { const { selected, clearSelected } = useListView(); diff --git a/src/app/modules/process/user-approved/core/_models.ts b/src/app/modules/process/user-approved/core/_models.ts deleted file mode 100644 index bc84896..0000000 --- a/src/app/modules/process/user-approved/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ID, Response } from "../../../../../_digifi/helpers"; -export type User = { - id?: ID; - name?: string; - avatar?: string; - // email?: string - position?: string; - role?: string; - last_login?: string; - two_steps?: boolean; - joined_day?: string; - online?: boolean; - initials?: { - label: string; - state: string; - }; - firstname?: string; - lastname?: string; - uid?: string; - loan_amount?: string; - payment_month?: string; - sales_agent?: string; - gender?: string | null; - marital_status?: string; - email?: string; - address?: string; - state?: string; - country?: string; - status?: string; - added?: string; - updated?: string; -}; - -export type UsersQueryResponse = Response>; - -export const initialUser: User = { - avatar: "avatars/300-6.jpg", - position: "Art Director", - role: "Administrator", - name: "", - email: "", -}; diff --git a/src/app/modules/process/user-approved/core/_requests.ts b/src/app/modules/process/user-approved/core/_requests.ts deleted file mode 100644 index ccf71ba..0000000 --- a/src/app/modules/process/user-approved/core/_requests.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../_digifi/helpers"; -import { User, UsersQueryResponse } from "./_models"; - -const API_URL = import.meta.env.VITE_APP_THEME_API_URL; -const USER_URL = `${API_URL}/user`; -// const GET_USERS_URL = `${API_URL}/users/query`; - -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; - -// const getStartedUsers = (query: string): Promise => { -// return axios -// .get(`${GET_USERS_URL}?${query}`) -// .then((d: AxiosResponse) => d.data); -// }; -const getStartedUsers = (query: string): Promise => { - // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION - return axios - .get(`${NEW_USER_ENDPOINT}/loan/started`) - .then((d: AxiosResponse) => d.data); -}; - -const getUserById = (id: ID): Promise => { - return axios - .get(`${USER_URL}/${id}`) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const createUser = (user: User): Promise => { - return axios - .put(USER_URL, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const updateUser = (user: User): Promise => { - return axios - .post(`${USER_URL}/${user.id}`, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const deleteUser = (userId: ID): Promise => { - return axios.delete(`${USER_URL}/${userId}`).then(() => {}); -}; - -const deleteSelectedUsers = (userIds: Array): Promise => { - const requests = userIds.map((id) => axios.delete(`${USER_URL}/${id}`)); - return axios.all(requests).then(() => {}); -}; - -export { - getStartedUsers, - deleteUser, - deleteSelectedUsers, - getUserById, - createUser, - updateUser, -}; diff --git a/src/app/modules/process/user-approved/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-approved/table/columns/CustomHeaderColumn.tsx index 838a12e..63eef09 100644 --- a/src/app/modules/process/user-approved/table/columns/CustomHeaderColumn.tsx +++ b/src/app/modules/process/user-approved/table/columns/CustomHeaderColumn.tsx @@ -1,6 +1,6 @@ import {FC} from 'react' import {ColumnInstance} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { column: ColumnInstance diff --git a/src/app/modules/process/user-approved/table/columns/CustomRow.tsx b/src/app/modules/process/user-approved/table/columns/CustomRow.tsx index a869cfe..af64ac0 100644 --- a/src/app/modules/process/user-approved/table/columns/CustomRow.tsx +++ b/src/app/modules/process/user-approved/table/columns/CustomRow.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import {FC} from 'react' import {Row} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { row: Row diff --git a/src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx index 4843e41..108da7b 100644 --- a/src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-approved/table/columns/UserActionsCell.tsx @@ -4,7 +4,7 @@ import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteUser } from "../../core/_requests"; +import { deleteUser } from "../../../core/_requests"; type Props = { id: ID; diff --git a/src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx index 76ea930..9d10d65 100644 --- a/src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx +++ b/src/app/modules/process/user-approved/table/columns/UserCustomHeader.tsx @@ -3,7 +3,7 @@ import { FC, PropsWithChildren, useMemo } from "react"; import { HeaderProps } from "react-table"; import { initialQueryState } from "../../../../../../_digifi/helpers"; import { useQueryRequest } from "../../core/QueryRequestProvider"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { className?: string; diff --git a/src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx index 6b45b58..7a1edf3 100644 --- a/src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx +++ b/src/app/modules/process/user-approved/table/columns/UserInfoCell.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { FC } from "react"; import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { user: User; diff --git a/src/app/modules/process/user-approved/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-approved/table/columns/UserSelectionHeader.tsx index bbb1eb0..1312c0e 100644 --- a/src/app/modules/process/user-approved/table/columns/UserSelectionHeader.tsx +++ b/src/app/modules/process/user-approved/table/columns/UserSelectionHeader.tsx @@ -1,7 +1,7 @@ import {FC, PropsWithChildren} from 'react' import {HeaderProps} from 'react-table' import {useListView} from '../../core/ListViewProvider' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { tableProps: PropsWithChildren> diff --git a/src/app/modules/process/user-approved/table/columns/_columns.tsx b/src/app/modules/process/user-approved/table/columns/_columns.tsx index 897f37a..a742770 100644 --- a/src/app/modules/process/user-approved/table/columns/_columns.tsx +++ b/src/app/modules/process/user-approved/table/columns/_columns.tsx @@ -6,7 +6,7 @@ import {UserActionsCell} from './UserActionsCell' import {UserSelectionCell} from './UserSelectionCell' import {UserCustomHeader} from './UserCustomHeader' import {UserSelectionHeader} from './UserSelectionHeader' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' import { AddedCell } from './AddedCell' const usersColumns: ReadonlyArray> = [ diff --git a/src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx index ff35559..16c3678 100644 --- a/src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx +++ b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalForm.tsx @@ -2,11 +2,11 @@ import { FC, useState } from "react"; import * as Yup from "yup"; import { useFormik } from "formik"; import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; -import { initialUser, User } from "../core/_models"; +import { initialUser, User } from "../../core/_models"; import clsx from "clsx"; import { useListView } from "../core/ListViewProvider"; import { UsersListLoading } from "../components/loading/UsersListLoading"; -import { createUser, updateUser } from "../core/_requests"; +import { createUser, updateUser } from "../../core/_requests"; import { useQueryResponse } from "../core/QueryResponseProvider"; type Props = { diff --git a/src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx index c3caa7f..c4f25bd 100644 --- a/src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx +++ b/src/app/modules/process/user-approved/user-edit-modal/UserEditModalFormWrapper.tsx @@ -2,7 +2,7 @@ import { useQuery } from "react-query"; import { UserEditModalForm } from "./UserEditModalForm"; import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; import { useListView } from "../core/ListViewProvider"; -import { getUserById } from "../core/_requests"; +import { getUserById } from "../../core/_requests"; const UserEditModalFormWrapper = () => { const { itemIdForUpdate, setItemIdForUpdate } = useListView(); diff --git a/src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx index 7f31f93..6c5df5b 100644 --- a/src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx +++ b/src/app/modules/process/user-pending/components/header/UsersListGrouping.tsx @@ -2,7 +2,7 @@ import { useQueryClient, useMutation } from "react-query"; import { QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteSelectedUsers } from "../../core/_requests"; +import { deleteSelectedUsers } from "../../../core/_requests"; const UsersListGrouping = () => { const { selected, clearSelected } = useListView(); diff --git a/src/app/modules/process/user-pending/core/_models.ts b/src/app/modules/process/user-pending/core/_models.ts deleted file mode 100644 index bc84896..0000000 --- a/src/app/modules/process/user-pending/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ID, Response } from "../../../../../_digifi/helpers"; -export type User = { - id?: ID; - name?: string; - avatar?: string; - // email?: string - position?: string; - role?: string; - last_login?: string; - two_steps?: boolean; - joined_day?: string; - online?: boolean; - initials?: { - label: string; - state: string; - }; - firstname?: string; - lastname?: string; - uid?: string; - loan_amount?: string; - payment_month?: string; - sales_agent?: string; - gender?: string | null; - marital_status?: string; - email?: string; - address?: string; - state?: string; - country?: string; - status?: string; - added?: string; - updated?: string; -}; - -export type UsersQueryResponse = Response>; - -export const initialUser: User = { - avatar: "avatars/300-6.jpg", - position: "Art Director", - role: "Administrator", - name: "", - email: "", -}; diff --git a/src/app/modules/process/user-pending/core/_requests.ts b/src/app/modules/process/user-pending/core/_requests.ts deleted file mode 100644 index ccf71ba..0000000 --- a/src/app/modules/process/user-pending/core/_requests.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../_digifi/helpers"; -import { User, UsersQueryResponse } from "./_models"; - -const API_URL = import.meta.env.VITE_APP_THEME_API_URL; -const USER_URL = `${API_URL}/user`; -// const GET_USERS_URL = `${API_URL}/users/query`; - -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; - -// const getStartedUsers = (query: string): Promise => { -// return axios -// .get(`${GET_USERS_URL}?${query}`) -// .then((d: AxiosResponse) => d.data); -// }; -const getStartedUsers = (query: string): Promise => { - // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION - return axios - .get(`${NEW_USER_ENDPOINT}/loan/started`) - .then((d: AxiosResponse) => d.data); -}; - -const getUserById = (id: ID): Promise => { - return axios - .get(`${USER_URL}/${id}`) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const createUser = (user: User): Promise => { - return axios - .put(USER_URL, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const updateUser = (user: User): Promise => { - return axios - .post(`${USER_URL}/${user.id}`, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const deleteUser = (userId: ID): Promise => { - return axios.delete(`${USER_URL}/${userId}`).then(() => {}); -}; - -const deleteSelectedUsers = (userIds: Array): Promise => { - const requests = userIds.map((id) => axios.delete(`${USER_URL}/${id}`)); - return axios.all(requests).then(() => {}); -}; - -export { - getStartedUsers, - deleteUser, - deleteSelectedUsers, - getUserById, - createUser, - updateUser, -}; diff --git a/src/app/modules/process/user-pending/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-pending/table/columns/CustomHeaderColumn.tsx index 838a12e..63eef09 100644 --- a/src/app/modules/process/user-pending/table/columns/CustomHeaderColumn.tsx +++ b/src/app/modules/process/user-pending/table/columns/CustomHeaderColumn.tsx @@ -1,6 +1,6 @@ import {FC} from 'react' import {ColumnInstance} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { column: ColumnInstance diff --git a/src/app/modules/process/user-pending/table/columns/CustomRow.tsx b/src/app/modules/process/user-pending/table/columns/CustomRow.tsx index a869cfe..af64ac0 100644 --- a/src/app/modules/process/user-pending/table/columns/CustomRow.tsx +++ b/src/app/modules/process/user-pending/table/columns/CustomRow.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import {FC} from 'react' import {Row} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { row: Row diff --git a/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx index 4843e41..71d9a5f 100644 --- a/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx @@ -4,7 +4,8 @@ import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteUser } from "../../core/_requests"; +import { deleteUser } from "../../../core/_requests"; + type Props = { id: ID; diff --git a/src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx index 76ea930..9d10d65 100644 --- a/src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx +++ b/src/app/modules/process/user-pending/table/columns/UserCustomHeader.tsx @@ -3,7 +3,7 @@ import { FC, PropsWithChildren, useMemo } from "react"; import { HeaderProps } from "react-table"; import { initialQueryState } from "../../../../../../_digifi/helpers"; import { useQueryRequest } from "../../core/QueryRequestProvider"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { className?: string; diff --git a/src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx index 6b45b58..7a1edf3 100644 --- a/src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx +++ b/src/app/modules/process/user-pending/table/columns/UserInfoCell.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { FC } from "react"; import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { user: User; diff --git a/src/app/modules/process/user-pending/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-pending/table/columns/UserSelectionHeader.tsx index bbb1eb0..1312c0e 100644 --- a/src/app/modules/process/user-pending/table/columns/UserSelectionHeader.tsx +++ b/src/app/modules/process/user-pending/table/columns/UserSelectionHeader.tsx @@ -1,7 +1,7 @@ import {FC, PropsWithChildren} from 'react' import {HeaderProps} from 'react-table' import {useListView} from '../../core/ListViewProvider' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { tableProps: PropsWithChildren> diff --git a/src/app/modules/process/user-pending/table/columns/_columns.tsx b/src/app/modules/process/user-pending/table/columns/_columns.tsx index 897f37a..a742770 100644 --- a/src/app/modules/process/user-pending/table/columns/_columns.tsx +++ b/src/app/modules/process/user-pending/table/columns/_columns.tsx @@ -6,7 +6,7 @@ import {UserActionsCell} from './UserActionsCell' import {UserSelectionCell} from './UserSelectionCell' import {UserCustomHeader} from './UserCustomHeader' import {UserSelectionHeader} from './UserSelectionHeader' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' import { AddedCell } from './AddedCell' const usersColumns: ReadonlyArray> = [ diff --git a/src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx index ff35559..16c3678 100644 --- a/src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx +++ b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalForm.tsx @@ -2,11 +2,11 @@ import { FC, useState } from "react"; import * as Yup from "yup"; import { useFormik } from "formik"; import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; -import { initialUser, User } from "../core/_models"; +import { initialUser, User } from "../../core/_models"; import clsx from "clsx"; import { useListView } from "../core/ListViewProvider"; import { UsersListLoading } from "../components/loading/UsersListLoading"; -import { createUser, updateUser } from "../core/_requests"; +import { createUser, updateUser } from "../../core/_requests"; import { useQueryResponse } from "../core/QueryResponseProvider"; type Props = { diff --git a/src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx index c3caa7f..c4f25bd 100644 --- a/src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx +++ b/src/app/modules/process/user-pending/user-edit-modal/UserEditModalFormWrapper.tsx @@ -2,7 +2,7 @@ import { useQuery } from "react-query"; import { UserEditModalForm } from "./UserEditModalForm"; import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; import { useListView } from "../core/ListViewProvider"; -import { getUserById } from "../core/_requests"; +import { getUserById } from "../../core/_requests"; const UserEditModalFormWrapper = () => { const { itemIdForUpdate, setItemIdForUpdate } = useListView(); diff --git a/src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx index 7f31f93..6c5df5b 100644 --- a/src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx +++ b/src/app/modules/process/user-ready/components/header/UsersListGrouping.tsx @@ -2,7 +2,7 @@ import { useQueryClient, useMutation } from "react-query"; import { QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteSelectedUsers } from "../../core/_requests"; +import { deleteSelectedUsers } from "../../../core/_requests"; const UsersListGrouping = () => { const { selected, clearSelected } = useListView(); diff --git a/src/app/modules/process/user-ready/core/_models.ts b/src/app/modules/process/user-ready/core/_models.ts deleted file mode 100644 index bc84896..0000000 --- a/src/app/modules/process/user-ready/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ID, Response } from "../../../../../_digifi/helpers"; -export type User = { - id?: ID; - name?: string; - avatar?: string; - // email?: string - position?: string; - role?: string; - last_login?: string; - two_steps?: boolean; - joined_day?: string; - online?: boolean; - initials?: { - label: string; - state: string; - }; - firstname?: string; - lastname?: string; - uid?: string; - loan_amount?: string; - payment_month?: string; - sales_agent?: string; - gender?: string | null; - marital_status?: string; - email?: string; - address?: string; - state?: string; - country?: string; - status?: string; - added?: string; - updated?: string; -}; - -export type UsersQueryResponse = Response>; - -export const initialUser: User = { - avatar: "avatars/300-6.jpg", - position: "Art Director", - role: "Administrator", - name: "", - email: "", -}; diff --git a/src/app/modules/process/user-ready/core/_requests.ts b/src/app/modules/process/user-ready/core/_requests.ts deleted file mode 100644 index ccf71ba..0000000 --- a/src/app/modules/process/user-ready/core/_requests.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../_digifi/helpers"; -import { User, UsersQueryResponse } from "./_models"; - -const API_URL = import.meta.env.VITE_APP_THEME_API_URL; -const USER_URL = `${API_URL}/user`; -// const GET_USERS_URL = `${API_URL}/users/query`; - -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; - -// const getStartedUsers = (query: string): Promise => { -// return axios -// .get(`${GET_USERS_URL}?${query}`) -// .then((d: AxiosResponse) => d.data); -// }; -const getStartedUsers = (query: string): Promise => { - // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION - return axios - .get(`${NEW_USER_ENDPOINT}/loan/started`) - .then((d: AxiosResponse) => d.data); -}; - -const getUserById = (id: ID): Promise => { - return axios - .get(`${USER_URL}/${id}`) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const createUser = (user: User): Promise => { - return axios - .put(USER_URL, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const updateUser = (user: User): Promise => { - return axios - .post(`${USER_URL}/${user.id}`, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const deleteUser = (userId: ID): Promise => { - return axios.delete(`${USER_URL}/${userId}`).then(() => {}); -}; - -const deleteSelectedUsers = (userIds: Array): Promise => { - const requests = userIds.map((id) => axios.delete(`${USER_URL}/${id}`)); - return axios.all(requests).then(() => {}); -}; - -export { - getStartedUsers, - deleteUser, - deleteSelectedUsers, - getUserById, - createUser, - updateUser, -}; diff --git a/src/app/modules/process/user-ready/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-ready/table/columns/CustomHeaderColumn.tsx index 838a12e..63eef09 100644 --- a/src/app/modules/process/user-ready/table/columns/CustomHeaderColumn.tsx +++ b/src/app/modules/process/user-ready/table/columns/CustomHeaderColumn.tsx @@ -1,6 +1,6 @@ import {FC} from 'react' import {ColumnInstance} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { column: ColumnInstance diff --git a/src/app/modules/process/user-ready/table/columns/CustomRow.tsx b/src/app/modules/process/user-ready/table/columns/CustomRow.tsx index a869cfe..af64ac0 100644 --- a/src/app/modules/process/user-ready/table/columns/CustomRow.tsx +++ b/src/app/modules/process/user-ready/table/columns/CustomRow.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import {FC} from 'react' import {Row} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { row: Row diff --git a/src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx index 4843e41..108da7b 100644 --- a/src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-ready/table/columns/UserActionsCell.tsx @@ -4,7 +4,7 @@ import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteUser } from "../../core/_requests"; +import { deleteUser } from "../../../core/_requests"; type Props = { id: ID; diff --git a/src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx index 76ea930..9d10d65 100644 --- a/src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx +++ b/src/app/modules/process/user-ready/table/columns/UserCustomHeader.tsx @@ -3,7 +3,7 @@ import { FC, PropsWithChildren, useMemo } from "react"; import { HeaderProps } from "react-table"; import { initialQueryState } from "../../../../../../_digifi/helpers"; import { useQueryRequest } from "../../core/QueryRequestProvider"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { className?: string; diff --git a/src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx index 6b45b58..7a1edf3 100644 --- a/src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx +++ b/src/app/modules/process/user-ready/table/columns/UserInfoCell.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { FC } from "react"; import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { user: User; diff --git a/src/app/modules/process/user-ready/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-ready/table/columns/UserSelectionHeader.tsx index bbb1eb0..1312c0e 100644 --- a/src/app/modules/process/user-ready/table/columns/UserSelectionHeader.tsx +++ b/src/app/modules/process/user-ready/table/columns/UserSelectionHeader.tsx @@ -1,7 +1,7 @@ import {FC, PropsWithChildren} from 'react' import {HeaderProps} from 'react-table' import {useListView} from '../../core/ListViewProvider' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { tableProps: PropsWithChildren> diff --git a/src/app/modules/process/user-ready/table/columns/_columns.tsx b/src/app/modules/process/user-ready/table/columns/_columns.tsx index 897f37a..a742770 100644 --- a/src/app/modules/process/user-ready/table/columns/_columns.tsx +++ b/src/app/modules/process/user-ready/table/columns/_columns.tsx @@ -6,7 +6,7 @@ import {UserActionsCell} from './UserActionsCell' import {UserSelectionCell} from './UserSelectionCell' import {UserCustomHeader} from './UserCustomHeader' import {UserSelectionHeader} from './UserSelectionHeader' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' import { AddedCell } from './AddedCell' const usersColumns: ReadonlyArray> = [ diff --git a/src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx index ff35559..16c3678 100644 --- a/src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx +++ b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalForm.tsx @@ -2,11 +2,11 @@ import { FC, useState } from "react"; import * as Yup from "yup"; import { useFormik } from "formik"; import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; -import { initialUser, User } from "../core/_models"; +import { initialUser, User } from "../../core/_models"; import clsx from "clsx"; import { useListView } from "../core/ListViewProvider"; import { UsersListLoading } from "../components/loading/UsersListLoading"; -import { createUser, updateUser } from "../core/_requests"; +import { createUser, updateUser } from "../../core/_requests"; import { useQueryResponse } from "../core/QueryResponseProvider"; type Props = { diff --git a/src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx index c3caa7f..c4f25bd 100644 --- a/src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx +++ b/src/app/modules/process/user-ready/user-edit-modal/UserEditModalFormWrapper.tsx @@ -2,7 +2,7 @@ import { useQuery } from "react-query"; import { UserEditModalForm } from "./UserEditModalForm"; import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; import { useListView } from "../core/ListViewProvider"; -import { getUserById } from "../core/_requests"; +import { getUserById } from "../../core/_requests"; const UserEditModalFormWrapper = () => { const { itemIdForUpdate, setItemIdForUpdate } = useListView(); diff --git a/src/app/modules/process/user-rejected/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-rejected/components/header/UsersListGrouping.tsx index 0a5df5a..d44fe1d 100644 --- a/src/app/modules/process/user-rejected/components/header/UsersListGrouping.tsx +++ b/src/app/modules/process/user-rejected/components/header/UsersListGrouping.tsx @@ -2,7 +2,7 @@ import {useQueryClient, useMutation} from 'react-query' import {QUERIES} from '../../../../../../_digifi/helpers' import {useListView} from '../../core/ListViewProvider' import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteSelectedUsers} from '../../core/_requests' +import {deleteSelectedUsers} from '../../../core/_requests' const UsersListGrouping = () => { const {selected, clearSelected} = useListView() diff --git a/src/app/modules/process/user-rejected/core/_models.ts b/src/app/modules/process/user-rejected/core/_models.ts deleted file mode 100644 index b9b06ec..0000000 --- a/src/app/modules/process/user-rejected/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {ID, Response} from '../../../../../../_digifi/helpers' -export type User = { - id?: ID - name?: string - avatar?: string - // email?: string - position?: string - role?: string - last_login?: string - two_steps?: boolean - joined_day?: string - online?: boolean - initials?: { - label: string - state: string - } - firstname?: string, - lastname?: string - uid?: string - loan_amount?: string - payment_month?: string - sales_agent?: string - gender?: string | null - marital_status?: string - email?: string - address?: string - state?: string - country?: string - status?: string - added?: string - updated?: string -} - -export type UsersQueryResponse = Response> - -export const initialUser: User = { - avatar: 'avatars/300-6.jpg', - position: 'Art Director', - role: 'Administrator', - name: '', - email: '', -} diff --git a/src/app/modules/process/user-rejected/core/_requests.ts b/src/app/modules/process/user-rejected/core/_requests.ts deleted file mode 100644 index a585521..0000000 --- a/src/app/modules/process/user-rejected/core/_requests.ts +++ /dev/null @@ -1,59 +0,0 @@ -import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../../_digifi/helpers"; -import { User, UsersQueryResponse } from "./_models"; - -const API_URL = import.meta.env.VITE_APP_THEME_API_URL; -const USER_URL = `${API_URL}/user`; -// const GET_USERS_URL = `${API_URL}/users/query`; - -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT - -// const getStartedUsers = (query: string): Promise => { -// return axios -// .get(`${GET_USERS_URL}?${query}`) -// .then((d: AxiosResponse) => d.data); -// }; -const getStartedUsers = (query: string): Promise => { // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION - return axios - .get(`${NEW_USER_ENDPOINT}/loan/started`) - .then((d: AxiosResponse) => d.data); -}; - -const getUserById = (id: ID): Promise => { - return axios - .get(`${USER_URL}/${id}`) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const createUser = (user: User): Promise => { - return axios - .put(USER_URL, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const updateUser = (user: User): Promise => { - return axios - .post(`${USER_URL}/${user.id}`, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const deleteUser = (userId: ID): Promise => { - return axios.delete(`${USER_URL}/${userId}`).then(() => {}); -}; - -const deleteSelectedUsers = (userIds: Array): Promise => { - const requests = userIds.map((id) => axios.delete(`${USER_URL}/${id}`)); - return axios.all(requests).then(() => {}); -}; - -export { - getStartedUsers, - deleteUser, - deleteSelectedUsers, - getUserById, - createUser, - updateUser, -}; diff --git a/src/app/modules/process/user-rejected/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-rejected/table/columns/CustomHeaderColumn.tsx index 838a12e..63eef09 100644 --- a/src/app/modules/process/user-rejected/table/columns/CustomHeaderColumn.tsx +++ b/src/app/modules/process/user-rejected/table/columns/CustomHeaderColumn.tsx @@ -1,6 +1,6 @@ import {FC} from 'react' import {ColumnInstance} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { column: ColumnInstance diff --git a/src/app/modules/process/user-rejected/table/columns/CustomRow.tsx b/src/app/modules/process/user-rejected/table/columns/CustomRow.tsx index a869cfe..af64ac0 100644 --- a/src/app/modules/process/user-rejected/table/columns/CustomRow.tsx +++ b/src/app/modules/process/user-rejected/table/columns/CustomRow.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import {FC} from 'react' import {Row} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { row: Row diff --git a/src/app/modules/process/user-rejected/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-rejected/table/columns/UserActionsCell.tsx index a5bd83b..8182ac5 100644 --- a/src/app/modules/process/user-rejected/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserActionsCell.tsx @@ -5,7 +5,7 @@ import {MenuComponent} from '../../../../../../_digifi/assets/ts/components' import {ID, KTIcon, QUERIES} from '../../../../../../_digifi/helpers' import {useListView} from '../../core/ListViewProvider' import {useQueryResponse} from '../../core/QueryResponseProvider' -import {deleteUser} from '../../core/_requests' +import {deleteUser} from '../../../core/_requests' type Props = { id: ID diff --git a/src/app/modules/process/user-rejected/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-rejected/table/columns/UserCustomHeader.tsx index cb40449..6f845f5 100644 --- a/src/app/modules/process/user-rejected/table/columns/UserCustomHeader.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserCustomHeader.tsx @@ -3,7 +3,7 @@ import {FC, PropsWithChildren, useMemo} from 'react' import {HeaderProps} from 'react-table' import {initialQueryState} from '../../../../../../_digifi/helpers' import {useQueryRequest} from '../../core/QueryRequestProvider' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { className?: string diff --git a/src/app/modules/process/user-rejected/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-rejected/table/columns/UserInfoCell.tsx index 215efd1..d199e44 100644 --- a/src/app/modules/process/user-rejected/table/columns/UserInfoCell.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserInfoCell.tsx @@ -2,7 +2,7 @@ import clsx from 'clsx' import {FC} from 'react' import {toAbsoluteUrl} from '../../../../../../_digifi/helpers' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { user: User diff --git a/src/app/modules/process/user-rejected/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-rejected/table/columns/UserSelectionHeader.tsx index bbb1eb0..1312c0e 100644 --- a/src/app/modules/process/user-rejected/table/columns/UserSelectionHeader.tsx +++ b/src/app/modules/process/user-rejected/table/columns/UserSelectionHeader.tsx @@ -1,7 +1,7 @@ import {FC, PropsWithChildren} from 'react' import {HeaderProps} from 'react-table' import {useListView} from '../../core/ListViewProvider' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { tableProps: PropsWithChildren> diff --git a/src/app/modules/process/user-rejected/table/columns/_columns.tsx b/src/app/modules/process/user-rejected/table/columns/_columns.tsx index 897f37a..a742770 100644 --- a/src/app/modules/process/user-rejected/table/columns/_columns.tsx +++ b/src/app/modules/process/user-rejected/table/columns/_columns.tsx @@ -6,7 +6,7 @@ import {UserActionsCell} from './UserActionsCell' import {UserSelectionCell} from './UserSelectionCell' import {UserCustomHeader} from './UserCustomHeader' import {UserSelectionHeader} from './UserSelectionHeader' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' import { AddedCell } from './AddedCell' const usersColumns: ReadonlyArray> = [ diff --git a/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalForm.tsx index 2136452..0c4db36 100644 --- a/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalForm.tsx +++ b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalForm.tsx @@ -2,11 +2,11 @@ import {FC, useState} from 'react' import * as Yup from 'yup' import {useFormik} from 'formik' import {isNotEmpty, toAbsoluteUrl} from '../../../../../_digifi/helpers' -import {initialUser, User} from '../core/_models' +import {initialUser, User} from '../../core/_models' import clsx from 'clsx' import {useListView} from '../core/ListViewProvider' import {UsersListLoading} from '../components/loading/UsersListLoading' -import {createUser, updateUser} from '../core/_requests' +import {createUser, updateUser} from '../../core/_requests' import {useQueryResponse} from '../core/QueryResponseProvider' type Props = { diff --git a/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalFormWrapper.tsx index a60b730..5fff2c9 100644 --- a/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalFormWrapper.tsx +++ b/src/app/modules/process/user-rejected/user-edit-modal/UserEditModalFormWrapper.tsx @@ -2,7 +2,7 @@ import {useQuery} from 'react-query' import {UserEditModalForm} from './UserEditModalForm' import {isNotEmpty, QUERIES} from '../../../../../_digifi/helpers' import {useListView} from '../core/ListViewProvider' -import {getUserById} from '../core/_requests' +import {getUserById} from '../../core/_requests' const UserEditModalFormWrapper = () => { const {itemIdForUpdate, setItemIdForUpdate} = useListView() diff --git a/src/app/modules/process/user-started/components/header/UsersListGrouping.tsx b/src/app/modules/process/user-started/components/header/UsersListGrouping.tsx index 7f31f93..6c5df5b 100644 --- a/src/app/modules/process/user-started/components/header/UsersListGrouping.tsx +++ b/src/app/modules/process/user-started/components/header/UsersListGrouping.tsx @@ -2,7 +2,7 @@ import { useQueryClient, useMutation } from "react-query"; import { QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteSelectedUsers } from "../../core/_requests"; +import { deleteSelectedUsers } from "../../../core/_requests"; const UsersListGrouping = () => { const { selected, clearSelected } = useListView(); diff --git a/src/app/modules/process/user-started/core/_models.ts b/src/app/modules/process/user-started/core/_models.ts deleted file mode 100644 index bc84896..0000000 --- a/src/app/modules/process/user-started/core/_models.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ID, Response } from "../../../../../_digifi/helpers"; -export type User = { - id?: ID; - name?: string; - avatar?: string; - // email?: string - position?: string; - role?: string; - last_login?: string; - two_steps?: boolean; - joined_day?: string; - online?: boolean; - initials?: { - label: string; - state: string; - }; - firstname?: string; - lastname?: string; - uid?: string; - loan_amount?: string; - payment_month?: string; - sales_agent?: string; - gender?: string | null; - marital_status?: string; - email?: string; - address?: string; - state?: string; - country?: string; - status?: string; - added?: string; - updated?: string; -}; - -export type UsersQueryResponse = Response>; - -export const initialUser: User = { - avatar: "avatars/300-6.jpg", - position: "Art Director", - role: "Administrator", - name: "", - email: "", -}; diff --git a/src/app/modules/process/user-started/core/_requests.ts b/src/app/modules/process/user-started/core/_requests.ts deleted file mode 100644 index ccf71ba..0000000 --- a/src/app/modules/process/user-started/core/_requests.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios, { AxiosResponse } from "axios"; -import { ID, Response } from "../../../../../_digifi/helpers"; -import { User, UsersQueryResponse } from "./_models"; - -const API_URL = import.meta.env.VITE_APP_THEME_API_URL; -const USER_URL = `${API_URL}/user`; -// const GET_USERS_URL = `${API_URL}/users/query`; - -const NEW_USER_ENDPOINT = import.meta.env.VITE_APP_USER_ENDPOINT; - -// const getStartedUsers = (query: string): Promise => { -// return axios -// .get(`${GET_USERS_URL}?${query}`) -// .then((d: AxiosResponse) => d.data); -// }; -const getStartedUsers = (query: string): Promise => { - // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION - return axios - .get(`${NEW_USER_ENDPOINT}/loan/started`) - .then((d: AxiosResponse) => d.data); -}; - -const getUserById = (id: ID): Promise => { - return axios - .get(`${USER_URL}/${id}`) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const createUser = (user: User): Promise => { - return axios - .put(USER_URL, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const updateUser = (user: User): Promise => { - return axios - .post(`${USER_URL}/${user.id}`, user) - .then((response: AxiosResponse>) => response.data) - .then((response: Response) => response.data); -}; - -const deleteUser = (userId: ID): Promise => { - return axios.delete(`${USER_URL}/${userId}`).then(() => {}); -}; - -const deleteSelectedUsers = (userIds: Array): Promise => { - const requests = userIds.map((id) => axios.delete(`${USER_URL}/${id}`)); - return axios.all(requests).then(() => {}); -}; - -export { - getStartedUsers, - deleteUser, - deleteSelectedUsers, - getUserById, - createUser, - updateUser, -}; diff --git a/src/app/modules/process/user-started/table/columns/CustomHeaderColumn.tsx b/src/app/modules/process/user-started/table/columns/CustomHeaderColumn.tsx index 838a12e..63eef09 100644 --- a/src/app/modules/process/user-started/table/columns/CustomHeaderColumn.tsx +++ b/src/app/modules/process/user-started/table/columns/CustomHeaderColumn.tsx @@ -1,6 +1,6 @@ import {FC} from 'react' import {ColumnInstance} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { column: ColumnInstance diff --git a/src/app/modules/process/user-started/table/columns/CustomRow.tsx b/src/app/modules/process/user-started/table/columns/CustomRow.tsx index a869cfe..af64ac0 100644 --- a/src/app/modules/process/user-started/table/columns/CustomRow.tsx +++ b/src/app/modules/process/user-started/table/columns/CustomRow.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import {FC} from 'react' import {Row} from 'react-table' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { row: Row diff --git a/src/app/modules/process/user-started/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-started/table/columns/UserActionsCell.tsx index 4843e41..108da7b 100644 --- a/src/app/modules/process/user-started/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-started/table/columns/UserActionsCell.tsx @@ -4,7 +4,7 @@ import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; import { useListView } from "../../core/ListViewProvider"; import { useQueryResponse } from "../../core/QueryResponseProvider"; -import { deleteUser } from "../../core/_requests"; +import { deleteUser } from "../../../core/_requests"; type Props = { id: ID; diff --git a/src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx b/src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx index 76ea930..9d10d65 100644 --- a/src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx +++ b/src/app/modules/process/user-started/table/columns/UserCustomHeader.tsx @@ -3,7 +3,7 @@ import { FC, PropsWithChildren, useMemo } from "react"; import { HeaderProps } from "react-table"; import { initialQueryState } from "../../../../../../_digifi/helpers"; import { useQueryRequest } from "../../core/QueryRequestProvider"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { className?: string; diff --git a/src/app/modules/process/user-started/table/columns/UserInfoCell.tsx b/src/app/modules/process/user-started/table/columns/UserInfoCell.tsx index 6b45b58..7a1edf3 100644 --- a/src/app/modules/process/user-started/table/columns/UserInfoCell.tsx +++ b/src/app/modules/process/user-started/table/columns/UserInfoCell.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { FC } from "react"; import { toAbsoluteUrl } from "../../../../../../_digifi/helpers"; -import { User } from "../../core/_models"; +import { User } from "../../../core/_models"; type Props = { user: User; diff --git a/src/app/modules/process/user-started/table/columns/UserSelectionHeader.tsx b/src/app/modules/process/user-started/table/columns/UserSelectionHeader.tsx index bbb1eb0..1312c0e 100644 --- a/src/app/modules/process/user-started/table/columns/UserSelectionHeader.tsx +++ b/src/app/modules/process/user-started/table/columns/UserSelectionHeader.tsx @@ -1,7 +1,7 @@ import {FC, PropsWithChildren} from 'react' import {HeaderProps} from 'react-table' import {useListView} from '../../core/ListViewProvider' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' type Props = { tableProps: PropsWithChildren> diff --git a/src/app/modules/process/user-started/table/columns/_columns.tsx b/src/app/modules/process/user-started/table/columns/_columns.tsx index 897f37a..a742770 100644 --- a/src/app/modules/process/user-started/table/columns/_columns.tsx +++ b/src/app/modules/process/user-started/table/columns/_columns.tsx @@ -6,7 +6,7 @@ import {UserActionsCell} from './UserActionsCell' import {UserSelectionCell} from './UserSelectionCell' import {UserCustomHeader} from './UserCustomHeader' import {UserSelectionHeader} from './UserSelectionHeader' -import {User} from '../../core/_models' +import {User} from '../../../core/_models' import { AddedCell } from './AddedCell' const usersColumns: ReadonlyArray> = [ diff --git a/src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx b/src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx index ff35559..16c3678 100644 --- a/src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx +++ b/src/app/modules/process/user-started/user-edit-modal/UserEditModalForm.tsx @@ -2,11 +2,11 @@ import { FC, useState } from "react"; import * as Yup from "yup"; import { useFormik } from "formik"; import { isNotEmpty, toAbsoluteUrl } from "../../../../../_digifi/helpers"; -import { initialUser, User } from "../core/_models"; +import { initialUser, User } from "../../core/_models"; import clsx from "clsx"; import { useListView } from "../core/ListViewProvider"; import { UsersListLoading } from "../components/loading/UsersListLoading"; -import { createUser, updateUser } from "../core/_requests"; +import { createUser, updateUser } from "../../core/_requests"; import { useQueryResponse } from "../core/QueryResponseProvider"; type Props = { diff --git a/src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx b/src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx index c3caa7f..c4f25bd 100644 --- a/src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx +++ b/src/app/modules/process/user-started/user-edit-modal/UserEditModalFormWrapper.tsx @@ -2,7 +2,7 @@ import { useQuery } from "react-query"; import { UserEditModalForm } from "./UserEditModalForm"; import { isNotEmpty, QUERIES } from "../../../../../_digifi/helpers"; import { useListView } from "../core/ListViewProvider"; -import { getUserById } from "../core/_requests"; +import { getUserById } from "../../core/_requests"; const UserEditModalFormWrapper = () => { const { itemIdForUpdate, setItemIdForUpdate } = useListView(); From c6fe8c7d5ad39baa7527f04141fedb47112f132c Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Wed, 15 May 2024 20:52:07 +0100 Subject: [PATCH 3/4] updated pending list action menu --- .../process/user-pending/table/columns/UserActionsCell.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx index 71d9a5f..d767532 100644 --- a/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx @@ -51,7 +51,7 @@ const UserActionsCell: FC = ({ id }) => { {/* begin::Menu item */} {/* end::Menu item */} @@ -63,7 +63,7 @@ const UserActionsCell: FC = ({ id }) => { data-kt-users-table-filter="delete_row" onClick={async () => await deleteItem.mutateAsync()} > - Delete + Start Processing
{/* end::Menu item */} From 4e60059290223dbde0a4650c0cbb196f0064c142 Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Wed, 15 May 2024 20:52:53 +0100 Subject: [PATCH 4/4] updated pending list action menu --- .../process/user-pending/table/columns/UserActionsCell.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx index d767532..15f0b94 100644 --- a/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx +++ b/src/app/modules/process/user-pending/table/columns/UserActionsCell.tsx @@ -45,7 +45,7 @@ const UserActionsCell: FC = ({ id }) => { {/* begin::Menu */}
{/* begin::Menu item */}