Skip to content

Commit

Permalink
feat: Conditionally render expiring learner credit alerts and modals
Browse files Browse the repository at this point in the history
  • Loading branch information
brobro10000 committed May 16, 2024
1 parent 58488e3 commit 0903570
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 17 deletions.
1 change: 0 additions & 1 deletion src/components/Admin/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ class Admin extends React.Component {
insights,
insightsLoading,
} = this.props;

const queryParams = new URLSearchParams(search || '');
const queryParamsLength = Array.from(queryParams.entries()).length;
const filtersActive = queryParamsLength !== 0 && !(queryParamsLength === 1 && queryParams.has('ordering'));
Expand Down
22 changes: 12 additions & 10 deletions src/components/BudgetExpiryAlertAndModal/data/hooks/useExpiry.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import {
getEnterpriseBudgetExpiringAlertCookieName,
getEnterpriseBudgetExpiringModalCookieName,
getExpirationMetadata,
getNonExpiredBudgets,
getExpiredAndNonExpiredBudgets,
} from '../utils';

const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, alertClose) => {
const [notification, setNotification] = useState(null);
const [expirationThreshold, setExpirationThreshold] = useState(null);
const [modal, setModal] = useState(null);
const [isNonExpiredBudget, setisNonExpiredBudget] = useState(false);

useEffect(() => {
if (!budgets || budgets.length === 0) {
Expand All @@ -20,18 +21,19 @@ const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, aler
// expired and non-expired budgets. In that case, we only want
// to determine the expiry threshold from the set of *non-expired* budgets,
// so that the alert and modal below do not falsely signal.
let budgetsToConsiderForExpirationMessaging = budgets;
let budgetsToConsiderForExpirationMessaging = [];

const nonExpiredBudgets = getNonExpiredBudgets(budgets);
const hasNonExpiredBudgets = nonExpiredBudgets.length > 0;
const { nonExpiredBudgets, expiredBudgets } = getExpiredAndNonExpiredBudgets(budgets);

// If the length of all budgets is different from the length of non-expired budgets,
// then there exists at least one expired budget (note that we already early-returned
// above if there are zero total budgets).
const hasExpiredBudgets = budgets.length !== nonExpiredBudgets.length;
// Consider the length of each budget
const hasNonExpiredBudgets = nonExpiredBudgets.length > 0;

if (hasNonExpiredBudgets && hasExpiredBudgets) {
// If an unexpired budget exists, set budgetsToConsiderForExpirationMessaging to nonExpiredBudgets
if (hasNonExpiredBudgets) {
budgetsToConsiderForExpirationMessaging = nonExpiredBudgets;
setisNonExpiredBudget(true);
} else {
budgetsToConsiderForExpirationMessaging = expiredBudgets;
}

const earliestExpiryBudget = budgetsToConsiderForExpirationMessaging.reduce(
Expand Down Expand Up @@ -97,7 +99,7 @@ const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, aler
};

return {
notification, modal, dismissModal, dismissAlert,
notification, modal, dismissModal, dismissAlert, isNonExpiredBudget,
};
};

Expand Down
7 changes: 5 additions & 2 deletions src/components/BudgetExpiryAlertAndModal/data/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import ExpiryThresholds from './expiryThresholds';

dayjs.extend(duration);

export const getNonExpiredBudgets = (budgets) => {
export const getExpiredAndNonExpiredBudgets = (budgets) => {
const today = dayjs();
return budgets.filter((budget) => today <= dayjs(budget.end));
return {
nonExpiredBudgets: budgets.filter((budget) => today <= dayjs(budget.end)),
expiredBudgets: budgets.filter((budget) => today > dayjs(budget.end)),
};
};

export const getExpirationMetadata = (endDateStr) => {
Expand Down
10 changes: 8 additions & 2 deletions src/components/BudgetExpiryAlertAndModal/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import EVENT_NAMES from '../../eventTracking';

import useExpiry from './data/hooks/useExpiry';

const BudgetExpiryAlertAndModal = ({ enterpriseUUID, enterpriseFeatures }) => {
const BudgetExpiryAlertAndModal = ({ enterpriseUUID, enterpriseFeatures, disableExpiryMessagingForLearnerCredit }) => {
const [modalIsOpen, modalOpen, modalClose] = useToggle(false);
const [alertIsOpen, alertOpen, alertClose] = useToggle(false);

Expand Down Expand Up @@ -46,7 +46,7 @@ const BudgetExpiryAlertAndModal = ({ enterpriseUUID, enterpriseFeatures }) => {
});

const {
notification, modal, dismissModal, dismissAlert,
notification, modal, dismissModal, dismissAlert, isNonExpiredBudget,
} = useExpiry(
enterpriseUUID,
budgets,
Expand All @@ -64,6 +64,10 @@ const BudgetExpiryAlertAndModal = ({ enterpriseUUID, enterpriseFeatures }) => {
};
}, [modal, notification]);

if (isNonExpiredBudget && disableExpiryMessagingForLearnerCredit) {
return null;
}

return (
<>
{notification && (
Expand Down Expand Up @@ -141,13 +145,15 @@ const BudgetExpiryAlertAndModal = ({ enterpriseUUID, enterpriseFeatures }) => {
const mapStateToProps = state => ({
enterpriseUUID: state.portalConfiguration.enterpriseId,
enterpriseFeatures: state.portalConfiguration.enterpriseFeatures,
disableExpiryMessagingForLearnerCredit: state.portalConfiguration.disableExpiryMessagingForLearnerCredit,
});

BudgetExpiryAlertAndModal.propTypes = {
enterpriseUUID: PropTypes.string.isRequired,
enterpriseFeatures: PropTypes.shape({
topDownAssignmentRealTimeLcm: PropTypes.bool.isRequired,
}),
disableExpiryMessagingForLearnerCredit: PropTypes.bool.isRequired,
};

export default connect(mapStateToProps)(BudgetExpiryAlertAndModal);
4 changes: 2 additions & 2 deletions src/containers/EnterpriseApp/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { toggleSidebarToggle } from '../../data/actions/sidebar';

const mapStateToProps = (state) => {
const enterpriseListState = state.table['enterprise-list'] || {};

return {
enterprises: enterpriseListState.data,
error: state.portalConfiguration.error,
disableExpiryMessagingForLearnerCredit: state.portalConfiguration.disableExpiryMessagingForLearnerCredit,
enableCodeManagementScreen: state.portalConfiguration.enableCodeManagementScreen,
enableSubscriptionManagementScreen: state.portalConfiguration.enableSubscriptionManagementScreen, // eslint-disable-line max-len
enableSubscriptionManagementScreen: state.portalConfiguration.enableSubscriptionManagementScreen,
enableSamlConfigurationScreen: state.portalConfiguration.enableSamlConfigurationScreen,
enableAnalyticsScreen: state.portalConfiguration.enableAnalyticsScreen,
enableLearnerPortal: state.portalConfiguration.enableLearnerPortal,
Expand Down
4 changes: 4 additions & 0 deletions src/data/reducers/portalConfiguration.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const initialState = {
enterpriseSlug: null,
enterpriseBranding: null,
identityProvider: null,
disableExpiryMessagingForLearnerCredit: false,
enableCodeManagementScreen: false,
enableReportingConfigScreen: false,
enableSubscriptionManagementScreen: false,
Expand Down Expand Up @@ -50,6 +51,7 @@ const portalConfiguration = (state = initialState, action) => {
enterpriseSlug: action.payload.data.slug,
enterpriseBranding: action.payload.data.branding_configuration,
identityProvider: action.payload.data.identity_provider,
disableExpiryMessagingForLearnerCredit: action.payload.data.disable_expiry_messaging_for_learner_credit,
enableCodeManagementScreen: action.payload.data.enable_portal_code_management_screen,
enableReportingConfigScreen: action.payload.data.enable_portal_reporting_config_screen,
enableSubscriptionManagementScreen: action.payload.data.enable_portal_subscription_management_screen, // eslint-disable-line max-len
Expand All @@ -76,6 +78,7 @@ const portalConfiguration = (state = initialState, action) => {
enterpriseSlug: null,
enterpriseBranding: null,
identityProvider: null,
disableExpiryMessagingForLearnerCredit: false,
enableCodeManagementScreen: false,
enableReportingConfigScreen: false,
enableSubscriptionManagementScreen: false,
Expand All @@ -100,6 +103,7 @@ const portalConfiguration = (state = initialState, action) => {
enterpriseSlug: null,
enterpriseBranding: null,
identityProvider: null,
disableExpiryMessagingForLearnerCredit: null,
enableCodeManagementScreen: false,
enableReportingConfigScreen: false,
enableSubscriptionManagementScreen: false,
Expand Down

0 comments on commit 0903570

Please sign in to comment.