Skip to content

Commit 2f08423

Browse files
authored
Merge pull request #2827 from FromDoppler/dat-2845-crear-new-addon-checkout
[DAT-2845] - Add EcoIA addon in the checkout
2 parents 27bb5e1 + f0b5d96 commit 2f08423

20 files changed

Lines changed: 1009 additions & 88 deletions

File tree

src/App.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import { PushNotifications } from './components/PushNotifications';
5151
import { PushNotificationPlanSelection } from './components/BuyProcess/PushNotificationPlanSelection';
5252
import { AdditionalServices } from './components/MyPlan/AdditionalServices';
5353
import { ConversationPlanSelection } from './components/BuyProcess/ConversationPlanSelection';
54+
import { EcoAIPlanSelection } from './components/BuyProcess/EcoAIPlanSelection';
5455

5556
// https://www.npmjs.com/package/smoothscroll-polyfill
5657
smoothscroll.polyfill();
@@ -242,6 +243,16 @@ const App = ({ locale, window, dependencies: { appSessionRef, sessionManager } }
242243
</PrivateRoute>
243244
}
244245
/>
246+
<Route
247+
path="/buy-ecoia-plan"
248+
element={
249+
<PrivateRoute>
250+
<BuyProcessLayout>
251+
<EcoAIPlanSelection />
252+
</BuyProcessLayout>
253+
</PrivateRoute>
254+
}
255+
/>
245256
<Route
246257
path="/checkout/:pathType/:planType"
247258
element={

src/components/BuyProcess/BuyProcessLayout/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
BUY_ECO_IA_PLAN,
23
BUY_CHAT_PLAN,
34
BUY_LANDING_PACK,
45
BUY_MARKETING_PLAN,
@@ -46,6 +47,13 @@ export const getSteps = (buyType, user) => {
4647
pathname: '/buy-push-notification-plans',
4748
visible: buyType === BUY_PUSH_NOTIFICATION_PLAN.toString(),
4849
},
50+
{
51+
id: 6,
52+
label: 'buy_process.stepper.ai_agent_plan_step',
53+
icon: 'dpicon iconapp-chatting',
54+
pathname: '/buy-ecoia-plan',
55+
visible: buyType === BUY_ECO_IA_PLAN.toString(),
56+
},
4957
{
5058
id: 5,
5159
label: 'buy_process.stepper.finalize_purchase_step',
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import PropTypes from 'prop-types';
2+
import { Formik, Field, Form, FieldArray, useFormikContext } from 'formik';
3+
import { MAX_ECOAI_PACKAGE, numberFormatOptions } from '../../../../doppler-types';
4+
import { FormattedMessage, FormattedNumber, useIntl } from 'react-intl';
5+
6+
const ecoAIFieldNames = {
7+
packages: 'packages',
8+
quantity: 'packagesQty',
9+
};
10+
11+
export const isInvalidInputValue = (values, index) => {
12+
return values[`${ecoAIFieldNames.packages}`][index][`${ecoAIFieldNames.quantity}`] < 0 ||
13+
values[`${ecoAIFieldNames.packages}`][index][`${ecoAIFieldNames.quantity}`] > MAX_ECOAI_PACKAGE;
14+
}
15+
16+
export const isGreatherToMax = (packsSet) =>
17+
packsSet.findIndex((pack) => pack[ecoAIFieldNames.quantity] > MAX_ECOAI_PACKAGE) > -1;
18+
19+
export const isLessToMin = (packsSet) =>
20+
packsSet.findIndex((pack) => pack[ecoAIFieldNames.quantity] < 0) > -1;
21+
22+
export const filterPackagesEqualOrGreatherToZero = (packsSet) =>
23+
packsSet.filter((pack) => pack[ecoAIFieldNames.quantity] > 0);
24+
25+
export const ButtonLess = ({ handleInputValue, index, value }) => {
26+
const { values, setFieldValue } = useFormikContext();
27+
28+
return (
29+
<button
30+
type="button"
31+
onClick={() =>
32+
handleInputValue(
33+
setFieldValue,
34+
values[`${ecoAIFieldNames.packages}`][index][`${ecoAIFieldNames.quantity}`],
35+
`${ecoAIFieldNames.packages}.${index}.${ecoAIFieldNames.quantity}`,
36+
'-',
37+
)
38+
}
39+
aria-label="button less"
40+
>
41+
<span className="dp-button-less">-</span>
42+
</button>
43+
);
44+
};
45+
46+
export const DeletePacksButton = ({ handleRemove, loadingRemovePages }) => {
47+
const intl = useIntl();
48+
const _ = (id, values) => intl.formatMessage({ id: id }, values);
49+
50+
return (
51+
<fieldset className="dp-buttons-packs">
52+
<button
53+
type="button"
54+
className={`dp-button button-medium primary-grey ${
55+
loadingRemovePages ? 'button--loading' : ''
56+
}`}
57+
disabled={loadingRemovePages}
58+
onClick={handleRemove}
59+
>
60+
{_('ai_agent_selection.remove_from_cart_button')}
61+
</button>
62+
</fieldset>
63+
);
64+
};
65+
66+
export const ButtonMore = ({ handleInputValue, index, value }) => {
67+
const { values, setFieldValue } = useFormikContext();
68+
69+
return (
70+
<button
71+
type="button"
72+
onClick={() =>
73+
handleInputValue(
74+
setFieldValue,
75+
values[`${ecoAIFieldNames.packages}`][index][`${ecoAIFieldNames.quantity}`],
76+
`${ecoAIFieldNames.packages}.${index}.${ecoAIFieldNames.quantity}`,
77+
'+',
78+
)
79+
}
80+
aria-label="button more"
81+
>
82+
<span className="dp-button-more">+</span>
83+
</button>
84+
);
85+
};
86+
87+
export const Packs = ({ packs, handleSave, formRef, handleRemove, loadingRemove }) => {
88+
const handleSubmit = (packsSet) => {
89+
const ecoAI = filterPackagesEqualOrGreatherToZero(packsSet);
90+
handleSave(ecoAI);
91+
};
92+
93+
const handleInputValue = (setFieldValue, currentValue, fieldName, operation) => {
94+
if (operation === '+') {
95+
if (currentValue < MAX_ECOAI_PACKAGE) {
96+
setFieldValue(fieldName, currentValue + 1);
97+
}
98+
} else if (currentValue > 0) {
99+
setFieldValue(fieldName, currentValue - 1);
100+
}
101+
};
102+
103+
const validateBeforeSubmit = (values) => {
104+
const packsSet = values[ecoAIFieldNames.packages];
105+
if (!isGreatherToMax(packsSet) && !isLessToMin(packsSet)) {
106+
handleSubmit(packsSet);
107+
}
108+
};
109+
110+
return (
111+
<>
112+
{/* <h3>{_('landing_selection.choose_landings')}</h3> */}
113+
<Formik
114+
initialValues={{
115+
packages: packs,
116+
}}
117+
innerRef={formRef}
118+
validate={validateBeforeSubmit}
119+
enableReinitialize={true}
120+
>
121+
{({ values }) => (
122+
<Form className="awa-form dp-packs">
123+
<FieldArray name={ecoAIFieldNames.packages}>
124+
<>
125+
{values[ecoAIFieldNames.packages].length > 0 &&
126+
values[ecoAIFieldNames.packages].map((pack, index) => (
127+
<fieldset key={`pack${index}`}>
128+
<div className="dp-pack-box">
129+
<p className="dp-mark">
130+
<FormattedMessage
131+
id="ai_agent_selection.plan_of_eco_ai_with_plural"
132+
values={{
133+
packs: pack.quantity,
134+
}}
135+
/>
136+
</p>
137+
</div>
138+
<div className="dp-pack-box">
139+
<h3>
140+
<FormattedMessage
141+
id={`landing_selection.pack_price`}
142+
values={{
143+
price: <FormattedNumber value={pack.fee} {...numberFormatOptions} />,
144+
}}
145+
/>
146+
</h3>
147+
</div>
148+
<div className="dp-pack-box">
149+
<label
150+
htmlFor="email"
151+
className="labelcontrol"
152+
aria-disabled="false"
153+
data-required={isInvalidInputValue(values, index)}
154+
>
155+
<ButtonLess
156+
handleInputValue={handleInputValue}
157+
index={index}
158+
value={pack.quantity}
159+
/>
160+
<Field
161+
disabled={pack.quantity === 1}
162+
name={`${ecoAIFieldNames.packages}.${index}.${ecoAIFieldNames.quantity}`}
163+
type="number"
164+
placeholder="0"
165+
aria-required="true"
166+
aria-placeholder="0"
167+
aria-invalid={isInvalidInputValue(values, index)}
168+
aria-label={`${ecoAIFieldNames.packages}.${index}.${ecoAIFieldNames.quantity}`}
169+
min={0}
170+
max={MAX_ECOAI_PACKAGE}
171+
/>
172+
<ButtonMore
173+
handleInputValue={handleInputValue}
174+
index={index}
175+
value={pack.quantity}
176+
/>
177+
</label>
178+
</div>
179+
</fieldset>
180+
))}
181+
</>
182+
</FieldArray>
183+
<DeletePacksButton handleRemove={handleRemove} loadingRemove={loadingRemove} />
184+
</Form>
185+
)}
186+
</Formik>
187+
</>
188+
);
189+
};
190+
191+
Packs.propTypes = {
192+
packs: PropTypes.arrayOf(
193+
PropTypes.shape({
194+
planId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
195+
description: PropTypes.string,
196+
quantity: PropTypes.number.isRequired,
197+
price: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.node]),
198+
unitPrice: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.node]),
199+
}),
200+
).isRequired,
201+
handleSave: PropTypes.func.isRequired,
202+
formRef: PropTypes.any,
203+
};

0 commit comments

Comments
 (0)