Files
marketplaces/src/app/components/telegram-login/telegram-login.component.ts
2026-06-19 01:57:27 +04:00

135 lines
3.5 KiB
TypeScript

import { Component, ChangeDetectionStrategy, inject, signal, computed, effect, OnDestroy } from '@angular/core';
import { AuthService } from '../../services/auth.service';
import { CartService } from '../../services/cart.service';
import { TranslatePipe } from '../../i18n/translate.pipe';
import { getDiscountedPrice } from '../../utils/item.utils';
@Component({
selector: 'app-telegram-login',
imports: [TranslatePipe],
templateUrl: './telegram-login.component.html',
styleUrls: ['./telegram-login.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TelegramLoginComponent implements OnDestroy {
private authService = inject(AuthService);
private cartService = inject(CartService);
showDialog = this.authService.showLoginDialog;
status = this.authService.status;
loginUrl = signal('');
webSessionID = signal('');
qrStatus = signal<'loading' | 'ready' | 'expired' | 'error'>('loading');
encodedQrUrl = computed(() => encodeURIComponent(this.loginUrl()));
private readonly pollIntervalMs = 5000;
private pollTimer?: ReturnType<typeof setInterval>;
constructor() {
console.log('TelegramLoginComponent initialized');
effect(() => {
if (this.showDialog()) {
this.initQrLogin();
} else {
this.stopPolling();
}
});
}
ngOnDestroy(): void {
this.stopPolling();
}
close(): void {
this.authService.hideLogin();
this.stopPolling();
}
openTelegramLogin(): void {
const url = this.loginUrl();
if (!url) return;
window.open(url, '_blank');
if (!this.pollTimer) {
const webSessionID = this.webSessionID();
if (webSessionID) {
this.startPolling(webSessionID);
}
}
}
refreshQr(): void {
this.stopPolling();
this.initQrLogin();
}
private initQrLogin(): void {
this.qrStatus.set('loading');
this.loginUrl.set('');
this.webSessionID.set('');
this.authService.createWebSession().subscribe({
next: (res) => {
this.loginUrl.set(res.url);
this.webSessionID.set(res.webSessionID);
this.qrStatus.set('ready');
this.startPolling(res.webSessionID);
},
error: () => {
this.qrStatus.set('error');
}
});
}
private startPolling(webSessionID: string): void {
this.stopPolling();
if (!webSessionID) return;
let checks = 0;
this.pollTimer = setInterval(() => {
checks++;
if (checks > 100) {
this.stopPolling();
this.qrStatus.set('expired');
return;
}
this.authService.checkSessionOnce(webSessionID).subscribe({
next: (session) => {
if (session?.active) {
this.stopPolling();
this.syncCartAndComplete(session.sessionId);
}
},
error: () => {
// Network error — keep polling
}
});
}, this.pollIntervalMs);
}
private syncCartAndComplete(sessionId: string): void {
const cartItems = this.cartService.items().map(item => ({
itemID: item.itemID,
quantity: item.quantity,
colour: item.colour || '',
size: item.size || '',
price: item.discount > 0
? item.price * (1 - item.discount / 100)
: item.price,
}));
this.authService.syncCart(sessionId, cartItems).subscribe(() => {
this.authService.onTelegramLoginComplete();
});
}
private stopPolling(): void {
if (this.pollTimer) {
clearInterval(this.pollTimer);
this.pollTimer = undefined;
}
}
}