very first commit

This commit is contained in:
sdarbinyan
2026-01-18 18:57:06 +04:00
commit bd80896886
152 changed files with 28211 additions and 0 deletions

View File

@@ -0,0 +1,174 @@
import { Component, OnInit, OnDestroy, signal, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { ApiService, CartService, TelegramService } from '../../services';
import { Item } from '../../models';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Subscription } from 'rxjs';
import { environment } from '../../../environments/environment';
@Component({
selector: 'app-item-detail',
standalone: true,
imports: [CommonModule, RouterLink, FormsModule],
templateUrl: './item-detail.component.html',
styleUrls: ['./item-detail.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ItemDetailComponent implements OnInit, OnDestroy {
item = signal<Item | null>(null);
selectedPhotoIndex = signal(0);
loading = signal(true);
error = signal<string | null>(null);
isnovo = environment.theme === 'novo';
newReview = {
rating: 0,
comment: '',
anonymous: false
};
reviewSubmitStatus = signal<'idle' | 'loading' | 'success' | 'error'>('idle');
private routeSubscription?: Subscription;
constructor(
private route: ActivatedRoute,
private apiService: ApiService,
private cartService: CartService,
private telegramService: TelegramService,
private sanitizer: DomSanitizer
) {}
ngOnInit(): void {
this.routeSubscription = this.route.params.subscribe(params => {
const id = parseInt(params['id'], 10);
this.loadItem(id);
});
}
ngOnDestroy(): void {
this.routeSubscription?.unsubscribe();
}
loadItem(itemID: number): void {
this.loading.set(true);
this.apiService.getItem(itemID).subscribe({
next: (item) => {
this.item.set(item);
this.loading.set(false);
},
error: (err) => {
this.error.set('Failed to load item');
this.loading.set(false);
console.error('Error loading item:', err);
}
});
}
selectPhoto(index: number): void {
this.selectedPhotoIndex.set(index);
}
addToCart(): void {
const currentItem = this.item();
if (currentItem) {
this.cartService.addItem(currentItem.itemID);
}
}
getDiscountedPrice(): number {
const currentItem = this.item();
if (!currentItem) return 0;
return currentItem.price * (1 - currentItem.discount / 100);
}
getSafeHtml(html: string): SafeHtml {
return this.sanitizer.sanitize(1, html) || '';
}
getRatingStars(rating: number): string {
const fullStars = Math.floor(rating);
const hasHalfStar = rating % 1 >= 0.5;
let stars = '⭐'.repeat(fullStars);
if (hasHalfStar) stars += '⭐';
return stars;
}
formatDate(timestamp: string): string {
const date = new Date(timestamp);
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
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',
month: 'long',
year: 'numeric'
});
}
setRating(rating: number): void {
this.newReview.rating = rating;
}
getUserDisplayName(): string | null {
if (!this.telegramService.isTelegramApp()) {
return 'Пользователь';
}
return this.telegramService.getDisplayName();
}
submitReview(): void {
if (!this.newReview.rating || !this.newReview.comment.trim()) {
return;
}
const currentItem = this.item();
if (!currentItem) return;
this.reviewSubmitStatus.set('loading');
const reviewData = {
itemID: currentItem.itemID,
rating: this.newReview.rating,
comment: this.newReview.comment.trim(),
username: this.newReview.anonymous ? null : this.getUserDisplayName(),
userId: this.telegramService.getUserId(),
timestamp: new Date().toISOString()
};
this.apiService.submitReview(reviewData).subscribe({
next: (response) => {
this.reviewSubmitStatus.set('success');
this.newReview = { rating: 0, comment: '', anonymous: false };
// Скрыть сообщение через 3 секунды
setTimeout(() => {
this.reviewSubmitStatus.set('idle');
}, 3000);
// Перезагрузить данные товара через небольшую задержку
setTimeout(() => {
this.loadItem(currentItem.itemID);
}, 500);
},
error: (err) => {
console.error('Error submitting review:', err);
this.reviewSubmitStatus.set('error');
// Скрыть сообщение об ошибке через 5 секунд
setTimeout(() => {
this.reviewSubmitStatus.set('idle');
}, 5000);
}
});
}
}