optimising and making it better

This commit is contained in:
sdarbinyan
2026-02-26 21:54:21 +04:00
parent 7a00a8f1e3
commit 10b4974719
58 changed files with 318 additions and 1804 deletions

View File

@@ -1,4 +1,4 @@
import { Component, computed, ChangeDetectionStrategy, signal, OnDestroy, OnInit } from '@angular/core';
import { Component, computed, ChangeDetectionStrategy, signal, OnDestroy } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { Router, RouterLink } from '@angular/router';
import { FormsModule } from '@angular/forms';
@@ -17,7 +17,7 @@ import { getDiscountedPrice, getMainImage, trackByItemId } from '../../utils/ite
styleUrls: ['./cart.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CartComponent implements OnInit, OnDestroy {
export class CartComponent implements OnDestroy {
items;
itemCount;
totalPrice;
@@ -59,10 +59,6 @@ export class CartComponent implements OnInit, OnDestroy {
this.totalPrice = this.cartService.totalPrice;
}
ngOnInit(): void {
// Component initialized
}
ngOnDestroy(): void {
this.stopPolling();
if (this.closeTimeout) {
@@ -109,16 +105,16 @@ export class CartComponent implements OnInit, OnDestroy {
};
const cleanup = () => {
document.removeEventListener('touchmove', onMove as any);
document.removeEventListener('touchmove', onMove);
document.removeEventListener('touchend', cleanup);
};
document.addEventListener('touchmove', onMove as any);
document.addEventListener('touchmove', onMove);
document.addEventListener('touchend', cleanup);
}
clearCart(): void {
if (confirm('<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?')) {
if (confirm('Вы уверены, что хотите очистить корзину?')) {
this.cartService.clearCart();
}
}
@@ -129,7 +125,7 @@ export class CartComponent implements OnInit, OnDestroy {
checkout(): void {
if (!this.termsAccepted) {
alert('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.');
alert('Пожалуйста, примите условия оферты, политику возврата и возврата для подтверждения оформления заказа.');
return;
}
this.openPaymentPopup();
@@ -251,7 +247,7 @@ export class CartComponent implements OnInit, OnDestroy {
this.linkCopied.set(true);
setTimeout(() => this.linkCopied.set(false), 2000);
}).catch(err => {
console.error('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:', err);
console.error('Ошибка копирования:', err);
});
}
}
@@ -316,7 +312,7 @@ export class CartComponent implements OnInit, OnDestroy {
next: () => {
this.emailSubmitting.set(false);
// Show success message
alert('Email <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.');
alert('Email успешно отправлен! Проверьте свою почту.');
// Close popup and redirect to home page
setTimeout(() => {
this.closePaymentPopup();
@@ -326,7 +322,7 @@ export class CartComponent implements OnInit, OnDestroy {
error: (err) => {
console.error('Error submitting email:', err);
this.emailSubmitting.set(false);
alert('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> email. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.');
alert('Произошла ошибка при отправке email. Пожалуйста, попробуйте снова.');
}
});
}
@@ -387,11 +383,11 @@ export class CartComponent implements OnInit, OnDestroy {
}
if (digitsOnly.length === 0) {
this.phoneError.set('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>');
this.phoneError.set('Номер телефона обязателен');
} else if (digitsOnly.length < 11) {
this.phoneError.set(`<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> ${11 - digitsOnly.length} <EFBFBD><EFBFBD><EFBFBD><EFBFBD>`);
this.phoneError.set(`Введите ещё ${11 - digitsOnly.length} цифр`);
} else if (digitsOnly.length > 11) {
this.phoneError.set('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>');
this.phoneError.set('Слишком много цифр');
} else {
this.phoneError.set('');
}
@@ -419,19 +415,19 @@ export class CartComponent implements OnInit, OnDestroy {
}
if (email.length === 0) {
this.emailError.set('Email <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>');
this.emailError.set('Email обязателен');
} else if (email.length < 5) {
this.emailError.set('Email <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 5 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)');
this.emailError.set('Email слишком короткий (минимум 5 символов)');
} else if (email.length > 100) {
this.emailError.set('Email <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 100 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)');
this.emailError.set('Email слишком длинный (максимум 100 символов)');
} else if (!email.includes('@')) {
this.emailError.set('Email <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> @');
this.emailError.set('Email должен содержать @');
} else if (!email.includes('.')) {
this.emailError.set('Email <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> (.com, .ru <EFBFBD> <20>.<2E>.)');
this.emailError.set('Email должен содержать домен (.com, .ru и т.д.)');
} else {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
this.emailError.set('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> email');
this.emailError.set('Некорректный формат email');
} else {
this.emailError.set('');
}

View File

@@ -24,6 +24,7 @@ export class CategoryComponent implements OnInit, OnDestroy {
private readonly count = 20;
private isLoadingMore = false;
private routeSubscription?: Subscription;
private scrollTimeout?: ReturnType<typeof setTimeout>;
constructor(
private route: ActivatedRoute,
@@ -41,6 +42,7 @@ export class CategoryComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
this.routeSubscription?.unsubscribe();
if (this.scrollTimeout) clearTimeout(this.scrollTimeout);
}
resetAndLoad(): void {
@@ -80,8 +82,6 @@ export class CategoryComponent implements OnInit, OnDestroy {
});
}
private scrollTimeout: any;
@HostListener('window:scroll')
onScroll(): void {
if (this.scrollTimeout) clearTimeout(this.scrollTimeout);

View File

@@ -1,7 +1,8 @@
import { Component, OnInit, signal, ChangeDetectionStrategy } from '@angular/core';
import { Component, OnInit, OnDestroy, signal, ChangeDetectionStrategy } from '@angular/core';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { ApiService } from '../../services';
import { Category } from '../../models';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-subcategories',
@@ -10,13 +11,15 @@ import { Category } from '../../models';
styleUrls: ['./subcategories.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SubcategoriesComponent implements OnInit {
export class SubcategoriesComponent implements OnInit, OnDestroy {
categories = signal<Category[]>([]);
subcategories = signal<Category[]>([]);
loading = signal(true);
error = signal<string | null>(null);
parentName = signal<string>('');
private routeSubscription?: Subscription;
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -24,12 +27,16 @@ export class SubcategoriesComponent implements OnInit {
) {}
ngOnInit(): void {
this.route.params.subscribe(params => {
this.routeSubscription = this.route.params.subscribe(params => {
const id = parseInt(params['id'], 10);
this.loadForParent(id);
});
}
ngOnDestroy(): void {
this.routeSubscription?.unsubscribe();
}
private loadForParent(parentID: number): void {
this.loading.set(true);
this.apiService.getCategories().subscribe({

View File

@@ -130,7 +130,7 @@
class="dexar-category-card"
[class.dexar-category-card--wide]="isWideCategory(category.categoryID)">
<div class="dexar-category-image">
@if (isWideCategory(category.categoryID) && category.wideBanner && category.wideBanner !== true) {
@if (isWideCategory(category.categoryID) && category.wideBanner) {
<img [src]="category.wideBanner" [alt]="category.name" loading="lazy" decoding="async" />
} @else if (category.icon) {
<img [src]="category.icon" [alt]="category.name" loading="lazy" decoding="async" />

View File

@@ -87,12 +87,6 @@ export class HomeComponent implements OnInit {
topLevel.forEach(cat => {
if (!cat.wideBanner) return;
// API may send wideBanner as a boolean flag instead of a URL
if (cat.wideBanner === true) {
this.wideCategories.update(set => { const next = new Set(set); next.add(cat.categoryID); return next; });
return;
}
const img = new Image();
img.onload = () => {
const ratio = img.naturalWidth / img.naturalHeight;
@@ -104,7 +98,7 @@ export class HomeComponent implements OnInit {
});
}
};
img.src = cat.wideBanner as string;
img.src = cat.wideBanner;
});
}

View File

@@ -1,11 +1,12 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-about',
imports: [],
templateUrl: './about.component.html',
styleUrls: ['./about.component.scss']
styleUrls: ['./about.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AboutComponent {
brandName = environment.brandName;

View File

@@ -1,11 +1,12 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-contacts',
imports: [],
templateUrl: './contacts.component.html',
styleUrls: ['./contacts.component.scss']
styleUrls: ['./contacts.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ContactsComponent {
brandName = environment.brandName;

View File

@@ -1,11 +1,12 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-delivery',
imports: [],
templateUrl: './delivery.component.html',
styleUrls: ['./delivery.component.scss']
styleUrls: ['./delivery.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DeliveryComponent {
brandName = environment.brandName;

View File

@@ -1,11 +1,12 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-faq',
imports: [],
templateUrl: './faq.component.html',
styleUrls: ['./faq.component.scss']
styleUrls: ['./faq.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FaqComponent {
brandName = environment.brandName;

View File

@@ -1,11 +1,12 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-guarantee',
imports: [],
templateUrl: './guarantee.component.html',
styleUrls: ['./guarantee.component.scss']
styleUrls: ['./guarantee.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class GuaranteeComponent {
brandName = environment.brandName;

View File

@@ -1,12 +1,14 @@
import { Component, OnInit, OnDestroy, signal, ChangeDetectionStrategy } from '@angular/core';
import { Component, OnInit, OnDestroy, signal, ChangeDetectionStrategy, inject } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { ApiService, CartService, TelegramService } from '../../services';
import { ApiService, CartService, TelegramService, SeoService } from '../../services';
import { Item } from '../../models';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Subscription } from 'rxjs';
import { environment } from '../../../environments/environment';
import { SecurityContext } from '@angular/core';
import { getDiscountedPrice } from '../../utils/item.utils';
@Component({
selector: 'app-item-detail',
@@ -31,6 +33,11 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
reviewSubmitStatus = signal<'idle' | 'loading' | 'success' | 'error'>('idle');
private routeSubscription?: Subscription;
private reviewResetTimeout?: ReturnType<typeof setTimeout>;
private reviewErrorTimeout?: ReturnType<typeof setTimeout>;
private reloadTimeout?: ReturnType<typeof setTimeout>;
private seoService = inject(SeoService);
constructor(
private route: ActivatedRoute,
@@ -49,6 +56,10 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
this.routeSubscription?.unsubscribe();
if (this.reviewResetTimeout) clearTimeout(this.reviewResetTimeout);
if (this.reviewErrorTimeout) clearTimeout(this.reviewErrorTimeout);
if (this.reloadTimeout) clearTimeout(this.reloadTimeout);
this.seoService.resetToDefaults();
}
loadItem(itemID: number): void {
@@ -57,6 +68,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
this.apiService.getItem(itemID).subscribe({
next: (item) => {
this.item.set(item);
this.seoService.setItemMeta(item);
this.loading.set(false);
},
error: (err) => {
@@ -81,18 +93,18 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
getDiscountedPrice(): number {
const currentItem = this.item();
if (!currentItem) return 0;
return currentItem.price * (1 - currentItem.discount / 100);
return getDiscountedPrice(currentItem);
}
getSafeHtml(html: string): SafeHtml {
return this.sanitizer.sanitize(1, html) || '';
return this.sanitizer.sanitize(SecurityContext.HTML, html) || '';
}
getRatingStars(rating: number): string {
const fullStars = Math.floor(rating);
const hasHalfStar = rating % 1 >= 0.5;
let stars = '?'.repeat(fullStars);
if (hasHalfStar) stars += '?';
let stars = ''.repeat(fullStars);
if (hasHalfStar) stars += '';
return stars;
}
@@ -102,10 +114,10 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
const diffMs = now.getTime() - date.getTime();
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
if (diffDays === 0) return '<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
if (diffDays === 1) return '<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
if (diffDays < 7) return `${diffDays} <EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD>`;
if (diffDays < 30) return `${Math.floor(diffDays / 7)} <EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD>`;
if (diffDays === 0) return 'Сегодня';
if (diffDays === 1) return 'Вчера';
if (diffDays < 7) return `${diffDays} дн. назад`;
if (diffDays < 30) return `${Math.floor(diffDays / 7)} нед. назад`;
return date.toLocaleDateString('ru-RU', {
day: 'numeric',
@@ -120,7 +132,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
getUserDisplayName(): string | null {
if (!this.telegramService.isTelegramApp()) {
return '<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
return 'Пользователь';
}
return this.telegramService.getDisplayName();
}
@@ -149,13 +161,13 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
this.reviewSubmitStatus.set('success');
this.newReview = { rating: 0, comment: '', anonymous: false };
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> 3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
setTimeout(() => {
// Сброс состояния через 3 секунды
this.reviewResetTimeout = setTimeout(() => {
this.reviewSubmitStatus.set('idle');
}, 3000);
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
setTimeout(() => {
// Перезагрузить данные товара после отправки отзыва
this.reloadTimeout = setTimeout(() => {
this.loadItem(currentItem.itemID);
}, 500);
},
@@ -163,8 +175,8 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
console.error('Error submitting review:', err);
this.reviewSubmitStatus.set('error');
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> 5 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
setTimeout(() => {
// Сброс состояния об ошибке через 5 секунд
this.reviewErrorTimeout = setTimeout(() => {
this.reviewSubmitStatus.set('idle');
}, 5000);
}

View File

@@ -1,11 +1,12 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-company-details',
imports: [],
templateUrl: './company-details.component.html',
styleUrls: ['./company-details.component.scss']
styleUrls: ['./company-details.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CompanyDetailsComponent {
brandName = environment.brandName;

View File

@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { RouterLink } from '@angular/router';
import { environment } from '../../../../environments/environment';
@@ -6,7 +6,8 @@ import { environment } from '../../../../environments/environment';
selector: 'app-payment-terms',
imports: [RouterLink],
templateUrl: './payment-terms.component.html',
styleUrls: ['./payment-terms.component.scss']
styleUrls: ['./payment-terms.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PaymentTermsComponent {
brandName = environment.brandName;

View File

@@ -1,11 +1,12 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-privacy-policy',
imports: [],
templateUrl: './privacy-policy.component.html',
styleUrls: ['./privacy-policy.component.scss']
styleUrls: ['./privacy-policy.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PrivacyPolicyComponent {
brandName = environment.brandName;

View File

@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { RouterLink } from '@angular/router';
import { environment } from '../../../../environments/environment';
@@ -6,7 +6,8 @@ import { environment } from '../../../../environments/environment';
selector: 'app-public-offer',
imports: [RouterLink],
templateUrl: './public-offer.component.html',
styleUrls: ['./public-offer.component.scss']
styleUrls: ['./public-offer.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PublicOfferComponent {
brandName = environment.brandName;

View File

@@ -1,12 +1,12 @@
import { Component } from '@angular/core';
import { RouterLink } from '@angular/router';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { environment } from '../../../../environments/environment';
@Component({
selector: 'app-return-policy',
imports: [],
templateUrl: './return-policy.component.html',
styleUrls: ['./return-policy.component.scss']
styleUrls: ['./return-policy.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ReturnPolicyComponent {
brandName = environment.brandName;

View File

@@ -48,6 +48,7 @@ export class SearchComponent implements OnDestroy {
ngOnDestroy(): void {
this.searchSubscription.unsubscribe();
this.searchSubject.complete();
if (this.scrollTimeout) clearTimeout(this.scrollTimeout);
}
onSearchInput(query: string): void {
@@ -106,7 +107,7 @@ export class SearchComponent implements OnDestroy {
});
}
private scrollTimeout: any;
private scrollTimeout?: ReturnType<typeof setTimeout>;
@HostListener('window:scroll')
onScroll(): void {