diff --git a/src/components/EnterpriseApp/data/constants.js b/src/components/EnterpriseApp/data/constants.js
index 5c881fefab..7bacfbd457 100644
--- a/src/components/EnterpriseApp/data/constants.js
+++ b/src/components/EnterpriseApp/data/constants.js
@@ -13,3 +13,9 @@ export const ROUTE_NAMES = {
subscriptionManagement: 'subscriptions',
contentHighlights: 'content-highlights',
};
+
+export const BUDGET_STATUSES = {
+ active: 'Active',
+ expired: 'Expired',
+ upcoming: 'Upcoming',
+};
diff --git a/src/components/EnterpriseSubsidiesContext/data/hooks.js b/src/components/EnterpriseSubsidiesContext/data/hooks.js
index 243d6063b8..fc91edb874 100644
--- a/src/components/EnterpriseSubsidiesContext/data/hooks.js
+++ b/src/components/EnterpriseSubsidiesContext/data/hooks.js
@@ -43,10 +43,10 @@ export const useEnterpriseOffers = ({ enablePortalLearnerCreditManagementScreen,
const { isActive } = subsidy; // Always check isActive for enterprise subsidies
const isCurrent = isActive; // You can adjust this based on your specific requirements
const activeSubsidyData = {
- id: subsidy.uuid || subsidy.id,
- name: subsidy.title || subsidy.displayName,
- start: subsidy.activeDatetime || subsidy.startDatetime,
- end: subsidy.expirationDatetime || subsidy.endDatetime,
+ id: subsidy.uuid,
+ name: subsidy.title,
+ start: subsidy.activeDatetime,
+ end: subsidy.expirationDatetime,
isCurrent,
source,
};
@@ -61,10 +61,10 @@ export const useEnterpriseOffers = ({ enablePortalLearnerCreditManagementScreen,
const source = 'ecommerceApi';
const { isCurrent } = subsidy;
const activeSubsidyData = {
- id: subsidy.uuid || subsidy.id,
- name: subsidy.title || subsidy.displayName,
- start: subsidy.activeDatetime || subsidy.startDatetime,
- end: subsidy.expirationDatetime || subsidy.endDatetime,
+ id: subsidy.id,
+ name: subsidy.displayName,
+ start: subsidy.startDatetime,
+ end: subsidy.endDatetime,
isCurrent,
source,
};
diff --git a/src/components/learner-credit-management/BudgetCard-V2.jsx b/src/components/learner-credit-management/BudgetCard-V2.jsx
index 09a5c8cdf5..11e563e606 100644
--- a/src/components/learner-credit-management/BudgetCard-V2.jsx
+++ b/src/components/learner-credit-management/BudgetCard-V2.jsx
@@ -1,18 +1,44 @@
+/* eslint-disable */
import React from 'react';
import PropTypes from 'prop-types';
-import dayjs from 'dayjs';
import {
Stack,
+ Col,
+ Card,
+ Skeleton,
} from '@edx/paragon';
import { useOfferSummary } from './data/hooks';
import SubBudgetCard from './Budgetcard-V3';
+const LoadingCards = () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
const BudgetCard = ({
offer,
enterpriseUUID,
enterpriseSlug,
offerType,
+ displayName,
}) => {
const {
start,
@@ -24,37 +50,35 @@ const BudgetCard = ({
offerSummary,
} = useOfferSummary(enterpriseUUID, offer);
- const formattedStartDate = dayjs(start).format('MMMM D, YYYY');
- const formattedExpirationDate = dayjs(end).format('MMMM D, YYYY');
-
return (
- <>
- Budgets
- {!isLoadingOfferSummary
- && offerType === 'ecommerceApi'
- ? (
-
- )
- : offerSummary?.budgetsSumary.map((budget) => (
-
- ))}
- >
+ Budgets
+ {isLoadingOfferSummary ? (
+
+ ) : offerType === 'ecommerceApi' ? (
+
+ ) : (
+ offerSummary?.budgetsSummary.map((budget) => (
+
+ ))
+ )}
);
};
@@ -69,6 +93,7 @@ BudgetCard.propTypes = {
enterpriseUUID: PropTypes.string.isRequired,
enterpriseSlug: PropTypes.string.isRequired,
offerType: PropTypes.string.isRequired,
+ displayName: PropTypes.string,
};
export default BudgetCard;
diff --git a/src/components/learner-credit-management/Budgetcard-V3.jsx b/src/components/learner-credit-management/Budgetcard-V3.jsx
index 97c275b4e7..5f981acc9b 100644
--- a/src/components/learner-credit-management/Budgetcard-V3.jsx
+++ b/src/components/learner-credit-management/Budgetcard-V3.jsx
@@ -1,99 +1,103 @@
+/* eslint-disable */
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import dayjs from 'dayjs';
import {
- Card,
- Button,
- Stack,
- Row,
- Col,
+ Card,
+ Button,
+ Stack,
+ Row,
+ Col,
} from '@edx/paragon';
-import { ROUTE_NAMES } from '../EnterpriseApp/data/constants';
+import { BUDGET_STATUSES, ROUTE_NAMES } from '../EnterpriseApp/data/constants';
+import { getBudgetStatus } from './data/utils';
const SubBudgetCard = ({
- id,
- start,
- end,
- available,
- spent,
- enterpriseSlug,
+ id,
+ start,
+ end,
+ available,
+ spent,
+ displayName,
+ enterpriseSlug,
}) => {
- const formattedStartDate = dayjs(start).format('MMMM D, YYYY');
- const formattedExpirationDate = dayjs(end).format('MMMM D, YYYY');
+ const formattedStartDate = dayjs(start).format('MMMM D, YYYY');
+ const formattedExpirationDate = dayjs(end).format('MMMM D, YYYY');
+ const budgetStatus = getBudgetStatus(start, end);
- const renderActions = (id) => (
-
- );
-
- const renderCardHeader = (budgetType, id) => {
- const subtitle = (
-
-
- {formattedStartDate} - {formattedExpirationDate}
-
-
+ const renderActions = (id) => (
+
);
- return (
-
- {renderActions(id)}
-
+ const renderCardHeader = (budgetType, id) => {
+ const subtitle = (
+
+
+ {formattedStartDate} - {formattedExpirationDate}
+
+
+ );
+
+ return (
+
+ {budgetStatus !== BUDGET_STATUSES.upcoming && renderActions(id)}
+
)}
- />
- );
- };
+ />
+ );
+ };
- const renderCardSection = (available, spent) => (
-
-
-
- Available
- {available}
-
-
- Spent
- {spent}
-
-
-
- );
+ const renderCardSection = (available, spent) => (
+
+
+
+ Available
+ {available}
+
+
+ Spent
+ {spent}
+
+
+
+ );
- return (
-
-
-
- {renderCardHeader('Overview', id)}
- {renderCardSection(available, spent)}
-
-
-
- );
+ return (
+
+
+
+ {renderCardHeader(displayName || 'Overview', id)}
+ {budgetStatus !== BUDGET_STATUSES.upcoming && renderCardSection(available, spent)}
+
+
+
+ );
};
SubBudgetCard.propTypes = {
- enterpriseSlug: PropTypes.string.isRequired,
- id: PropTypes.string,
- start: PropTypes.string,
- end: PropTypes.string,
- spent: PropTypes.number,
- available: PropTypes.number,
-
+ enterpriseSlug: PropTypes.string.isRequired,
+ id: PropTypes.string,
+ start: PropTypes.string,
+ end: PropTypes.string,
+ spent: PropTypes.number,
+ available: PropTypes.number,
+ displayName: PropTypes.string,
};
export default SubBudgetCard;
diff --git a/src/components/learner-credit-management/MultipleBudgetsPicker.jsx b/src/components/learner-credit-management/MultipleBudgetsPicker.jsx
index 9dc6a227c1..8bedc5dd5e 100644
--- a/src/components/learner-credit-management/MultipleBudgetsPicker.jsx
+++ b/src/components/learner-credit-management/MultipleBudgetsPicker.jsx
@@ -25,6 +25,7 @@ const MultipleBudgetsPicker = ({
enterpriseSlug={enterpriseSlug}
enableLearnerPortal={enableLearnerPortal}
offerType={offer.source}
+ displayName={offer.name}
/>
))}
diff --git a/src/components/learner-credit-management/data/hooks.js b/src/components/learner-credit-management/data/hooks.js
index 5e107e9428..31577f36a7 100644
--- a/src/components/learner-credit-management/data/hooks.js
+++ b/src/components/learner-credit-management/data/hooks.js
@@ -74,7 +74,7 @@ const applyFiltersToOptions = (filters, options) => {
}
};
-export const useOfferRedemptions = (enterpriseUUID, offerId= null, budgetId = null) => {
+export const useOfferRedemptions = (enterpriseUUID, offerId = null, budgetId = null) => {
const shouldTrackFetchEvents = useRef(false);
const [isLoading, setIsLoading] = useState(true);
const [offerRedemptions, setOfferRedemptions] = useState({
diff --git a/src/components/learner-credit-management/data/tests/hooks.test.js b/src/components/learner-credit-management/data/tests/hooks.test.js
index f70f533d4d..5459167674 100644
--- a/src/components/learner-credit-management/data/tests/hooks.test.js
+++ b/src/components/learner-credit-management/data/tests/hooks.test.js
@@ -73,7 +73,7 @@ describe('useOfferSummary', () => {
remainingFunds: 4800,
percentUtilized: 0.04,
offerId: 1,
- budgetsSumary: [],
+ budgetsSummary: [],
offerType: undefined,
};
expect(result.current).toEqual({
diff --git a/src/components/learner-credit-management/data/tests/utils.test.js b/src/components/learner-credit-management/data/tests/utils.test.js
index b24abe27d4..f39d9f33a9 100644
--- a/src/components/learner-credit-management/data/tests/utils.test.js
+++ b/src/components/learner-credit-management/data/tests/utils.test.js
@@ -23,7 +23,7 @@ describe('transformOfferSummary', () => {
remainingFunds: 0.0,
percentUtilized: 1.0,
offerType: EXEC_ED_OFFER_TYPE,
- budgetsSumary: [],
+ budgetsSummary: [],
offerId: undefined,
});
});
@@ -36,7 +36,7 @@ describe('transformOfferSummary', () => {
percentOfOfferSpent: null,
offerType: 'Site',
offerId: '123',
- budgetsSumary: [],
+ budgetsSummary: [],
};
expect(transformOfferSummary(offerSummary)).toEqual({
@@ -48,7 +48,7 @@ describe('transformOfferSummary', () => {
redeemedFundsExecEd: undefined,
redeemedFundsOcm: undefined,
offerId: '123',
- budgetsSumary: [],
+ budgetsSummary: [],
});
});
});
diff --git a/src/components/learner-credit-management/data/utils.js b/src/components/learner-credit-management/data/utils.js
index 1c7a52c459..fc193744c2 100644
--- a/src/components/learner-credit-management/data/utils.js
+++ b/src/components/learner-credit-management/data/utils.js
@@ -3,6 +3,7 @@ import {
LOW_REMAINING_BALANCE_PERCENT_THRESHOLD,
NO_BALANCE_REMAINING_DOLLAR_THRESHOLD,
} from './constants';
+import { BUDGET_STATUSES } from '../../EnterpriseApp/data/constants';
/**
* Transforms offer summary from API for display in the UI, guarding
* against bad data (e.g., accounting for refunds).
@@ -12,23 +13,22 @@ import {
*/
export const transformOfferSummary = (offerSummary) => {
if (!offerSummary) { return null; }
- let budgetsSumary = []
-
+ const budgetsSummary = [];
if (offerSummary?.budgets) {
- const budgets = offerSummary?.budgets
+ const budgets = offerSummary?.budgets;
for (let i = 0; i < budgets.length; i++) {
- let redeemedFunds = budgets[i].amountOfPolicySpent && parseFloat(budgets[i].amountOfPolicySpent);
- let remainingFunds = budgets[i].remainingBalance && parseFloat(budgets[i].remainingBalance);
+ const redeemedFunds = budgets[i].amountOfPolicySpent && parseFloat(budgets[i].amountOfPolicySpent);
+ const remainingFunds = budgets[i].remainingBalance && parseFloat(budgets[i].remainingBalance);
// Create an object with key-value pairs
const budgetEntry = {
redeemedFunds,
remainingFunds,
- ...budgets[i]
+ ...budgets[i],
};
- budgetsSumary.push(budgetEntry);
+ budgetsSummary.push(budgetEntry);
}
}
-
+
const totalFunds = offerSummary.maxDiscount && parseFloat(offerSummary.maxDiscount);
let redeemedFunds = offerSummary.amountOfOfferSpent && parseFloat(offerSummary.amountOfOfferSpent);
let redeemedFundsOcm = offerSummary.amountOfferSpentOcm && parseFloat(offerSummary.amountOfferSpentOcm);
@@ -64,7 +64,7 @@ export const transformOfferSummary = (offerSummary) => {
percentUtilized,
offerType,
offerId,
- budgetsSumary,
+ budgetsSummary,
};
};
@@ -110,7 +110,20 @@ export const getProgressBarVariant = ({ percentUtilized, remainingFunds }) => {
return variant;
};
-// Utility function to check if the ID is a UUID
-export const isUUID = (id) => {
- return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(id);
-}
+// Utility function to check if the ID is a UUID
+export const isUUID = (id) => /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(id);
+
+// Utility function to check the budget status
+export const getBudgetStatus = (startDateStr, endDateStr) => {
+ const currentDate = new Date();
+ const startDate = new Date(startDateStr);
+ const endDate = new Date(endDateStr);
+
+ if (currentDate < startDate) {
+ return BUDGET_STATUSES.upcoming;
+ }
+ if (currentDate >= startDate && currentDate <= endDate) {
+ return BUDGET_STATUSES.active;
+ }
+ return BUDGET_STATUSES.expired;
+};
diff --git a/src/components/learner-credit-management/tests/BudgetCard.test.jsx b/src/components/learner-credit-management/tests/BudgetCard.test.jsx
index dcff64ce3e..bd445a8676 100644
--- a/src/components/learner-credit-management/tests/BudgetCard.test.jsx
+++ b/src/components/learner-credit-management/tests/BudgetCard.test.jsx
@@ -81,7 +81,7 @@ describe('', () => {
remainingFunds: 4800,
percentUtilized: 0.04,
offerType: 'Site',
- budgetsSumary: [
+ budgetsSummary: [
{
id: 123,
start: '2022-01-01',