Skip to content
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
8 changes: 6 additions & 2 deletions src/app/models/cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ export interface ILineItem {
export interface IVariant {
id: number;
sku?: string;
prices: IPrice[];
prices: IPrices[];
images: { url: string }[];
}

export interface IPrice {
value: IMoney;
discounted?: IDiscounted;
}

export interface IPrices {
value: IMoney;
discounted?: IDiscounted | null;
}

export interface IMoney {
Expand Down
11 changes: 6 additions & 5 deletions src/app/services/cart-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ export const createCartData = (cart: Cart): ICartData => {
centAmount: price.value.centAmount,
fractionDigits: price.value.fractionDigits,
},
discountedPrice: price.discounted
discounted: price.discounted
? {
// Проверяем, есть ли скидочная цена
currencyCode: price.discounted.value.currencyCode,
centAmount: price.discounted.value.centAmount,
fractionDigits: price.discounted.value.fractionDigits,
value: {
currencyCode: price.discounted.value.currencyCode,
centAmount: price.discounted.value.centAmount,
fractionDigits: price.discounted.value.fractionDigits,
},
}
: null, // Если нет скидочной цены, возвращаем null
}))
Expand Down
85 changes: 60 additions & 25 deletions src/app/services/cart-handler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { showSucessMessage } from '@utils/toast-messages';
import { showErrorMessage } from '@utils/toast-messages';
import { addProductToCart } from './add-product-cart';
import { createAnonymousCart, createCustomerCart } from './carts';

Expand All @@ -7,27 +7,45 @@ class CartHandler {

private currentCartVersion: number | null = null;

public currentCustomerCartId: string | null = null;

private currentCustomerCartVersion: number | null = null;

private userId: string | null = null;

constructor(userId: string | null) {
this.userId = userId;
this.currentCartId = null;
this.currentCartVersion = null;
this.currentCustomerCartId = null;
this.currentCustomerCartVersion = null;

if (!userId) {
this.loadCartFromLocalStorage();
} else {
this.loadCartFromServer(userId);
this.loadCartAuthFromLocalStorage();
}
}

public handleAddToCart(productId: string, quantity: number): void {
if (!this.currentCartId || !this.currentCartVersion) {
// Определяем, какие переменные корзины использовать
let cartId;
let cartVersion;

if (this.userId) {
// Проверка, зарегистрирован ли пользователь
cartId = this.currentCustomerCartId;
cartVersion = this.currentCustomerCartVersion;
} else {
// Для анонимных пользователей
cartId = this.currentCartId;
cartVersion = this.currentCartVersion;
}

if (!cartId || !cartVersion) {
this.createCartAndAddProduct(productId, quantity);
} else {
this.addProductToExistingCart(
this.currentCartId,
this.currentCartVersion,
productId,
quantity
);
this.addProductToExistingCart(cartId, cartVersion, productId, quantity);
}
}

Expand All @@ -36,18 +54,19 @@ class CartHandler {
createCustomerCart(
this.userId,
(cartData) => {
this.currentCartId = cartData.id;
this.currentCartVersion = cartData.version;
this.currentCustomerCartId = cartData.id;
this.currentCustomerCartVersion = cartData.version;
this.saveCartAuthToLocalStorage();
this.addProductToExistingCart(
this.currentCartId,
this.currentCartVersion,
this.currentCustomerCartId,
this.currentCustomerCartVersion,
productId,
quantity
);
},
(errorMessage) => {
const SUCSESS_MSG = `Error creating user cart: ${errorMessage}`;
showSucessMessage(SUCSESS_MSG);
showErrorMessage(SUCSESS_MSG);
}
);
} else {
Expand All @@ -65,7 +84,7 @@ class CartHandler {
},
(errorMessage) => {
const SUCSESS_MSG = `Error creating anonymous cart: ${errorMessage}`;
showSucessMessage(SUCSESS_MSG);
showErrorMessage(SUCSESS_MSG);
}
);
}
Expand All @@ -83,19 +102,22 @@ class CartHandler {
productId,
quantity,
(cartData) => {
this.currentCartId = cartData.id;
this.currentCartVersion = cartData.version;
console.log(
`User ID before deciding to save to localStorage: ${this.userId}`
);
if (!this.userId) {
if (this.userId) {
// Для зарегистрированных пользователей
this.currentCustomerCartId = cartData.id;
this.currentCustomerCartVersion = cartData.version;
this.saveCartAuthToLocalStorage();
} else {
// Для анонимных пользователей
this.currentCartId = cartData.id;
this.currentCartVersion = cartData.version;
this.saveCartToLocalStorage();
}
console.log('Product added to cart:', cartData);
},
(errorMessage) => {
const SUCSESS_MSG = `Error adding product to cart: ${errorMessage}`;
showSucessMessage(SUCSESS_MSG);
showErrorMessage(SUCSESS_MSG);
}
);
}
Expand All @@ -117,9 +139,22 @@ class CartHandler {
}
}

// метод для загрузки корзины зарегистрированного пользователя с сервера
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars
private loadCartFromServer(userId: string): void {}
private saveCartAuthToLocalStorage(): void {
const cartData = {
currentCustomerCartId: this.currentCustomerCartId,
currentCustomerCartVersion: this.currentCustomerCartVersion,
};
localStorage.setItem('customerCart', JSON.stringify(cartData));
}

public loadCartAuthFromLocalStorage(): void {
const savedCart = localStorage.getItem('customerCart');
if (savedCart) {
const cartData = JSON.parse(savedCart);
this.currentCustomerCartId = cartData.currentCustomerCartId;
this.currentCustomerCartVersion = cartData.currentCustomerCartVersion;
}
}
}

export default CartHandler;
4 changes: 2 additions & 2 deletions src/app/services/carts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export const createAnonymousCart = (
.execute()
.then((response: ClientResponse<Cart>) => {
const cartData: Cart = response.body;
successCallback(cartData);
if (cartData.id) {
LocalStorageManager.setCartId(cartData.id);
successCallback(cartData);
} else {
errorCallback('Failed to retrieve cart ID');
}
Expand All @@ -46,10 +46,10 @@ export const createCustomerCart = (
.execute()
.then((response: ClientResponse<Cart>) => {
const cartData: Cart = response.body;
successCallback(cartData);
if (cartData.id) {
LocalStorageManager.setCartId(cartData.id);
console.log('Cart ID saved to localStorage:', cartData.id);
successCallback(cartData);
} else {
errorCallback('Failed to retrieve cart ID');
}
Expand Down
4 changes: 0 additions & 4 deletions src/app/utils/cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ export default class CookieManager {
const days = 14; // Срок жизни cookie, например, 14 дней
const expires = new Date(Date.now() + days * 86400000).toUTCString(); // Вычисляем время истечения cookie
document.cookie = `userId=${encodeURIComponent(userId)}; expires=${expires}; path=/; Secure`;
console.log(
`Cookie set: userId=${encodeURIComponent(userId)}; expires=${expires}; path=/; Secure`
);
}

// Получение userId из cookie
Expand All @@ -19,7 +16,6 @@ export default class CookieManager {
static clearUserId() {
document.cookie =
'userId=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure';
console.log('Cookie cleared: userId');
}

static isCustomerAuthorized(): boolean {
Expand Down
7 changes: 7 additions & 0 deletions src/app/views/basket/basket-product.scss
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
}

.cart-product-prices {
display: flex;
gap: 20px;

&:not(:last-child) {
margin-right: 15%;
}
Expand All @@ -81,5 +84,9 @@
.cart-product-price {
}

.cart-product-discounted-price {
color: red;
}

.cart-product-quantity {
}
30 changes: 19 additions & 11 deletions src/app/views/basket/basket-product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,18 @@ export default class BasketProductView extends View {
};
this.pricesContainer = new BaseComponent(pricesProductAttrs);

const price = `${(this.productCartData.lineItem.price.value.centAmount / 10 ** this.productCartData.lineItem.price.value.fractionDigits).toFixed(this.productCartData.lineItem.price.value.fractionDigits)}`;
// const price = `${(this.productCartData.lineItem.price.value.centAmount / 10 ** this.productCartData.lineItem.price.value.fractionDigits).toFixed(this.productCartData.lineItem.price.value.fractionDigits)}`;

const { lineItem } = this.productCartData;
// Основная цена
const price = `${(lineItem.variant.prices[0].value.centAmount / 10 ** lineItem.variant.prices[0].value.fractionDigits).toFixed(lineItem.variant.prices[0].value.fractionDigits)}`;

// Скидочная цена
const discountedPrice =
lineItem.variant.prices[0].discounted &&
lineItem.variant.prices[0].discounted.value
? `${(lineItem.variant.prices[0].discounted.value.centAmount / 10 ** lineItem.variant.prices[0].discounted.value.fractionDigits).toFixed(lineItem.variant.prices[0].discounted.value.fractionDigits)}`
: '';

const productPriceAttrs: IAttributes = {
classList: ['cart-product-price'],
Expand All @@ -125,24 +136,21 @@ export default class BasketProductView extends View {
const productPrice = new BaseComponent(productPriceAttrs);
this.pricesContainer.appendChild(productPrice);

// Форматируем скидочную цену, если она существует, без currencyCode
const discountedPrice = this.productCartData.lineItem.variant.prices[0]
.discounted
? `${(this.productCartData.lineItem.variant.prices[0].discounted.value.centAmount / 10 ** this.productCartData.lineItem.variant.prices[0].discounted.value.fractionDigits).toFixed(this.productCartData.lineItem.variant.prices[0].discounted.value.fractionDigits)}`
: '';

console.log(`Discounted Price: ${discountedPrice}`);

// Добавляем цену со скидкой только если она есть

// Условное добавление элемента для скидочной цены, если она существует
if (discountedPrice) {
const productDiscountPriceAttrs: IAttributes = {
classList: ['product-price-discount'],
const discountedPriceAttrs: IAttributes = {
classList: ['cart-product-discounted-price'],
content: `$ ${discountedPrice}`,
};
const productDiscountPrice = new BaseComponent(productDiscountPriceAttrs);
this.pricesContainer.appendChild(productDiscountPrice);
const discountedPriceElement = new BaseComponent(discountedPriceAttrs);
this.pricesContainer.appendChild(discountedPriceElement);
productPrice.addClass('price-strikethrough');
}

const { quantity } = this.productCartData.lineItem;

// Добавляем контейнер для количества
Expand Down
33 changes: 28 additions & 5 deletions src/app/views/product/product-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Cart } from '@commercetools/platform-sdk';
import CartHandler from '@services/cart-handler';
import { getCartById } from '@services/cart-data';
import { ICartData } from '@models/cart';
import CookieManager from '@utils/cookie';
import ImageSliderProducts from './slider';
import ModalImageSliderProducts from './slider-modal';

Expand Down Expand Up @@ -247,8 +248,10 @@ export default class ProductPageView extends View {
// Если продукта нет в корзине, добавляем его
this.cartHandler.handleAddToCart(productId, quantity);
this.addCartButton.node.classList.add('button-disabled');
localStorage.setItem(`product-${productId}-disabled`, 'true');
} else {
this.addCartButton.node.classList.remove('button-disabled');
localStorage.removeItem(`product-${productId}-disabled`);
}
});
}
Expand All @@ -257,16 +260,28 @@ export default class ProductPageView extends View {
productId: string,
callback: (isInCart: boolean) => void
): void {
// получаем сartId из LS
this.cartHandler.loadCartFromLocalStorage();
const { currentCartId } = this.cartHandler;
if (!currentCartId) {
// Получаем userId из куков
const userId = CookieManager.getUserId();

// Если userId существует, используем метод для зарегистрированных пользователей
if (userId) {
this.cartHandler.loadCartAuthFromLocalStorage(); // Загрузка корзины зарегистрированного пользователя
} else {
this.cartHandler.loadCartFromLocalStorage(); // Загрузка корзины анонимного пользователя
}
// Определяем, какой ID корзины использовать
const cartId = userId
? this.cartHandler.currentCustomerCartId
: this.cartHandler.currentCartId;

// Проверяем, есть ли ID корзины после загрузки данных
if (!cartId) {
callback(false);
return;
}

getCartById(
currentCartId,
cartId,
(cartData: ICartData) => {
// Проверка наличия продукта в корзине
const isInCart = cartData.lineItems.some(
Expand Down Expand Up @@ -302,6 +317,14 @@ export default class ProductPageView extends View {
});

detailsProduct.appendChild(cartContainer);

// Проверяем и восстанавливаем состояние кнопки из localStorage
const disabledState = localStorage.getItem(
`product-${this.productData.id}-disabled`
);
if (disabledState) {
this.addCartButton.node.classList.add('button-disabled');
}
}

private initializeProductDescription(detailsProduct: BaseComponent) {
Expand Down