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.
- package/.eslintrc.json +11 -2
- package/i18n/locales/ar-SA.json +209 -125
- package/i18n/locales/es-ES.json +210 -126
- package/i18n/locales/fa-IR.json +209 -125
- package/i18n/locales/fr-CA.json +209 -125
- package/i18n/locales/fr-FR.json +209 -125
- package/i18n/locales/ko-KR.json +209 -125
- package/i18n/locales/pt-PT.json +212 -128
- package/i18n/locales/ru-RU.json +209 -125
- package/i18n/locales/vi-VN.json +209 -125
- package/js/api/joanie.ts +14 -17
- package/js/api/lms/dummy.ts +1 -12
- package/js/components/ContractFrame/AbstractContractFrame.spec.tsx +16 -9
- package/js/components/ContractFrame/AbstractContractFrame.tsx +32 -25
- package/js/components/ContractFrame/LearnerContractFrame.tsx +2 -2
- package/js/components/ContractFrame/_styles.scss +6 -14
- package/js/components/CreditCardSelector/index.spec.tsx +7 -7
- package/js/components/CreditCardSelector/index.tsx +2 -2
- package/js/components/DownloadContractButton/index.spec.tsx +1 -1
- package/js/components/OpenEdxFullNameForm/index.spec.tsx +229 -0
- package/js/components/OpenEdxFullNameForm/index.tsx +7 -7
- package/js/components/PaymentInterfaces/LyraPopIn.tsx +2 -2
- package/js/components/PaymentInterfaces/PayplugLightbox.tsx +1 -1
- package/js/components/PaymentInterfaces/__mocks__/index.tsx +1 -4
- package/js/components/PaymentInterfaces/types.ts +5 -2
- package/js/components/PurchaseButton/index.spec.tsx +69 -37
- package/js/components/SaleTunnel/AddressSelector/index.spec.tsx +2 -1
- package/js/components/SaleTunnel/CertificateSaleTunnel/index.tsx +2 -2
- package/js/components/SaleTunnel/CredentialSaleTunnel/index.tsx +6 -10
- package/js/components/SaleTunnel/GenericSaleTunnel.tsx +75 -41
- package/js/components/SaleTunnel/SaleTunnelInformation/index.tsx +0 -30
- package/js/components/SaleTunnel/SaleTunnelSavePaymentMethod/_styles.scss +12 -0
- package/js/components/SaleTunnel/SaleTunnelSavePaymentMethod/index.tsx +160 -0
- package/js/components/SaleTunnel/SaleTunnelSuccess/index.tsx +15 -29
- package/js/components/SaleTunnel/Sponsors/SaleTunnelSponsors.tsx +5 -0
- package/js/components/SaleTunnel/SubscriptionButton/_styles.scss +7 -0
- package/js/components/SaleTunnel/SubscriptionButton/index.tsx +202 -0
- package/js/components/SaleTunnel/_styles.scss +10 -1
- package/js/components/SaleTunnel/hooks/useTerms.tsx +0 -77
- package/js/components/SaleTunnel/index.credential.spec.tsx +12 -21
- package/js/components/SaleTunnel/index.full-process.spec.tsx +110 -48
- package/js/components/SaleTunnel/index.spec.tsx +330 -779
- package/js/components/SignContractButton/index.omniscientOrders.spec.tsx +16 -11
- package/js/components/SignContractButton/index.spec.tsx +16 -20
- package/js/components/SignContractButton/index.tsx +3 -1
- package/js/hooks/useCreditCards/index.spec.tsx +70 -6
- package/js/hooks/useCreditCards/index.ts +49 -11
- package/js/hooks/useOrders/index.spec.tsx +322 -0
- package/js/hooks/{useOrders.ts → useOrders/index.ts} +40 -14
- package/js/hooks/useProductOrder/index.spec.tsx +77 -60
- package/js/hooks/useProductOrder/index.tsx +2 -2
- package/js/hooks/useResources/useResourcesRoot.ts +1 -0
- package/js/pages/DashboardCreditCardsManagement/CreditCardBrandLogo.spec.tsx +1 -1
- package/js/pages/DashboardCreditCardsManagement/CreditCardBrandLogo.tsx +4 -2
- package/js/pages/TeacherDashboardContractsLayout/components/ContractActionsBar/index.spec.tsx +8 -5
- package/js/pages/TeacherDashboardContractsLayout/components/SignOrganizationContractButton/index.spec.tsx +8 -9
- package/js/pages/TeacherDashboardCourseLearnersLayout/components/CourseLearnerDataGrid/index.spec.tsx +1 -1
- package/js/pages/TeacherDashboardCourseLearnersLayout/components/CourseLearnerDataGrid/index.tsx +1 -6
- package/js/settings/settings.test.ts +11 -2
- package/js/translations/ar-SA.json +1 -1
- package/js/translations/es-ES.json +1 -1
- package/js/translations/fa-IR.json +1 -1
- package/js/translations/fr-CA.json +1 -1
- package/js/translations/fr-FR.json +1 -1
- package/js/translations/ko-KR.json +1 -1
- package/js/translations/pt-PT.json +1 -1
- package/js/translations/ru-RU.json +1 -1
- package/js/translations/vi-VN.json +1 -1
- package/js/types/Joanie.ts +49 -34
- package/js/utils/OrderHelper/index.ts +38 -42
- package/js/utils/search/getSuggestionsSection/index.spec.ts +3 -2
- package/js/utils/test/factories/joanie.ts +36 -51
- package/js/widgets/Dashboard/components/DashboardItem/CourseEnrolling/index.tsx +8 -18
- package/js/widgets/Dashboard/components/DashboardItem/Enrollment/ProductCertificateFooter/index.spec.tsx +26 -32
- package/js/widgets/Dashboard/components/DashboardItem/Enrollment/ProductCertificateFooter/index.tsx +11 -6
- package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrder.spec.tsx +7 -6
- package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrder.tsx +9 -10
- package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderContract.spec.tsx +3 -1
- package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderContract.useUnionResource.cache.spec.tsx +6 -7
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentDetailsModal/index.tsx +28 -8
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentRetryModal/index.tsx +4 -6
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.spec.tsx +18 -71
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.tsx +34 -35
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateMessage/index.tsx +27 -24
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.spec.tsx +18 -73
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.tsx +32 -16
- package/js/widgets/Dashboard/components/DashboardOrderLoader/index.tsx +3 -11
- package/js/widgets/Dashboard/components/Signature/SignatureDummy.tsx +25 -3
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCourseRuns/EnrollableCourseRunList.tsx +2 -6
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCourseRuns/index.spec.tsx +7 -14
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseRunItem/index.spec.tsx +7 -5
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseRunItem/index.tsx +5 -7
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.spec.tsx +242 -332
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.stories.tsx +12 -13
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.tsx +10 -21
- package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/index.joanie.spec.tsx +2 -2
- package/package.json +27 -27
- package/scss/components/_index.scss +2 -1
- package/js/components/PaymentButton/_styles.scss +0 -27
- package/js/components/SaleTunnel/GenericPaymentButton/index.tsx +0 -333
- package/js/components/SaleTunnel/SaleTunnelNotValidated/index.tsx +0 -70
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/ProductSignatureHeader/index.tsx +0 -41
package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentDetailsModal/index.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Alert,
|
|
3
3
|
Button,
|
|
4
|
+
Loader,
|
|
4
5
|
Modal,
|
|
5
6
|
ModalProps,
|
|
6
7
|
ModalSize,
|
|
@@ -8,12 +9,14 @@ import {
|
|
|
8
9
|
VariantType,
|
|
9
10
|
} from '@openfun/cunningham-react';
|
|
10
11
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
|
11
|
-
import { useState } from 'react';
|
|
12
|
+
import { useState, useEffect } from 'react';
|
|
12
13
|
import { PaymentScheduleGrid } from 'components/PaymentScheduleGrid';
|
|
13
14
|
import { CreditCard, Order } from 'types/Joanie';
|
|
14
15
|
import { CreditCardSelector } from 'components/CreditCardSelector';
|
|
15
16
|
import { OrderHelper } from 'utils/OrderHelper';
|
|
16
17
|
import { OrderPaymentRetryModal } from 'widgets/Dashboard/components/DashboardItem/Order/OrderPaymentRetryModal';
|
|
18
|
+
import { Maybe } from 'types/utils';
|
|
19
|
+
import { useCreditCard } from 'hooks/useCreditCards';
|
|
17
20
|
|
|
18
21
|
const messages = defineMessages({
|
|
19
22
|
title: {
|
|
@@ -57,7 +60,7 @@ export const OrderPaymentDetailsModal = ({ order, ...props }: PaymentModalProps)
|
|
|
57
60
|
<h3 className="order-payment-details__title mb-s">
|
|
58
61
|
<FormattedMessage {...messages.paymentMethodTitle} />
|
|
59
62
|
</h3>
|
|
60
|
-
<CreditCardSelectorWrapper />
|
|
63
|
+
<CreditCardSelectorWrapper selectedCreditCardId={order.credit_card_id} />
|
|
61
64
|
<h3 className="order-payment-details__title mb-s mt-b">
|
|
62
65
|
<FormattedMessage {...messages.scheduleTitle} />
|
|
63
66
|
</h3>
|
|
@@ -91,14 +94,31 @@ export const OrderPaymentDetailsModal = ({ order, ...props }: PaymentModalProps)
|
|
|
91
94
|
);
|
|
92
95
|
};
|
|
93
96
|
|
|
94
|
-
const CreditCardSelectorWrapper = (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
const CreditCardSelectorWrapper = ({
|
|
98
|
+
selectedCreditCardId,
|
|
99
|
+
}: {
|
|
100
|
+
selectedCreditCardId: Maybe<string>;
|
|
101
|
+
}) => {
|
|
102
|
+
const {
|
|
103
|
+
item: creditCard,
|
|
104
|
+
states: { fetching },
|
|
105
|
+
} = useCreditCard(selectedCreditCardId);
|
|
106
|
+
const [selectedCreditCard, setSelectedCreditCard] = useState<Maybe<CreditCard>>(creditCard);
|
|
107
|
+
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (!selectedCreditCard && creditCard) {
|
|
110
|
+
setSelectedCreditCard(creditCard);
|
|
111
|
+
}
|
|
112
|
+
}, [creditCard]);
|
|
113
|
+
|
|
114
|
+
if (fetching) {
|
|
115
|
+
return <Loader size="small" />;
|
|
116
|
+
}
|
|
117
|
+
|
|
98
118
|
return (
|
|
99
119
|
<CreditCardSelector
|
|
100
|
-
creditCard={creditCard}
|
|
101
|
-
setCreditCard={
|
|
120
|
+
creditCard={selectedCreditCard || creditCard}
|
|
121
|
+
setCreditCard={setSelectedCreditCard}
|
|
102
122
|
quickRemove={false}
|
|
103
123
|
allowEdit={false}
|
|
104
124
|
/>
|
package/js/widgets/Dashboard/components/DashboardItem/Order/OrderPaymentRetryModal/index.tsx
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '@openfun/cunningham-react';
|
|
10
10
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
|
11
11
|
import { useRef, useState } from 'react';
|
|
12
|
-
import { CreditCard, Order, PaymentInstallment,
|
|
12
|
+
import { CreditCard, Order, PaymentInstallment, ACTIVE_ORDER_STATES } from 'types/Joanie';
|
|
13
13
|
import { CreditCardSelector } from 'components/CreditCardSelector';
|
|
14
14
|
import { useJoanieApi } from 'contexts/JoanieApiContext';
|
|
15
15
|
import { Payment, PaymentErrorMessageId } from 'components/PaymentInterfaces/types';
|
|
@@ -98,7 +98,8 @@ export const OrderPaymentRetryModal = ({ installment, order, ...props }: Props)
|
|
|
98
98
|
setError(intl.formatMessage(messages.errorFailedSubmitInstallmentPayment));
|
|
99
99
|
setState(ComponentStates.ERROR);
|
|
100
100
|
}
|
|
101
|
-
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
102
|
+
} catch (_error) {
|
|
102
103
|
setError(intl.formatMessage(messages.errorFailedSubmitInstallmentPayment));
|
|
103
104
|
setState(ComponentStates.ERROR);
|
|
104
105
|
}
|
|
@@ -111,10 +112,7 @@ export const OrderPaymentRetryModal = ({ installment, order, ...props }: Props)
|
|
|
111
112
|
|
|
112
113
|
const isOrderValidated = async (id: string): Promise<Boolean> => {
|
|
113
114
|
const orderToCheck = await API.user.orders.get({ id });
|
|
114
|
-
return (
|
|
115
|
-
orderToCheck?.state === OrderState.VALIDATED ||
|
|
116
|
-
orderToCheck?.state === OrderState.PENDING_PAYMENT
|
|
117
|
-
);
|
|
115
|
+
return orderToCheck !== null && ACTIVE_ORDER_STATES.includes(orderToCheck.state);
|
|
118
116
|
};
|
|
119
117
|
|
|
120
118
|
const settled = async () => {
|
package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.spec.tsx
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import { screen } from '@testing-library/react';
|
|
3
3
|
import { createIntl } from 'react-intl';
|
|
4
|
-
import {
|
|
5
|
-
ContractDefinitionFactory,
|
|
6
|
-
ContractFactory,
|
|
7
|
-
CredentialOrderFactory,
|
|
8
|
-
} from 'utils/test/factories/joanie';
|
|
4
|
+
import { CredentialOrderFactory } from 'utils/test/factories/joanie';
|
|
9
5
|
import { OrderState } from 'types/Joanie';
|
|
10
6
|
import { render } from 'utils/test/render';
|
|
11
7
|
import { IntlWrapper } from 'utils/test/wrappers/IntlWrapper';
|
|
@@ -13,86 +9,37 @@ import OrderStateLearnerMessage, { messages } from '.';
|
|
|
13
9
|
|
|
14
10
|
const intl = createIntl({ locale: 'en' });
|
|
15
11
|
|
|
16
|
-
describe('<
|
|
12
|
+
describe('<OrderStateLearnerMessage/>', () => {
|
|
17
13
|
it.each([
|
|
18
|
-
[OrderState.
|
|
19
|
-
[OrderState.SUBMITTED, 'Submitted'],
|
|
20
|
-
[OrderState.PENDING, 'Pending'],
|
|
14
|
+
[OrderState.ASSIGNED, 'Pending'],
|
|
21
15
|
[OrderState.CANCELED, 'Canceled'],
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
it.each([
|
|
34
|
-
[OrderState.DRAFT, 'Draft'],
|
|
35
|
-
[OrderState.SUBMITTED, 'Submitted'],
|
|
36
|
-
[OrderState.PENDING, 'Pending'],
|
|
37
|
-
[OrderState.CANCELED, 'Canceled'],
|
|
38
|
-
])(
|
|
39
|
-
'should display message from order state: %s when order have no contract',
|
|
40
|
-
(state, expectedMessage) => {
|
|
41
|
-
const orderWithContract = CredentialOrderFactory({
|
|
42
|
-
state,
|
|
43
|
-
contract: ContractFactory().one(),
|
|
44
|
-
}).one();
|
|
45
|
-
render(<OrderStateLearnerMessage order={orderWithContract} />, {
|
|
46
|
-
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
47
|
-
});
|
|
48
|
-
expect(screen.getByText(expectedMessage)).toBeInTheDocument();
|
|
49
|
-
},
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
it('should display message for validated order that need learner signature', () => {
|
|
53
|
-
const order = CredentialOrderFactory({
|
|
54
|
-
state: OrderState.VALIDATED,
|
|
55
|
-
contract: null,
|
|
56
|
-
}).one();
|
|
57
|
-
|
|
58
|
-
const contractDefinition = ContractDefinitionFactory().one();
|
|
59
|
-
|
|
60
|
-
render(<OrderStateLearnerMessage order={order} contractDefinition={contractDefinition} />, {
|
|
61
|
-
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
62
|
-
});
|
|
63
|
-
expect(screen.getByText('Signature required')).toBeInTheDocument();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("should display message for validated order that don't have a generated certificate", () => {
|
|
67
|
-
const order = CredentialOrderFactory({
|
|
68
|
-
state: OrderState.VALIDATED,
|
|
69
|
-
contract: ContractFactory({ student_signed_on: new Date().toISOString() }).one(),
|
|
70
|
-
certificate_id: undefined,
|
|
71
|
-
}).one();
|
|
16
|
+
[OrderState.COMPLETED, 'On going'],
|
|
17
|
+
[OrderState.DRAFT, 'Pending'],
|
|
18
|
+
[OrderState.FAILED_PAYMENT, 'Last direct debit has failed'],
|
|
19
|
+
[OrderState.NO_PAYMENT, 'First direct debit has failed'],
|
|
20
|
+
[OrderState.PENDING, 'Pending for the first direct debit'],
|
|
21
|
+
[OrderState.PENDING_PAYMENT, 'On going'],
|
|
22
|
+
[OrderState.SIGNING, 'Signature required'],
|
|
23
|
+
[OrderState.TO_SAVE_PAYMENT_METHOD, 'Payment method is missing'],
|
|
24
|
+
[OrderState.TO_SIGN, 'Signature required'],
|
|
25
|
+
])('should display message from order state: %s', (state, expectedMessage) => {
|
|
26
|
+
const order = CredentialOrderFactory({ state }).one();
|
|
72
27
|
render(<OrderStateLearnerMessage order={order} />, {
|
|
73
28
|
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
74
29
|
});
|
|
75
|
-
expect(
|
|
76
|
-
screen.getByText(intl.formatMessage(messages.statusOnGoing), {
|
|
77
|
-
exact: false,
|
|
78
|
-
}),
|
|
79
|
-
);
|
|
30
|
+
expect(screen.getByText(expectedMessage)).toBeInTheDocument();
|
|
80
31
|
});
|
|
81
32
|
|
|
82
|
-
it('should display message for
|
|
33
|
+
it('should display message for completed order that have a generated certificate', () => {
|
|
83
34
|
const order = CredentialOrderFactory({
|
|
84
|
-
state: OrderState.
|
|
85
|
-
contract: ContractFactory({
|
|
86
|
-
student_signed_on: new Date().toISOString(),
|
|
87
|
-
organization_signed_on: new Date().toISOString(),
|
|
88
|
-
}).one(),
|
|
35
|
+
state: OrderState.COMPLETED,
|
|
89
36
|
certificate_id: 'FAKE_CERTIFICATE_ID',
|
|
90
37
|
}).one();
|
|
91
38
|
render(<OrderStateLearnerMessage order={order} />, {
|
|
92
39
|
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
93
40
|
});
|
|
94
41
|
expect(
|
|
95
|
-
screen.getByText(intl.formatMessage(messages.
|
|
42
|
+
screen.getByText(intl.formatMessage(messages.statusPassed), {
|
|
96
43
|
exact: false,
|
|
97
44
|
}),
|
|
98
45
|
);
|
package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.tsx
CHANGED
|
@@ -1,71 +1,70 @@
|
|
|
1
1
|
import { defineMessages } from 'react-intl';
|
|
2
|
-
import OrderStateMessage, { OrderStateMessageBaseProps } from '../OrderStateMessage';
|
|
2
|
+
import OrderStateMessage, { OrderStateMessageBaseProps, MessageKeys } from '../OrderStateMessage';
|
|
3
3
|
|
|
4
|
-
export const messages = defineMessages({
|
|
4
|
+
export const messages = defineMessages<MessageKeys>({
|
|
5
5
|
statusDraft: {
|
|
6
|
-
id: 'components.DashboardItem.Order.
|
|
6
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusDraft',
|
|
7
7
|
description: 'Status shown on the dashboard order item when order is draft.',
|
|
8
|
-
defaultMessage: '
|
|
8
|
+
defaultMessage: 'Pending',
|
|
9
9
|
},
|
|
10
|
-
|
|
11
|
-
id: 'components.DashboardItem.Order.
|
|
12
|
-
description: 'Status shown on the dashboard order item when order is
|
|
13
|
-
defaultMessage: '
|
|
10
|
+
statusAssigned: {
|
|
11
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusAssigned',
|
|
12
|
+
description: 'Status shown on the dashboard order item when order is assigned.',
|
|
13
|
+
defaultMessage: 'Pending',
|
|
14
14
|
},
|
|
15
15
|
statusPending: {
|
|
16
|
-
id: 'components.DashboardItem.Order.
|
|
16
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusPending',
|
|
17
17
|
description: 'Status shown on the dashboard order item when order is pending.',
|
|
18
|
-
defaultMessage: 'Pending',
|
|
18
|
+
defaultMessage: 'Pending for the first direct debit',
|
|
19
19
|
},
|
|
20
|
-
|
|
21
|
-
id: 'components.DashboardItem.Order.
|
|
22
|
-
description:
|
|
23
|
-
'Status shown on the dashboard order item when order is validated with no certificate',
|
|
20
|
+
statusPendingPayment: {
|
|
21
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusPendingPayment',
|
|
22
|
+
description: 'Status shown on the dashboard order item when order is pending for payment',
|
|
24
23
|
defaultMessage: 'On going',
|
|
25
24
|
},
|
|
26
25
|
statusCompleted: {
|
|
27
|
-
id: 'components.DashboardItem.Order.
|
|
28
|
-
description:
|
|
29
|
-
|
|
30
|
-
defaultMessage: 'Completed',
|
|
31
|
-
},
|
|
32
|
-
statusPendingPayment: {
|
|
33
|
-
id: 'components.DashboardItem.Order.OrderStateMessage.statusPendingPayment',
|
|
34
|
-
description:
|
|
35
|
-
'Status shown on the dashboard order item when order is validated with certificate and pending payment',
|
|
36
|
-
defaultMessage: 'Completed',
|
|
26
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusCompleted',
|
|
27
|
+
description: 'Status shown on the dashboard order item when order is completed',
|
|
28
|
+
defaultMessage: 'On going',
|
|
37
29
|
},
|
|
38
30
|
statusWaitingSignature: {
|
|
39
|
-
id: 'components.DashboardItem.Order.
|
|
31
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusWaitingSignature',
|
|
40
32
|
description:
|
|
41
33
|
"Status shown on the dashboard order item when order is validated with contract's learner signature missing.",
|
|
42
34
|
defaultMessage: 'Signature required',
|
|
43
35
|
},
|
|
44
36
|
statusWaitingCounterSignature: {
|
|
45
|
-
id: 'components.DashboardItem.Order.
|
|
37
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusWaitingCounterSignature',
|
|
46
38
|
description:
|
|
47
39
|
"Status shown on the dashboard order item when order is validated with contract's organization signature missing.",
|
|
48
40
|
defaultMessage: 'On going',
|
|
49
41
|
},
|
|
42
|
+
statusWaitingPaymentMethod: {
|
|
43
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusWaitingPaymentMethod',
|
|
44
|
+
description:
|
|
45
|
+
'Status shown on the dashboard order item when order is in to_save_payment_method state.',
|
|
46
|
+
defaultMessage: 'Payment method is missing',
|
|
47
|
+
},
|
|
50
48
|
statusCanceled: {
|
|
51
|
-
id: 'components.DashboardItem.Order.
|
|
49
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusCanceled',
|
|
52
50
|
description: 'Status shown on the dashboard order item when order is canceled',
|
|
53
51
|
defaultMessage: 'Canceled',
|
|
54
52
|
},
|
|
55
53
|
statusNoPayment: {
|
|
56
|
-
id: 'components.DashboardItem.Order.
|
|
54
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusNoPayment',
|
|
57
55
|
description: 'Status shown on the dashboard order item when order is in no payment state',
|
|
58
|
-
defaultMessage: '
|
|
56
|
+
defaultMessage: 'First direct debit has failed',
|
|
59
57
|
},
|
|
60
58
|
statusFailedPayment: {
|
|
61
|
-
id: 'components.DashboardItem.Order.
|
|
59
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusFailedPayment',
|
|
62
60
|
description: 'Status shown on the dashboard order item when order is in failed payment state',
|
|
63
|
-
defaultMessage: '
|
|
61
|
+
defaultMessage: 'Last direct debit has failed',
|
|
64
62
|
},
|
|
65
|
-
|
|
66
|
-
id: 'components.DashboardItem.Order.
|
|
67
|
-
description:
|
|
68
|
-
|
|
63
|
+
statusPassed: {
|
|
64
|
+
id: 'components.DashboardItem.Order.OrderStateLearnerMessage.statusPassed',
|
|
65
|
+
description:
|
|
66
|
+
'Status shown on the dashboard order item when order is completed and has a certificate',
|
|
67
|
+
defaultMessage: 'Successfully completed',
|
|
69
68
|
},
|
|
70
69
|
});
|
|
71
70
|
|
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
import { FormattedMessage, MessageDescriptor } from 'react-intl';
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
CertificateOrder,
|
|
5
|
-
CredentialOrder,
|
|
6
|
-
OrderState,
|
|
7
|
-
ContractDefinition,
|
|
8
|
-
NestedCourseOrder,
|
|
9
|
-
} from 'types/Joanie';
|
|
3
|
+
import { CertificateOrder, CredentialOrder, OrderState, NestedCourseOrder } from 'types/Joanie';
|
|
10
4
|
import { StringHelper } from 'utils/StringHelper';
|
|
11
5
|
import { handle } from 'utils/errors/handle';
|
|
12
6
|
import { OrderHelper, OrderStatus } from 'utils/OrderHelper';
|
|
13
7
|
|
|
14
8
|
export interface OrderStateMessageBaseProps {
|
|
15
9
|
order: CredentialOrder | CertificateOrder | NestedCourseOrder;
|
|
16
|
-
contractDefinition?: ContractDefinition;
|
|
17
10
|
}
|
|
18
11
|
|
|
12
|
+
export type MessageKeys =
|
|
13
|
+
| 'statusDraft'
|
|
14
|
+
| 'statusAssigned'
|
|
15
|
+
| 'statusPending'
|
|
16
|
+
| 'statusPendingPayment'
|
|
17
|
+
| 'statusCompleted'
|
|
18
|
+
| 'statusWaitingSignature'
|
|
19
|
+
| 'statusWaitingCounterSignature'
|
|
20
|
+
| 'statusWaitingPaymentMethod'
|
|
21
|
+
| 'statusCanceled'
|
|
22
|
+
| 'statusNoPayment'
|
|
23
|
+
| 'statusFailedPayment'
|
|
24
|
+
| 'statusPassed';
|
|
25
|
+
|
|
19
26
|
interface OrderStateMessageProps extends OrderStateMessageBaseProps {
|
|
20
|
-
messages: Record<
|
|
27
|
+
messages: Record<MessageKeys, MessageDescriptor>;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
const OrderStateMessage = ({ order,
|
|
30
|
+
const OrderStateMessage = ({ order, messages }: OrderStateMessageProps) => {
|
|
24
31
|
useEffect(() => {
|
|
25
32
|
if (!Object.values(OrderState).includes(order.state)) {
|
|
26
33
|
handle(new Error(`Unknown order state ${order.state}`));
|
|
@@ -28,27 +35,23 @@ const OrderStateMessage = ({ order, contractDefinition, messages }: OrderStateMe
|
|
|
28
35
|
}, [order.state]);
|
|
29
36
|
|
|
30
37
|
const orderStatusMessagesMap = {
|
|
31
|
-
[OrderStatus.
|
|
32
|
-
[OrderStatus.SUBMITTED]: messages.statusSubmitted,
|
|
33
|
-
[OrderStatus.PENDING]: messages.statusPending,
|
|
38
|
+
[OrderStatus.ASSIGNED]: messages.statusAssigned,
|
|
34
39
|
[OrderStatus.CANCELED]: messages.statusCanceled,
|
|
35
|
-
[OrderStatus.
|
|
36
|
-
[OrderStatus.WAITING_COUNTER_SIGNATURE]: messages.statusWaitingCounterSignature,
|
|
40
|
+
[OrderStatus.DRAFT]: messages.statusDraft,
|
|
37
41
|
[OrderStatus.COMPLETED]: messages.statusCompleted,
|
|
38
|
-
[OrderStatus.
|
|
42
|
+
[OrderStatus.FAILED_PAYMENT]: messages.statusFailedPayment,
|
|
39
43
|
[OrderStatus.NO_PAYMENT]: messages.statusNoPayment,
|
|
44
|
+
[OrderStatus.PASSED]: messages.statusPassed,
|
|
45
|
+
[OrderStatus.PENDING]: messages.statusPending,
|
|
40
46
|
[OrderStatus.PENDING_PAYMENT]: messages.statusPendingPayment,
|
|
41
|
-
[OrderStatus.
|
|
47
|
+
[OrderStatus.WAITING_COUNTER_SIGNATURE]: messages.statusWaitingCounterSignature,
|
|
48
|
+
[OrderStatus.WAITING_PAYMENT_METHOD]: messages.statusWaitingPaymentMethod,
|
|
49
|
+
[OrderStatus.WAITING_SIGNATURE]: messages.statusWaitingSignature,
|
|
42
50
|
};
|
|
43
|
-
const status = OrderHelper.getState(order
|
|
51
|
+
const status = OrderHelper.getState(order);
|
|
44
52
|
|
|
45
53
|
if (status === null) {
|
|
46
|
-
return (
|
|
47
|
-
<FormattedMessage
|
|
48
|
-
{...messages.statusOther}
|
|
49
|
-
values={{ state: StringHelper.capitalizeFirst(order.state) }}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
54
|
+
return StringHelper.capitalizeFirst(order.state);
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
return <FormattedMessage {...orderStatusMessagesMap[status]} />;
|
package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.spec.tsx
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import { screen } from '@testing-library/react';
|
|
3
3
|
import { createIntl } from 'react-intl';
|
|
4
|
-
import {
|
|
5
|
-
ContractDefinitionFactory,
|
|
6
|
-
ContractFactory,
|
|
7
|
-
CredentialOrderFactory,
|
|
8
|
-
} from 'utils/test/factories/joanie';
|
|
4
|
+
import { ContractFactory, CredentialOrderFactory } from 'utils/test/factories/joanie';
|
|
9
5
|
import { OrderState } from 'types/Joanie';
|
|
10
6
|
import { render } from 'utils/test/render';
|
|
11
7
|
import { IntlWrapper } from 'utils/test/wrappers/IntlWrapper';
|
|
@@ -15,100 +11,49 @@ const intl = createIntl({ locale: 'en' });
|
|
|
15
11
|
|
|
16
12
|
describe('<OrderStateTeacherMessage/>', () => {
|
|
17
13
|
it.each([
|
|
18
|
-
[OrderState.
|
|
19
|
-
[OrderState.SUBMITTED, 'Pending'],
|
|
20
|
-
[OrderState.PENDING, 'Pending'],
|
|
14
|
+
[OrderState.ASSIGNED, 'Pending'],
|
|
21
15
|
[OrderState.CANCELED, 'Canceled'],
|
|
22
|
-
|
|
23
|
-
'should display message from order state: %s when order have no contract',
|
|
24
|
-
(state, expectedMessage) => {
|
|
25
|
-
const order = CredentialOrderFactory({ state }).one();
|
|
26
|
-
render(<OrderStateTeacherMessage order={order} />, {
|
|
27
|
-
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
28
|
-
});
|
|
29
|
-
expect(screen.getByText(expectedMessage)).toBeInTheDocument();
|
|
30
|
-
},
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
it.each([
|
|
16
|
+
[OrderState.COMPLETED, 'On going'],
|
|
34
17
|
[OrderState.DRAFT, 'Pending'],
|
|
35
|
-
[OrderState.
|
|
36
|
-
[OrderState.
|
|
37
|
-
[OrderState.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
render(
|
|
46
|
-
<OrderStateTeacherMessage
|
|
47
|
-
order={orderWithContract}
|
|
48
|
-
contractDefinition={ContractDefinitionFactory().one()}
|
|
49
|
-
/>,
|
|
50
|
-
{
|
|
51
|
-
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
52
|
-
},
|
|
53
|
-
);
|
|
54
|
-
expect(screen.getByText(expectedMessage)).toBeInTheDocument();
|
|
55
|
-
},
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
it('should display message for validated order that need learner signature', () => {
|
|
59
|
-
const order = CredentialOrderFactory({
|
|
60
|
-
state: OrderState.VALIDATED,
|
|
61
|
-
contract: null,
|
|
62
|
-
}).one();
|
|
63
|
-
|
|
64
|
-
const contractDefinition = ContractDefinitionFactory().one();
|
|
65
|
-
|
|
66
|
-
render(<OrderStateTeacherMessage order={order} contractDefinition={contractDefinition} />, {
|
|
18
|
+
[OrderState.FAILED_PAYMENT, 'Last direct debit has failed'],
|
|
19
|
+
[OrderState.NO_PAYMENT, 'First direct debit has failed'],
|
|
20
|
+
[OrderState.PENDING, 'Pending for the first direct debit'],
|
|
21
|
+
[OrderState.PENDING_PAYMENT, 'On going'],
|
|
22
|
+
[OrderState.SIGNING, "Pending for learner's signature"],
|
|
23
|
+
[OrderState.TO_SAVE_PAYMENT_METHOD, 'Payment method is missing'],
|
|
24
|
+
[OrderState.TO_SIGN, "Pending for learner's signature"],
|
|
25
|
+
])('should display message from order state: %s', (state, expectedMessage) => {
|
|
26
|
+
const order = CredentialOrderFactory({ state }).one();
|
|
27
|
+
render(<OrderStateTeacherMessage order={order} />, {
|
|
67
28
|
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
68
29
|
});
|
|
69
|
-
expect(screen.getByText(
|
|
30
|
+
expect(screen.getByText(expectedMessage)).toBeInTheDocument();
|
|
70
31
|
});
|
|
71
32
|
|
|
72
33
|
it('should display message for validated order that need organization signature', () => {
|
|
73
34
|
const order = CredentialOrderFactory({
|
|
74
|
-
state: OrderState.
|
|
35
|
+
state: OrderState.PENDING_PAYMENT,
|
|
75
36
|
contract: ContractFactory({
|
|
76
37
|
student_signed_on: new Date().toISOString(),
|
|
77
38
|
}).one(),
|
|
78
39
|
}).one();
|
|
79
|
-
const contractDefinition = ContractDefinitionFactory().one();
|
|
80
|
-
|
|
81
|
-
render(<OrderStateTeacherMessage order={order} contractDefinition={contractDefinition} />, {
|
|
82
|
-
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
83
|
-
});
|
|
84
|
-
expect(screen.getByText('To be signed')).toBeInTheDocument();
|
|
85
|
-
});
|
|
86
40
|
|
|
87
|
-
it("should display message for validated order that don't have a generated certificate", () => {
|
|
88
|
-
const order = CredentialOrderFactory({
|
|
89
|
-
state: OrderState.VALIDATED,
|
|
90
|
-
certificate_id: undefined,
|
|
91
|
-
}).one();
|
|
92
41
|
render(<OrderStateTeacherMessage order={order} />, {
|
|
93
42
|
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
94
43
|
});
|
|
95
|
-
expect(
|
|
96
|
-
screen.getByText(intl.formatMessage(messages.statusOnGoing), {
|
|
97
|
-
exact: false,
|
|
98
|
-
}),
|
|
99
|
-
);
|
|
44
|
+
expect(screen.getByText('To be signed')).toBeInTheDocument();
|
|
100
45
|
});
|
|
101
46
|
|
|
102
47
|
it('should display message for validated order that have a generated certificate', () => {
|
|
103
48
|
const order = CredentialOrderFactory({
|
|
104
|
-
state: OrderState.
|
|
49
|
+
state: OrderState.COMPLETED,
|
|
105
50
|
certificate_id: 'FAKE_CERTIFICATE_ID',
|
|
106
51
|
}).one();
|
|
107
52
|
render(<OrderStateTeacherMessage order={order} />, {
|
|
108
53
|
wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
|
|
109
54
|
});
|
|
110
55
|
expect(
|
|
111
|
-
screen.getByText(intl.formatMessage(messages.
|
|
56
|
+
screen.getByText(intl.formatMessage(messages.statusPassed), {
|
|
112
57
|
exact: false,
|
|
113
58
|
}),
|
|
114
59
|
);
|
package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.tsx
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
import { defineMessages } from 'react-intl';
|
|
2
|
-
import OrderStateMessage, { OrderStateMessageBaseProps } from '../OrderStateMessage';
|
|
2
|
+
import OrderStateMessage, { MessageKeys, OrderStateMessageBaseProps } from '../OrderStateMessage';
|
|
3
3
|
|
|
4
|
-
export const messages = defineMessages({
|
|
4
|
+
export const messages = defineMessages<MessageKeys>({
|
|
5
5
|
statusDraft: {
|
|
6
6
|
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusDraft',
|
|
7
7
|
description: 'Status shown on the dashboard order item when order is draft.',
|
|
8
8
|
defaultMessage: 'Pending',
|
|
9
9
|
},
|
|
10
|
-
|
|
11
|
-
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.
|
|
12
|
-
description: 'Status shown on the dashboard order item when order is
|
|
10
|
+
statusAssigned: {
|
|
11
|
+
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusAssigned',
|
|
12
|
+
description: 'Status shown on the dashboard order item when order is assigned.',
|
|
13
13
|
defaultMessage: 'Pending',
|
|
14
14
|
},
|
|
15
15
|
statusPending: {
|
|
16
16
|
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusPending',
|
|
17
17
|
description: 'Status shown on the dashboard order item when order is pending.',
|
|
18
|
-
defaultMessage: 'Pending',
|
|
18
|
+
defaultMessage: 'Pending for the first direct debit',
|
|
19
19
|
},
|
|
20
|
-
|
|
21
|
-
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.
|
|
20
|
+
statusPendingPayment: {
|
|
21
|
+
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusPendingPayment',
|
|
22
22
|
description:
|
|
23
23
|
'Status shown on the dashboard order item when order is validated with no certificate',
|
|
24
|
-
defaultMessage: '
|
|
24
|
+
defaultMessage: 'On going',
|
|
25
25
|
},
|
|
26
26
|
statusCompleted: {
|
|
27
27
|
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusCompleted',
|
|
28
|
-
description:
|
|
29
|
-
|
|
30
|
-
defaultMessage: 'Certified',
|
|
28
|
+
description: 'Status shown on the dashboard order item when order is completed',
|
|
29
|
+
defaultMessage: 'On going',
|
|
31
30
|
},
|
|
32
31
|
statusWaitingSignature: {
|
|
33
32
|
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusWaitingSignature',
|
|
@@ -35,6 +34,12 @@ export const messages = defineMessages({
|
|
|
35
34
|
"Status shown on the dashboard order item when order is validated with contract's learner signature missing.",
|
|
36
35
|
defaultMessage: "Pending for learner's signature",
|
|
37
36
|
},
|
|
37
|
+
statusWaitingPaymentMethod: {
|
|
38
|
+
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusWaitingPaymentMethod',
|
|
39
|
+
description:
|
|
40
|
+
'Status shown on the dashboard order item when order is in to_save_payment_method state.',
|
|
41
|
+
defaultMessage: 'Payment method is missing',
|
|
42
|
+
},
|
|
38
43
|
statusWaitingCounterSignature: {
|
|
39
44
|
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusWaitingCounterSignature',
|
|
40
45
|
description:
|
|
@@ -46,10 +51,21 @@ export const messages = defineMessages({
|
|
|
46
51
|
description: 'Status shown on the dashboard order item when order is canceled',
|
|
47
52
|
defaultMessage: 'Canceled',
|
|
48
53
|
},
|
|
49
|
-
|
|
50
|
-
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.
|
|
51
|
-
description: 'Status shown on the dashboard order item when order
|
|
52
|
-
defaultMessage: '
|
|
54
|
+
statusNoPayment: {
|
|
55
|
+
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusNoPayment',
|
|
56
|
+
description: 'Status shown on the dashboard order item when order is in no payment state',
|
|
57
|
+
defaultMessage: 'First direct debit has failed',
|
|
58
|
+
},
|
|
59
|
+
statusFailedPayment: {
|
|
60
|
+
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusFailedPayment',
|
|
61
|
+
description: 'Status shown on the dashboard order item when order is in failed payment state',
|
|
62
|
+
defaultMessage: 'Last direct debit has failed',
|
|
63
|
+
},
|
|
64
|
+
statusPassed: {
|
|
65
|
+
id: 'components.DashboardItem.Order.OrderStateTeacherMessage.statusPassed',
|
|
66
|
+
description:
|
|
67
|
+
'Status shown on the dashboard order item when order is completed with certificate',
|
|
68
|
+
defaultMessage: 'Certified',
|
|
53
69
|
},
|
|
54
70
|
});
|
|
55
71
|
|
|
@@ -4,7 +4,6 @@ import { useMemo } from 'react';
|
|
|
4
4
|
import { useOmniscientOrder } from 'hooks/useOrders';
|
|
5
5
|
import { Spinner } from 'components/Spinner';
|
|
6
6
|
import Banner, { BannerType } from 'components/Banner';
|
|
7
|
-
import { useCourseProduct } from 'hooks/useCourseProducts';
|
|
8
7
|
import { isCredentialOrder } from 'pages/DashboardCourses/useOrdersEnrollments';
|
|
9
8
|
import { handle } from 'utils/errors/handle';
|
|
10
9
|
import { OrderHelper } from 'utils/OrderHelper';
|
|
@@ -39,10 +38,6 @@ export const DashboardOrderLoader = () => {
|
|
|
39
38
|
item: order,
|
|
40
39
|
states: { fetching: fetchingOrder, error: errorOrder },
|
|
41
40
|
} = useOmniscientOrder(params.orderId);
|
|
42
|
-
const {
|
|
43
|
-
item: courseProduct,
|
|
44
|
-
states: { fetching: fetchingCourseProduct, error: errorCourseProduct },
|
|
45
|
-
} = useCourseProduct({ course_id: order?.course?.code, product_id: order?.product_id });
|
|
46
41
|
const intl = useIntl();
|
|
47
42
|
|
|
48
43
|
const credentialOrder = order && isCredentialOrder(order) ? order : undefined;
|
|
@@ -52,12 +47,9 @@ export const DashboardOrderLoader = () => {
|
|
|
52
47
|
return intl.formatMessage(messages.wrongLinkedProductError);
|
|
53
48
|
}
|
|
54
49
|
}, [credentialOrder]);
|
|
55
|
-
const error = errorOrder ||
|
|
56
|
-
const fetching = fetchingOrder
|
|
57
|
-
const needsSignature = OrderHelper.orderNeedsSignature(
|
|
58
|
-
order,
|
|
59
|
-
courseProduct?.product.contract_definition,
|
|
60
|
-
);
|
|
50
|
+
const error = errorOrder || wrongLinkedProductError;
|
|
51
|
+
const fetching = fetchingOrder;
|
|
52
|
+
const needsSignature = order ? OrderHelper.orderNeedsSignature(order) : false;
|
|
61
53
|
|
|
62
54
|
return (
|
|
63
55
|
<>
|