From d6b171a0a7f1e36643dac8f792138ceddca91c40 Mon Sep 17 00:00:00 2001 From: x2Skyz Date: Mon, 1 Dec 2025 16:08:27 +0700 Subject: [PATCH] -suscess chat ai system --- .../chat-widget-component.ts | 156 ++++++++++-------- 1 file changed, 89 insertions(+), 67 deletions(-) diff --git a/ng-ttc-frontend/src/app/component/chat-widget-component/chat-widget-component.ts b/ng-ttc-frontend/src/app/component/chat-widget-component/chat-widget-component.ts index bb7c12a..446f647 100644 --- a/ng-ttc-frontend/src/app/component/chat-widget-component/chat-widget-component.ts +++ b/ng-ttc-frontend/src/app/component/chat-widget-component/chat-widget-component.ts @@ -1,7 +1,8 @@ import { GeneralService } from './../../services/generalservice'; import { ReactiveFormsModule, FormGroup, FormControl, Validators } from '@angular/forms'; -import { IChat } from '../../interfaces/main.interface' -import { Component, HostListener } from '@angular/core'; +import { IChat } from '../../interfaces/main.interface'; +import { Component, HostListener, OnDestroy } from '@angular/core'; +import { Subscription } from 'rxjs'; @Component({ selector: 'app-chat-widget-component', @@ -9,76 +10,62 @@ import { Component, HostListener } from '@angular/core'; templateUrl: './chat-widget-component.html', styleUrl: './chat-widget-component.css', }) -export class ChatWidgetComponent { +export class ChatWidgetComponent implements OnDestroy { + // --- State --- isOpen = false; - // newMessage = ''; - chatForm!: FormGroup; - messages:IChat[]=[]; - - // State สำหรับจัดการขนาด isMaximized = false; - isResizing = false; + isLoading = false; // Added to track API state + first = true; - // ขนาดเริ่มต้น (px) + // --- Form & Data --- + chatForm!: FormGroup; + messages: IChat[] = []; + private subscriptions: Subscription = new Subscription(); + + // --- Resize State --- chatWidth = 320; chatHeight = 384; - - // ตัวแปรสำหรับคำนวณการลาก + isResizing = false; private startX = 0; private startY = 0; private startWidth = 0; private startHeight = 0; + constructor(private generalService: GeneralService) { + this.setupFormControl(); + } - constructor( - private generalService: GeneralService - ) { - this.setupFormControl(); // เรียกใช้ตอนเริ่ม Component + ngOnDestroy(): void { + // Best Practice: Unsubscribe to prevent memory leaks + this.subscriptions.unsubscribe(); } setupFormControl() { this.chatForm = new FormGroup({ - message: new FormControl('', [Validators.required]) + message: new FormControl('', [Validators.required]), }); } - - toggleChat() { this.isOpen = !this.isOpen; - let body = {methods: 'ind'} - this.OnAiChat(body); - const isAlreadyHave = this.messages.some(sub => sub.text == 'รอAi ประมวณผลสักครู่'); - if(isAlreadyHave === false){ - this.messages.push({ - text: 'รอAi ประมวณผลสักครู่', - isUser: false - }) - } this.isMaximized = false; - } - OnAiChat(value: any){ - let url = 'https://n8n.nuttakit.work/webhook/Ai' - let request = { - methods: value.methods || 'cht', - message: value.message ?? '' - } - this.generalService.postUrl(url, request).subscribe({ - next: (result: any) => { - if (result.code === 200) { - this.messages.push(result.data) - }else{ - this.generalService.trowApi(result); + // Only trigger welcome message logic if opening + if (this.isOpen) { + if (this.first) { + // Initial handshake with AI + this.OnAiChat({ methods: 'ind' }); + + // Add "Waiting" message only if it doesn't exist + const isAlreadyHave = this.messages.some((sub) => sub.text === 'รอAi ประมวณผลสักครู่'); + if (!isAlreadyHave) { + this.messages.push({ + text: 'รอAi ประมวณผลสักครู่', + isUser: false, + }); } - }, - error: (error: any) => { - - }, - complete: () => { - } - }) + } } toggleMaximize() { @@ -86,44 +73,79 @@ export class ChatWidgetComponent { } sendMessage() { - let newMessage = this.chatForm.get('message')?.value; - if (newMessage.trim()) { - this.messages.push({ text: newMessage, isUser: true }); - newMessage = ''; - // setTimeout(() => { - // this.messages.push({ - // text: 'รับทราบครับ ระบบกำลังประมวลผล...', - // isUser: false - // }); - // }, 1000); + if (this.chatForm.invalid) return; + + const messageText = this.chatForm.get('message')?.value; + + if (messageText && messageText.trim()) { + // 1. Add User Message to UI + this.messages.push({ text: messageText, isUser: true }); + + // 2. Clear the form input + this.chatForm.reset(); + + // 3. Set loading state + this.isLoading = true; + + // 4. Send to API + this.OnAiChat({ methods: 'cht', message: messageText }); } } - // --- Logic สำหรับการ Resize (ลากขยาย) --- + OnAiChat(value: { methods: string; message?: string }) { + // Best Practice: Move URL to environment.ts in the future + const url = 'https://n8n.nuttakit.work/webhook/Ai'; + + const request = { + methods: value.methods || 'cht', + message: value.message ?? '', + }; + + const sub = this.generalService.postUrl(url, request).subscribe({ + next: (result: any) => { + if (result.code === 200) { + // Push AI response + this.messages.push(result.data); + this.first = false; + } else { + // Handle API logic errors + // specific check for the method if it exists + if(this.generalService['trowApi']) { + this.generalService.trowApi(result); + } + } + }, + error: (error: any) => { + console.error('Chat Error:', error); + this.messages.push({ text: 'ขออภัย เกิดข้อผิดพลาดในการเชื่อมต่อ', isUser: false }); + }, + complete: () => { + this.isLoading = false; + }, + }); + + this.subscriptions.add(sub); + } + + // --- Resize Logic (Preserved) --- startResizing(event: MouseEvent) { - event.preventDefault(); // ป้องกันการเลือก Text + event.preventDefault(); this.isResizing = true; - - // บันทึกตำแหน่งเมาส์และขนาดปัจจุบัน this.startX = event.clientX; this.startY = event.clientY; this.startWidth = this.chatWidth; this.startHeight = this.chatHeight; } - // ใช้ @HostListener เพื่อดักจับ MouseMove ทั่วทั้ง Window @HostListener('window:mousemove', ['$event']) onMouseMove(event: MouseEvent) { if (!this.isResizing) return; - // คำนวณความต่าง (Delta) - // หมายเหตุ: ลากไปทางซ้าย (ค่า X น้อยลง) ต้องทำให้กว้างขึ้น -> ใช้ startX - clientX - // ลากไปข้างบน (ค่า Y น้อยลง) ต้องทำให้สูงขึ้น -> ใช้ startY - clientY + // Logic assumes resizing from Top-Left corner (expanding Up and Left) const deltaX = this.startX - event.clientX; const deltaY = this.startY - event.clientY; - // กำหนดขนาดใหม่ (จำกัดขนาดต่ำสุดไม่ให้เล็กเกินไป) this.chatWidth = Math.max(300, this.startWidth + deltaX); this.chatHeight = Math.max(350, this.startHeight + deltaY); }