-
-
Notifications
You must be signed in to change notification settings - Fork 130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add price override in react delivery form #4860
base: master
Are you sure you want to change the base?
Changes from all commits
05a0697
fd4e5a5
0064f49
9c3f4fb
55b7307
cf0ad48
d93c78a
fdc6094
c5a01db
46cc535
3a4c5a7
512e362
0a1bd7e
2d7d093
5e09e38
bb46a8d
53bad10
03e1381
7544262
488c887
7547c94
de69878
55b5473
f75b104
f46b614
722f3c4
71b3dc6
2c2965f
53fa7d2
edc9f36
3622567
7b01640
30b9903
932aaba
8558f26
f34ccd1
faced90
61a1d15
19e6417
0eb4117
e79fb86
0a73058
26a78f8
3d1d9b4
a599b7a
96b1beb
7b10b09
49efaba
7d79b98
c2a9a54
b3bb9f0
a9d9468
f402ce2
ecf9e7f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for the catch i ll fix this |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
import React, { useCallback, useEffect, useRef, useState } from 'react' | ||
import React, { useCallback, useEffect, useState } from 'react' | ||
import { Button } from 'antd' | ||
import { Formik, Form, FieldArray } from 'formik' | ||
import Task from '../../../../js/app/components/delivery-form/Task.js' | ||
import { antdLocale } from '../../../../js/app/i18n' | ||
import { ConfigProvider } from 'antd' | ||
import moment from 'moment' | ||
import { money } from '../../controllers/Incident/utils.js' | ||
|
||
import Map from '../../../../js/app/components/delivery-form/Map.js' | ||
import Spinner from '../../../../js/app/components/core/Spinner.js' | ||
import _ from 'lodash' | ||
|
||
import BarcodesModal from '../BarcodesModal.jsx' | ||
import ShowPrice from '../../../../js/app/components/delivery-form/ShowPrice.js' | ||
import Task from '../../../../js/app/components/delivery-form/Task.js' | ||
|
||
import { PhoneNumberUtil } from 'google-libphonenumber' | ||
import { getCountry } from '../../../../js/app/i18n' | ||
|
@@ -18,8 +18,8 @@ import { parsePhoneNumberFromString } from 'libphonenumber-js' | |
|
||
|
||
import "./DeliveryForm.scss" | ||
import BarcodesModal from '../BarcodesModal.jsx' | ||
import OverridePrice from '../../../../js/app/components/delivery-form/OverridePrice.js' | ||
import _ from 'lodash' | ||
|
||
|
||
/** used in case of phone validation */ | ||
const phoneUtil = PhoneNumberUtil.getInstance(); | ||
|
@@ -107,6 +107,8 @@ const baseURL = location.protocol + '//' + location.host | |
|
||
export default function ({ storeId, deliveryId, order }) { | ||
|
||
console.log(order) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove? |
||
// This variable is used to test the store role and restrictions. We need to have it passed as prop to make it work. | ||
const isAdmin = true | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to call |
||
|
@@ -124,18 +126,20 @@ export default function ({ storeId, deliveryId, order }) { | |
tasks: [ | ||
pickupSchema, | ||
dropoffSchema, | ||
] | ||
], | ||
}) | ||
const [isLoading, setIsLoading] = useState(Boolean(deliveryId)) | ||
const [overridePrice, setOverridePrice] = useState(false) | ||
const [priceLoading, setPriceLoading] = useState(false) | ||
|
||
|
||
let deliveryPrice | ||
|
||
if (order) { | ||
if (deliveryId && order) { | ||
const orderInfos = JSON.parse(order) | ||
deliveryPrice = {exVAT: +orderInfos.total, VAT: +orderInfos.total - +orderInfos.taxTotal,} | ||
} | ||
|
||
|
||
const { t } = useTranslation() | ||
|
||
const validate = (values) => { | ||
|
@@ -170,12 +174,13 @@ export default function ({ storeId, deliveryId, order }) { | |
} | ||
} | ||
|
||
return Object.keys(errors.tasks).length > 0 ? errors : {} | ||
} | ||
|
||
// Could not figure out why, but sometimes Formik "re-renders" even if the values are the same. | ||
// so i store a ref to previous values to avoid re-calculating the price. | ||
const previousValues = useRef(initialValues); | ||
if (overridePrice && !values.variantName) { | ||
errors.variantName = t("DELIVERY_FORM_ERROR_VARIANT_NAME") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
return Object.keys(errors.tasks).length > 0 || errors.variantName ? errors : {}; | ||
} | ||
|
||
useEffect(() => { | ||
const deliveryURL = `${baseURL}/api/deliveries/${deliveryId}?groups=barcode,address,delivery` | ||
|
@@ -213,8 +218,6 @@ export default function ({ storeId, deliveryId, order }) { | |
} | ||
}) | ||
|
||
previousValues.current = delivery.response | ||
|
||
setInitialValues(delivery.response) | ||
setTrackingLink(delivery.response.trackingUrl) | ||
setAddresses(addresses.response['hydra:member']) | ||
|
@@ -261,11 +264,23 @@ export default function ({ storeId, deliveryId, order }) { | |
const createOrEditADelivery = async (deliveryId) => { | ||
const url = getUrl(deliveryId); | ||
const method = deliveryId ? 'put' : 'post'; | ||
return await httpClient[method](url, { | ||
|
||
let data = { | ||
store: storeDeliveryInfos['@id'], | ||
tasks: values.tasks | ||
}); | ||
} | ||
|
||
if (values.variantIncVATPrice && values.variantName) { | ||
data = { | ||
...data, | ||
arbitraryPrice: { | ||
variantPrice: values.variantIncVATPrice, | ||
variantName: values.variantName | ||
} | ||
} | ||
} | ||
|
||
return await httpClient[method](url, data); | ||
} | ||
|
||
const {response, error} = await createOrEditADelivery(deliveryId) | ||
|
@@ -299,73 +314,50 @@ export default function ({ storeId, deliveryId, order }) { | |
}, [storeDeliveryInfos]) | ||
|
||
|
||
const getPrice = (values) => { | ||
const getPrice = _.debounce( | ||
(values) => { | ||
|
||
if (_.isEqual(previousValues.current, values)) { | ||
return | ||
} | ||
const tasksCopy = structuredClone(values.tasks) | ||
const tasksWithoutId = tasksCopy.map(task => { | ||
if (task["@id"]) { | ||
delete task["@id"] | ||
} | ||
return task | ||
}) | ||
|
||
const infos = { | ||
store: storeDeliveryInfos["@id"], | ||
tasks: tasksWithoutId, | ||
}; | ||
|
||
const calculatePrice = async () => { | ||
|
||
previousValues.current = values | ||
setPriceLoading(true) | ||
|
||
const tasksCopy = structuredClone(values.tasks) | ||
const tasksWithoutId = tasksCopy.map(task => { | ||
if (task["@id"]) { | ||
delete task["@id"] | ||
const url = `${baseURL}/api/retail_prices/calculate` | ||
const { response, error } = await httpClient.post(url, infos) | ||
|
||
if (error) { | ||
setPriceError({ isPriceError: true, priceErrorMessage: error.response.data['hydra:description'] }) | ||
setCalculatePrice(0) | ||
} | ||
return task | ||
}) | ||
|
||
let packages = [] | ||
|
||
for (const task of values.tasks) { | ||
if (task.packages && task.type ==="DROPOFF") { | ||
packages.push(...task.packages) | ||
} | ||
} | ||
|
||
const mergedPackages = _(packages) | ||
.groupBy('type') | ||
.map((items, type) => ({ | ||
type, | ||
quantity: _.sumBy(items, 'quantity'), | ||
})) | ||
.value() | ||
if (response) { | ||
setCalculatePrice(response) | ||
setPriceError({ isPriceError: false, priceErrorMessage: ' ' }) | ||
} | ||
|
||
let totalWeight = 0 | ||
setPriceLoading(false) | ||
|
||
for (const task of values.tasks) { | ||
if (task.weight && task.type ==="DROPOFF") { | ||
totalWeight+= task.weight | ||
} | ||
} | ||
|
||
const infos = { | ||
store: storeDeliveryInfos["@id"], | ||
weight: totalWeight, | ||
packages: mergedPackages, | ||
tasks: tasksWithoutId, | ||
}; | ||
|
||
const calculatePrice = async () => { | ||
const url = `${baseURL}/api/retail_prices/calculate` | ||
const { response, error } = await httpClient.post(url, infos) | ||
|
||
if (error) { | ||
setPriceError({ isPriceError: true, priceErrorMessage: error.response.data['hydra:description'] }) | ||
setCalculatePrice(0) | ||
} | ||
|
||
if (response) { | ||
setCalculatePrice(response) | ||
setPriceError({ isPriceError: false, priceErrorMessage: ' ' }) | ||
|
||
if (values.tasks.every(task => task.address.streetAddress)) { | ||
calculatePrice() | ||
} | ||
|
||
} | ||
if (values.tasks.every(task => task.address.streetAddress)) { | ||
calculatePrice() | ||
} | ||
|
||
} | ||
}, | ||
1000 | ||
) | ||
|
||
return ( | ||
isLoading ? | ||
|
@@ -384,8 +376,8 @@ export default function ({ storeId, deliveryId, order }) { | |
{({ values, isSubmitting }) => { | ||
|
||
useEffect(() => { | ||
getPrice(values) | ||
}, [values]); | ||
if(!overridePrice && !deliveryId) getPrice(values) | ||
}, [values.tasks, overridePrice, deliveryId]); | ||
|
||
return ( | ||
<Form > | ||
|
@@ -433,18 +425,27 @@ export default function ({ storeId, deliveryId, order }) { | |
addresses={addresses} | ||
storeId={storeId} | ||
storeDeliveryInfos={storeDeliveryInfos} | ||
onAdd={arrayHelpers.push} | ||
dropoffSchema={dropoffSchema} | ||
onRemove={arrayHelpers.remove} | ||
showRemoveButton={originalIndex > 1} | ||
showAddButton={originalIndex === values.tasks.length - 1} | ||
packages={storePackages} | ||
isAdmin={isAdmin} | ||
tags={tags} | ||
/> | ||
</div> | ||
); | ||
})} | ||
|
||
{storeDeliveryInfos.multiDropEnabled ? <div | ||
className="new-order__dropoffs__add p-4 border mb-4"> | ||
<p>{t('DELIVERY_FORM_MULTIDROPOFF')}</p> | ||
<Button | ||
disabled={false} | ||
onClick={() => { | ||
arrayHelpers.push(dropoffSchema) | ||
}}> | ||
{t('DELIVERY_FORM_ADD_DROPOFF')} | ||
</Button> | ||
</div> : null} | ||
</div> | ||
</div> | ||
)} | ||
|
@@ -472,57 +473,26 @@ export default function ({ storeId, deliveryId, order }) { | |
/> | ||
</div> | ||
|
||
<div className='order-informations__total-price border-top border-bottom pt-3 pb-3 mb-4'> | ||
{deliveryPrice ? | ||
<div className='mb-4'> | ||
<div className='font-weight-bold mb-2'>{ t("DELIVERY_FORM_OLD_PRICE")}</div> | ||
<div>{money(deliveryPrice.exVAT)} {t("DELIVERY_FORM_TOTAL_VAT")}</div> | ||
<div>{money(deliveryPrice.VAT)} {t("DELIVERY_FORM_TOTAL_EX_VAT")}</div> | ||
<div className='mt-2 text-danger'>Editing price is not yet available in beta version.</div> | ||
</div> : null } | ||
|
||
{!deliveryId ? | ||
<> | ||
<div className='font-weight-bold mb-2'>{deliveryId ? t("DELIVERY_FORM_NEW_PRICE") : t("DELIVERY_FORM_TOTAL_PRICE")} </div> | ||
<div> | ||
{calculatedPrice.amount | ||
? | ||
<div> | ||
<div className='mb-1'> | ||
{money(calculatedPrice.amount)} {t("DELIVERY_FORM_TOTAL_VAT")} | ||
</div> | ||
<div> | ||
{money(calculatedPrice.amount - calculatedPrice.tax.amount)} {t("DELIVERY_FORM_TOTAL_EX_VAT")} | ||
</div> | ||
</div> | ||
: | ||
<div> | ||
<div className='mb-1'> | ||
{money(0)} {t("DELIVERY_FORM_TOTAL_VAT")} | ||
</div> | ||
<div> | ||
{money(0)} {t("DELIVERY_FORM_TOTAL_EX_VAT")} | ||
</div> | ||
</div> | ||
} | ||
<OverridePrice/> | ||
</div> | ||
{priceError.isPriceError ? | ||
<div className="alert alert-danger mt-4" role="alert"> | ||
{priceError.priceErrorMessage} | ||
</div> | ||
: null} | ||
</> : | ||
null | ||
} | ||
|
||
<div className='order-informations__total-price border-top border-bottom pt-3 mb-4'> | ||
<ShowPrice | ||
isAdmin={isAdmin} | ||
deliveryId={deliveryId} | ||
deliveryPrice={deliveryPrice} | ||
calculatedPrice={calculatedPrice} | ||
setCalculatePrice={setCalculatePrice} | ||
priceError={priceError} | ||
setOverridePrice={setOverridePrice} | ||
overridePrice={overridePrice} | ||
priceLoading={priceLoading} | ||
/> | ||
</div> | ||
|
||
<div className='order-informations__complete-order'> | ||
<Button | ||
type="primary" | ||
style={{ height: '2.5em' }} | ||
htmlType="submit" disabled={isSubmitting || deliveryId && isAdmin === false}> | ||
htmlType="submit" | ||
disabled={isSubmitting || deliveryId && isAdmin === false}> | ||
{t("DELIVERY_FORM_SUBMIT")} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should also be disabled when |
||
</Button> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it always be excl. VAT and then incl. VAT?