// 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 } from '@angular/common/http'; // import { 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{6}$/)]], // }); // } // 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 >= 6) 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; // } // sharedWindow: Window | null = null; // Add this at the top of your class // onSubmit(): void { // if (this.loginForm.invalid) { // this.loginForm.markAllAsTouched(); // return; // } // const { email, password } = this.loginForm.value; // this.btcService.userLogin(email, password).subscribe({ // next: (response: HttpResponse<{ name: string; employeeId: string }>) => { // const employee = response.body; // this.passwordStatus = true; // // Save user info // localStorage.setItem('userName', employee?.name || 'Unknown User'); // localStorage.setItem('employeeId', employee?.employeeId || email); // // ✅ Trigger shared display window via Electron // (window as any).electronAPI?.openSecondScreen?.(); // // ✅ Navigate to home // this.router.navigate(['/home']); // }, // error: () => { // this.loginError = 'Invalid login credentials'; // }, // }); // } // 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); // }); // } // } 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{6}$/)]], }); } 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 >= 6) 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: HttpResponse<{ name: string; employeeId: string }>) => { const employee = response.body; this.passwordStatus = true; const printData = { name: employee?.name || 'Unknown User', employeeId: employee?.employeeId || email, action: 'login', }; localStorage.setItem('userName', printData.name); localStorage.setItem('employeeId', printData.employeeId); // ✅ Re-enable print logic this.printAndRedirect(printData); }, error: () => { this.loginError = 'Invalid login credentials'; }, }); } private async printAndRedirect(printData: { name: string; employeeId: string; action: string }) { try { const res = await fetch('http://localhost:9100/print', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(printData), }); if (!res.ok) throw new Error('Print failed'); console.log('🖨️ Print successful'); // ✅ Open second screen (window as any).electronAPI?.openSecondScreen?.(); // ✅ Navigate to home screen this.router.navigate(['/home']); } catch (err) { console.error('‼️ Print failed', err); this.loginError = 'Login OK, but printing failed. Please check the printer.'; } } 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); }); } }