Skip to content
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

Core js refacto part v3 #287

Merged
merged 9 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions _dev/js/theme/components/http/useDefaultHttpRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import useHttpRequest from './useHttpRequest';
* Default http request accepting payload as object and returning promise with response
* @param {string} url - url to send request
* @param {object} payload - payload to send
* @param {object} options - request options for example different headers
* @returns {Promise<unknown>}
*/
const useDefaultHttpRequest = (url, payload) => {
const { request } = useHttpRequest(url);
const useDefaultHttpRequest = (url, payload, options = {}) => {
const { request } = useHttpRequest(url, options);

return new Promise((resolve, reject) => {
request
Expand Down
2 changes: 1 addition & 1 deletion _dev/js/theme/components/http/useHttpPayloadDefinition.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const useHttpPayloadDefinition = (payload, definition) => {
regex,
} = fieldDefinition;

if (required && !value) {
if (required && typeof value === 'undefined') {
validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.REQUIRED}`);
}

Expand Down
53 changes: 17 additions & 36 deletions _dev/js/theme/components/product.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import $ from 'jquery';
import prestashop from 'prestashop';
import useCustomQuantityInput from './useCustomQuantityInput';
import { each } from '../utils/DOMHelpers';

$(() => {
const createInputFile = () => {
Expand All @@ -13,35 +15,24 @@ $(() => {
});
};

const createProductSpin = () => {
const $quantityInput = $('#quantity_wanted');
const initProductQuantityInput = () => {
const initQtySpinner = (spinner) => {
const { init } = useCustomQuantityInput(spinner, {
onQuantityChange: (event) => {
prestashop.emit('updateProduct', {
eventType: 'updatedProductQuantity',
event,
});
},
});

$quantityInput.TouchSpin({
verticalupclass: 'material-icons touchspin-up',
verticaldownclass: 'material-icons touchspin-down',
buttondown_class: 'btn btn-touchspin js-touchspin',
buttonup_class: 'btn btn-touchspin js-touchspin',
min: parseInt($quantityInput.attr('min'), 10),
max: 1000000,
});
init();
};

$quantityInput.on('focusout', () => {
if ($quantityInput.val() === '' || $quantityInput.val() < $quantityInput.attr('min')) {
$quantityInput.val($quantityInput.attr('min'));
$quantityInput.trigger('change');
}
});

$('body').on('change keyup', '#quantity_wanted', (event) => {
$(event.currentTarget).trigger('touchspin.stopspin');
prestashop.emit('updateProduct', {
eventType: 'updatedProductQuantity',
event,
});
});
each('.js-product-qty-spinner', initQtySpinner);
};

createProductSpin();
initProductQuantityInput();
createInputFile();
let updateEvenType = false;

Expand All @@ -66,17 +57,6 @@ $(() => {
prestashop.on('updatedProduct', (event) => {
createInputFile();

if (event && event.product_minimal_quantity) {
const minimalProductQuantity = parseInt(event.product_minimal_quantity, 10);
const quantityInputSelector = '#quantity_wanted';
const quantityInput = $(quantityInputSelector);

// @see http://www.virtuosoft.eu/code/bootstrap-touchspin/ about Bootstrap TouchSpin
quantityInput.trigger('touchspin.updatesettings', {
min: minimalProductQuantity,
});
}

if (updateEvenType === 'updatedProductCombination') {
$('.js-product-images').replaceWith(event.product_cover_thumbnails);
$('.js-product-images-modal').replaceWith(event.product_images_modal);
Expand All @@ -86,5 +66,6 @@ $(() => {
updateEvenType = false;

prestashop.pageLazyLoad.update();
initProductQuantityInput();
});
});
53 changes: 26 additions & 27 deletions _dev/js/theme/components/quickview.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import $ from 'jquery';
import prestashop from 'prestashop';
import DOMReady from '../utils/DOMReady';
import parseToHtml from '../utils/parseToHtml';

$(() => {
prestashop.on('clickQuickView', (elm) => {
const data = {
action: 'quickview',
id_product: elm.dataset.idProduct,
id_product_attribute: elm.dataset.idProductAttribute,
};
$.post(prestashop.urls.pages.product, data, null, 'json')
.then((resp) => {
const $body = $('body');
$('body').append(resp.quickview_html);
const productModal = $(
`#quickview-modal-${resp.product.id}-${resp.product.id_product_attribute}`,
);
productModal.modal('show');
$body.addClass('js-quickview-open');
productModal.on('hidden.bs.modal', () => {
productModal.remove();
$body.removeClass('js-quickview-open');
});
})
.fail((resp) => {
prestashop.emit('handleError', {
eventType: 'clickQuickView',
resp,
});
});
/**
* Handle open quick view
*/
const handleQuickViewOpen = ({
resp,
}) => {
const body = document.querySelector('body');
body.append(parseToHtml(resp.quickview_html));

// TO DO REMOVE JQUERY
const productModal = $(
`#quickview-modal-${resp.product.id}-${resp.product.id_product_attribute}`,
);
productModal.modal('show');

body.classList.add('js-quickview-open');

productModal.on('hidden.bs.modal', () => {
productModal.remove();
body.classList.remove('js-quickview-open');
});
};

DOMReady(() => {
prestashop.on('clickViewOpen', handleQuickViewOpen);
});
40 changes: 38 additions & 2 deletions _dev/js/theme/components/useCustomQuantityInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,40 @@ const useCustomQuantityInput = (spinnerElement, {
maxQty = input.getAttribute('max') ? parseInt(input.getAttribute('max'), 10) : defaultMaxQty;
};

/**
* Update minimum quantity
* @method updateMinQty
* @public
* @param newMinQty
* @returns {void}
*/
const updateMinQty = (newMinQty) => {
const qtyValue = Number.parseInt(newMinQty, 10);

if (Number.isNaN(qtyValue)) {
throw new Error('Invalid minimum quantity');
}

minQty = qtyValue;
};

/**
* Update maximum quantity
* @method updateMaxQty
* @public
* @param newMaxQty
* @returns {void}
*/
const updateMaxQty = (newMaxQty) => {
const qtyValue = Number.parseInt(newMaxQty, 10);

if (Number.isNaN(qtyValue)) {
throw new Error('Invalid maximum quantity');
}

maxQty = qtyValue;
};

/**
* Should dispatch change event
* @method shouldDispatchChange
Expand Down Expand Up @@ -299,7 +333,7 @@ const useCustomQuantityInput = (spinnerElement, {
/**
* Destroy spinner instance and detach events
* @method destroy
* @static
* @public
* @returns {void}
*/
const destroy = () => {
Expand All @@ -310,7 +344,7 @@ const useCustomQuantityInput = (spinnerElement, {
/**
* Initialize spinner instance and attach events
* @method init
* @static
* @public
* @returns {void}
*/
const init = () => {
Expand All @@ -324,6 +358,8 @@ const useCustomQuantityInput = (spinnerElement, {
init,
destroy,
getDOMElements,
updateMinQty,
updateMaxQty,
};
};

Expand Down
4 changes: 2 additions & 2 deletions _dev/js/theme/core/cart/handler/cart/addToCartHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ const addToCartHandler = async (event) => {
const payload = {
id_product: idProduct,
qty,
id_product_attribute: idProductAttribute,
id_customization: idCustomization,
id_product_attribute: Number.parseInt(idProductAttribute, 10),
id_customization: Number.parseInt(idCustomization, 10),
};

const { getRequest } = addToCartRequest(payload);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import prestashop from 'prestashop';
import productStateStore from '../../store/productStateStore';

const { setFormChanged } = productStateStore();

/**
* Sets the form changed state
* Side effect: emits 'updateProduct' event
* @param event {Event}
*/
const productFormChangeHandler = (event) => {
setFormChanged(true);

prestashop.emit('updateProduct', {
eventType: 'updatedProductCombination',
event,
});
};

export default productFormChangeHandler;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import prestashop from 'prestashop';
import productFormDataPersister from '../../persister/productFormDataPersister';
import productStateStore from '../../store/productStateStore';

const { setOnPopState, isFormChanged } = productStateStore();

const { get } = productFormDataPersister();

/**
* Handle popstate event for product page
* Side effect: emits 'updateProduct' event, sets popState in productStateStore
* @param {Event} event
*/
const productPopStateHandler = (event) => {
setOnPopState(true);

const formData = event?.state?.form || get();

if ((!formData || formData?.length === 0) && !isFormChanged()) {
return;
}

const form = document.querySelector(`${prestashop.selectors.product.actions} .js-product-form`);

const handleFormElementState = (data) => {
const element = form.querySelector(`[name="${data.name}"]`);

if (element) {
element.value = data.value;
}
};

formData.forEach(handleFormElementState);

prestashop.emit('updateProduct', {
eventType: 'updatedProductCombination',
event,
});
};

export default productPopStateHandler;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import useAlertToast from '../../../../components/useAlertToast';

const { danger } = useAlertToast();

/**
* Handle product update error
* @param event
*/
const productUpdateErrorHandler = (event) => {
if (event?.errorMessage) {
danger(event.errorMessage);
}
};

export default productUpdateErrorHandler;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import prestashop from 'prestashop';

/**
* Update product customization input value
* Side effect: update product customization input value
* @param eventType {string} - event type
* @param eventData {object} - event data
* @param eventData.id_customization {number} - customization id
* @return {void}
*/
const updateProductCustomizationHandler = (eventType, { id_customization: idCustomization }) => {
const customizationIdInput = document.querySelector(prestashop.selectors.cart.productCustomizationId);

// refill customizationId input value when updating quantity or combination
if (
(eventType === 'updatedProductQuantity' || eventType === 'updatedProductCombination')
&& idCustomization
) {
if (customizationIdInput) {
customizationIdInput.value = idCustomization;
}
} else if (customizationIdInput) {
customizationIdInput.value = 0;
}
};

export default updateProductCustomizationHandler;
Loading