Skip to content

Commit

Permalink
feat(RSS-ECOMM-5_11): translate breadcrumbs (#351)
Browse files Browse the repository at this point in the history
* fix: cart table header styles

* fix: footer styles

* feat: translate breadcrumbs

* refactor: product page model component

* feat: add scroll to top on pagination click

* refactor: replace header heart svg

* feat: translate wishlist breadcrumbs

* refactor: remove unnecessary check
  • Loading branch information
stardustmeg authored Jun 8, 2024
1 parent 8ec81b2 commit 67dc9ad
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 60 deletions.
13 changes: 12 additions & 1 deletion src/features/Pagination/view/PaginationView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class PaginationView {
} else {
this.callback(String(DEFAULT_PAGE + DEFAULT_PAGE));
}
this.scrollToTop();
});

return this.nextPageButton;
Expand All @@ -67,7 +68,10 @@ class PaginationView {
text: page.toString(),
});

btn.getHTML().addEventListener('click', () => this.callback(page.toString()));
btn.getHTML().addEventListener('click', () => {
this.callback(page.toString());
this.scrollToTop();
});

this.pageButtons.push(btn);

Expand All @@ -85,6 +89,7 @@ class PaginationView {
if (currentPage) {
this.callback(String(Number(currentPage) - DEFAULT_PAGE));
}
this.scrollToTop();
});
return this.prevPageButton;
}
Expand All @@ -100,6 +105,12 @@ class PaginationView {
}
}

private scrollToTop(): void {
if (window.scrollY !== 0) {
window.scrollTo({ top: 0 });
}
}

private switchStateNavigationButtons(page: number): void {
this.prevPageButton.getHTML().disabled = page === DEFAULT_PAGE;
this.nextPageButton.getHTML().disabled = page === this.pageButtons.length;
Expand Down
23 changes: 12 additions & 11 deletions src/pages/CartPage/view/CartPageView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { languageVariants } from '@/shared/types/common';
import type ProductOrderModel from '@/widgets/ProductOrder/model/ProductOrderModel';

import RouterModel from '@/app/Router/model/RouterModel.ts';
import ButtonModel from '@/shared/Button/model/ButtonModel.ts';
import ConfirmModel from '@/shared/Confirm/model/ConfirmModel.ts';
import InputModel from '@/shared/Input/model/InputModel.ts';
import LinkModel from '@/shared/Link/model/LinkModel.ts';
Expand All @@ -12,6 +13,7 @@ import getStore from '@/shared/Store/Store.ts';
import { USER_MESSAGE } from '@/shared/constants/confirmUserMessage.ts';
import { PAGE_ID } from '@/shared/constants/pages.ts';
import createBaseElement from '@/shared/utils/createBaseElement.ts';
import { cartPrice, minusCartPrice } from '@/shared/utils/messageTemplates.ts';

import styles from './cartPageView.module.scss';

Expand All @@ -23,13 +25,13 @@ type textElementsType = {
};

const TITLE = {
BUTTON_CHECKOUT: { en: 'Proceed To Checkout', ru: 'Оформить заказ' },
BUTTON_CHECKOUT: { en: 'Proceed to Checkout', ru: 'Оформить заказ' },
BUTTON_COUPON: { en: 'Apply', ru: 'Применить' },
CART_TOTAL: { en: 'Cart Totals', ru: 'Итого по корзине' },
CLEAR: { en: 'Clear all', ru: 'Очистить' },
CONTINUE: { en: 'Continue Shopping', ru: 'Продолжить покупки' },
COUPON_APPLY: { en: 'Coupon Apply', ru: 'Применить купон' },
COUPON_DISCOUNT: { en: 'Cart Coupons', ru: 'Скидки на корзину' },
COUPON_APPLY: { en: 'Apply Coupon', ru: 'Применить купон' },
COUPON_DISCOUNT: { en: 'Cart Discount', ru: 'Скидка на корзину' },
EMPTY: {
en: `Oops! Looks like you haven't added the item to your cart yet.`,
ru: `Ой! Похоже, вы еще не добавили товар в корзину.`,
Expand All @@ -44,7 +46,7 @@ const TITLE = {
class CartPageView {
private addDiscountCallback: DiscountCallback;

private clear: LinkModel;
private clear: ButtonModel;

private clearCallback: ClearCallback;

Expand Down Expand Up @@ -103,7 +105,7 @@ class CartPageView {
innerContent: TITLE.COUPON_DISCOUNT[this.language],
tag: 'p',
});
this.clear = new LinkModel({ classes: [styles.continue, styles.clear], text: TITLE.CLEAR[this.language] });
this.clear = new ButtonModel({ classes: [styles.continue, styles.clear], text: TITLE.CLEAR[this.language] });
this.totalWrap = this.createWrapHTML();
this.totalWrap.classList.add(styles.total);
this.page.append(this.productWrap);
Expand Down Expand Up @@ -226,8 +228,7 @@ class CartPageView {
const tdDelete = createBaseElement({ cssClasses: [styles.th, styles.deleteCell, styles.mainText], tag: 'th' });

this.textElement.push({ element: this.clear.getHTML(), textItem: TITLE.CLEAR });
this.clear.getHTML().addEventListener('click', (event) => {
event.preventDefault();
this.clear.getHTML().addEventListener('click', () => {
const confirmModel = new ConfirmModel(
() => this.clearCallback(),
USER_MESSAGE[getStore().getState().currentLanguage].CLEAR_CART,
Expand Down Expand Up @@ -362,7 +363,7 @@ class CartPageView {
});
const couponValue = createBaseElement({
cssClasses: [styles.title],
innerContent: `-$ ${discount.value.toFixed(2)}`,
innerContent: minusCartPrice(discount.value.toFixed(2)),
tag: 'p',
});
couponItem.append(couponTitle, couponValue);
Expand All @@ -373,15 +374,15 @@ class CartPageView {
const totalDiscountWrap = createBaseElement({ cssClasses: [styles.couponWrap], tag: 'div' });
const totalDiscountValue = createBaseElement({
cssClasses: [styles.title, styles.totalDiscount],
innerContent: `-$ ${totalDiscount.toFixed(2)}`,
innerContent: minusCartPrice(totalDiscount.toFixed(2)),
tag: 'p',
});
totalDiscountWrap.append(this.totalDiscountTitle, totalDiscountValue);
this.discountTotal.append(totalDiscountWrap);
}
const subTotal = cart.total + totalDiscount;
this.subTotal.innerHTML = `$ ${subTotal.toFixed(2)}`;
this.total.innerHTML = `$ ${cart.total.toFixed(2)}`;
this.subTotal.innerHTML = cartPrice(subTotal.toFixed(2));
this.total.innerHTML = cartPrice(cart.total.toFixed(2));
}
}
export default CartPageView;
7 changes: 6 additions & 1 deletion src/pages/CartPage/view/cartPageView.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,18 @@ $color: var(--steam-green-800);
width: max-content;
height: max-content;
text-transform: none;
cursor: pointer;

&::after {
bottom: var(--five);
}
}

.clear {
@include link(0 0, $color);

text-transform: none;
}

.mobileHide {
@media (max-width: 768px) {
display: none;
Expand Down
58 changes: 40 additions & 18 deletions src/pages/ProductPage/model/ProductPageModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import getStore from '@/shared/Store/Store.ts';
import { setCurrentPage } from '@/shared/Store/actions.ts';
import observeStore, { selectCurrentLanguage } from '@/shared/Store/observer.ts';
import { LANGUAGE_CHOICE } from '@/shared/constants/common.ts';
import { PAGE_ID } from '@/shared/constants/pages.ts';
import { PAGE_ID, PAGE_TITLE } from '@/shared/constants/pages.ts';
import { SEARCH_PARAMS_FIELD } from '@/shared/constants/product.ts';
import * as buildPath from '@/shared/utils/buildPathname.ts';
import { showErrorMessage } from '@/shared/utils/userMessage.ts';
Expand All @@ -18,7 +18,7 @@ import ProductInfoModel from '@/widgets/ProductInfo/model/ProductInfoModel.ts';
import ProductPageView from '../view/ProductPageView.ts';

class ProductPageModel implements Page {
private breadcrumbs = new BreadcrumbsModel();
private currentProduct: Product | null = null;

private view: ProductPageView;

Expand All @@ -28,24 +28,27 @@ class ProductPageModel implements Page {
}

private createBreadcrumbLinks(currentProduct: Product): BreadcrumbLink[] {
const { currentLanguage } = getStore().getState();
const isRuLanguage = currentLanguage === LANGUAGE_CHOICE.RU;
const category = currentProduct.category[0].parent;
const subcategory = currentProduct.category[0];

const links: BreadcrumbLink[] = [
{ link: PAGE_ID.MAIN_PAGE, name: PAGE_ID.MAIN_PAGE.toString() },
{ link: PAGE_ID.CATALOG_PAGE, name: PAGE_ID.CATALOG_PAGE.toString() },
{ link: PAGE_ID.MAIN_PAGE, name: PAGE_TITLE[currentLanguage].main },
{ link: PAGE_ID.CATALOG_PAGE, name: PAGE_TITLE[currentLanguage].catalog },
];

if (category) {
links.push({
link: buildPath.catalogPathWithIDAndQuery(null, { category: [category.id] }),
name: category.name[0].value,
name: category.name[Number(isRuLanguage)].value,
});
}

if (subcategory && category) {
links.push({
link: buildPath.catalogPathWithIDAndQuery(null, { category: [category.id], subcategory: [subcategory.id] }),
name: subcategory.name[0].value,
name: subcategory.name[Number(isRuLanguage)].value,
});
}

Expand All @@ -59,16 +62,8 @@ class ProductPageModel implements Page {
.getProductByKey(params.product?.id ?? '')
.then((productData) => {
if (productData) {
const productInfo = new ProductInfoModel({
currentSize: currentSize ?? productData.variant[0].size,
...productData,
});
this.initBreadcrumbs(productData);
this.getHTML().append(productInfo.getHTML(), this.view.getFullDescriptionWrapper());
this.view.setFullDescription(
productData.fullDescription[Number(getStore().getState().currentLanguage === LANGUAGE_CHOICE.RU)].value,
);
this.observeLanguage(productData.fullDescription);
this.currentProduct = productData;
this.updatePageContent(productData, currentSize);
}
})
.catch(showErrorMessage);
Expand All @@ -77,16 +72,43 @@ class ProductPageModel implements Page {
}

private initBreadcrumbs(currentProduct: Product): void {
this.breadcrumbs.addBreadcrumbLinks(this.createBreadcrumbLinks(currentProduct));
this.getHTML().append(this.breadcrumbs.getHTML());
const breadcrumbsContainer = this.view.getBreadcrumbsContainer();
if (!breadcrumbsContainer) {
return;
}

const breadcrumbs = new BreadcrumbsModel();
breadcrumbs.addBreadcrumbLinks(this.createBreadcrumbLinks(currentProduct));

while (breadcrumbsContainer.firstChild) {
breadcrumbsContainer.removeChild(breadcrumbsContainer.firstChild);
}
breadcrumbsContainer.appendChild(breadcrumbs.getHTML());
}

private observeLanguage(fullDescription: localization[]): void {
observeStore(selectCurrentLanguage, () => {
this.view.setFullDescription(
fullDescription[Number(getStore().getState().currentLanguage === LANGUAGE_CHOICE.RU)].value,
);
if (this.currentProduct) {
this.initBreadcrumbs(this.currentProduct);
}
});
}

private updatePageContent(productData: Product, currentSize: null | string): void {
this.initBreadcrumbs(productData);

const productInfo = new ProductInfoModel({
currentSize: currentSize ?? productData.variant[0].size,
...productData,
});
this.getHTML().append(productInfo.getHTML(), this.view.getFullDescriptionWrapper());
this.view.setFullDescription(
productData.fullDescription[Number(getStore().getState().currentLanguage === LANGUAGE_CHOICE.RU)].value,
);
this.observeLanguage(productData.fullDescription);
}

public getHTML(): HTMLDivElement {
Expand Down
17 changes: 17 additions & 0 deletions src/pages/ProductPage/view/ProductPageView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import createBaseElement from '@/shared/utils/createBaseElement.ts';
import styles from './productPageView.module.scss';

class ProductPageView {
private breadcrumbsContainer: HTMLDivElement;

private fullDescription: HTMLParagraphElement;

private fullDescriptionWrapper: HTMLDivElement;
Expand All @@ -17,12 +19,21 @@ class ProductPageView {
constructor(parent: HTMLDivElement) {
this.parent = parent;
this.parent.innerHTML = '';
this.breadcrumbsContainer = this.createBreadcrumbsContainer();
this.fullDescription = this.createFullDescription();
this.fullDescriptionWrapper = this.createFullDescriptionWrapper();
this.page = this.createHTML();
window.scrollTo(0, 0);
}

private createBreadcrumbsContainer(): HTMLDivElement {
this.breadcrumbsContainer = createBaseElement({
cssClasses: [styles.breadcrumbsContainer],
tag: 'div',
});
return this.breadcrumbsContainer;
}

private createFullDescription(): HTMLParagraphElement {
this.fullDescription = createBaseElement({
cssClasses: [styles.fullDescription],
Expand Down Expand Up @@ -56,11 +67,16 @@ class ProductPageView {
tag: 'div',
});

this.page.prepend(this.breadcrumbsContainer);
this.parent.append(this.page);

return this.page;
}

public getBreadcrumbsContainer(): HTMLDivElement {
return this.breadcrumbsContainer;
}

public getFullDescriptionWrapper(): HTMLDivElement {
return this.fullDescriptionWrapper;
}
Expand All @@ -74,4 +90,5 @@ class ProductPageView {
return this.fullDescription;
}
}

export default ProductPageView;
18 changes: 0 additions & 18 deletions src/pages/UserProfilePage/view/UserProfilePageView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ class UserProfilePageView {

private userProfileWrapper: HTMLDivElement;

private wishListLink: LinkModel;

constructor(parent: HTMLDivElement) {
this.parent = parent;
clearOutElement(this.parent);
Expand All @@ -42,7 +40,6 @@ class UserProfilePageView {
this.addressesLink = this.createAddressesLink();
this.ordersLink = this.createOrdersLink();
this.supportLink = this.createSupportLink();
this.wishListLink = this.createWishListLink();
this.accountMenu = this.createAccountMenu();

this.setLinksHandlers();
Expand Down Expand Up @@ -168,21 +165,6 @@ class UserProfilePageView {
return this.userProfileWrapper;
}

private createWishListLink(): LinkModel {
this.wishListLink = new LinkModel({
attrs: {
href: USER_PROFILE_MENU_LINK.WISHLIST,
},
classes: [styles.link],
text: USER_INFO_MENU_LINK[getStore().getState().currentLanguage].WISHLIST,
});
this.links.push(this.wishListLink);

observeCurrentLanguage(this.wishListLink.getHTML(), USER_INFO_MENU_LINK, USER_INFO_MENU_LINK_KEYS.WISHLIST);

return this.wishListLink;
}

private setLinksHandlers(): boolean {
this.links.forEach((link) => {
link.getHTML().addEventListener('click', (event) => {
Expand Down
Loading

0 comments on commit 67dc9ad

Please sign in to comment.