import { Component, ElementRef, ViewChild, ChangeDetectorRef, OnInit, OnDestroy, } from '@angular/core'; import { FormBuilder, FormGroup, Validators, ReactiveFormsModule, } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { Router } from '@angular/router'; import { BtcService } from '../service/btc.service'; import { HttpClientModule, HttpResponse } from '@angular/common/http'; @Component({ selector: 'app-login', standalone: true, imports: [CommonModule, ReactiveFormsModule, HttpClientModule], templateUrl: './login.component.html', styleUrls: ['./login.component.css'], }) export class LoginComponent implements OnInit, OnDestroy { loginForm: FormGroup; focusedField: 'email' | 'password' | null = null; loginError: string | null = null; passwordStatus: boolean = true; scanningEnabled: boolean = true; @ViewChild('emailInput', { static: true }) emailInputRef!: ElementRef; @ViewChild('passwordInput', { static: true }) passwordInputRef!: ElementRef; private barcodeBuffer = ''; private scanStartedAt = 0; private readonly SCAN_GAP_MS = 100; constructor( private fb: FormBuilder, private cdRef: ChangeDetectorRef, private router: Router, private btcService: BtcService ) { this.loginForm = this.fb.group({ email: ['', Validators.required], password: ['', [Validators.required, Validators.pattern(/^\d{7}$/)]], }); } ngOnInit(): void { window.addEventListener('keydown', this.handleScan); } ngOnDestroy(): void { window.removeEventListener('keydown', this.handleScan); } toggleScan(): void { this.scanningEnabled = !this.scanningEnabled; } handleScan = (event: KeyboardEvent): void => { if (this.focusedField !== 'email') return; if (!this.scanningEnabled) { const ctrl = this.loginForm.get('email')!; let val = ctrl.value || ''; if (event.key >= '0' && event.key <= '9') { if (val.length < 12) { val += event.key; ctrl.setValue(val); this.emailInputRef.nativeElement.value = val; } event.preventDefault(); } else if (event.key === 'Backspace') { val = val.slice(0, -1); ctrl.setValue(val); this.emailInputRef.nativeElement.value = val; event.preventDefault(); } else if (event.key === 'Delete') { ctrl.setValue(''); this.emailInputRef.nativeElement.value = ''; event.preventDefault(); } return; } const now = Date.now(); if (now - this.scanStartedAt > this.SCAN_GAP_MS) { this.barcodeBuffer = ''; } this.scanStartedAt = now; if (event.key === 'Enter') { this.commitScan(); return; } const ch = this.toPrintableChar(event); if (ch) this.barcodeBuffer += ch; }; private toPrintableChar(ev: KeyboardEvent): string { if (ev.key.length === 1) return ev.key; if (ev.key === 'Process') { if (ev.keyCode >= 48 && ev.keyCode <= 57) return String.fromCharCode(ev.keyCode); if (ev.keyCode >= 65 && ev.keyCode <= 90) return String.fromCharCode(ev.keyCode); } return ''; } private commitScan(): void { if (!this.barcodeBuffer) return; this.loginForm.get('email')!.setValue(this.barcodeBuffer); this.emailInputRef.nativeElement.value = this.barcodeBuffer; this.setFocus('password'); setTimeout(() => this.passwordInputRef.nativeElement.focus(), 0); this.barcodeBuffer = ''; } removeReadonly(input: HTMLInputElement): void { input.removeAttribute('readonly'); setTimeout(() => input.setAttribute('readonly', 'true'), 100); } setFocus(field: 'email' | 'password'): void { this.focusedField = field; } formatUsernameDisplay(raw: string): string { return /^\d+$/.test(raw) ? raw.replace(/(\d{4})(?=\d)/g, '$1-') : raw; } onNumpadClick(value: string): void { if (this.focusedField === 'password') { const ctrl = this.loginForm.get('password')!; const current = ctrl.value || ''; if (current.length >= 7) return; const newVal = current + value; ctrl.setValue(newVal); this.passwordInputRef.nativeElement.value = newVal; setTimeout(() => { this.passwordInputRef.nativeElement.focus(); this.passwordInputRef.nativeElement.setSelectionRange( newVal.length, newVal.length ); }, 0); this.cdRef.detectChanges(); } else if (this.focusedField === 'email' && !this.scanningEnabled) { const ctrl = this.loginForm.get('email')!; let val = ctrl.value || ''; if (val.length < 12) { val += value; ctrl.setValue(val); this.emailInputRef.nativeElement.value = val; } setTimeout(() => { this.emailInputRef.nativeElement.focus(); this.emailInputRef.nativeElement.setSelectionRange( val.length, val.length ); }, 0); this.cdRef.detectChanges(); } } onBackspace(): void { if (this.focusedField === 'password') { const ctrl = this.loginForm.get('password')!; const current = ctrl.value || ''; const newVal = current.slice(0, -1); ctrl.setValue(newVal); this.passwordInputRef.nativeElement.value = newVal; setTimeout(() => { this.passwordInputRef.nativeElement.focus(); this.passwordInputRef.nativeElement.setSelectionRange( newVal.length, newVal.length ); }, 0); this.cdRef.detectChanges(); } else if (this.focusedField === 'email' && !this.scanningEnabled) { const ctrl = this.loginForm.get('email')!; let val = ctrl.value || ''; val = val.slice(0, -1); ctrl.setValue(val); this.emailInputRef.nativeElement.value = val; setTimeout(() => { this.emailInputRef.nativeElement.focus(); this.emailInputRef.nativeElement.setSelectionRange( val.length, val.length ); }, 0); this.cdRef.detectChanges(); } } resetUserPassMessage() { this.passwordStatus = true; } onSubmit(): void { if (this.loginForm.invalid) { this.loginForm.markAllAsTouched(); return; } const { email, password } = this.loginForm.value; this.btcService.userLogin(email, password).subscribe({ next: (response) => { const employee = response.body; console.log('🧠 Raw employee response:', employee); const userName = employee?.userName || 'Unknown User'; const employeeId = employee?.userIdNumber || email; console.log('✅ Parsed name:', userName); console.log('✅ Parsed ID:', employeeId); this.passwordStatus = true; // Prepare print data const printData = { name: userName, employeeId: employeeId, action: 'login', type: 'login' // ← ADD THIS }; // Store in localStorage localStorage.setItem('userName', userName); localStorage.setItem('employeeId', employeeId); localStorage.setItem('password', password); // Optional print logic fetch('http://localhost:9100/print', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(printData), }) .then((res) => { if (!res.ok) throw new Error('Print failed'); console.log('🖨️ Print successful'); // Open second screen (window as any).electronAPI?.openSecondScreen?.(); // // Navigate to home this.router.navigate(['/home']); }) .catch((err) => { console.error('‼️ Print failed', err); this.loginError = 'Login OK, but printing failed.'; }); }, error: () => { this.loginError = 'Invalid login credentials'; }, }); } showConfirmModal : boolean = false; confirmShutdown() : void{ this.showConfirmModal = false; this.shutdownSystem(); } shutdownSystem(): void { fetch('http://localhost:3000/shutdown', { method: 'POST', }) .then((res) => { if (!res.ok) throw new Error('Shutdown failed'); console.log('🛑 Shutdown triggered'); }) .catch((err) => { console.error('‼️ Failed to shutdown', err); }); } }