-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathContactDetailsStep.jsx
121 lines (109 loc) · 3.89 KB
/
ContactDetailsStep.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import {FormioForm} from '@open-formulieren/formio-renderer';
import PropTypes from 'prop-types';
import {useContext} from 'react';
import {flushSync} from 'react-dom';
import {FormattedMessage, useIntl} from 'react-intl';
import {Navigate, useNavigate} from 'react-router';
import {useAsync} from 'react-use';
import {ConfigContext} from 'Context';
import {get} from 'api';
import {getCached, setCached} from 'cache';
import {CardTitle} from 'components/Card';
import Loader from 'components/Loader';
import useTitle from 'hooks/useTitle';
import {useCreateAppointmentContext} from '../CreateAppointment/CreateAppointmentState';
import SubmitRow from '../SubmitRow';
const CACHED_CONTACT_DETAILS_FIELDS_KEY = 'appointments|contactDetailsFields';
const CACHED_CONTACT_DETAILS_FIELDS_MAX_AGE_MS = 15 * 60 * 1000; // 15 minutes
export const getContactDetailsFields = async (baseUrl, productIds) => {
const fullKey = `${CACHED_CONTACT_DETAILS_FIELDS_KEY}:${productIds.join(';')}`;
let components = getCached(fullKey, CACHED_CONTACT_DETAILS_FIELDS_MAX_AGE_MS);
if (components === null) {
const multiParams = productIds.map(id => ({product_id: id}));
components = await get(`${baseUrl}appointments/customer-fields`, {}, multiParams);
setCached(fullKey, components);
}
return components;
};
const ContactDetailsStep = ({navigateTo = null}) => {
const intl = useIntl();
const {baseUrl, requiredFieldsWithAsterisk} = useContext(ConfigContext);
const {
submitStep,
appointmentData,
stepData,
stepErrors: {initialErrors},
clearStepErrors,
} = useCreateAppointmentContext();
const navigate = useNavigate();
useTitle(
intl.formatMessage({
description: 'Appointments: contact details step page title',
defaultMessage: 'Contact details',
})
);
const products = appointmentData?.products || [];
const productIds = products.map(p => p.productId).sort();
const {
loading,
value: components,
error,
} = useAsync(async () => {
if (!productIds.length) return [];
return await getContactDetailsFields(baseUrl, productIds);
}, [baseUrl, JSON.stringify(productIds)]);
if (error) throw error;
// if we don't have products or appointment details in the state, redirect back to the start
if (!products.length || !appointmentData.location || !appointmentData.datetime) {
return <Navigate to="/" replace />;
}
return (
<>
<CardTitle
title={
<FormattedMessage
description="Appointments: contact details step title"
defaultMessage="Contact details"
/>
}
headingType="subtitle"
padded
/>
{loading && <Loader modifiers={['centered']} />}
{!loading && (
<FormioForm
components={components}
values={stepData}
errors={initialErrors?.contactDetails}
onSubmit={async values => {
flushSync(() => {
clearStepErrors();
submitStep(values);
});
if (navigateTo !== null) navigate(navigateTo);
}}
requiredFieldsWithAsterisk={requiredFieldsWithAsterisk}
>
{/* TODO: ensure we can pass an ID for the submit button so that we don't
need to rely on children anymore to submit the form */}
<SubmitRow
canSubmit={!loading}
nextText={intl.formatMessage({
description: 'Appointments contact details step: next step text',
defaultMessage: 'To overview',
})}
previousText={intl.formatMessage({
description: 'Appointments contact details step: previous step text',
defaultMessage: 'Back to location and time',
})}
navigateBackTo="kalender"
/>
</FormioForm>
)}
</>
);
};
ContactDetailsStep.propTypes = {
navigateTo: PropTypes.string,
};
export default ContactDetailsStep;