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

feat(RSS-ECOMM-5_11): translate breadcrumbs #351

Merged
merged 9 commits into from
Jun 8, 2024
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