Skip to content

Commit

Permalink
Front changes part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
Oksydan committed Dec 5, 2023
1 parent 4d1908e commit d382b2d
Show file tree
Hide file tree
Showing 36 changed files with 531 additions and 234 deletions.
14 changes: 14 additions & 0 deletions _theme_dev/src/css/theme/components/_cart-preview-content.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

.cart-preview-content {
$self: &;

&--dropdown {
#{$self} {
&__products {
max-height: rem-calc(300px);
overflow-y: auto;
overflow-x: hidden;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

.cart-preview-dropdown {
width: rem-calc(320px);
}
2 changes: 2 additions & 0 deletions _theme_dev/src/css/theme/components/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "cart-preview-dropdown";
@import "cart-preview-content";
3 changes: 3 additions & 0 deletions _theme_dev/src/css/theme/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import "@themeAbstract";
@import "components";

16 changes: 16 additions & 0 deletions _theme_dev/src/js/theme/handler/closePreviewDropdownHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const closePreviewDropdownHandler = (e) => {
e.preventDefault();
e.stopPropagation();

const target = e.delegateTarget?.dataset?.target;

if (target) {
const dropdown = document.querySelector(target);

if (dropdown) {
bootstrap.Dropdown.getOrCreateInstance(dropdown).hide();
}
}
}

Check failure on line 14 in _theme_dev/src/js/theme/handler/closePreviewDropdownHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Missing semicolon

export default closePreviewDropdownHandler;
6 changes: 6 additions & 0 deletions _theme_dev/src/js/theme/handler/openNotificationHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

Check failure on line 1 in _theme_dev/src/js/theme/handler/openNotificationHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Too many blank lines at the beginning of file. Max of 0 allowed
const openNotificationHandler = (resp) => {

Check failure on line 2 in _theme_dev/src/js/theme/handler/openNotificationHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

'resp' is defined but never used

}

Check failure on line 4 in _theme_dev/src/js/theme/handler/openNotificationHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Missing semicolon

export default openNotificationHandler;
28 changes: 28 additions & 0 deletions _theme_dev/src/js/theme/handler/updateCartHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import updatePreviewCartRequest from "../request/updatePreviewCartRequest";

Check failure on line 1 in _theme_dev/src/js/theme/handler/updateCartHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Strings must use singlequote

const updateCartHandler = (event) => {
debugger

Check failure on line 4 in _theme_dev/src/js/theme/handler/updateCartHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Unexpected 'debugger' statement

Check failure on line 4 in _theme_dev/src/js/theme/handler/updateCartHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Missing semicolon
if (!event?.reason || !event?.resp || event?.resp?.hasError) {
return;
}

const payload = {
id_customization: event.reason.idCustomization,
id_product_attribute: event.reason.idProductAttribute,
id_product: event.reason.idProduct,
action: event.reason.linkAction,
};

// refreshCartPreviewUrl is defined as a global variable in the module
const { getRequest } = updatePreviewCartRequest(refreshCartPreviewUrl, payload);

Check failure on line 17 in _theme_dev/src/js/theme/handler/updateCartHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

'refreshCartPreviewUrl' is not defined

getRequest()
.then((resp) => {
prestashop.emit('updatedCartPreview', resp);
})
.catch((resp) => {
prestashop.emit('handleError', { eventType: 'updateShoppingCart', resp });
});
}

Check failure on line 26 in _theme_dev/src/js/theme/handler/updateCartHandler.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Missing semicolon

export default updateCartHandler;
74 changes: 28 additions & 46 deletions _theme_dev/src/js/theme/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
function initShoppingCart() {
const bindEvents = () => {
const blockCart = document.querySelector('.js-blockcart');

// blockCart.addEventListener('show.bs.dropdown', () => { Change to vanilla js when bootstrap 5 is adopted
eventHandlerOn(blockCart, 'show.bs.dropdown', () => {
document.body.classList.add('header-dropdown-open', 'block-cart-open');
});

// blockCart.addEventListener('hide.bs.dropdown', (e) => { Change to vanilla js when bootstrap 5 is adopted
eventHandlerOn(blockCart, 'hide.bs.dropdown', (e) => {
const { target } = e;
if (!target.classList.contains('dropdown-close')
&& (target.classList.contains('keep-open') || target.closest('.keep-open')
|| (e.clickEvent && e.clickEvent.target.closest('.keep-open')))) {
return false; // returning false should stop the dropdown from hiding.
}
document.body.classList.remove('header-dropdown-open', 'block-cart-open');
return true;
});
};
import selectorsMap from './selectors/selectorsMap';
import closePreviewDropdownHandler from './handler/closePreviewDropdownHandler';
import updateCartHandler from "./handler/updateCartHandler";

Check failure on line 3 in _theme_dev/src/js/theme/index.js

View workflow job for this annotation

GitHub Actions / Code quality - ESLint

Strings must use singlequote

const cartPreviewController = () => {
const {
cartPreviewBtn,
cartPreview,
cartPreviewContent,
cartDropdownClose
} = selectorsMap;

const showModal = (modalHtml) => {
const getBlockCartModalElement = () => document.querySelector('#blockcart-modal');
Expand All @@ -40,21 +30,11 @@ function initShoppingCart() {
bootstrap.Modal.getOrCreateInstance(newModal).show();
};

bindEvents();

const handleModalErrorToggle = (resp) => {
const errorModal = document.querySelector('#blockcart-error');
const alertBlock = document.querySelector('.js-blockcart-alert');

alertBlock.innerHTML = resp.errors.join('<br/>');
bootstrap.Modal.getOrCreateInstance(errorModal).show();
};

const handleUpdateCartBlock = (resp) => {
const previewHtml = parseToHtml(resp.preview).querySelector('.js-blockcart');
const previewHtml = parseToHtml(resp.preview).querySelector('.js-cart-preview');

if (previewHtml) {
document.querySelector('.js-blockcart').replaceWith(previewHtml);
document.querySelector('.js-cart-preview').replaceWith(previewHtml);
}

if (resp.modal) {
Expand All @@ -64,30 +44,21 @@ function initShoppingCart() {
prestashop.emit('updatedBlockCart', resp);

if (document.body.classList.contains('block-cart-open')) {
const dropdown = document.body.querySelector('.js-blockcart [data-toggle="dropdown"]');
const dropdown = document.body.querySelector('.js-cart-preview [data-toggle="dropdown"]');

if (dropdown) {
bootstrap.Dropdown.getOrCreateInstance(dropdown).show();
}
}

bindEvents();

document.body.classList.remove('cart-loading');
};

const handleUpdateCart = (event) => {
const refreshURL = document.querySelector('.js-blockcart')?.dataset?.refreshUrl;
const refreshURL = document.querySelector('.js-cart-preview')?.dataset?.refreshUrl;

if (!refreshURL) {
return;
}

if (event && event.resp && event.resp.hasError) {
handleModalErrorToggle(event.resp);
return;
}

const requestData = {
id_customization: event.reason.idCustomization,
id_product_attribute: event.reason.idProductAttribute,
Expand All @@ -107,9 +78,20 @@ function initShoppingCart() {
});
};

prestashop.on('updateCart', handleUpdateCart);
const init = () => {
prestashop.on('updateCart', updateCartHandler);

each(cartDropdownClose, (el) => {
eventHandlerOn(el, 'click', closePreviewDropdownHandler);
});
}

return {
init
}
}

DOMReady(() => {
initShoppingCart();
const { init } = cartPreviewController();
init();
});
26 changes: 26 additions & 0 deletions _theme_dev/src/js/theme/request/updatePreviewCartRequest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import useHttpRequest from '@js/utils/http/useHttpRequest';

const updatePreviewCartRequest = (url, payload = {}) => {
const { request } = useHttpRequest(url);

/**
* Executes the request to get the preview cart.
* @function
* @memberof updatePreviewCartRequest
* @return {Promise<Object>} A Promise that resolves with the response data.
*/
const getRequest = () => new Promise((resolve) => {
request
.query(payload)
.post()
.json((resp) => {
resolve(resp);
});
});

return {
getRequest,
};
};

export default updatePreviewCartRequest;
9 changes: 9 additions & 0 deletions _theme_dev/src/js/theme/selectors/selectorsMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

const selectorsMap = {
cartPreviewBtn: '.js-cart-preview-btn',
cartPreview: '.js-cart-preview',
cartPreviewContent: '.js-cart-preview-content',
cartDropdownClose: '.js-close-cart-dropdown',
}

export default selectorsMap;
8 changes: 7 additions & 1 deletion config/front/services.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
imports:
- { resource: ../common.yml }


services:
_defaults:
public: false
Expand All @@ -17,3 +16,10 @@ services:
- '../../src/{Controller,Form}'
- '../../src/index.php'
- '../../src/*/index.php'

Oksydan\IsShoppingcart\Hook\:
resource: '../../src/Hook/*'
public: true
exclude:
- '../../src/Hook/index.php'
- '../../src/Hook/*/index.php'
29 changes: 10 additions & 19 deletions controllers/front/ajax.php
Original file line number Diff line number Diff line change
@@ -1,35 +1,26 @@
<?php

use Oksydan\IsShoppingcart\View\PreviewRender;
use PrestaShop\PrestaShop\Adapter\Presenter\Cart\CartPresenter;

class Is_ShoppingcartAjaxModuleFrontController extends ModuleFrontController
class Is_shoppingcartAjaxModuleFrontController extends ModuleFrontController
{
/**
* @var bool
*/
public $ssl = true;

/**
* @see FrontController::displayAjax()
* @see FrontController::displayAjaxGetCartPreview()
*
* @return void
*/
public function displayAjax(): void
public function displayAjaxGetCartPreview(): void
{
$modal = null;
xdebug_break();
$previewContentRender = $this->get(PreviewRender::class);
$previewBtnRender = $this->get(PreviewRender::class);

if ($this->module instanceof Is_Shoppingcart && Tools::getValue('action') === 'add-to-cart') {
$modal = $this->renderModal(
$this->context->cart,
(int) Tools::getValue('id_product'),
(int) Tools::getValue('id_product_attribute'),
(int) Tools::getValue('id_customization')
);
}
header('Content-Type: application/json');

$this->ajaxRender(json_encode([
'preview' => $this->module instanceof Is_Shoppingcart ? $this->module->hookDisplayTop(['cart' => $this->context->cart]) : '',
'modal' => $modal,
'previewContent' => $previewContentRender->render($this->context->cart),
'previewBtn' => $previewBtnRender->render($this->context->cart),
]));
}

Expand Down
1 change: 0 additions & 1 deletion is_shoppingcart.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ public function install(): bool
public function installHooks(): bool
{
return $this->registerHook('displayTop')
&& $this->registerHook('displayBeforeBodyClosingTag')
&& $this->registerHook('actionFrontControllerSetMedia');
}

Expand Down
23 changes: 23 additions & 0 deletions src/Configuration/NotificationsTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Oksydan\IsShoppingcart\Configuration;

class NotificationsTypes
{
public const NOTIFICATION_TYPE_TOAST = 'toast';

public const NOTIFICATION_TYPE_MODAL = 'modal';

public const NOTIFICATION_TYPE_NONE = 'none';

public static function getTypes(): array
{
return [
self::NOTIFICATION_TYPE_TOAST,
self::NOTIFICATION_TYPE_MODAL,
self::NOTIFICATION_TYPE_NONE,
];
}
}
19 changes: 19 additions & 0 deletions src/Configuration/PreviewTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Oksydan\IsShoppingcart\Configuration;

class PreviewTypes
{
public const PREVIEW_TYPE_OFFCANVAS = 'offcanvas';
public const PREVIEW_TYPE_DROPDOWN = 'dropdown';

public static function getTypes(): array
{
return [
self::PREVIEW_TYPE_OFFCANVAS,
self::PREVIEW_TYPE_DROPDOWN,
];
}
}
9 changes: 5 additions & 4 deletions src/Form/ChoiceProvider/NotificationTypeChoiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Oksydan\IsShoppingcart\Form\ChoiceProvider;

use Oksydan\IsShoppingcart\Configuration\NotificationsTypes;
use Oksydan\IsShoppingcart\Translations\TranslationDomains;
use PrestaShop\PrestaShop\Core\Form\FormChoiceProviderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
Expand Down Expand Up @@ -31,7 +32,7 @@ public function getChoices(): array
{
$choices = [];

foreach (self::TYPES as $type) {
foreach (NotificationsTypes::getTypes() as $type) {
$choices[$this->getLabelByType($type)] = $type;
}

Expand All @@ -41,11 +42,11 @@ public function getChoices(): array
private function getLabelByType(string $type): string
{
switch ($type) {
case 'modal':
case NotificationsTypes::NOTIFICATION_TYPE_MODAL:
return $this->translator->trans('Modal', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN);
case 'toast':
case NotificationsTypes::NOTIFICATION_TYPE_TOAST:
return $this->translator->trans('Floating toast', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN);
case 'none':
case NotificationsTypes::NOTIFICATION_TYPE_NONE:
return $this->translator->trans('No notification', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN);
default:
throw new \InvalidArgumentException(sprintf('Unknown type "%s"', $type));
Expand Down
Loading

0 comments on commit d382b2d

Please sign in to comment.