Files
marketplaces/src/app/services/cart.service.ts

149 lines
4.4 KiB
TypeScript
Raw Normal View History

2026-01-18 18:57:06 +04:00
import { Injectable, signal, computed, effect } from '@angular/core';
import { ApiService } from './api.service';
import { Item, CartItem } from '../models';
2026-02-19 01:23:25 +04:00
import { environment } from '../../environments/environment';
2026-01-18 18:57:06 +04:00
import type { } from '../types/telegram.types';
@Injectable({
providedIn: 'root'
})
export class CartService {
2026-02-19 01:23:25 +04:00
private readonly STORAGE_KEY = `${environment.brandName.toLowerCase().replace(/\s+/g, '_')}_cart`;
2026-01-18 18:57:06 +04:00
private cartItems = signal<CartItem[]>([]);
private isTelegram = typeof window !== 'undefined' && !!window.Telegram?.WebApp;
items = this.cartItems.asReadonly();
itemCount = computed(() => {
const items = this.cartItems();
if (!Array.isArray(items)) return 0;
return items.reduce((total, item) => total + item.quantity, 0);
});
totalPrice = computed(() => {
const items = this.cartItems();
if (!Array.isArray(items)) return 0;
return items.reduce((total, item) => {
const price = item.price * (1 - item.discount / 100);
return total + (price * item.quantity);
}, 0);
});
constructor(private apiService: ApiService) {
this.loadCart();
// Auto-save whenever cart changes
effect(() => {
const items = this.cartItems();
this.saveToStorage(items);
});
}
private saveToStorage(items: CartItem[]): void {
const data = JSON.stringify(items);
// Always save to sessionStorage
sessionStorage.setItem(this.STORAGE_KEY, data);
// Also save to Telegram CloudStorage if available
if (this.isTelegram) {
window.Telegram!.WebApp.CloudStorage.setItem(this.STORAGE_KEY, data, (err) => {
if (err) {
console.error('Error saving to Telegram CloudStorage:', err);
}
});
}
}
private loadCart(): void {
if (this.isTelegram) {
// Load from Telegram CloudStorage first
window.Telegram!.WebApp.CloudStorage.getItem(this.STORAGE_KEY, (err, value) => {
if (err) {
console.error('Error loading from Telegram CloudStorage:', err);
this.loadFromSessionStorage();
} else if (value) {
2026-02-19 01:23:25 +04:00
this.parseAndSetCart(value) || this.loadFromSessionStorage();
2026-01-18 18:57:06 +04:00
} else {
// No data in CloudStorage, try sessionStorage
this.loadFromSessionStorage();
}
});
} else {
this.loadFromSessionStorage();
}
}
private loadFromSessionStorage(): void {
const stored = sessionStorage.getItem(this.STORAGE_KEY);
if (stored) {
2026-02-19 01:23:25 +04:00
this.parseAndSetCart(stored);
}
}
/** Parse JSON cart data, migrate legacy items, and set the signal. Returns true on success. */
private parseAndSetCart(json: string): boolean {
try {
const items = JSON.parse(json);
if (Array.isArray(items)) {
this.cartItems.set(items.map(item => ({
...item,
quantity: item.quantity || 1
})));
return true;
2026-01-18 18:57:06 +04:00
}
2026-02-19 01:23:25 +04:00
} catch (err) {
console.error('Error parsing cart data:', err);
2026-01-18 18:57:06 +04:00
}
2026-02-19 01:23:25 +04:00
this.cartItems.set([]);
return false;
2026-01-18 18:57:06 +04:00
}
addItem(itemID: number, quantity: number = 1): void {
const currentItems = this.cartItems();
const existingItem = currentItems.find(i => i.itemID === itemID);
if (existingItem) {
// Item exists, increase quantity
this.updateQuantity(itemID, existingItem.quantity + quantity);
} else {
// Get item details from API and add to cart
this.apiService.getItem(itemID).subscribe({
next: (item) => {
const cartItem: CartItem = { ...item, quantity };
this.cartItems.set([...this.cartItems(), cartItem]);
},
error: (err) => {
console.error('Error adding to cart:', err);
alert('Ошибка добавления в корзину: ' + (err.error?.message || err.message));
}
});
}
}
updateQuantity(itemID: number, quantity: number): void {
if (quantity <= 0) {
this.removeItem(itemID);
return;
}
const currentItems = this.cartItems();
const updatedItems = currentItems.map(item =>
item.itemID === itemID ? { ...item, quantity } : item
);
this.cartItems.set(updatedItems);
}
removeItems(itemIDs: number[]): void {
const currentItems = this.cartItems();
const updatedItems = currentItems.filter(item => !itemIDs.includes(item.itemID));
this.cartItems.set(updatedItems);
}
removeItem(itemID: number): void {
this.removeItems([itemID]);
}
clearCart(): void {
this.cartItems.set([]);
}
}