richie-education 2.28.2-dev39 → 2.28.2-dev58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/.eslintrc.json +11 -2
  2. package/i18n/locales/ar-SA.json +209 -125
  3. package/i18n/locales/es-ES.json +210 -126
  4. package/i18n/locales/fa-IR.json +209 -125
  5. package/i18n/locales/fr-CA.json +209 -125
  6. package/i18n/locales/fr-FR.json +209 -125
  7. package/i18n/locales/ko-KR.json +209 -125
  8. package/i18n/locales/pt-PT.json +212 -128
  9. package/i18n/locales/ru-RU.json +209 -125
  10. package/i18n/locales/vi-VN.json +209 -125
  11. package/js/api/joanie.ts +14 -17
  12. package/js/api/lms/dummy.ts +1 -12
  13. package/js/components/ContractFrame/AbstractContractFrame.spec.tsx +16 -9
  14. package/js/components/ContractFrame/AbstractContractFrame.tsx +32 -25
  15. package/js/components/ContractFrame/LearnerContractFrame.tsx +2 -2
  16. package/js/components/ContractFrame/_styles.scss +6 -14
  17. package/js/components/CreditCardSelector/index.spec.tsx +7 -7
  18. package/js/components/CreditCardSelector/index.tsx +2 -2
  19. package/js/components/DownloadContractButton/index.spec.tsx +1 -1
  20. package/js/components/OpenEdxFullNameForm/index.spec.tsx +229 -0
  21. package/js/components/OpenEdxFullNameForm/index.tsx +7 -7
  22. package/js/components/PaymentInterfaces/LyraPopIn.tsx +2 -2
  23. package/js/components/PaymentInterfaces/PayplugLightbox.tsx +1 -1
  24. package/js/components/PaymentInterfaces/__mocks__/index.tsx +1 -4
  25. package/js/components/PaymentInterfaces/types.ts +5 -2
  26. package/js/components/PurchaseButton/index.spec.tsx +69 -37
  27. package/js/components/SaleTunnel/AddressSelector/index.spec.tsx +2 -1
  28. package/js/components/SaleTunnel/CertificateSaleTunnel/index.tsx +2 -2
  29. package/js/components/SaleTunnel/CredentialSaleTunnel/index.tsx +6 -10
  30. package/js/components/SaleTunnel/GenericSaleTunnel.tsx +75 -41
  31. package/js/components/SaleTunnel/SaleTunnelInformation/index.tsx +0 -30
  32. package/js/components/SaleTunnel/SaleTunnelSavePaymentMethod/_styles.scss +12 -0
  33. package/js/components/SaleTunnel/SaleTunnelSavePaymentMethod/index.tsx +160 -0
  34. package/js/components/SaleTunnel/SaleTunnelSuccess/index.tsx +15 -29
  35. package/js/components/SaleTunnel/Sponsors/SaleTunnelSponsors.tsx +5 -0
  36. package/js/components/SaleTunnel/SubscriptionButton/_styles.scss +7 -0
  37. package/js/components/SaleTunnel/SubscriptionButton/index.tsx +202 -0
  38. package/js/components/SaleTunnel/_styles.scss +10 -1
  39. package/js/components/SaleTunnel/hooks/useTerms.tsx +0 -77
  40. package/js/components/SaleTunnel/index.credential.spec.tsx +12 -21
  41. package/js/components/SaleTunnel/index.full-process.spec.tsx +110 -48
  42. package/js/components/SaleTunnel/index.spec.tsx +330 -779
  43. package/js/components/SignContractButton/index.omniscientOrders.spec.tsx +16 -11
  44. package/js/components/SignContractButton/index.spec.tsx +16 -20
  45. package/js/components/SignContractButton/index.tsx +3 -1
  46. package/js/hooks/useCreditCards/index.spec.tsx +70 -6
  47. package/js/hooks/useCreditCards/index.ts +49 -11
  48. package/js/hooks/useOrders/index.spec.tsx +322 -0
  49. package/js/hooks/{useOrders.ts → useOrders/index.ts} +40 -14
  50. package/js/hooks/useProductOrder/index.spec.tsx +77 -60
  51. package/js/hooks/useProductOrder/index.tsx +2 -2
  52. package/js/hooks/useResources/useResourcesRoot.ts +1 -0
  53. package/js/pages/DashboardCreditCardsManagement/CreditCardBrandLogo.spec.tsx +1 -1
  54. package/js/pages/DashboardCreditCardsManagement/CreditCardBrandLogo.tsx +4 -2
  55. package/js/pages/TeacherDashboardContractsLayout/components/ContractActionsBar/index.spec.tsx +8 -5
  56. package/js/pages/TeacherDashboardContractsLayout/components/SignOrganizationContractButton/index.spec.tsx +8 -9
  57. package/js/pages/TeacherDashboardCourseLearnersLayout/components/CourseLearnerDataGrid/index.spec.tsx +1 -1
  58. package/js/pages/TeacherDashboardCourseLearnersLayout/components/CourseLearnerDataGrid/index.tsx +1 -6
  59. package/js/settings/settings.test.ts +11 -2
  60. package/js/translations/ar-SA.json +1 -1
  61. package/js/translations/es-ES.json +1 -1
  62. package/js/translations/fa-IR.json +1 -1
  63. package/js/translations/fr-CA.json +1 -1
  64. package/js/translations/fr-FR.json +1 -1
  65. package/js/translations/ko-KR.json +1 -1
  66. package/js/translations/pt-PT.json +1 -1
  67. package/js/translations/ru-RU.json +1 -1
  68. package/js/translations/vi-VN.json +1 -1
  69. package/js/types/Joanie.ts +49 -34
  70. package/js/utils/OrderHelper/index.ts +38 -42
  71. package/js/utils/search/getSuggestionsSection/index.spec.ts +3 -2
  72. package/js/utils/test/factories/joanie.ts +36 -51
  73. package/js/widgets/Dashboard/components/DashboardItem/CourseEnrolling/index.tsx +8 -18
  74. package/js/widgets/Dashboard/components/DashboardItem/Enrollment/ProductCertificateFooter/index.spec.tsx +26 -32
  75. package/js/widgets/Dashboard/components/DashboardItem/Enrollment/ProductCertificateFooter/index.tsx +11 -6
  76. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrder.spec.tsx +7 -6
  77. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrder.tsx +9 -10
  78. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderContract.spec.tsx +3 -1
  79. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderContract.useUnionResource.cache.spec.tsx +6 -7
  80. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentDetailsModal/index.tsx +28 -8
  81. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentRetryModal/index.tsx +4 -6
  82. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.spec.tsx +18 -71
  83. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.tsx +34 -35
  84. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateMessage/index.tsx +27 -24
  85. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.spec.tsx +18 -73
  86. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.tsx +32 -16
  87. package/js/widgets/Dashboard/components/DashboardOrderLoader/index.tsx +3 -11
  88. package/js/widgets/Dashboard/components/Signature/SignatureDummy.tsx +25 -3
  89. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCourseRuns/EnrollableCourseRunList.tsx +2 -6
  90. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCourseRuns/index.spec.tsx +7 -14
  91. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseRunItem/index.spec.tsx +7 -5
  92. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseRunItem/index.tsx +5 -7
  93. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.spec.tsx +242 -332
  94. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.stories.tsx +12 -13
  95. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.tsx +10 -21
  96. package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/index.joanie.spec.tsx +2 -2
  97. package/package.json +27 -27
  98. package/scss/components/_index.scss +2 -1
  99. package/js/components/PaymentButton/_styles.scss +0 -27
  100. package/js/components/SaleTunnel/GenericPaymentButton/index.tsx +0 -333
  101. package/js/components/SaleTunnel/SaleTunnelNotValidated/index.tsx +0 -70
  102. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/ProductSignatureHeader/index.tsx +0 -41
@@ -4,6 +4,7 @@ import { defineMessages, FormattedMessage } from 'react-intl';
4
4
  import { SignatureProps } from 'components/ContractFrame';
5
5
  import { DummyContractPlaceholder } from 'widgets/Dashboard/components/Signature/DummyContractPlaceholder';
6
6
  import { CONTRACT_SETTINGS } from 'settings';
7
+ import { getAPIEndpoint } from 'api/joanie';
7
8
 
8
9
  const messages = defineMessages({
9
10
  button: {
@@ -23,12 +24,31 @@ enum SignatureDummySteps {
23
24
  SIGNING_LOADING,
24
25
  }
25
26
 
26
- export const SignatureDummy = ({ onDone }: SignatureProps) => {
27
+ export const SignatureDummy = ({ invitationLink, onDone }: SignatureProps) => {
27
28
  const [step, setStep] = useState(SignatureDummySteps.SIGNING);
28
29
 
30
+ const baseUrl = getAPIEndpoint();
31
+ // eslint-disable-next-line compat/compat
32
+ const link = new URL(invitationLink);
33
+ const reference = link.searchParams.get('reference');
34
+ const event = link.searchParams.get('eventTarget');
35
+ const sendSignatureNotification = () => {
36
+ fetch(`${baseUrl}/signature/notifications/`, {
37
+ method: 'POST',
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ },
41
+ body: JSON.stringify({
42
+ event_type: event,
43
+ reference,
44
+ }),
45
+ });
46
+ };
47
+
29
48
  const sign = () => {
30
49
  setStep(SignatureDummySteps.SIGNING_LOADING);
31
50
  setTimeout(() => {
51
+ sendSignatureNotification();
32
52
  onDone();
33
53
  }, CONTRACT_SETTINGS.dummySignatureSignTimeout);
34
54
  };
@@ -44,11 +64,13 @@ export const SignatureDummy = ({ onDone }: SignatureProps) => {
44
64
  </div>
45
65
  )}
46
66
  {step === SignatureDummySteps.SIGNING_LOADING && (
47
- <div className="ContractFrame__loading-container">
67
+ <div className="ContractFrame__container">
48
68
  <h3 className="ContractFrame__caption">
49
69
  <FormattedMessage {...messages.signing} />
50
70
  </h3>
51
- <Loader />
71
+ <div className="ContractFrame__footer">
72
+ <Loader />
73
+ </div>
52
74
  </div>
53
75
  )}
54
76
  </>
@@ -11,7 +11,6 @@ import useDateFormat from 'hooks/useDateFormat';
11
11
  import { IntlHelper } from 'utils/IntlHelper';
12
12
  import WebAnalyticsAPIHandler from 'api/web-analytics';
13
13
  import EnrollmentDate from 'components/EnrollmentDate';
14
- import { Product } from 'types/Joanie';
15
14
  import { OrderHelper } from 'utils/OrderHelper';
16
15
  import { messages as sharedMessages } from '../CourseRunItem';
17
16
  import CourseRunSection, { messages as sectionMessages } from './CourseRunSection';
@@ -53,16 +52,13 @@ const messages = defineMessages({
53
52
  interface Props {
54
53
  courseRuns: Joanie.CourseRun[];
55
54
  order: Joanie.Order;
56
- product: Product;
57
55
  }
58
56
 
59
- const EnrollableCourseRunList = ({ courseRuns, order, product }: Props) => {
57
+ const EnrollableCourseRunList = ({ courseRuns, order }: Props) => {
60
58
  const intl = useIntl();
61
59
  const formatDate = useDateFormat();
62
60
  const formRef = useRef<HTMLFormElement>(null);
63
- const needsSignature = order
64
- ? OrderHelper.orderNeedsSignature(order, product.contract_definition)
65
- : false;
61
+ const needsSignature = order ? OrderHelper.orderNeedsSignature(order) : false;
66
62
 
67
63
  const [selectedCourseRun, setSelectedCourseRun] = useState<Maybe<Joanie.CourseRun>>();
68
64
  const [submitted, setSubmitted] = useState(false);
@@ -11,7 +11,7 @@ import {
11
11
  CredentialOrderFactory,
12
12
  ProductFactory,
13
13
  } from 'utils/test/factories/joanie';
14
- import type { CourseLight, CourseRun, Enrollment } from 'types/Joanie';
14
+ import { CourseLight, CourseRun, Enrollment, OrderState } from 'types/Joanie';
15
15
  import { Deferred } from 'utils/test/deferred';
16
16
  import { CourseStateTextEnum, Priority } from 'types';
17
17
  import { IntlHelper } from 'utils/IntlHelper';
@@ -114,10 +114,9 @@ describe('CourseProductCourseRuns', () => {
114
114
 
115
115
  it('renders a warning message when no course runs are provided', () => {
116
116
  const order = CredentialOrderFactory().one();
117
- const product = ProductFactory().one();
118
117
 
119
118
  fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
120
- render(<EnrollableCourseRunList courseRuns={[]} order={order} product={product} />, {
119
+ render(<EnrollableCourseRunList courseRuns={[]} order={order} />, {
121
120
  wrapper: BaseJoanieAppWrapper,
122
121
  });
123
122
 
@@ -127,12 +126,9 @@ describe('CourseProductCourseRuns', () => {
127
126
  it('renders a list of course runs with a call to action to enroll', async () => {
128
127
  const courseRuns: CourseRun[] = CourseRunFactory().many(2);
129
128
  const order = CredentialOrderFactory().one();
130
- const product = ProductFactory({
131
- contract_definition: undefined,
132
- }).one();
133
129
 
134
130
  fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
135
- render(<EnrollableCourseRunList courseRuns={courseRuns} order={order} product={product} />, {
131
+ render(<EnrollableCourseRunList courseRuns={courseRuns} order={order} />, {
136
132
  wrapper: BaseJoanieAppWrapper,
137
133
  });
138
134
 
@@ -247,7 +243,7 @@ describe('CourseProductCourseRuns', () => {
247
243
  fetchMock.get(`https://joanie.endpoint/api/v1.0/courses/${course.code}/`, HttpStatusCode.OK);
248
244
  fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
249
245
 
250
- render(<EnrollableCourseRunList courseRuns={courseRuns} order={order} product={product} />, {
246
+ render(<EnrollableCourseRunList courseRuns={courseRuns} order={order} />, {
251
247
  wrapper: BaseJoanieAppWrapper,
252
248
  });
253
249
 
@@ -355,12 +351,10 @@ describe('CourseProductCourseRuns', () => {
355
351
  text: CourseStateTextEnum.STARTING_ON,
356
352
  },
357
353
  }).one();
358
- const product = ProductFactory().one();
359
- product.contract_definition = undefined;
360
354
  const order = CredentialOrderFactory().one();
361
355
 
362
356
  fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
363
- render(<EnrollableCourseRunList courseRuns={[courseRun]} order={order} product={product} />, {
357
+ render(<EnrollableCourseRunList courseRuns={[courseRun]} order={order} />, {
364
358
  wrapper: BaseJoanieAppWrapper,
365
359
  });
366
360
 
@@ -438,11 +432,10 @@ describe('CourseProductCourseRuns', () => {
438
432
  text: CourseStateTextEnum.STARTING_ON,
439
433
  },
440
434
  }).one();
441
- const product = ProductFactory().one();
442
- const order = CredentialOrderFactory().one();
435
+ const order = CredentialOrderFactory({ state: OrderState.TO_SIGN }).one();
443
436
 
444
437
  fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
445
- render(<EnrollableCourseRunList courseRuns={[courseRun]} order={order} product={product} />, {
438
+ render(<EnrollableCourseRunList courseRuns={[courseRun]} order={order} />, {
446
439
  wrapper: BaseJoanieAppWrapper,
447
440
  });
448
441
 
@@ -1,6 +1,6 @@
1
1
  import { faker } from '@faker-js/faker';
2
2
  import { screen, getByText } from '@testing-library/react';
3
- import { CredentialOrderFactory, ProductFactory } from 'utils/test/factories/joanie';
3
+ import { CredentialOrderFactory } from 'utils/test/factories/joanie';
4
4
  import type { CourseRun, CredentialOrder } from 'types/Joanie';
5
5
  import { OrderState } from 'types/Joanie';
6
6
  import { render } from 'utils/test/render';
@@ -15,14 +15,16 @@ jest.mock('../CourseProductCourseRuns', () => ({
15
15
  describe('CourseRunItem', () => {
16
16
  it('does not allow user which purchase the product to enroll to course if order state is not validated', async () => {
17
17
  const order: CredentialOrder = CredentialOrderFactory({
18
- state: faker.helpers.arrayElement([OrderState.CANCELED, OrderState.PENDING]),
18
+ state: faker.helpers.arrayElement([
19
+ OrderState.CANCELED,
20
+ OrderState.PENDING,
21
+ OrderState.NO_PAYMENT,
22
+ ]),
19
23
  }).one();
20
- const product = ProductFactory().one();
21
- product.contract_definition = undefined;
22
24
 
23
25
  const targetCourse = order.target_courses[0];
24
26
 
25
- render(<CourseRunItem targetCourse={targetCourse} order={order} product={product} />, {
27
+ render(<CourseRunItem targetCourse={targetCourse} order={order} />, {
26
28
  wrapper: null,
27
29
  });
28
30
 
@@ -2,8 +2,8 @@ import { useEffect, useRef } from 'react';
2
2
  import { defineMessages } from 'react-intl';
3
3
  import { Priority } from 'types';
4
4
  import type * as Joanie from 'types/Joanie';
5
- import { OrderState, Product } from 'types/Joanie';
6
5
  import { CoursesHelper } from 'utils/CoursesHelper';
6
+ import { OrderHelper } from 'utils/OrderHelper';
7
7
  import {
8
8
  CourseRunList,
9
9
  EnrollableCourseRunList,
@@ -26,13 +26,12 @@ other {Languages:}
26
26
  interface Props {
27
27
  targetCourse: Joanie.TargetCourse;
28
28
  order?: Joanie.CredentialOrder;
29
- product: Product;
30
29
  }
31
30
 
32
- const CourseRunItem = ({ targetCourse, order, product }: Props) => {
33
- const isEnrollable = order?.state === OrderState.VALIDATED;
31
+ const CourseRunItem = ({ targetCourse, order }: Props) => {
32
+ const isEnrollable = OrderHelper.allowEnrollment(order);
34
33
  const courseRunEnrollment = isEnrollable
35
- ? CoursesHelper.findActiveCourseEnrollmentInOrder(targetCourse, order)
34
+ ? CoursesHelper.findActiveCourseEnrollmentInOrder(targetCourse, order!)
36
35
  : undefined;
37
36
  const isEnrolled = !!courseRunEnrollment?.is_active;
38
37
 
@@ -92,8 +91,7 @@ const CourseRunItem = ({ targetCourse, order, product }: Props) => {
92
91
  {isEnrollable && !isEnrolled && (
93
92
  <EnrollableCourseRunList
94
93
  courseRuns={targetCourse.course_runs.filter(isOpenedCourseRun)}
95
- order={order}
96
- product={product}
94
+ order={order!}
97
95
  />
98
96
  )}
99
97
  {isEnrollable && isEnrolled && <EnrolledCourseRun enrollment={courseRunEnrollment} />}