From 06819d89f7bce2ce606b69338a29b560db1d180d Mon Sep 17 00:00:00 2001 From: Hamzah Ullah Date: Fri, 27 Sep 2024 13:00:20 -0400 Subject: [PATCH] feat: swap start and enroll-by date in variant dropdown (#1321) --- .../NewAssignmentModalDropdown.jsx | 15 ++-- .../data/tests/utils.test.js | 89 ++++++++++++++++++- .../learner-credit-management/data/utils.js | 25 ++++-- 3 files changed, 112 insertions(+), 17 deletions(-) diff --git a/src/components/learner-credit-management/assignment-modal/NewAssignmentModalDropdown.jsx b/src/components/learner-credit-management/assignment-modal/NewAssignmentModalDropdown.jsx index e38c63e386..17cc846863 100644 --- a/src/components/learner-credit-management/assignment-modal/NewAssignmentModalDropdown.jsx +++ b/src/components/learner-credit-management/assignment-modal/NewAssignmentModalDropdown.jsx @@ -3,6 +3,7 @@ import { Dropdown, Stack } from '@openedx/paragon'; import dayjs from 'dayjs'; import PropTypes from 'prop-types'; import { useState } from 'react'; +import classNames from 'classnames'; import { SHORT_MONTH_DATE_FORMAT } from '../data'; const messages = defineMessages({ @@ -40,7 +41,7 @@ const NewAssignmentModalDropdown = ({ if (clickedDropdownItem && clickedDropdownItem.key === courseRun.key) { return null; } - return 'text-muted'; + return true; }; const startLabel = ({ start }) => (dayjs(start).isBefore(dayjs()) ? 'Started' : 'Starts'); return ( @@ -66,13 +67,13 @@ const NewAssignmentModalDropdown = ({ onMouseUp={() => setClickedDropdownItem(null)} > - {intl.formatMessage(messages.enrollBy, { - enrollByDate: dayjs(courseRun.enrollBy).format(SHORT_MONTH_DATE_FORMAT), + {intl.formatMessage(messages.startDate, { + startLabel: startLabel(courseRun), + startDate: dayjs(courseRun.start).format(SHORT_MONTH_DATE_FORMAT), })} - - {intl.formatMessage(messages.startDate, { - startLabel: startLabel(courseRun), - startDate: dayjs(courseRun.start).format(SHORT_MONTH_DATE_FORMAT), + + {intl.formatMessage(messages.enrollBy, { + enrollByDate: dayjs(courseRun.enrollBy).format(SHORT_MONTH_DATE_FORMAT), })} 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 a4c9bf24e8..bcfb62022d 100644 --- a/src/components/learner-credit-management/data/tests/utils.test.js +++ b/src/components/learner-credit-management/data/tests/utils.test.js @@ -1,10 +1,12 @@ import { createIntl } from '@edx/frontend-platform/i18n'; +import dayjs from 'dayjs'; import { - transformSubsidySummary, getBudgetStatus, - orderBudgets, getTranslatedBudgetStatus, getTranslatedBudgetTerm, + orderBudgets, + startAndEnrollBySortLogic, + transformSubsidySummary, } from '../utils'; import { EXEC_ED_OFFER_TYPE } from '../constants'; @@ -258,3 +260,86 @@ describe('getTranslatedBudgetTerm', () => { expect(getTranslatedBudgetTerm(mockintl, term2)).toEqual(''); }); }); + +describe('startAndEnrollBySortLogic', () => { + it.each([ + // Unique start and enroll-by dates + { + sampleData: [ + { + enrollBy: dayjs().add(1, 'day').toISOString(), + start: dayjs().add(3, 'day').toISOString(), + expectedOrder: 2, + }, + { + enrollBy: dayjs().subtract(2, 'day').toISOString(), + start: dayjs().add(1, 'day').toISOString(), + expectedOrder: 1, + }, + { + enrollBy: dayjs().subtract(6, 'day').toISOString(), + start: dayjs().add(12, 'day').toISOString(), + expectedOrder: 4, + }, + { + enrollBy: dayjs().add(3, 'day').toISOString(), + start: dayjs().add(5, 'day').toISOString(), + expectedOrder: 3, + }, + ], + }, + // unique start, same enroll by dates + { + sampleData: [ + { + enrollBy: dayjs().add(1, 'day').toISOString(), + start: dayjs().add(3, 'day').toISOString(), + expectedOrder: 2, + }, + { + enrollBy: dayjs().subtract(1, 'day').toISOString(), + start: dayjs().add(1, 'day').toISOString(), + expectedOrder: 1, + }, + { + enrollBy: dayjs().subtract(6, 'day').toISOString(), + start: dayjs().add(12, 'day').toISOString(), + expectedOrder: 4, + }, + { + enrollBy: dayjs().add(6, 'day').toISOString(), + start: dayjs().add(5, 'day').toISOString(), + expectedOrder: 3, + }, + ], + }, + // unique enroll-by, same start dates + { + sampleData: [ + { + enrollBy: dayjs().add(1, 'day').toISOString(), + start: dayjs().add(1, 'day').toISOString(), + expectedOrder: 1, + }, + { + enrollBy: dayjs().subtract(2, 'day').toISOString(), + start: dayjs().add(1, 'day').toISOString(), + expectedOrder: 2, + }, + { + enrollBy: dayjs().subtract(6, 'day').toISOString(), + start: dayjs().add(12, 'day').toISOString(), + expectedOrder: 4, + }, + { + enrollBy: dayjs().add(3, 'day').toISOString(), + start: dayjs().add(12, 'day').toISOString(), + expectedOrder: 3, + }, + ], + }, + ])('sorts start date and enroll by date as expected', ({ sampleData }) => { + const sortedDates = sampleData.sort(startAndEnrollBySortLogic); + expect(sortedDates).toEqual(sampleData.sort((a, b) => a.expectedOrder - b.expectedOrder)); + }); +}); diff --git a/src/components/learner-credit-management/data/utils.js b/src/components/learner-credit-management/data/utils.js index b7f4129a68..ba72720861 100644 --- a/src/components/learner-credit-management/data/utils.js +++ b/src/components/learner-credit-management/data/utils.js @@ -648,6 +648,21 @@ const isEnrollByDateWithinThreshold = ({ hasEnrollBy, enrollBy, isLateRedemption return dayjs(enrollBy).isAfter(enrollmentEffectiveDate, 'seconds'); }; +export const startAndEnrollBySortLogic = (prev, next) => { + // Label relevant timestamps to milliseconds for the most granular sort + const prevEnrollByDateTimestamp = dayjs(prev.enrollBy).valueOf(); + const nextEnrollByDateTimestamp = dayjs(next.enrollBy).valueOf(); + const prevStartDateTimestamp = dayjs(prev.start).valueOf(); + const nextStartDateTimestamp = dayjs(next.start).valueOf(); + + // When start dates are equivalent, compare enrollBy dates. + if (dayjs(prev.start).isSame(next.start, 'day')) { + return prevEnrollByDateTimestamp - nextEnrollByDateTimestamp; + } + // Otherwise, compare start dates + return prevStartDateTimestamp - nextStartDateTimestamp; +}; + /** * Filters assignable course runs based on the following criteria: * - If the start date or enrollStart date (min date) is before the subsidy expiration - 14 day threshold @@ -734,12 +749,6 @@ export const getAssignableCourseRuns = ({ courseRuns, subsidyExpirationDatetime, enrollBy: getNormalizedEnrollByDate(courseRun.enrollBy), }; }); - // Sorts by the enrollBy date. If enrollBy is equivalent, sort by start. - const sortedAssignableCourseRuns = assignableCourseRuns.sort((a, b) => { - if (a.enrollBy === b.enrollBy) { - return dayjs(a.start).unix() - dayjs(b.start).unix(); - } - return a.enrollBy - b.enrollBy; - }); - return sortedAssignableCourseRuns; + // Sorts by the enrollBy date. If enrollBy is equivalent, sort by start + return assignableCourseRuns.sort(startAndEnrollBySortLogic); };