import { Component, OnInit, AfterViewChecked, ElementRef, ViewChild } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { CouchdbService } from '../couchdb.service'; // Import the service import emailjs, { EmailJSResponseStatus } from 'emailjs-com'; interface Answer { text: string; next: string; } interface Node { type: string; text: string; answers?: Answer[]; next?: string; } interface DecisionTree { startNode: string; nodes: { [key: string]: Node }; } @Component({ selector: 'app-chatbot', templateUrl: './chatbot.component.html', styleUrls: ['./chatbot.component.css'] }) export class ChatbotComponent implements OnInit, AfterViewChecked { decisionTree: DecisionTree = { startNode: '', nodes: {} }; currentNode: Node = { type: '', text: '' }; conversation: { speaker: string; text: string }[] = []; userInput = ''; errorMessage = ''; isMinimized = true; leaveDetails: any = {}; leaveBalance = 0; @ViewChild('chatContent') private chatContent!: ElementRef; constructor(private couchdbService: CouchdbService, private http: HttpClient) {} // Inject the service ngOnInit(): void { this.couchdbService.getDecisionTree().subscribe(data => { this.decisionTree = data.data; this.currentNode = this.decisionTree.nodes[this.decisionTree.startNode]; this.addMessage('bot', this.currentNode.text); }); } ngAfterViewChecked() { this.scrollToBottom(); } addMessage(speaker: string, text: string): void { this.conversation.push({ speaker, text }); this.scrollToBottom(); } selectAnswer(answer: Answer): void { this.addMessage('user', answer.text); // Check for redirection conditions if (this.currentNode.text === "Welcome to our Ticket service!") { if (answer.text === 'Raise Ticket' || answer.text === 'Ticket Status') { window.open('https://e.chain.portal.url', '_blank'); } } else if (this.currentNode.text === "Welcome to our Technical service!") { if (answer.text === 'Raise Support') { window.open('https://appTrack.portal.url', '_blank'); } } if (this.currentNode.text === "Are you sure you want to submit the form?") { if (answer.text === 'Yes, submit') { this.sendLeaveApplicationEmail(); this.userInput = ''; // Clear user input return; } else { // Handle other options if needed } } // Move to the next node based on the selected answer this.currentNode = this.decisionTree.nodes[answer.next]; this.processNode(); } submitInput(): void { if (!this.userInput.trim()) { this.displayErrorMessage('Please enter a value'); return; } // Validate email ID if (this.currentNode.text === "Enter your Email ID" || this.currentNode.text === "Enter manager Email ID") { if (!this.validateEmail(this.userInput)) { this.displayErrorMessage('Please enter a valid email ID'); return; } } // Validate dates if (this.currentNode.text === "Please provide the start date for your leave. (Format: YYYY-MM-DD)" || this.currentNode.text === "Please provide the end date for your leave. (Format: YYYY-MM-DD)") { if (!this.validateDate(this.userInput)) { this.displayErrorMessage('Please enter a valid date in the format YYYY-MM-DD'); return; } if (new Date(this.userInput) <= new Date()) { this.displayErrorMessage('Please enter a date greater than today\'s date'); return; } } this.addMessage('user', this.userInput); this.errorMessage = ''; this.leaveDetails[this.currentNode.text] = this.userInput; // Store user input in leaveDetails if (this.currentNode.text === "Please provide your employee ID") { this.checkEmployeeEligibility(this.userInput); } else { this.currentNode = this.decisionTree.nodes[this.currentNode.next || '']; this.processNode(); } this.userInput = ''; } validateEmail(email: string): boolean { const emailPattern = /^[a-zA-Z]+\.[a-zA-Z]+@chainsys\.com$/; return emailPattern.test(email); } validateDate(date: string): boolean { const datePattern = /^\d{4}-\d{2}-\d{2}$/; return datePattern.test(date); } checkEmployeeEligibility(employeeId: string): void { const url = `https://192.168.57.185:5984/employee-db/${employeeId}`; const headers = new HttpHeaders({ 'Authorization': 'Basic ' + btoa('d_couchdb:Welcome#2') }); this.http.get(url, { headers }).subscribe( data => { data.leaveBalance = data.leaveBalance || 0; // Ensure leaveBalance is initialized if null this.leaveBalance = data.leaveBalance; this.leaveDetails['leaveBalance'] = this.leaveBalance; if (this.leaveBalance > 0) { this.currentNode = this.decisionTree.nodes['nodeEligibilityResult']; } else { this.addMessage('bot', 'You are not eligible to apply for leave.'); this.currentNode = this.decisionTree.nodes[this.decisionTree.startNode]; } this.processNode(); }, error => { this.addMessage('bot', 'No record found.'); this.currentNode = this.decisionTree.nodes[this.decisionTree.startNode]; this.processNode(); } ); } processNode(): void { if (!this.currentNode) { console.error('Invalid node configuration'); return; } if (this.currentNode.type === 'question' && this.currentNode.text === 'No. of days') { // Adjust leave options based on leave balance const maxDays = Math.min(this.leaveBalance, 5); // Maximum of 5 days or leave balance, whichever is smaller this.currentNode.answers = this.currentNode.answers?.filter(answer => parseInt(answer.text, 10) <= maxDays); } const botMessage = this.replaceVariables(this.currentNode.text); this.addMessage('bot', botMessage); } replaceVariables(text: string): string { return text.replace(/\[\w+\]/g, match => this.leaveDetails[match.slice(1, -1)] || match); } toggleMinimize(event?: Event): void { if (event) { event.stopPropagation(); } this.isMinimized = !this.isMinimized; } closeChat(event?: Event): void { const confirmClose = confirm("Are you sure you want to close the chat?"); if (event) { event.stopPropagation(); } this.isMinimized = !this.isMinimized; } private scrollToBottom(): void { try { this.chatContent.nativeElement.scrollTop = this.chatContent.nativeElement.scrollHeight; } catch (err) { console.error('Scroll to bottom failed:', err); } } displayErrorMessage(message: string): void { this.errorMessage = message; setTimeout(() => { this.errorMessage = ''; }, 2000); } sendLeaveApplicationEmail(): void { const templateParams = { employee_email: this.leaveDetails['Enter your Email ID'], manager_email: this.leaveDetails['Enter manager Email ID'], employee_id: this.leaveDetails['Please provide your employee ID'], leave_type: this.leaveDetails['Type of leave'], leave_reason: this.leaveDetails['Reason for the leave'], leave_days: this.leaveDetails['No. of days'], start_date: this.leaveDetails['Please provide the start date for your leave. (Format: YYYY-MM-DD)'], end_date: this.leaveDetails['Please provide the end date for your leave. (Format: YYYY-MM-DD)'] }; emailjs.send('service_g7y50fu', 'template_20nsgam', templateParams, '8pjnXdcFSoOVX9B6c') .then((response: EmailJSResponseStatus) => { console.log('SUCCESS!', response.status, response.text); this.currentNode = this.decisionTree.nodes['node13']; this.processNode(); }, (error) => { console.error('FAILED...', error); }); } }