richie-education 3.3.2-dev6 → 3.4.1-dev3

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 (153) hide show
  1. package/.eslintrc.json +0 -3
  2. package/.storybook/main.js +11 -12
  3. package/.storybook/preview.tsx +49 -24
  4. package/cunningham.cjs +31 -0
  5. package/i18n/compile-translations.js +12 -10
  6. package/i18n/locales/ar-SA.json +20 -0
  7. package/i18n/locales/es-ES.json +20 -0
  8. package/i18n/locales/fa-IR.json +20 -0
  9. package/i18n/locales/fr-CA.json +20 -0
  10. package/i18n/locales/fr-FR.json +21 -1
  11. package/i18n/locales/ko-KR.json +20 -0
  12. package/i18n/locales/pt-PT.json +42 -22
  13. package/i18n/locales/ru-RU.json +20 -0
  14. package/i18n/locales/vi-VN.json +20 -0
  15. package/jest.config.js +5 -0
  16. package/js/components/AddressesManagement/AddressForm/index.stories.tsx +1 -1
  17. package/js/components/AddressesManagement/AddressForm/index.tsx +4 -3
  18. package/js/components/AddressesManagement/index.stories.tsx +1 -1
  19. package/js/components/AddressesManagement/index.tsx +5 -3
  20. package/js/components/Badge/index.stories.tsx +1 -1
  21. package/js/components/Badge/index.tsx +1 -1
  22. package/js/components/Banner/index.stories.tsx +1 -1
  23. package/js/components/CourseGlimpse/index.stories.tsx +1 -1
  24. package/js/components/CourseGlimpseList/index.stories.tsx +1 -1
  25. package/js/components/CreditCardSelector/_styles.scss +2 -2
  26. package/js/components/CreditCardSelector/index.tsx +11 -3
  27. package/js/components/DownloadCertificateButton/index.tsx +2 -1
  28. package/js/components/DownloadContractButton/index.tsx +7 -1
  29. package/js/components/Form/Form/index.tsx +4 -2
  30. package/js/components/Icon/index.stories.tsx +2 -1
  31. package/js/components/Modal/index.stories.tsx +1 -1
  32. package/js/components/Modal/index.tsx +2 -1
  33. package/js/components/OpenEdxFullNameForm/index.stories.tsx +1 -1
  34. package/js/components/OpenEdxFullNameForm/index.tsx +2 -2
  35. package/js/components/PaymentScheduleGrid/_styles.scss +2 -2
  36. package/js/components/PurchaseButton/index.stories.tsx +1 -1
  37. package/js/components/RegisteredAddress/index.stories.tsx +1 -1
  38. package/js/components/RegisteredAddress/index.tsx +4 -2
  39. package/js/components/SaleTunnel/AddressSelector/CreateAddressFormModal.tsx +1 -1
  40. package/js/components/SaleTunnel/AddressSelector/EditAddressFormModal.tsx +1 -1
  41. package/js/components/SaleTunnel/AddressSelector/index.tsx +4 -2
  42. package/js/components/SaleTunnel/SaleTunnelInformation/SaleTunnelInformationGroup.tsx +4 -3
  43. package/js/components/SaleTunnel/SaleTunnelInformation/SaleTunnelInformationSingular.tsx +27 -5
  44. package/js/components/SaleTunnel/SubscriptionButton/index.tsx +7 -5
  45. package/js/components/SaleTunnel/_styles.scss +9 -8
  46. package/js/components/SaleTunnel/index.credential.spec.tsx +50 -1
  47. package/js/components/SaleTunnel/index.stories.tsx +1 -1
  48. package/js/components/Spinner/index.stories.tsx +1 -1
  49. package/js/components/Tabs/index.stories.tsx +1 -1
  50. package/js/components/Tabs/index.tsx +2 -1
  51. package/js/components/TeacherDashboardCourseList/index.tsx +2 -1
  52. package/js/hooks/useAddressesManagement.tsx +4 -2
  53. package/js/hooks/useCreditCards/index.ts +6 -4
  54. package/js/hooks/useDashboardAddressForm.tsx +3 -3
  55. package/js/hooks/useMatchMedia.ts +1 -1
  56. package/js/hooks/useResources/useResourcesRoot.ts +1 -1
  57. package/js/hooks/useUnionResource/index.ts +6 -2
  58. package/js/hooks/useUnionResource/utils/fetchEntity.ts +1 -0
  59. package/js/pages/DashboardAddressesManagement/DashboardAddressBox.tsx +3 -3
  60. package/js/pages/DashboardAddressesManagement/DashboardCreateAddress.stories.tsx +1 -1
  61. package/js/pages/DashboardAddressesManagement/DashboardCreateAddress.tsx +1 -1
  62. package/js/pages/DashboardAddressesManagement/DashboardEditAddress.stories.tsx +1 -1
  63. package/js/pages/DashboardAddressesManagement/DashboardEditAddress.tsx +3 -2
  64. package/js/pages/DashboardAddressesManagement/index.stories.tsx +1 -1
  65. package/js/pages/DashboardAddressesManagement/index.tsx +1 -1
  66. package/js/pages/DashboardCourses/index.tsx +2 -1
  67. package/js/pages/DashboardCreditCardsManagement/CreditCardBrandLogo.stories.tsx +1 -1
  68. package/js/pages/DashboardCreditCardsManagement/DashboardCreditCardBox.tsx +3 -3
  69. package/js/pages/DashboardCreditCardsManagement/DashboardEditCreditCard.stories.tsx +1 -1
  70. package/js/pages/DashboardCreditCardsManagement/DashboardEditCreditCard.tsx +3 -2
  71. package/js/pages/DashboardCreditCardsManagement/index.stories.tsx +1 -1
  72. package/js/pages/DashboardOpenEdxProfile/index.stories.tsx +1 -1
  73. package/js/pages/TeacherDashboardContractsLayout/components/BulkDownloadContractButton/index.tsx +4 -2
  74. package/js/pages/TeacherDashboardContractsLayout/components/SignOrganizationContractButton/index.tsx +2 -1
  75. package/js/pages/TeacherDashboardContractsLayout/hooks/useCheckContractArchiveExists/index.spec.tsx +4 -4
  76. package/js/pages/TeacherDashboardContractsLayout/hooks/useDownloadContractArchive/index.spec.tsx +8 -9
  77. package/js/pages/TeacherDashboardContractsLayout/hooks/useDownloadContractArchive/index.tsx +14 -3
  78. package/js/pages/TeacherDashboardCourseLearnersLayout/components/CourseLearnerDataGrid/index.tsx +6 -1
  79. package/js/pages/TeacherDashboardCourseLoader/CourseRunList/utils.tsx +2 -1
  80. package/js/pages/TeacherDashboardOrganizationAgreements/BulkAgreementContractButton.tsx +4 -2
  81. package/js/pages/TeacherDashboardOrganizationAgreements/SignOrganizationAgreementButton.tsx +2 -1
  82. package/js/pages/TeacherDashboardOrganizationQuotes/index.full-process.spec.tsx +2 -2
  83. package/js/pages/TeacherDashboardOrganizationQuotes/index.spec.tsx +1 -1
  84. package/js/pages/TeacherDashboardOrganizationQuotes/index.tsx +3 -2
  85. package/js/translations/ar-SA.json +1 -1
  86. package/js/translations/es-ES.json +1 -1
  87. package/js/translations/fa-IR.json +1 -1
  88. package/js/translations/fr-CA.json +1 -1
  89. package/js/translations/fr-FR.json +1 -1
  90. package/js/translations/ko-KR.json +1 -1
  91. package/js/translations/pt-PT.json +1 -1
  92. package/js/translations/ru-RU.json +1 -1
  93. package/js/translations/vi-VN.json +1 -1
  94. package/js/types/Joanie.ts +1 -1
  95. package/js/utils/ProductHelper/index.spec.ts +1 -1
  96. package/js/utils/StorybookHelper/index.tsx +3 -6
  97. package/js/utils/cunningham-tokens.ts +1111 -142
  98. package/js/utils/errors/handle.spec.ts +3 -3
  99. package/js/utils/react-query/useSessionMutation/index.ts +8 -3
  100. package/js/utils/test/factories/joanie.ts +1 -1
  101. package/js/widgets/Dashboard/components/DashboardAvatar/index.stories.tsx +1 -1
  102. package/js/widgets/Dashboard/components/DashboardBox/index.stories.tsx +13 -5
  103. package/js/widgets/Dashboard/components/DashboardBreadcrumbs/index.stories.tsx +1 -1
  104. package/js/widgets/Dashboard/components/DashboardBreadcrumbs/index.tsx +3 -2
  105. package/js/widgets/Dashboard/components/DashboardCard/index.spec.tsx +13 -2
  106. package/js/widgets/Dashboard/components/DashboardCard/index.stories.tsx +12 -4
  107. package/js/widgets/Dashboard/components/DashboardCard/index.tsx +1 -1
  108. package/js/widgets/Dashboard/components/DashboardItem/BatchOrder/BatchOrderPaymentModal/BatchOrderPaymentManager.tsx +1 -1
  109. package/js/widgets/Dashboard/components/DashboardItem/BatchOrder/BatchOrderPaymentModal/index.tsx +2 -1
  110. package/js/widgets/Dashboard/components/DashboardItem/Certificate/index.stories.tsx +1 -1
  111. package/js/widgets/Dashboard/components/DashboardItem/Contract/index.stories.tsx +1 -1
  112. package/js/widgets/Dashboard/components/DashboardItem/CourseEnrolling/index.stories.tsx +1 -1
  113. package/js/widgets/Dashboard/components/DashboardItem/CourseEnrolling/index.tsx +8 -4
  114. package/js/widgets/Dashboard/components/DashboardItem/Enrollment/DashboardItemEnrollment.stories.tsx +1 -1
  115. package/js/widgets/Dashboard/components/DashboardItem/Enrollment/ProductCertificateFooter/index.tsx +1 -1
  116. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderReadonly.stories.tsx +1 -1
  117. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderWritable.stories.tsx +1 -1
  118. package/js/widgets/Dashboard/components/DashboardItem/Order/Installment/index.tsx +1 -1
  119. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentDetailsModal/_styles.scss +2 -2
  120. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentRetryModal/index.tsx +2 -1
  121. package/js/widgets/Dashboard/components/DashboardItem/Order/OrganizationBlock/index.tsx +6 -3
  122. package/js/widgets/Dashboard/components/DashboardItem/index.stories.tsx +1 -1
  123. package/js/widgets/Dashboard/components/DashboardItem/index.tsx +2 -1
  124. package/js/widgets/Dashboard/components/DashboardListAvatar/index.stories.tsx +1 -1
  125. package/js/widgets/Dashboard/components/DashboardSidebar/index.stories.tsx +1 -1
  126. package/js/widgets/Dashboard/components/LearnerDashboardSidebar/index.stories.tsx +1 -1
  127. package/js/widgets/Dashboard/components/ProtectedOutlet/AuthenticatedOutlet.spec.tsx +1 -1
  128. package/js/widgets/Dashboard/components/ProtectedOutlet/ProtectedOutlet.spec.tsx +1 -1
  129. package/js/widgets/Dashboard/components/SearchBar/index.tsx +2 -1
  130. package/js/widgets/Dashboard/components/TeacherDashboardOrganizationSidebar/index.stories.tsx +1 -1
  131. package/js/widgets/Dashboard/components/TeacherDashboardProfileSidebar/index.stories.tsx +1 -1
  132. package/js/widgets/Dashboard/hooks/useRouteInfo/index.spec.tsx +2 -2
  133. package/js/widgets/Dashboard/index.spec.tsx +1 -1
  134. package/js/widgets/Search/components/SearchFilterValueParent/index.stories.tsx +1 -1
  135. package/js/widgets/Search/components/SearchFiltersPane/index.tsx +2 -1
  136. package/js/widgets/Slider/index.stories.tsx +1 -1
  137. package/js/widgets/Slider/index.tsx +7 -6
  138. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCertificateItem/index.stories.tsx +1 -1
  139. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseRunItem/index.stories.tsx +1 -1
  140. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.stories.tsx +1 -1
  141. package/js/widgets/SyllabusCourseRunsList/components/CourseWishButton/index.tsx +4 -2
  142. package/js/widgets/SyllabusCourseRunsList/components/SyllabusCourseRun/index.stories.tsx +1 -1
  143. package/js/widgets/SyllabusCourseRunsList/components/SyllabusCourseRunCompacted/index.stories.tsx +41 -0
  144. package/js/widgets/UserLogin/index.stories.tsx +1 -1
  145. package/package.json +76 -81
  146. package/scss/components/_subheader.scss +1 -1
  147. package/scss/components/templates/richie/slider/_slider.scss +1 -1
  148. package/scss/objects/_course_glimpses.scss +1 -0
  149. package/scss/trumps/_bootstrap.scss +1 -0
  150. package/scss/vendors/css/cunningham-tokens.css +1259 -154
  151. package/scss/vendors/cunningham-tokens.scss +1479 -150
  152. package/tsconfig.json +1 -1
  153. package/webpack.config.js +8 -0
@@ -1911,6 +1911,14 @@
1911
1911
  "description": "Validate button for the credit card modal",
1912
1912
  "message": "Validate"
1913
1913
  },
1914
+ "components.SaleTunnel.Information.cpf.buttonLabel": {
1915
+ "description": "Label for the button redirecting to Mon Compte Formation",
1916
+ "message": "Go to Mon Compte Formation"
1917
+ },
1918
+ "components.SaleTunnel.Information.cpf.description": {
1919
+ "description": "Explanatory text for the CPF payment option",
1920
+ "message": "Purchase your training course by using your Personal Training Account (CPF) on Mon Compte Formation."
1921
+ },
1914
1922
  "components.SaleTunnel.Information.description": {
1915
1923
  "description": "Description of the information section",
1916
1924
  "message": "This information will be used for billing"
@@ -1951,6 +1959,18 @@
1951
1959
  "description": "Message displayed representing the payment schedule when the order is free.",
1952
1960
  "message": "No payment required. This order is fully covered."
1953
1961
  },
1962
+ "components.SaleTunnel.Information.paymentMode.classic": {
1963
+ "description": "Label for the classic card payment option",
1964
+ "message": "Credit card payment"
1965
+ },
1966
+ "components.SaleTunnel.Information.paymentMode.cpf": {
1967
+ "description": "Label for the CPF (Mon Compte Formation) payment option",
1968
+ "message": "My Training Account (CPF)"
1969
+ },
1970
+ "components.SaleTunnel.Information.paymentMode.title": {
1971
+ "description": "Title for the payment mode selection section",
1972
+ "message": "Payment method"
1973
+ },
1954
1974
  "components.SaleTunnel.Information.paymentSchedule": {
1955
1975
  "description": "Title for the payment schedule section",
1956
1976
  "message": "Payment schedule"
@@ -1911,6 +1911,14 @@
1911
1911
  "description": "Validate button for the credit card modal",
1912
1912
  "message": "Validate"
1913
1913
  },
1914
+ "components.SaleTunnel.Information.cpf.buttonLabel": {
1915
+ "description": "Label for the button redirecting to Mon Compte Formation",
1916
+ "message": "Go to Mon Compte Formation"
1917
+ },
1918
+ "components.SaleTunnel.Information.cpf.description": {
1919
+ "description": "Explanatory text for the CPF payment option",
1920
+ "message": "Purchase your training course by using your Personal Training Account (CPF) on Mon Compte Formation."
1921
+ },
1914
1922
  "components.SaleTunnel.Information.description": {
1915
1923
  "description": "Description of the information section",
1916
1924
  "message": "This information will be used for billing"
@@ -1951,6 +1959,18 @@
1951
1959
  "description": "Message displayed representing the payment schedule when the order is free.",
1952
1960
  "message": "No payment required. This order is fully covered."
1953
1961
  },
1962
+ "components.SaleTunnel.Information.paymentMode.classic": {
1963
+ "description": "Label for the classic card payment option",
1964
+ "message": "Credit card payment"
1965
+ },
1966
+ "components.SaleTunnel.Information.paymentMode.cpf": {
1967
+ "description": "Label for the CPF (Mon Compte Formation) payment option",
1968
+ "message": "My Training Account (CPF)"
1969
+ },
1970
+ "components.SaleTunnel.Information.paymentMode.title": {
1971
+ "description": "Title for the payment mode selection section",
1972
+ "message": "Payment method"
1973
+ },
1954
1974
  "components.SaleTunnel.Information.paymentSchedule": {
1955
1975
  "description": "Title for the payment schedule section",
1956
1976
  "message": "Payment schedule"
package/jest.config.js CHANGED
@@ -17,6 +17,10 @@ module.exports = {
17
17
  transformIgnorePatterns: [
18
18
  'node_modules/(?!(' +
19
19
  'react-intl' +
20
+ '|@formatjs' +
21
+ '|intl-messageformat' +
22
+ '|@tanstack' +
23
+ '|uuid' +
20
24
  '|lodash-es' +
21
25
  '|@hookform/resolvers' +
22
26
  '|query-string' +
@@ -25,6 +29,7 @@ module.exports = {
25
29
  '|filter-obj' +
26
30
  '|@openfun/cunningham-react' +
27
31
  '|keycloak-js' +
32
+ '|@faker-js/faker' +
28
33
  ')/)',
29
34
  ],
30
35
  globals: {
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { StorybookHelper } from 'utils/StorybookHelper';
3
3
  import { AddressFactory } from 'utils/test/factories/joanie';
4
4
  import AddressForm from '.';
@@ -1,6 +1,6 @@
1
1
  import { yupResolver } from '@hookform/resolvers/yup';
2
2
  import { Fragment, useEffect } from 'react';
3
- import { FormProvider, useForm } from 'react-hook-form';
3
+ import { FormProvider, Resolver, useForm } from 'react-hook-form';
4
4
  import { FormattedMessage, useIntl } from 'react-intl';
5
5
  import { Button, Checkbox } from '@openfun/cunningham-react';
6
6
  import { getLocalizedCunninghamErrorProp } from 'components/Form/utils';
@@ -39,7 +39,7 @@ const AddressForm = ({ handleReset, onSubmit, address }: Props) => {
39
39
  defaultValues: address || defaultValues,
40
40
  mode: 'onBlur',
41
41
  reValidateMode: 'onChange',
42
- resolver: yupResolver(validationSchema),
42
+ resolver: yupResolver(validationSchema) as Resolver<AddressFormValues>,
43
43
  });
44
44
  const { register, handleSubmit, reset, formState } = form;
45
45
 
@@ -140,7 +140,8 @@ const AddressForm = ({ handleReset, onSubmit, address }: Props) => {
140
140
  {address ? (
141
141
  <Fragment>
142
142
  <Button
143
- color="tertiary"
143
+ color="brand"
144
+ variant="tertiary"
144
145
  onClick={handleCancel}
145
146
  title={intl.formatMessage(messages.cancelTitleButton)}
146
147
  >
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { StorybookHelper } from 'utils/StorybookHelper';
3
3
  import { RichieContextFactory } from 'utils/test/factories/richie';
4
4
  import AddressesManagement from '.';
@@ -1,4 +1,4 @@
1
- import { Children, useEffect, useState, RefAttributes } from 'react';
1
+ import { Children, useEffect, useState, Ref } from 'react';
2
2
  import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
3
3
  import { Button } from '@openfun/cunningham-react';
4
4
  import AddressForm, { type AddressFormValues } from 'components/AddressesManagement/AddressForm';
@@ -105,9 +105,10 @@ export const messages = defineMessages({
105
105
  },
106
106
  });
107
107
 
108
- interface AddressesManagementProps extends RefAttributes<HTMLDivElement> {
108
+ interface AddressesManagementProps {
109
109
  handleClose: () => void;
110
110
  selectAddress: (address: Joanie.Address) => void;
111
+ ref?: Ref<HTMLDivElement>;
111
112
  }
112
113
 
113
114
  const AddressesManagement = ({ handleClose, selectAddress, ref }: AddressesManagementProps) => {
@@ -191,7 +192,8 @@ const AddressesManagement = ({ handleClose, selectAddress, ref }: AddressesManag
191
192
  <div className="AddressesManagement" ref={ref}>
192
193
  <Button
193
194
  className="AddressesManagement__closeButton"
194
- color="tertiary"
195
+ color="brand"
196
+ variant="tertiary"
195
197
  size="small"
196
198
  onClick={handleClose}
197
199
  >
@@ -1,4 +1,4 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import Badge from '.';
3
3
 
4
4
  export default {
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { PropsWithChildren } from 'react/ts5.0';
2
+ import { PropsWithChildren } from 'react';
3
3
 
4
4
  type BadgeProps = PropsWithChildren<{
5
5
  color?: 'primary' | 'secondary' | 'tertiary';
@@ -1,4 +1,4 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import Banner, { BannerType } from './index';
3
3
 
4
4
  export default {
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { CourseLightFactory, RichieContextFactory } from 'utils/test/factories/richie';
3
3
  import { CourseGlimpse, getCourseGlimpseProps } from 'components/CourseGlimpse';
4
4
  import { CourseCertificateOffer, CourseOffer } from 'types/Course';
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { RichieContextFactory, CourseLightFactory } from 'utils/test/factories/richie';
3
3
  import { CourseGlimpseList, getCourseGlimpseListProps } from '.';
4
4
 
@@ -15,8 +15,8 @@
15
15
  text-align: left;
16
16
  font-size: rem-calc(12px);
17
17
  color: r-theme-val(credit-card-selector, title-color);
18
- font-weight: var(--c--theme--font--weights--bold);
19
- font-family: var(--c--theme--font--families--accent);
18
+ font-weight: var(--c--globals--font--weights--bold);
19
+ font-family: var(--c--globals--font--families--accent);
20
20
  }
21
21
 
22
22
  &__meta {
@@ -111,7 +111,8 @@ export const CreditCardSelector = ({
111
111
  {allowEdit && creditCards?.length > 0 && (
112
112
  <Button
113
113
  icon={<span className="material-icons">edit</span>}
114
- color="tertiary-text"
114
+ color="brand"
115
+ variant="tertiary"
115
116
  size="medium"
116
117
  onClick={modal.open}
117
118
  aria-label={intl.formatMessage(messages.editCreditCardAriaLabel)}
@@ -122,7 +123,8 @@ export const CreditCardSelector = ({
122
123
  <Button
123
124
  onClick={() => setCreditCard(undefined)}
124
125
  size="small"
125
- color="secondary"
126
+ color="brand"
127
+ variant="secondary"
126
128
  className="mt-t"
127
129
  fullWidth={isMobile}
128
130
  >
@@ -217,7 +219,13 @@ const CreditCardSelectorModal = ({
217
219
  size={ModalSize.MEDIUM}
218
220
  title={intl.formatMessage(messages.modalTitle)}
219
221
  actions={
220
- <Button color="primary" size="small" fullWidth={true} onClick={() => onChange(selected)}>
222
+ <Button
223
+ color="brand"
224
+ variant="primary"
225
+ size="small"
226
+ fullWidth={true}
227
+ onClick={() => onChange(selected)}
228
+ >
221
229
  <FormattedMessage {...messages.modalTitle} />
222
230
  </Button>
223
231
  }
@@ -38,7 +38,8 @@ const DownloadCertificateButton = ({
38
38
  <Button
39
39
  className={className}
40
40
  size="small"
41
- color="secondary"
41
+ color="brand"
42
+ variant="secondary"
42
43
  disabled={loading}
43
44
  onClick={onDownloadClick}
44
45
  >
@@ -39,7 +39,13 @@ const DownloadContractButton = ({ contract, className }: DownloadContractButtonP
39
39
  };
40
40
 
41
41
  return (
42
- <Button size="small" className={className} color="secondary" onClick={downloadContract}>
42
+ <Button
43
+ size="small"
44
+ className={className}
45
+ color="brand"
46
+ variant="secondary"
47
+ onClick={downloadContract}
48
+ >
43
49
  <FormattedMessage {...messages.contractDownloadActionLabel} />
44
50
  </Button>
45
51
  );
@@ -1,8 +1,10 @@
1
1
  import c from 'classnames';
2
2
  import { PropsWithChildren } from 'react';
3
3
 
4
- interface FormProps
5
- extends React.DetailedHTMLProps<React.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement> {}
4
+ interface FormProps extends React.DetailedHTMLProps<
5
+ React.FormHTMLAttributes<HTMLFormElement>,
6
+ HTMLFormElement
7
+ > {}
6
8
 
7
9
  const Form = ({ children, onSubmit, className, name, noValidate = true }: FormProps) => {
8
10
  return (
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { PropsWithChildren, useState, useRef, CSSProperties } from 'react';
3
3
  import { HttpStatusCode } from 'utils/errors/HttpError';
4
4
  import { Icon, IconTypeEnum } from './index';
@@ -69,6 +69,7 @@ const IconContainer = ({ name, enumKey }: IconContainerProps) => {
69
69
  };
70
70
 
71
71
  const clipboardCopy = () => {
72
+ // eslint-disable-next-line compat/compat
72
73
  navigator.clipboard.writeText(`${ENUM_NAME}.${enumKey}`);
73
74
  setShowTooltip(true);
74
75
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { useState } from 'react';
3
3
  import { Modal } from './index';
4
4
 
@@ -78,7 +78,8 @@ export const Modal = ({
78
78
  className="modal__closeButton"
79
79
  onClick={(e) => props.onRequestClose?.(e)}
80
80
  title={intl.formatMessage(messages.closeDialog)}
81
- color="tertiary"
81
+ color="brand"
82
+ variant="tertiary"
82
83
  size="small"
83
84
  >
84
85
  <Icon name={IconTypeEnum.ROUND_CLOSE} />
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { BaseJoanieAppWrapper } from 'utils/test/wrappers/BaseJoanieAppWrapper';
3
3
  import OpenEdxFullNameForm from '.';
4
4
 
@@ -1,6 +1,6 @@
1
1
  import { ButtonElement, Input, Alert, VariantType } from '@openfun/cunningham-react';
2
2
  import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
3
- import { FormProvider, useForm } from 'react-hook-form';
3
+ import { FormProvider, Resolver, useForm } from 'react-hook-form';
4
4
  import * as Yup from 'yup';
5
5
  import { yupResolver } from '@hookform/resolvers/yup';
6
6
  import { useEffect, useMemo, useRef } from 'react';
@@ -78,7 +78,7 @@ const OpenEdxFullNameForm = () => {
78
78
  defaultValues,
79
79
  mode: 'onBlur',
80
80
  reValidateMode: 'onChange',
81
- resolver: yupResolver(validationSchema),
81
+ resolver: yupResolver(validationSchema) as Resolver<OpenEdxFullNameFormValues>,
82
82
  });
83
83
 
84
84
  const { getValues, register, handleSubmit, reset, formState } = form;
@@ -18,8 +18,8 @@
18
18
  height: 24px;
19
19
  padding: 0 12px;
20
20
  border-radius: 24px;
21
- font-family: var(--c--theme--font--families--accent);
22
- font-weight: var(--c--theme--font--weight--semibold);
21
+ font-family: var(--c--globals--font--families--accent);
22
+ font-weight: var(--c--globals--font--weights--medium);
23
23
  font-size: rem-calc(12px);
24
24
 
25
25
  &--canceled,
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { ProductFactory } from 'utils/test/factories/joanie';
3
3
  import PurchaseButton from '.';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react';
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { StorybookHelper } from 'utils/StorybookHelper';
3
3
  import { AddressFactory } from 'utils/test/factories/joanie';
4
4
  import RegisteredAddress from '.';
@@ -91,7 +91,8 @@ const RegisteredAddress = ({ promote, select, edit, remove, address }: Props) =>
91
91
  </Button>
92
92
  <Button
93
93
  aria-label={intl.formatMessage(messages.editButtonLabel, { title: address.title })}
94
- color="secondary"
94
+ color="brand"
95
+ variant="secondary"
95
96
  size="small"
96
97
  onClick={() => edit(address)}
97
98
  >
@@ -101,7 +102,8 @@ const RegisteredAddress = ({ promote, select, edit, remove, address }: Props) =>
101
102
  aria-label={intl.formatMessage(messages.deleteButtonLabel, {
102
103
  title: address.title,
103
104
  })}
104
- color="secondary"
105
+ color="brand"
106
+ variant="secondary"
105
107
  size="small"
106
108
  disabled={address.is_main}
107
109
  onClick={() => remove(address)}
@@ -52,7 +52,7 @@ export const CreateAddressFormModal = (props: AddressFormModalProps) => {
52
52
  size={ModalSize.MEDIUM}
53
53
  title={intl.formatMessage(messages.title)}
54
54
  actions={
55
- <Button color="primary" size="small" onClick={handleSubmit(onSubmit)}>
55
+ <Button color="brand" variant="primary" size="small" onClick={handleSubmit(onSubmit)}>
56
56
  <FormattedMessage {...messages.submit} />
57
57
  </Button>
58
58
  }
@@ -49,7 +49,7 @@ export const EditAddressFormModal = ({
49
49
  size={ModalSize.MEDIUM}
50
50
  title={intl.formatMessage(messages.title)}
51
51
  actions={
52
- <Button color="primary" size="small" onClick={handleSubmit(onSubmit)}>
52
+ <Button color="brand" variant="primary" size="small" onClick={handleSubmit(onSubmit)}>
53
53
  <FormattedMessage {...messages.save} />
54
54
  </Button>
55
55
  }
@@ -75,7 +75,8 @@ export const AddressSelector = () => {
75
75
  <Button
76
76
  size="small"
77
77
  icon={<span className="material-icons">edit</span>}
78
- color="tertiary"
78
+ color="brand"
79
+ variant="tertiary"
79
80
  onClick={editFormModal.open}
80
81
  fullWidth={isMobile}
81
82
  >
@@ -85,7 +86,8 @@ export const AddressSelector = () => {
85
86
  <Button
86
87
  size="small"
87
88
  icon={<span className="material-icons">add</span>}
88
- color="primary"
89
+ color="brand"
90
+ variant="primary"
89
91
  onClick={createFormModal.open}
90
92
  fullWidth={isMobile}
91
93
  >
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useState } from 'react';
2
2
  import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
3
- import { FormProvider, useForm } from 'react-hook-form';
3
+ import { FormProvider, Resolver, useForm } from 'react-hook-form';
4
4
  import { yupResolver } from '@hookform/resolvers/yup';
5
5
  import * as Yup from 'yup';
6
6
  import { Step, StepLabel, Stepper } from '@mui/material';
@@ -197,7 +197,7 @@ const BatchOrderForm = () => {
197
197
  const form = useForm<BatchOrder>({
198
198
  defaultValues: batchOrder || defaultValues,
199
199
  mode: 'onBlur',
200
- resolver: yupResolver(validationSchema),
200
+ resolver: yupResolver(validationSchema) as Resolver<BatchOrder>,
201
201
  });
202
202
  const { watch } = form;
203
203
  const values = watch();
@@ -268,7 +268,8 @@ const BatchOrderForm = () => {
268
268
  }
269
269
  }}
270
270
  hidden={activeStep === 0}
271
- color="tertiary"
271
+ color="brand"
272
+ variant="tertiary"
272
273
  >
273
274
  <FormattedMessage {...messages.previousButton} />
274
275
  </Button>
@@ -143,7 +143,7 @@ const messages = defineMessages({
143
143
  id: 'components.SaleTunnel.Information.cpf.description',
144
144
  description: 'Explanatory text for the CPF payment option',
145
145
  defaultMessage:
146
- 'Pay for your training using your personal training account (CPF) on Mon Compte Formation.',
146
+ 'Purchase your training course by using your Personal Training Account (CPF) on Mon Compte Formation.',
147
147
  },
148
148
  cpfButtonLabel: {
149
149
  id: 'components.SaleTunnel.Information.cpf.buttonLabel',
@@ -236,7 +236,12 @@ export const SaleTunnelInformationSingular = () => {
236
236
  </div>
237
237
  )}
238
238
  {paymentMode === PaymentMode.CPF ? (
239
- <CpfPayment deepLink={deepLink!} />
239
+ <CpfPayment
240
+ deepLink={deepLink!}
241
+ discount={discount}
242
+ voucherError={voucherError}
243
+ setVoucherError={setVoucherError}
244
+ />
240
245
  ) : (
241
246
  <>
242
247
  {needsPayment && (
@@ -443,7 +448,13 @@ const Voucher = ({
443
448
  label={intl.formatMessage(messages.voucherTitle)}
444
449
  disabled={!!voucherCode}
445
450
  />
446
- <Button size="small" color="primary" onClick={submitVoucher} disabled={!!voucherCode}>
451
+ <Button
452
+ size="small"
453
+ color="brand"
454
+ variant="primary"
455
+ onClick={submitVoucher}
456
+ disabled={!!voucherCode}
457
+ >
447
458
  <FormattedMessage {...messages.voucherValidate} />
448
459
  </Button>
449
460
  </div>
@@ -493,14 +504,24 @@ const PaymentScheduleBlock = ({ schedule }: { schedule: PaymentSchedule }) => {
493
504
  );
494
505
  };
495
506
 
496
- const CpfPayment = ({ deepLink }: { deepLink: string }) => {
507
+ const CpfPayment = ({
508
+ deepLink,
509
+ discount,
510
+ voucherError,
511
+ setVoucherError,
512
+ }: {
513
+ deepLink: string;
514
+ discount?: string;
515
+ voucherError: HttpError | null;
516
+ setVoucherError: (value: HttpError | null) => void;
517
+ }) => {
497
518
  return (
498
519
  <div className="sale-tunnel__cpf">
499
520
  <p className="description mb-s">
500
521
  <FormattedMessage {...messages.cpfDescription} />
501
522
  </p>
502
523
  <Button
503
- color="primary"
524
+ color="brand"
504
525
  fullWidth={true}
505
526
  href={deepLink}
506
527
  target="_blank"
@@ -508,6 +529,7 @@ const CpfPayment = ({ deepLink }: { deepLink: string }) => {
508
529
  >
509
530
  <FormattedMessage {...messages.cpfButtonLabel} />
510
531
  </Button>
532
+ <Voucher discount={discount} voucherError={voucherError} setVoucherError={setVoucherError} />
511
533
  </div>
512
534
  );
513
535
  };
@@ -110,9 +110,6 @@ const SubscriptionButton = ({ buildOrderPayload }: Props) => {
110
110
  paymentMode,
111
111
  } = useSaleTunnelContext();
112
112
 
113
- if (paymentMode === PaymentMode.CPF) {
114
- return null;
115
- }
116
113
  const { methods: orderMethods } = useOrders(undefined, { enabled: false });
117
114
  const { methods: batchOrderMethods } = useBatchOrder();
118
115
  const [state, setState] = useState<ComponentStates>(ComponentStates.IDLE);
@@ -138,12 +135,17 @@ const SubscriptionButton = ({ buildOrderPayload }: Props) => {
138
135
  return;
139
136
  }
140
137
 
141
- if (!billingAddress && needsPayment) {
138
+ if (!billingAddress && needsPayment && paymentMode !== PaymentMode.CPF) {
142
139
  handleError(SubscriptionErrorMessageId.ERROR_ADDRESS);
143
140
  return;
144
141
  }
145
142
 
146
- if (!saleTunnelProps.isWithdrawable && !hasWaivedWithdrawalRight && needsPayment) {
143
+ if (
144
+ !saleTunnelProps.isWithdrawable &&
145
+ !hasWaivedWithdrawalRight &&
146
+ needsPayment &&
147
+ paymentMode !== PaymentMode.CPF
148
+ ) {
147
149
  handleError(SubscriptionErrorMessageId.ERROR_WITHDRAWAL_RIGHT);
148
150
  return;
149
151
  }
@@ -32,12 +32,13 @@
32
32
  &__right {
33
33
  flex: 1;
34
34
  overflow: hidden;
35
+ position: relative;
35
36
  }
36
37
 
37
38
  &__column {
38
39
  display: flex;
39
40
  flex-direction: column;
40
- gap: var(--c--theme--spacings--b);
41
+ gap: var(--c--globals--spacings--b);
41
42
  }
42
43
  }
43
44
 
@@ -135,7 +136,7 @@
135
136
  margin-top: 1rem;
136
137
  display: flex;
137
138
  justify-content: space-between;
138
- font-size: var(--c--theme--font--sizes--l);
139
+ font-size: var(--c--globals--font--sizes--md);
139
140
  }
140
141
  }
141
142
 
@@ -159,8 +160,8 @@
159
160
  gap: 0.5rem;
160
161
 
161
162
  .title {
162
- font-weight: var(--c--theme--font--weights--bold);
163
- font-size: var(--c--theme--font--sizes--l);
163
+ font-weight: var(--c--globals--font--weights--bold);
164
+ font-size: var(--c--globals--font--sizes--md);
164
165
  margin: 0 0 0.5rem;
165
166
  }
166
167
 
@@ -209,17 +210,17 @@
209
210
  }
210
211
 
211
212
  .block-title {
212
- font-size: var(--c--theme--font--sizes--l);
213
+ font-size: var(--c--globals--font--sizes--md);
213
214
  color: r-theme-val(sale-tunnel, title-color);
214
- font-weight: var(--c--theme--font--weights--extrabold);
215
+ font-weight: var(--c--globals--font--weights--extrabold);
215
216
  text-align: left;
216
- font-family: var(--c--theme--font--families--accent);
217
+ font-family: var(--c--globals--font--families--accent);
217
218
  }
218
219
 
219
220
  .sub-block-title {
220
221
  font-size: 12px;
221
222
  color: r-theme-val(sale-tunnel, title-color);
222
- font-weight: var(--c--theme--font--weights--bold);
223
+ font-weight: var(--c--globals--font--weights--bold);
223
224
  text-align: left;
224
225
  }
225
226