diff --git a/src/components/learner-credit-management/MultipleBudgetsPage.jsx b/src/components/learner-credit-management/MultipleBudgetsPage.jsx
index 95a34f6483..7705ef3b1a 100644
--- a/src/components/learner-credit-management/MultipleBudgetsPage.jsx
+++ b/src/components/learner-credit-management/MultipleBudgetsPage.jsx
@@ -12,6 +12,7 @@ import {
import { connect } from 'react-redux';
import { Helmet } from 'react-helmet';
+import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import Hero from '../Hero';
import MultipleBudgetsPicker from './MultipleBudgetsPicker';
import { EnterpriseSubsidiesContext } from '../EnterpriseSubsidiesContext';
@@ -19,8 +20,6 @@ import { EnterpriseSubsidiesContext } from '../EnterpriseSubsidiesContext';
import { configuration } from '../../config';
import { useEnterpriseBudgets } from '../EnterpriseSubsidiesContext/data/hooks';
-const PAGE_TITLE = 'Learner Credit Management';
-
const MultipleBudgetsPage = ({
enterpriseUUID,
enterpriseSlug,
@@ -28,6 +27,12 @@ const MultipleBudgetsPage = ({
enterpriseFeatures,
enablePortalLearnerCreditManagementScreen,
}) => {
+ const intl = useIntl();
+ const PAGE_TITLE = intl.formatMessage({
+ id: 'lcm.page.title',
+ defaultMessage: 'Learner Credit Management',
+ description: 'Title for the Learner Credit Management page',
+ });
const { isLoading } = useContext(EnterpriseSubsidiesContext);
const { data: budgetsOverview } = useEnterpriseBudgets({
enterpriseId: enterpriseUUID,
@@ -43,7 +48,13 @@ const MultipleBudgetsPage = ({
<>
- Loading budgets...
+
+
+
>
);
}
@@ -57,17 +68,30 @@ const MultipleBudgetsPage = ({
- No budgets for your organization
+
+
+
- We were unable to find any budgets for your organization. Please contact
- Customer Support if you have questions.
+
- Contact support
+
diff --git a/src/components/learner-credit-management/MultipleBudgetsPicker.jsx b/src/components/learner-credit-management/MultipleBudgetsPicker.jsx
index 0af1fe06a5..8816cddd3b 100644
--- a/src/components/learner-credit-management/MultipleBudgetsPicker.jsx
+++ b/src/components/learner-credit-management/MultipleBudgetsPicker.jsx
@@ -10,8 +10,9 @@ import {
} from '@edx/paragon';
import groupBy from 'lodash/groupBy';
+import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import BudgetCard from './BudgetCard';
-import { getBudgetStatus, orderBudgets } from './data/utils';
+import { getBudgetStatus, getTranslatedBudgetStatus, orderBudgets } from './data/utils';
const MultipleBudgetsPicker = ({
budgets,
@@ -20,7 +21,7 @@ const MultipleBudgetsPicker = ({
enableLearnerPortal,
}) => {
const orderedBudgets = orderBudgets(budgets);
-
+ const intl = useIntl();
const rows = useMemo(
() => orderedBudgets.map(budget => {
const budgetLabel = getBudgetStatus({
@@ -49,7 +50,7 @@ const MultipleBudgetsPicker = ({
));
const budgetLabelsByStatus = groupBy(budgetLabels, 'status');
const reducedChoices = Object.keys(budgetLabelsByStatus).map(budgetLabel => ({
- name: budgetLabel,
+ name: getTranslatedBudgetStatus(intl, budgetLabel),
number: budgetLabelsByStatus[budgetLabel].length,
value: budgetLabel,
}));
@@ -57,7 +58,15 @@ const MultipleBudgetsPicker = ({
return (
<>
- Budgets
+
+
+
+
+
(
);
const renderCardHeader = (budgetType, budgetId) => {
const subtitle = (
- {budgetLabel.status}
+ {getTranslatedBudgetStatus(intl, budgetLabel.status)}
{(budgetLabel.term && formattedDate) && (
- {budgetLabel.term} {formattedDate}
+ {getTranslatedBudgetTerm(intl, budgetLabel.term)} {formattedDate}
)}
@@ -119,26 +134,52 @@ const BaseSubBudgetCard = ({
const renderCardSection = () => (
Balance}
+ title={(
+
+
+
+)}
muted
>
- Available
+
+
+
{isFetchingBudgets ? : formatPrice(available)}
{isAssignable && (
- Assigned
+
+
+
{isFetchingBudgets ? : formatPrice(pending)}
)}
- Spent
+
+
+
{isFetchingBudgets ? : formatPrice(spent)}
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 4ea9294d6e..7420be9d58 100644
--- a/src/components/learner-credit-management/data/tests/utils.test.js
+++ b/src/components/learner-credit-management/data/tests/utils.test.js
@@ -2,6 +2,8 @@ import {
transformSubsidySummary,
getBudgetStatus,
orderBudgets,
+ getTranslatedBudgetStatus,
+ getTranslatedBudgetTerm,
} from '../utils';
import { EXEC_ED_OFFER_TYPE } from '../constants';
@@ -206,3 +208,47 @@ describe('orderBudgets', () => {
expect(sortedBudgets.map((budget) => budget.name)).toEqual(['Budget A', 'Budget B']);
});
});
+
+describe('getTranslatedBudgetStatus', () => {
+ it('should translate the budget status correctly', () => {
+ const intl = { formatMessage: jest.fn() };
+ const status = 'Retired';
+
+ getTranslatedBudgetStatus(intl, status);
+
+ expect(intl.formatMessage).toHaveBeenCalledWith({
+ id: 'lcm.budgets.budget.card.status.retired',
+ defaultMessage: 'Retired',
+ description: 'Status for a retired budget',
+ });
+ });
+ it('should handle the case for an unknown value', () => {
+ const intl = { formatMessage: jest.fn() };
+ const status = 'unknown';
+
+ expect(getTranslatedBudgetStatus(intl, status)).toEqual('');
+ });
+});
+
+describe('getTranslatedBudgetTerm', () => {
+ it('should translate the budget term correctly', () => {
+ const intl = { formatMessage: jest.fn() };
+ const term = 'Expiring';
+
+ getTranslatedBudgetTerm(intl, term);
+
+ expect(intl.formatMessage).toHaveBeenCalledWith({
+ id: 'lcm.budgets.budget.card.term.expiring',
+ defaultMessage: 'Expiring',
+ description: 'Term for when a budget is expiring',
+ });
+ });
+ it('should handle the case when unknown or null term', () => {
+ const intl = { formatMessage: jest.fn() };
+ const term1 = 'unknown';
+ const term2 = null;
+
+ expect(getTranslatedBudgetTerm(intl, term1)).toEqual('');
+ expect(getTranslatedBudgetTerm(intl, term2)).toEqual('');
+ });
+});
diff --git a/src/components/learner-credit-management/data/utils.js b/src/components/learner-credit-management/data/utils.js
index 55071c12a5..2fc358df5a 100644
--- a/src/components/learner-credit-management/data/utils.js
+++ b/src/components/learner-credit-management/data/utils.js
@@ -455,3 +455,84 @@ export const transformSelectedRows = (selectedFlatRows) => {
totalSelectedRows,
};
};
+
+/**
+ * Translates the budget status using the provided `intl` object.
+ *
+ * @param {object} intl - The `intl` object used for translation.
+ * @param {string} status - The status of the budget.
+ * @returns {string} The translated budget status.
+ */
+export const getTranslatedBudgetStatus = (intl, status) => {
+ switch (status) {
+ case BUDGET_STATUSES.active:
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.status.active',
+ defaultMessage: 'Active',
+ description: 'Status for an active budget',
+ });
+ case BUDGET_STATUSES.expiring:
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.status.expiring',
+ defaultMessage: 'Expiring',
+ description: 'Status for an expiring budget',
+ });
+ case BUDGET_STATUSES.expired:
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.status.expired',
+ defaultMessage: 'Expired',
+ description: 'Status for an expired budget',
+ });
+ case BUDGET_STATUSES.retired:
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.status.retired',
+ defaultMessage: 'Retired',
+ description: 'Status for a retired budget',
+ });
+ case BUDGET_STATUSES.scheduled:
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.status.scheduled',
+ defaultMessage: 'Scheduled',
+ description: 'Status for a scheduled budget',
+ });
+ default:
+ return '';
+ }
+};
+
+/**
+ * Translates the budget term using the provided `intl` object.
+ * @param {object} intl - The `intl` object used for translation.
+ * @param {string} term - The term of the budget.
+ * @returns {string} The translated budget term.
+ */
+export const getTranslatedBudgetTerm = (intl, term) => {
+ switch (term) {
+ case 'Starts':
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.term.starts',
+ defaultMessage: 'Starts',
+ description: 'Term for when a budget starts',
+ });
+ case 'Expires':
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.term.expires',
+ defaultMessage: 'Expires',
+ description: 'Term for when a budget expires',
+ });
+ case 'Expiring':
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.term.expiring',
+ defaultMessage: 'Expiring',
+ description: 'Term for when a budget is expiring',
+ });
+ case 'Expired':
+ return intl.formatMessage({
+ id: 'lcm.budgets.budget.card.term.expired',
+ defaultMessage: 'Expired',
+ description: 'Term for when a budget has expired',
+ });
+ default:
+ return '';
+ }
+};