diff --git a/src/Configuration/Customers/CustomerDetailView/CustomerIntegrations.jsx b/src/Configuration/Customers/CustomerDetailView/CustomerIntegrations.jsx index ec6fbe777..c81ff8883 100644 --- a/src/Configuration/Customers/CustomerDetailView/CustomerIntegrations.jsx +++ b/src/Configuration/Customers/CustomerDetailView/CustomerIntegrations.jsx @@ -15,6 +15,10 @@ const CustomerIntegrations = ({ integrationCount++; } + if (!integrationCount) { + return null; + } + return (
{(integrationCount > 0) && ( diff --git a/src/Configuration/Customers/CustomerDetailView/CustomerPlanContainer.jsx b/src/Configuration/Customers/CustomerDetailView/CustomerPlanContainer.jsx index 5b15f46fe..6725e2195 100644 --- a/src/Configuration/Customers/CustomerDetailView/CustomerPlanContainer.jsx +++ b/src/Configuration/Customers/CustomerDetailView/CustomerPlanContainer.jsx @@ -1,23 +1,25 @@ -import { useState } from 'react'; -import { useParams } from 'react-router-dom'; +import { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { Form, Skeleton } from '@openedx/paragon'; -import useAllAssociatedPlans from '../data/hooks/useAllAssociatedPlans'; import LearnerCreditPlanCard from './LearnerCreditPlanCard'; import SubscriptionPlanCard from './SubscriptionPlanCard'; -const CustomerPlanContainer = ({ slug }) => { - const { id } = useParams(); - const { - activeSubsidies, - activeSubscriptions, - countOfActivePlans, - countOfAllPlans, - inactiveSubsidies, - inactiveSubscriptions, - isLoading, - } = useAllAssociatedPlans(id); +const CustomerPlanContainer = ({ + slug, + activeSubsidies, + activeSubscriptions, + countOfActivePlans, + countOfAllPlans, + inactiveSubsidies, + inactiveSubscriptions, + isLoading, +}) => { const [showInactive, setShowInactive] = useState(false); + useEffect(() => { + if (!countOfActivePlans && countOfAllPlans) { + setShowInactive(true); + } + }, []); const renderActiveSubsidiesCard = activeSubsidies.map(subsidy => ( )); @@ -30,23 +32,25 @@ const CustomerPlanContainer = ({ slug }) => { const renderInActiveSubscriptions = inactiveSubscriptions.map(subscription => ( )); + return (
{!isLoading ? (

Associated subsidy plans ({showInactive ? countOfAllPlans : countOfActivePlans})

- { - setShowInactive(prevState => !prevState); - }} - data-testid="show-removed-toggle" - > - Show inactive - + {(countOfAllPlans > countOfActivePlans && countOfActivePlans) ? ( + { + setShowInactive(prevState => !prevState); + }} + data-testid="show-removed-toggle" + > + Show inactive + + ) : null}

{renderActiveSubsidiesCard} @@ -65,6 +69,33 @@ const CustomerPlanContainer = ({ slug }) => { CustomerPlanContainer.propTypes = { slug: PropTypes.string.isRequired, + activeSubsidies: PropTypes.arrayOf(PropTypes.shape({ + uuid: PropTypes.string.isRequired, + activeDatetime: PropTypes.string.isRequired, + expirationDatetime: PropTypes.string.isRequired, + created: PropTypes.string.isRequired, + })).isRequired, + activeSubscriptions: PropTypes.arrayOf(PropTypes.shape({ + uuid: PropTypes.string.isRequired, + startDate: PropTypes.string.isRequired, + expirationDate: PropTypes.string.isRequired, + created: PropTypes.string.isRequired, + })).isRequired, + countOfActivePlans: PropTypes.number.isRequired, + countOfAllPlans: PropTypes.number.isRequired, + inactiveSubsidies: PropTypes.arrayOf(PropTypes.shape({ + uuid: PropTypes.string.isRequired, + activeDatetime: PropTypes.string.isRequired, + expirationDatetime: PropTypes.string.isRequired, + created: PropTypes.string.isRequired, + })).isRequired, + inactiveSubscriptions: PropTypes.arrayOf(PropTypes.shape({ + uuid: PropTypes.string.isRequired, + startDate: PropTypes.string.isRequired, + expirationDate: PropTypes.string.isRequired, + created: PropTypes.string.isRequired, + })).isRequired, + isLoading: PropTypes.bool.isRequired, }; export default CustomerPlanContainer; diff --git a/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx b/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx index c8f5c41e3..4e3d2c344 100644 --- a/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx +++ b/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx @@ -13,12 +13,14 @@ import { getEnterpriseCustomer } from '../data/utils'; import CustomerIntegrations from './CustomerIntegrations'; import EnterpriseCustomerUsersTable from './EnterpriseCustomerUsersTable'; import CustomerPlanContainer from './CustomerPlanContainer'; +import useAllAssociatedPlans from '../data/hooks/useAllAssociatedPlans'; const CustomerViewContainer = () => { const { id } = useParams(); const [enterpriseCustomer, setEnterpriseCustomer] = useState({}); const [isLoading, setIsLoading] = useState(true); const intl = useIntl(); + const associatedPlans = useAllAssociatedPlans(id); const fetchData = useCallback( async () => { @@ -38,6 +40,23 @@ const CustomerViewContainer = () => { fetchData(); }, []); + const renderPlanContainer = () => { + if (!isLoading && !associatedPlans.isLoading && associatedPlans.countOfAllPlans) { + return ( + + + + ); + } + if (!associatedPlans.isLoading && !associatedPlans.countOfAllPlans) { + return false; + } + if (associatedPlans.isLoading) { + return ; + } + return null; + }; + return (
{!isLoading ? ( @@ -64,11 +83,9 @@ const CustomerViewContainer = () => { - - {!isLoading ? : } - + {renderPlanContainer()} - + { isLoading, enterpriseUsersTableData, fetchEnterpriseUsersData, + showTable, } = useCustomerUsersTableData(id); + return (
-

Associated users ({enterpriseUsersTableData.itemCount})

-
- + {showTable ? ( +
+

Associated users {enterpriseUsersTableData.itemCount > 0 + && ({enterpriseUsersTableData.itemCount})} +

+
+ +
+ ) : null}
); }; diff --git a/src/Configuration/Customers/CustomerDetailView/tests/CustomerPlanContainer.test.jsx b/src/Configuration/Customers/CustomerDetailView/tests/CustomerPlanContainer.test.jsx index 667e8b9a0..e3338a483 100644 --- a/src/Configuration/Customers/CustomerDetailView/tests/CustomerPlanContainer.test.jsx +++ b/src/Configuration/Customers/CustomerDetailView/tests/CustomerPlanContainer.test.jsx @@ -5,7 +5,6 @@ import userEvent from '@testing-library/user-event'; import { getConfig } from '@edx/frontend-platform'; import { IntlProvider } from '@edx/frontend-platform/i18n'; -import useAllAssociatedPlans from '../../data/hooks/useAllAssociatedPlans'; import { formatDate } from '../../data/utils'; import CustomerPlanContainer from '../CustomerPlanContainer'; @@ -19,11 +18,6 @@ jest.mock('@edx/frontend-platform', () => ({ getConfig: jest.fn(), })); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ id: 'test-uuid' }), -})); - const CUSTOMER_SLUG = 'test-slug'; describe('CustomerPlanContainer', () => { @@ -44,7 +38,7 @@ describe('CustomerPlanContainer', () => { SUBSIDY_BASE_URL: 'http:www.enterprise-subsidy.com', LICENSE_MANAGER_URL: 'http:www.license-manager.com', })); - useAllAssociatedPlans.mockReturnValue({ + const mockProps = { isLoading: false, activeSubsidies: [{ activeDatetime: '2024-08-23T20:02:57.651943Z', @@ -69,10 +63,10 @@ describe('CustomerPlanContainer', () => { uuid: 'test-uuid', isActive: false, }], - }); + }; render( - + , ); const djangoLinks = screen.getAllByRole('link', { name: 'Open in Django' }); diff --git a/src/Configuration/Customers/CustomerDetailView/tests/CustomerViewIntegrations.test.jsx b/src/Configuration/Customers/CustomerDetailView/tests/CustomerViewIntegrations.test.jsx index 0b825655d..05d6987fa 100644 --- a/src/Configuration/Customers/CustomerDetailView/tests/CustomerViewIntegrations.test.jsx +++ b/src/Configuration/Customers/CustomerDetailView/tests/CustomerViewIntegrations.test.jsx @@ -63,4 +63,20 @@ describe('CustomerViewIntegrations', () => { expect(screen.getByText('API')).toBeInTheDocument(); }); }); + it('does not render cards', async () => { + formatDate.mockReturnValue('September 15, 2024'); + render( + + + , + ); + await waitFor(() => { + expect(screen.queryByText('Associated integrations (0)')).not.toBeInTheDocument(); + }); + }); }); diff --git a/src/Configuration/Customers/CustomerDetailView/tests/EnterpriseCustomerUsersTable.test.jsx b/src/Configuration/Customers/CustomerDetailView/tests/EnterpriseCustomerUsersTable.test.jsx index 1848313a9..4fde961e5 100644 --- a/src/Configuration/Customers/CustomerDetailView/tests/EnterpriseCustomerUsersTable.test.jsx +++ b/src/Configuration/Customers/CustomerDetailView/tests/EnterpriseCustomerUsersTable.test.jsx @@ -33,6 +33,7 @@ const mockData = { ], }, fetchEnterpriseUsersData: mockFetchEnterpriseUsersData, + showTable: true, }; jest.mock('../../data/hooks/useCustomerUsersTableData'); @@ -80,4 +81,24 @@ describe('EnterpriseCustomerUsersTable', () => { }); }); }); + + it('does not render user table section', () => { + const emptyResults = { + isLoading: false, + enterpriseUsersTableData: { + itemCount: 0, + pageCount: 1, + results: [], + }, + fetchEnterpriseUsersData: mockFetchEnterpriseUsersData, + }; + useCustomerUsersTableData.mockReturnValue(emptyResults); + render( + + + , + ); + expect(screen.queryByText('Search user details')).not.toBeInTheDocument(); + expect(screen.queryByText('Associated users (0)')).not.toBeInTheDocument(); + }); }); diff --git a/src/Configuration/Customers/data/hooks/useCustomerUsersTableData.js b/src/Configuration/Customers/data/hooks/useCustomerUsersTableData.js index ab673e938..e7e52efc4 100644 --- a/src/Configuration/Customers/data/hooks/useCustomerUsersTableData.js +++ b/src/Configuration/Customers/data/hooks/useCustomerUsersTableData.js @@ -1,5 +1,5 @@ import { - useCallback, useMemo, useState, + useCallback, useMemo, useState, useEffect, } from 'react'; import { camelCaseObject } from '@edx/frontend-platform/utils'; import { logError } from '@edx/frontend-platform/logging'; @@ -9,6 +9,7 @@ import LmsApiService from '../../../../data/services/EnterpriseApiService'; const useCustomerUsersTableData = (enterpriseUuid) => { const [isLoading, setIsLoading] = useState(true); + const [showTable, setShowTable] = useState(false); const [enterpriseUsersTableData, setEnterpriseUsersTableData] = useState({ itemCount: 0, pageCount: 0, @@ -66,10 +67,23 @@ const useCustomerUsersTableData = (enterpriseUuid) => { [fetchEnterpriseUsersData], ); + useEffect(() => { + const args = { + pageIndex: 0, + filters: [], + sortBy: [], + }; + fetchEnterpriseUsersData(args); + if (enterpriseUsersTableData.itemCount) { + setShowTable(true); + } + }, [fetchEnterpriseUsersData, enterpriseUsersTableData.itemCount]); + return { isLoading, enterpriseUsersTableData, fetchEnterpriseUsersData: debouncedFetchEnterpriseUsersData, + showTable, }; };