303 lines
8.2 KiB
TypeScript
Executable File
303 lines
8.2 KiB
TypeScript
Executable File
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<HTMLInputElement>;
|
|
@ViewChild('passwordInput', { static: true })
|
|
passwordInputRef!: ElementRef<HTMLInputElement>;
|
|
|
|
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);
|
|
});
|
|
}
|
|
}
|