ublo-lib 1.23.6 → 1.24.0
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/es/common/components/custom-contact-form/custom-contact-form.d.ts +1 -0
- package/es/common/components/custom-contact-form/custom-contact-form.d.ts.map +1 -1
- package/es/common/components/custom-contact-form/custom-contact-form.js +2 -2
- package/es/common/components/custom-contact-form/messages.js +1 -1
- package/es/common/components/gesco-contact-form/data/phone-prefixes.json +251 -0
- package/es/common/components/gesco-contact-form/gesco-contact-form.d.ts +17 -0
- package/es/common/components/gesco-contact-form/gesco-contact-form.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/gesco-contact-form.js +85 -281
- package/es/common/components/gesco-contact-form/gesco-contact-form.module.css +31 -14
- package/es/common/components/gesco-contact-form/hooks/use-params.d.ts +15 -0
- package/es/common/components/gesco-contact-form/hooks/use-params.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/hooks/use-params.js +24 -0
- package/es/common/components/gesco-contact-form/index.d.ts +3 -0
- package/es/common/components/gesco-contact-form/index.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/index.js +1 -1
- package/es/common/components/gesco-contact-form/phone-code-select.d.ts +8 -0
- package/es/common/components/gesco-contact-form/phone-code-select.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/phone-code-select.js +48 -0
- package/es/common/components/gesco-contact-form/phone-code-select.module.css +21 -0
- package/es/common/components/gesco-contact-form/services/api.d.ts +30 -0
- package/es/common/components/gesco-contact-form/services/api.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/services/api.js +12 -0
- package/es/common/components/gesco-contact-form/services/form.d.ts +31 -0
- package/es/common/components/gesco-contact-form/services/form.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/services/form.js +28 -0
- package/es/common/components/gesco-contact-form/services/messages.d.ts +33 -0
- package/es/common/components/gesco-contact-form/services/messages.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/services/messages.js +70 -0
- package/es/common/components/gesco-contact-form/services/plausible.d.ts +3 -0
- package/es/common/components/gesco-contact-form/services/plausible.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/services/plausible.js +11 -0
- package/es/common/components/gesco-contact-form/types.d.ts +33 -0
- package/es/common/components/gesco-contact-form/types.d.ts.map +1 -0
- package/es/common/components/gesco-contact-form/types.js +1 -0
- package/package.json +23 -23
- package/es/common/components/gesco-contact-form/api.js +0 -37
- package/es/common/components/gesco-contact-form/data.js +0 -53
- package/es/common/components/gesco-contact-form/messages.js +0 -74
- package/es/common/components/gesco-contact-form/validation.js +0 -65
|
@@ -1,290 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
2
|
import * as React from "react";
|
|
2
|
-
import Select from "dt-design-system/es/select";
|
|
3
|
+
import Select, { formatOptions } from "dt-design-system/es/select";
|
|
3
4
|
import Input from "dt-design-system/es/input";
|
|
4
5
|
import Textarea from "dt-design-system/es/textarea";
|
|
5
6
|
import Button from "dt-design-system/es/button";
|
|
6
|
-
import
|
|
7
|
+
import Loader from "dt-design-system/es/loader";
|
|
8
|
+
import Information from "dt-design-system/es/information";
|
|
7
9
|
import * as Icons from "dt-design-system/es/icons";
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import * as
|
|
11
|
-
import * as
|
|
12
|
-
import * as API from "./api";
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
children: _jsx(ContactForm, {
|
|
19
|
-
...props
|
|
20
|
-
})
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
|
-
export default React.memo(ContactFormWithSnackbar);
|
|
24
|
-
function ContactForm({
|
|
25
|
-
lang,
|
|
26
|
-
resort,
|
|
27
|
-
channel = "ESF",
|
|
28
|
-
merchant,
|
|
29
|
-
categories,
|
|
30
|
-
facet = "WINTER",
|
|
31
|
-
integration = false,
|
|
32
|
-
uat = false,
|
|
33
|
-
onSubmit
|
|
34
|
-
}) {
|
|
35
|
-
const [submiting, setSubmiting] = React.useState(false);
|
|
36
|
-
const [params, setParams] = React.useState(Data.DEFAULT_PARAMS);
|
|
37
|
-
const [fields, setFields] = React.useState(Data.DEFAULT_FIELDS);
|
|
38
|
-
const [needCategory, setNeedCategory] = React.useState(false);
|
|
39
|
-
const [hasError, setHasError] = React.useState(false);
|
|
40
|
-
const snackbar = useSnackbar();
|
|
41
|
-
const widgetLang = lang === "fr" ? "fr" : "en";
|
|
42
|
-
const update = React.useCallback((forceTouch, name, val, overrideValidators) => {
|
|
43
|
-
setFields(fields => {
|
|
44
|
-
const field = fields[name];
|
|
45
|
-
const value = val !== undefined ? val : field.value;
|
|
46
|
-
const touched = forceTouch || field.touched;
|
|
47
|
-
const validators = overrideValidators || field.validators;
|
|
48
|
-
const error = touched ? Validation.validate(widgetLang, name, value, validators, fields) : undefined;
|
|
49
|
-
if (field.value !== value || field.error !== undefined && field.error !== error || field.touched !== touched) {
|
|
50
|
-
return {
|
|
51
|
-
...fields,
|
|
52
|
-
[name]: {
|
|
53
|
-
...field,
|
|
54
|
-
value,
|
|
55
|
-
error,
|
|
56
|
-
touched
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
} else {
|
|
60
|
-
return fields;
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
}, [widgetLang]);
|
|
64
|
-
const handleCategory = React.useCallback(params => {
|
|
65
|
-
const needCategory = params?.categories?.length > 1;
|
|
66
|
-
setNeedCategory(needCategory);
|
|
67
|
-
if (!needCategory) {
|
|
68
|
-
if (params?.categories?.length === 1) {
|
|
69
|
-
update(true, "category", params.categories[0].code, []);
|
|
70
|
-
} else {
|
|
71
|
-
update(true, "category", undefined, []);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}, [update]);
|
|
75
|
-
React.useEffect(() => {
|
|
76
|
-
const getParams = async () => {
|
|
77
|
-
const params = await API.fetchParams(widgetLang, resort, merchant, channel, categories, integration, uat);
|
|
78
|
-
if (params === undefined || params.error !== undefined) {
|
|
79
|
-
setHasError(true);
|
|
80
|
-
} else {
|
|
81
|
-
setParams(params);
|
|
82
|
-
handleCategory(params);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
getParams();
|
|
86
|
-
}, [categories, channel, handleCategory, integration, merchant, resort, uat, widgetLang]);
|
|
87
|
-
const validateAll = () => {
|
|
88
|
-
Object.keys(fields).forEach(key => {
|
|
89
|
-
update(true, key, undefined, !needCategory && key === "category" ? undefined : fields[key].validators);
|
|
90
|
-
});
|
|
91
|
-
};
|
|
92
|
-
const isValidated = () => {
|
|
93
|
-
return Object.keys(fields).reduce((acc, key) => {
|
|
94
|
-
const field = fields[key];
|
|
95
|
-
return acc && field.touched && field.error === undefined;
|
|
96
|
-
}, true);
|
|
97
|
-
};
|
|
98
|
-
const changed = name => value => {
|
|
99
|
-
update(false, name, value);
|
|
100
|
-
};
|
|
101
|
-
const changedStayFrom = value => {
|
|
102
|
-
update(true, "stayFrom", value);
|
|
103
|
-
update(true, "stayTo", value);
|
|
104
|
-
};
|
|
105
|
-
const blured = name => e => {
|
|
106
|
-
const {
|
|
107
|
-
value
|
|
108
|
-
} = e.target;
|
|
109
|
-
update(true, name, value);
|
|
110
|
-
};
|
|
111
|
-
const submitForm = async e => {
|
|
112
|
-
e.preventDefault();
|
|
113
|
-
setSubmiting(true);
|
|
114
|
-
validateAll();
|
|
115
|
-
if (isValidated()) {
|
|
116
|
-
const payload = Object.keys(fields).reduce((acc, key) => {
|
|
117
|
-
const field = fields[key];
|
|
118
|
-
return {
|
|
119
|
-
...acc,
|
|
120
|
-
[key]: field.value
|
|
121
|
-
};
|
|
122
|
-
}, {});
|
|
123
|
-
onSubmit?.(payload);
|
|
124
|
-
const result = await API.postMessage({
|
|
125
|
-
lang: widgetLang,
|
|
10
|
+
import PhoneCodeSelect from "./phone-code-select";
|
|
11
|
+
import useParams from "./hooks/use-params";
|
|
12
|
+
import * as Messages from "./services/messages";
|
|
13
|
+
import * as Form from "./services/form";
|
|
14
|
+
import * as API from "./services/api";
|
|
15
|
+
import * as Plausible from "./services/plausible";
|
|
16
|
+
import styles from "./gesco-contact-form.module.css";
|
|
17
|
+
export default function GescoContactForm({ lang = "fr", channel = "ESF", resort, merchant, categories, facet = "WINTER", host = "https://admin.mon-sejour-en-montagne.com", onSubmit, messagesOverrides = {}, }) {
|
|
18
|
+
const { params, error } = useParams({
|
|
19
|
+
lang,
|
|
126
20
|
channel,
|
|
127
21
|
resort,
|
|
128
22
|
merchant,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}, integration, uat);
|
|
132
|
-
if (result.error) {
|
|
133
|
-
const message = Messages.get(widgetLang, result.error.message);
|
|
134
|
-
snackbar.show({
|
|
135
|
-
type: "error",
|
|
136
|
-
message: message || result.error.message
|
|
137
|
-
});
|
|
138
|
-
} else {
|
|
139
|
-
snackbar.show({
|
|
140
|
-
type: "success",
|
|
141
|
-
message: Messages.get(widgetLang, "messageSent")
|
|
142
|
-
});
|
|
143
|
-
const country = params.countries.find(country => country.code === payload.country);
|
|
144
|
-
const subject = params.subjects.find(subject => subject.id === Number(payload.subject));
|
|
145
|
-
Plausible.sendGoal("Contact-us", {
|
|
146
|
-
Country: country?.name,
|
|
147
|
-
Subject: subject?.label
|
|
148
|
-
});
|
|
149
|
-
setFields(Data.DEFAULT_FIELDS);
|
|
150
|
-
handleCategory(params);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
setSubmiting(false);
|
|
154
|
-
setTimeout(() => setSubmiting(false), 2000);
|
|
155
|
-
};
|
|
156
|
-
if (hasError) {
|
|
157
|
-
return _jsx("div", {
|
|
158
|
-
className: css.error,
|
|
159
|
-
children: Messages.get(widgetLang, "parametersError")
|
|
23
|
+
categories,
|
|
24
|
+
host,
|
|
160
25
|
});
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
})),
|
|
231
|
-
onBlur: blured("country"),
|
|
232
|
-
error: fields.country.error,
|
|
233
|
-
valid: fields.country.touched && !fields.country.error
|
|
234
|
-
}), needCategory && _jsx(Select, {
|
|
235
|
-
icon: "Plane",
|
|
236
|
-
label: Messages.get(widgetLang, "category"),
|
|
237
|
-
className: css.fullWidthField,
|
|
238
|
-
placeholder: Messages.get(widgetLang, "defaultCategory"),
|
|
239
|
-
value: fields.category.value,
|
|
240
|
-
onValueChange: changed("category"),
|
|
241
|
-
options: params.categories.map(({
|
|
242
|
-
code,
|
|
243
|
-
label
|
|
244
|
-
}) => ({
|
|
245
|
-
label,
|
|
246
|
-
value: code
|
|
247
|
-
})),
|
|
248
|
-
onBlur: blured("category"),
|
|
249
|
-
error: fields.category.error,
|
|
250
|
-
valid: fields.category.touched && !fields.category.error
|
|
251
|
-
}), _jsx(Input, {
|
|
252
|
-
className: css.stayField,
|
|
253
|
-
type: "date",
|
|
254
|
-
label: Messages.get(widgetLang, "stayFromDate"),
|
|
255
|
-
value: fields.stayFrom.value,
|
|
256
|
-
placeholder: Messages.get(widgetLang, "dateFormat"),
|
|
257
|
-
onValueChange: changedStayFrom,
|
|
258
|
-
error: fields.stayFrom.error,
|
|
259
|
-
valid: fields.stayFrom.touched && !fields.stayFrom.error
|
|
260
|
-
}), _jsx(Input, {
|
|
261
|
-
className: css.stayField,
|
|
262
|
-
type: "date",
|
|
263
|
-
label: Messages.get(widgetLang, "stayToDate"),
|
|
264
|
-
value: fields.stayTo.value,
|
|
265
|
-
placeholder: Messages.get(widgetLang, "dateFormat"),
|
|
266
|
-
onValueChange: changed("stayTo"),
|
|
267
|
-
error: fields.stayTo.error,
|
|
268
|
-
valid: fields.stayTo.touched && !fields.stayTo.error
|
|
269
|
-
}), _jsx(Textarea, {
|
|
270
|
-
className: css.fullWidthField,
|
|
271
|
-
label: Messages.get(widgetLang, "message"),
|
|
272
|
-
value: fields.message.value,
|
|
273
|
-
onValueChange: changed("message"),
|
|
274
|
-
onBlur: blured("message"),
|
|
275
|
-
error: fields.message.error,
|
|
276
|
-
autoSizing: true,
|
|
277
|
-
valid: fields.message.touched && !fields.message.error
|
|
278
|
-
}), _jsx("div", {
|
|
279
|
-
className: css.send,
|
|
280
|
-
children: submiting ? _jsxs(Button, {
|
|
281
|
-
className: css.buttonSending,
|
|
282
|
-
disabled: true,
|
|
283
|
-
children: [_jsx(Icons.Loader2, {}), Messages.get(widgetLang, "submit")]
|
|
284
|
-
}) : _jsxs(Button, {
|
|
285
|
-
type: "submit",
|
|
286
|
-
children: [_jsx(Icons.Plane, {}), Messages.get(widgetLang, "submit")]
|
|
287
|
-
})
|
|
288
|
-
})]
|
|
289
|
-
});
|
|
290
|
-
}
|
|
26
|
+
const [submiting, setSubmiting] = React.useState(false);
|
|
27
|
+
const [stayToMin, setStayToMin] = React.useState();
|
|
28
|
+
const [stayFromMax, setStayFromMax] = React.useState();
|
|
29
|
+
const [sendSuccess, setSendSuccess] = React.useState(false);
|
|
30
|
+
const [sendError, setSendError] = React.useState(false);
|
|
31
|
+
const [formKey, setFormKey] = React.useState(0);
|
|
32
|
+
const _lang = lang === "fr" ? "fr" : "en";
|
|
33
|
+
const needCategory = params?.categories?.length !== undefined && params?.categories?.length > 1;
|
|
34
|
+
const loading = !error && params === undefined;
|
|
35
|
+
const defaultCategoryValue = params?.categories?.[0].code;
|
|
36
|
+
const messages = Messages.get(_lang, messagesOverrides);
|
|
37
|
+
const subjectOptions = formatOptions("label", "id", params?.subjects);
|
|
38
|
+
const categoryOptions = formatOptions("label", "code", params?.categories);
|
|
39
|
+
const countryOptions = formatOptions("name", "code", params?.countries);
|
|
40
|
+
const submitForm = async (e) => {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
setSubmiting(true);
|
|
43
|
+
setSendSuccess(false);
|
|
44
|
+
setSendError(false);
|
|
45
|
+
const form = e.currentTarget;
|
|
46
|
+
let values = Form.extractValues(form.elements);
|
|
47
|
+
if (!values.category && defaultCategoryValue) {
|
|
48
|
+
values = { ...values, category: defaultCategoryValue };
|
|
49
|
+
}
|
|
50
|
+
const payload = Form.buildPayload({ lang: _lang, merchant, channel, resort, facet }, values);
|
|
51
|
+
try {
|
|
52
|
+
const result = await API.send(host, payload);
|
|
53
|
+
if (result.error) {
|
|
54
|
+
throw new Error(result.error);
|
|
55
|
+
}
|
|
56
|
+
onSubmit?.(payload);
|
|
57
|
+
setSendSuccess(true);
|
|
58
|
+
form.reset();
|
|
59
|
+
setFormKey(formKey + 1);
|
|
60
|
+
Plausible.sendEvent(values, params);
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
// eslint-disable-next-line no-console
|
|
64
|
+
console.error(e);
|
|
65
|
+
setSendError(true);
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
setSubmiting(false);
|
|
69
|
+
}
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
setSubmiting(false);
|
|
72
|
+
setSendSuccess(true);
|
|
73
|
+
}, 3000);
|
|
74
|
+
};
|
|
75
|
+
const hideSuccess = () => {
|
|
76
|
+
setSendSuccess(false);
|
|
77
|
+
};
|
|
78
|
+
const hideError = () => {
|
|
79
|
+
setSendError(false);
|
|
80
|
+
};
|
|
81
|
+
const updateStayToMin = (value) => {
|
|
82
|
+
setStayToMin(value);
|
|
83
|
+
};
|
|
84
|
+
const updateStayFromMax = (value) => {
|
|
85
|
+
setStayFromMax(value);
|
|
86
|
+
};
|
|
87
|
+
return (_jsxs("form", { className: styles.form, onSubmit: submitForm, children: [_jsx(Select, { name: "subject", label: messages.subject, className: styles.fullWidthField, placeholder: messages.defaultSubject, options: subjectOptions, loading: loading, disabled: Boolean(error), required: true }), _jsx(Input, { name: "firstname", type: "text", icon: "User", label: messages.firstname, loading: loading, pattern: ".{2,}", patternError: Messages.format(messages.lengthError, {
|
|
88
|
+
label: messages.firstname,
|
|
89
|
+
length: "1",
|
|
90
|
+
}), disabled: Boolean(error), required: true }), _jsx(Input, { name: "lastname", type: "text", icon: "User", label: messages.lastname, loading: loading, pattern: ".{2,}", patternError: Messages.format(messages.lengthError, {
|
|
91
|
+
label: messages.lastname,
|
|
92
|
+
length: "1",
|
|
93
|
+
}), disabled: Boolean(error), required: true }), _jsx(Input, { name: "email", type: "email", icon: "Mail", label: messages.email, loading: loading, pattern: "[^@\\s]+@[^@\\s]+\\.[^@\\s]+", patternError: messages.emailError, disabled: Boolean(error), required: true }), _jsxs("div", { className: styles.phoneGroup, children: [_jsx(PhoneCodeSelect, { messages: messages, loading: loading, disabled: Boolean(error) }), _jsx(Input, { name: "phone", type: "phone", icon: "Smartphone", label: messages.phone, loading: loading, inputMode: "numeric", pattern: "[0-9 ]{9,15}$", patternError: messages.phoneError, disabled: Boolean(error), required: true })] }), _jsx(Select, { name: "country", icon: "Globe", label: messages.country, className: styles.fullWidthField, placeholder: messages.defaultCountry, options: countryOptions, loading: loading, disabled: Boolean(error), required: true }), needCategory && (_jsx(Select, { name: "category", icon: "Plane", label: messages.category, className: styles.fullWidthField, placeholder: messages.defaultCategory, options: categoryOptions, loading: loading, disabled: Boolean(error), required: true })), _jsx(Input, { name: "stayFrom", className: styles.stayField, type: "date", label: messages.stayFromDate, placeholder: messages.dateFormat, loading: loading, onValueChange: updateStayToMin, hint: stayFromMax, max: stayFromMax, disabled: Boolean(error), extended: true, required: true }), _jsx(Input, { name: "stayTo", className: styles.stayField, type: "date", label: messages.stayToDate, placeholder: messages.dateFormat, loading: loading, onValueChange: updateStayFromMax, hint: stayToMin, min: stayToMin, disabled: Boolean(error), extended: true, required: true }), _jsx(Textarea, { name: "message", className: styles.fullWidthField, label: messages.message, loading: loading, disabled: Boolean(error), required: true, autoSizing: true }), _jsx("div", { className: styles.send, children: _jsxs(Button, { type: "submit", disabled: Boolean(error) || loading || submiting, children: [submiting ? _jsx(Loader, { className: styles.loader }) : _jsx(Icons.Plane, {}), messages.submit] }) }), sendSuccess && (_jsx(Information, { className: styles.response, type: "success", close: hideSuccess, children: messages.sendSucesss })), sendError && (_jsx(Information, { className: styles.response, type: "error", close: hideError, children: messages.sendError })), error && (_jsx(Information, { className: styles.error, type: "warning", children: messages.parametersError }))] }, formKey));
|
|
94
|
+
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
.error {
|
|
2
|
-
padding: 16px;
|
|
3
|
-
background-color: var(--ds-grey-100, #f5f5f5);
|
|
4
|
-
border-radius: var(--ds-radius-200, 10px);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
1
|
.form {
|
|
2
|
+
--gap: 12px;
|
|
3
|
+
|
|
4
|
+
position: relative;
|
|
8
5
|
display: grid;
|
|
9
6
|
grid-template-columns: 1fr;
|
|
10
|
-
gap:
|
|
7
|
+
gap: var(--gap);
|
|
8
|
+
margin-bottom: 20px;
|
|
11
9
|
}
|
|
12
10
|
|
|
13
11
|
@media (min-width: 560px) {
|
|
@@ -16,6 +14,16 @@
|
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
16
|
|
|
17
|
+
.phoneGroup {
|
|
18
|
+
display: flex;
|
|
19
|
+
gap: var(--gap);
|
|
20
|
+
align-items: flex-start;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.phoneGroup > div:last-child {
|
|
24
|
+
flex: 1 1 auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
@media (min-width: 560px) {
|
|
20
28
|
.fullWidthField {
|
|
21
29
|
grid-column: span 2;
|
|
@@ -39,13 +47,22 @@
|
|
|
39
47
|
}
|
|
40
48
|
}
|
|
41
49
|
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
.loader {
|
|
51
|
+
--ds-loader-spinner-size: 17px;
|
|
52
|
+
--ds-loader-thickness: 2px;
|
|
53
|
+
--ds-loader-foreground: var(--ds-grey-800, #000);
|
|
45
54
|
}
|
|
46
55
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
.response {
|
|
57
|
+
grid-column: 1 / -1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.error {
|
|
61
|
+
position: absolute;
|
|
62
|
+
top: 50%;
|
|
63
|
+
left: 50%;
|
|
64
|
+
padding: 16px;
|
|
65
|
+
border-radius: var(--ds-radius-200, 10px);
|
|
66
|
+
transform: translate(-50%, -50%);
|
|
67
|
+
box-shadow: var(--ds-shadow-400, 0 30px 60px rgba(0, 0, 0, 0.12));
|
|
51
68
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Params } from "../types";
|
|
2
|
+
type Arguments = {
|
|
3
|
+
lang: string;
|
|
4
|
+
channel: string;
|
|
5
|
+
resort?: number;
|
|
6
|
+
merchant?: string;
|
|
7
|
+
categories?: string[];
|
|
8
|
+
host: string;
|
|
9
|
+
};
|
|
10
|
+
export default function useParams(args: Arguments): {
|
|
11
|
+
params: Params | undefined;
|
|
12
|
+
error: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=use-params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-params.d.ts","sourceRoot":"","sources":["../../../../../src/common/components/gesco-contact-form/hooks/use-params.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,IAAI,EAAE,SAAS;;;EAuBhD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as API from "../services/api";
|
|
3
|
+
export default function useParams(args) {
|
|
4
|
+
const [params, setParams] = React.useState();
|
|
5
|
+
const [error, setError] = React.useState();
|
|
6
|
+
const { lang, resort, merchant, channel, categories, host } = args;
|
|
7
|
+
React.useEffect(() => {
|
|
8
|
+
const runEffect = async () => {
|
|
9
|
+
try {
|
|
10
|
+
const payload = { lang, channel, resort, merchant, categories };
|
|
11
|
+
const result = await API.getParams(host, payload);
|
|
12
|
+
if (!result || result.error) {
|
|
13
|
+
throw new Error(result.error);
|
|
14
|
+
}
|
|
15
|
+
setParams(result);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
setError(error);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
runEffect();
|
|
22
|
+
}, [categories, channel, host, lang, merchant, resort]);
|
|
23
|
+
return { params, error };
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/common/components/gesco-contact-form/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,sBAAsB,CAAC;AAEpD,eAAe,gBAAgB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import GescoContactForm from "./gesco-contact-form";
|
|
2
|
-
export default GescoContactForm;
|
|
2
|
+
export default GescoContactForm;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
messages: Record<string, string>;
|
|
3
|
+
loading?: boolean;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export default function PhoneCodeSelect({ messages, loading, disabled, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=phone-code-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone-code-select.d.ts","sourceRoot":"","sources":["../../../../src/common/components/gesco-contact-form/phone-code-select.tsx"],"names":[],"mappings":"AAMA,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA0BF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,QAAQ,EACR,OAAO,EACP,QAAQ,GACT,EAAE,KAAK,2CA4CP"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Select from "dt-design-system/es/custom-select";
|
|
3
|
+
import * as Flags from "dt-design-system/es/flags";
|
|
4
|
+
import prefixes from "./data/phone-prefixes.json";
|
|
5
|
+
import styles from "./phone-code-select.module.css";
|
|
6
|
+
const IGNORED_CODES = [
|
|
7
|
+
"33",
|
|
8
|
+
"44",
|
|
9
|
+
"32",
|
|
10
|
+
"31",
|
|
11
|
+
"41",
|
|
12
|
+
"1",
|
|
13
|
+
"352",
|
|
14
|
+
"353",
|
|
15
|
+
"34",
|
|
16
|
+
"55",
|
|
17
|
+
"49",
|
|
18
|
+
"39",
|
|
19
|
+
"351",
|
|
20
|
+
"61",
|
|
21
|
+
];
|
|
22
|
+
const FIRST_PREFIX = prefixes[0];
|
|
23
|
+
export default function PhoneCodeSelect({ messages, loading, disabled, }) {
|
|
24
|
+
const defaultValue = `${FIRST_PREFIX.country}|${FIRST_PREFIX.code}`;
|
|
25
|
+
const deduppedPrefixes = prefixes
|
|
26
|
+
.reduce((acc, prefix) => {
|
|
27
|
+
const { code } = prefix;
|
|
28
|
+
const splitted = code
|
|
29
|
+
.split(", ")
|
|
30
|
+
.map((splitted) => ({ ...prefix, code: splitted }));
|
|
31
|
+
return [...acc, ...splitted];
|
|
32
|
+
}, [])
|
|
33
|
+
.sort((a, b) => {
|
|
34
|
+
if (IGNORED_CODES.includes(a.code) || IGNORED_CODES.includes(b.code)) {
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
return a.code.localeCompare(b.code);
|
|
38
|
+
});
|
|
39
|
+
const options = deduppedPrefixes.map(({ country, code, iso }) => {
|
|
40
|
+
const Icon = Flags[iso.toLowerCase()] || "svg";
|
|
41
|
+
return {
|
|
42
|
+
label: (_jsxs("span", { className: styles.option, children: [_jsx(Icon, { className: styles.icon }), _jsxs("span", { className: styles.code, children: ["+", code] })] })),
|
|
43
|
+
value: `${country}|${code}`,
|
|
44
|
+
kind: "item",
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
return (_jsx(Select, { name: "phoneCode", className: styles.select, label: messages.phoneCode, options: options, defaultValue: defaultValue, loading: loading, disabled: disabled, required: true }));
|
|
48
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.select {
|
|
2
|
+
flex: 0 0 110px;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.option {
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
gap: 10px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.icon {
|
|
12
|
+
flex: 0 0 20px;
|
|
13
|
+
width: 20px;
|
|
14
|
+
height: auto;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.icon:empty {
|
|
18
|
+
height: 15px;
|
|
19
|
+
background-color: var(--ds-grey-200, #ededed);
|
|
20
|
+
border-radius: calc(var(--ds-radius-100, 4px) / 2);
|
|
21
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type ParamsPayload = {
|
|
2
|
+
lang: string;
|
|
3
|
+
channel: string;
|
|
4
|
+
resort?: number;
|
|
5
|
+
merchant?: string;
|
|
6
|
+
categories?: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function getParams(host: string, payload: ParamsPayload): Promise<any>;
|
|
9
|
+
type SendPayload = {
|
|
10
|
+
lang: "fr" | "en";
|
|
11
|
+
channel: string;
|
|
12
|
+
resort?: number;
|
|
13
|
+
merchant?: string;
|
|
14
|
+
facet: "WINTER" | "SUMMER";
|
|
15
|
+
subject: string;
|
|
16
|
+
firstname: string;
|
|
17
|
+
lastname: string;
|
|
18
|
+
email: string;
|
|
19
|
+
phone: string;
|
|
20
|
+
country: string;
|
|
21
|
+
category?: string;
|
|
22
|
+
stayFrom: string;
|
|
23
|
+
stayTo: string;
|
|
24
|
+
message: string;
|
|
25
|
+
userAgent?: string;
|
|
26
|
+
language?: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function send(host: string, payload: SendPayload): Promise<any>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../../src/common/components/gesco-contact-form/services/api.ts"],"names":[],"mappings":"AAGA,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,gBAInE;AAED,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,gBAI5D"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// import * as Fetcher from "ublo-lib/es/common/utils/fetcher";
|
|
2
|
+
import * as Fetcher from "../../../utils/fetcher";
|
|
3
|
+
export async function getParams(host, payload) {
|
|
4
|
+
const endpoint = `${host}/api/gesco/contact/parameters`;
|
|
5
|
+
const result = await Fetcher.post(endpoint, payload);
|
|
6
|
+
return result;
|
|
7
|
+
}
|
|
8
|
+
export async function send(host, payload) {
|
|
9
|
+
const endpoint = `${host}/api/gesco/contact/send`;
|
|
10
|
+
const result = await Fetcher.post(endpoint, payload);
|
|
11
|
+
return result;
|
|
12
|
+
}
|