From 40ba31d3468c994df0d521174d096250bc5adfa6 Mon Sep 17 00:00:00 2001 From: Cyril Nxumalo Date: Fri, 30 Aug 2024 10:36:43 +0200 Subject: [PATCH] chore: Migrate deprecated Table to DataTable for RegisteredLearnersTable --- .../RegisteredLearnersTable.test.jsx.snap | 258 ++++++++++++++++-- .../data/hooks/useRegisteredLearners.js | 49 ++++ .../RegisteredLearnersTable/index.jsx | 74 +++-- 3 files changed, 330 insertions(+), 51 deletions(-) create mode 100644 src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js diff --git a/src/components/RegisteredLearnersTable/__snapshots__/RegisteredLearnersTable.test.jsx.snap b/src/components/RegisteredLearnersTable/__snapshots__/RegisteredLearnersTable.test.jsx.snap index a371442a53..fba44a0cd6 100644 --- a/src/components/RegisteredLearnersTable/__snapshots__/RegisteredLearnersTable.test.jsx.snap +++ b/src/components/RegisteredLearnersTable/__snapshots__/RegisteredLearnersTable.test.jsx.snap @@ -2,35 +2,245 @@ exports[`RegisteredLearnersTable renders empty state correctly 1`] = `
- - - - -
- There are no results. +
+
+
+
+
+
+
+
+
+
+
+
+ + loading + +
+
+ + + + + + + + +
+ + + Email + + + + + + + + + + + Account Created + + + + + + + +
+
+
+ +
diff --git a/src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js b/src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js new file mode 100644 index 0000000000..7878c464f6 --- /dev/null +++ b/src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js @@ -0,0 +1,49 @@ +import { useCallback, useMemo, useState } from 'react'; +import { camelCaseObject } from '@edx/frontend-platform/utils'; +import debounce from 'lodash.debounce'; +import { logError } from '@edx/frontend-platform/logging'; +import EnterpriseDataApiService from '../../../../data/services/EnterpriseDataApiService'; + +const useRegisteredLearners = (enterpriseId) => { + const [isLoading, setIsLoading] = useState(true); + const [registeredLearners, setRegisteredLearners] = useState({ + itemCount: 0, + pageCount: 0, + results: [], + }); + + const fetchRegisteredLearners = useCallback(async (args) => { + try { + setIsLoading(true); + const options = { + page: args.pageIndex + 1, // `DataTable` uses zero-indexed array + pageSize: args.pageSize, + }; + const response = await EnterpriseDataApiService.fetchUnenrolledRegisteredLearners(enterpriseId, options); + const data = camelCaseObject(response.data); + + setRegisteredLearners({ + itemCount: data.count, + pageCount: data.numPages ?? Math.floor(data.count / options.pageSize), + results: data.results, + }); + } catch (error) { + logError(error); + } finally { + setIsLoading(false); + } + }, [enterpriseId]); + + const debouncedFetchRegisteredLearners = useMemo( + () => debounce(fetchRegisteredLearners, 300), + [fetchRegisteredLearners], + ); + + return { + isLoading, + registeredLearners, + fetchRegisteredLearners: debouncedFetchRegisteredLearners, + }; +}; + +export default useRegisteredLearners; diff --git a/src/components/RegisteredLearnersTable/index.jsx b/src/components/RegisteredLearnersTable/index.jsx index fefe7f95c9..dfb9e0c5c8 100644 --- a/src/components/RegisteredLearnersTable/index.jsx +++ b/src/components/RegisteredLearnersTable/index.jsx @@ -1,54 +1,74 @@ import React from 'react'; - +import PropTypes from 'prop-types'; import { useIntl } from '@edx/frontend-platform/i18n'; +import { DataTable } from '@openedx/paragon'; +import useRegisteredLearners from './data/hooks/useRegisteredLearners'; +import { i18nFormatTimestamp } from '../../utils'; -import TableContainer from '../../containers/TableContainer'; +const UserEmail = ({ row }) => ( + {row.original.user_email} +); -import { i18nFormatTimestamp } from '../../utils'; -import EnterpriseDataApiService from '../../data/services/EnterpriseDataApiService'; +UserEmail.propTypes = { + row: PropTypes.shape({ + original: PropTypes.shape({ + user_email: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, +}; -const RegisteredLearnersTable = () => { +const RegisteredLearnersTable = ({ enterpriseId }) => { const intl = useIntl(); + const { + isLoading, + registeredLearners: tableData, + fetchRegisteredLearners: fetchTableData, + } = useRegisteredLearners(enterpriseId); - const tableColumns = [ + const columns = [ { - label: intl.formatMessage({ + Header: intl.formatMessage({ id: 'admin.portal.lpr.registered.learners.table.user_email.column.heading', defaultMessage: 'Email', description: 'Column heading for the user email column in the registered learners table', }), - key: 'user_email', - columnSortable: true, + accessor: 'user_email', + Cell: UserEmail, }, { - label: intl.formatMessage({ + Header: intl.formatMessage({ id: 'admin.portal.lpr.registered.learners.table.lms_user_created.column.heading', defaultMessage: 'Account Created', description: 'Column heading for the lms user created column in the registered learners table', }), - key: 'lms_user_created', - columnSortable: true, + accessor: 'lms_user_created', + Cell: ({ row }) => i18nFormatTimestamp({ intl, timestamp: row.values.lms_user_created }), }, ]; - const formatLearnerData = learners => learners.map(learner => ({ - ...learner, - user_email: {learner.user_email}, - lms_user_created: i18nFormatTimestamp({ - intl, timestamp: learner.lms_user_created, - }), - })); - return ( - ); }; +RegisteredLearnersTable.propTypes = { + enterpriseId: PropTypes.string.isRequired, +}; + export default RegisteredLearnersTable;