livechat-assistant 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/ng-package.json +10 -0
  2. package/package.json +19 -23
  3. package/src/lib/components/chat-history/chat-history.component.html +83 -0
  4. package/src/lib/components/chat-history/chat-history.component.scss +0 -0
  5. package/src/lib/components/chat-history/chat-history.component.spec.ts +23 -0
  6. package/src/lib/components/chat-history/chat-history.component.ts +97 -0
  7. package/src/lib/components/chat-widget/chat-widget.component.html +87 -0
  8. package/src/lib/components/chat-widget/chat-widget.component.scss +77 -0
  9. package/src/lib/components/chat-widget/chat-widget.component.spec.ts +23 -0
  10. package/src/lib/components/chat-widget/chat-widget.component.ts +84 -0
  11. package/src/lib/components/help-support/help-support.component.html +106 -0
  12. package/src/lib/components/help-support/help-support.component.scss +0 -0
  13. package/src/lib/components/help-support/help-support.component.spec.ts +23 -0
  14. package/src/lib/components/help-support/help-support.component.ts +46 -0
  15. package/src/lib/components/home/home.component.html +64 -0
  16. package/src/lib/components/home/home.component.scss +0 -0
  17. package/src/lib/components/home/home.component.spec.ts +23 -0
  18. package/src/lib/components/home/home.component.ts +18 -0
  19. package/src/lib/components/index.ts +2 -0
  20. package/src/lib/components/message/message.component.html +119 -0
  21. package/src/lib/components/message/message.component.scss +0 -0
  22. package/src/lib/components/message/message.component.spec.ts +23 -0
  23. package/src/lib/components/message/message.component.ts +48 -0
  24. package/src/lib/components/success-message/success-message.component.html +33 -0
  25. package/src/lib/components/success-message/success-message.component.scss +65 -0
  26. package/src/lib/components/success-message/success-message.component.spec.ts +23 -0
  27. package/src/lib/components/success-message/success-message.component.ts +34 -0
  28. package/src/lib/components/support-buttons/support-buttons.component.html +42 -0
  29. package/src/lib/components/support-buttons/support-buttons.component.scss +49 -0
  30. package/src/lib/components/support-buttons/support-buttons.component.spec.ts +21 -0
  31. package/src/lib/components/support-buttons/support-buttons.component.ts +33 -0
  32. package/src/lib/environment/environment.test.ts +15 -0
  33. package/src/lib/livechat-assistant.component.spec.ts +23 -0
  34. package/src/lib/livechat-assistant.component.ts +15 -0
  35. package/src/lib/livechat-assistant.service.spec.ts +16 -0
  36. package/src/lib/livechat-assistant.service.ts +9 -0
  37. package/src/lib/services/index.ts +1 -0
  38. package/src/lib/services/request.ts +58 -0
  39. package/src/lib/utilities/helper.ts +23 -0
  40. package/src/lib/utilities/index.ts +1 -0
  41. package/src/public-api.ts +10 -0
  42. package/src/styles.css +5 -0
  43. package/tsconfig.lib.json +15 -0
  44. package/tsconfig.lib.prod.json +11 -0
  45. package/tsconfig.spec.json +15 -0
  46. package/fesm2022/livechat-assistant.mjs +0 -445
  47. package/fesm2022/livechat-assistant.mjs.map +0 -1
  48. package/index.d.ts +0 -5
  49. package/lib/components/chat-history/chat-history.component.d.ts +0 -94
  50. package/lib/components/chat-widget/chat-widget.component.d.ts +0 -17
  51. package/lib/components/help-support/help-support.component.d.ts +0 -15
  52. package/lib/components/home/home.component.d.ts +0 -8
  53. package/lib/components/index.d.ts +0 -2
  54. package/lib/components/message/message.component.d.ts +0 -16
  55. package/lib/components/success-message/success-message.component.d.ts +0 -15
  56. package/lib/components/support-buttons/support-buttons.component.d.ts +0 -12
  57. package/lib/environment/environment.test.d.ts +0 -15
  58. package/lib/livechat-assistant.component.d.ts +0 -5
  59. package/lib/livechat-assistant.service.d.ts +0 -6
  60. package/lib/services/index.d.ts +0 -1
  61. package/lib/services/request.d.ts +0 -12
  62. package/lib/utilities/helper.d.ts +0 -9
  63. package/lib/utilities/index.d.ts +0 -1
  64. package/public-api.d.ts +0 -5
@@ -0,0 +1,46 @@
1
+ import { NgIf } from '@angular/common';
2
+ import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core';
3
+ import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
4
+
5
+ @Component({
6
+ selector: 'app-help-support',
7
+ imports: [ReactiveFormsModule, NgIf],
8
+ templateUrl: './help-support.component.html',
9
+ styleUrl: './help-support.component.scss',
10
+ standalone: true,
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ })
13
+ export class HelpSupportComponent {
14
+ showTooltip = false;
15
+ contactForm!: FormGroup;
16
+ @Output() navigate= new EventEmitter<number>();
17
+
18
+ constructor(private fb: FormBuilder) {}
19
+
20
+ ngOnInit() {
21
+ this.contactForm = this.fb.group({
22
+ name: ['', [Validators.required]],
23
+ email: ['', [Validators.required, Validators.email]],
24
+ subject: ['', [Validators.required]],
25
+ message: ['', [Validators.required]]
26
+ });
27
+ }
28
+
29
+ onSubmit() {
30
+ if (this.contactForm.valid) {
31
+ console.log('Form submitted:', this.contactForm.value);
32
+
33
+ this.contactForm.reset();
34
+ } else {
35
+ // Mark all fields as touched to show validation errors
36
+ Object.keys(this.contactForm.controls).forEach(key => {
37
+ this.contactForm.get(key)?.markAsTouched();
38
+ });
39
+ }
40
+
41
+ }
42
+
43
+ navigateToTab(tabIndex:number) {
44
+ this.navigate.emit(tabIndex);
45
+ }
46
+ }
@@ -0,0 +1,64 @@
1
+ <div class="rounded-lg flex flex-col overflow-hidden max-h-[600px]">
2
+ <div class="relative h-32 bg-gradient-to-br from-cyan-300 via-blue-600 to-orange-400 overflow-hidden">
3
+ <div class="absolute inset-0">
4
+ <div class="absolute top-0 left-0 w-24 h-24 bg-blue-700 transform rotate-45 -translate-x-8 -translate-y-8"></div>
5
+ <div class="absolute top-4 right-0 w-32 h-32 bg-orange-400 transform rotate-12 translate-x-12"></div>
6
+ <div class="absolute bottom-0 left-8 w-28 h-28 bg-cyan-400 transform -rotate-12 translate-y-12"></div>
7
+ </div>
8
+ <button class="absolute top-3 right-3 w-6 h-6 bg-white/20 rounded-full flex items-center justify-center text-white hover:bg-white/30">
9
+ ×
10
+ </button>
11
+
12
+ <!-- Logo -->
13
+ <div class="absolute bottom-4 left-4 w-10 h-10 bg-white rounded-full flex items-center justify-center shadow-lg">
14
+ <svg class="w-6 h-6 text-blue-600" fill="currentColor" viewBox="0 0 24 24">
15
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/>
16
+ </svg>
17
+ </div>
18
+ </div>
19
+
20
+ <div class="flex-1 overflow-y-auto p-4 hideScroll">
21
+ <div>
22
+ <h2 class="text-lg font-semibold dark:text-neutral-200 text-gray-800 mt-4">Hi, Penny 👋</h2>
23
+ <p class="text-sm text-neutral-500 dark:text-neutral-200 mb-5">Preline support team is here to help.</p>
24
+
25
+ <button (click)="navigateToTab(3)" class="w-full bg-blue-600 text-white py-3 rounded-lg font-medium hover:bg-blue-700 transition mb-6">
26
+ Send us a message
27
+ </button>
28
+
29
+ <div class="space-y-4">
30
+ <p class="text-sm font-semibold text-neutral-500 dark:text-neutral-200">Popular topics</p>
31
+
32
+ <a href="#" class="flex items-center justify-between p-3 dark:bg-neutral-800 bg-neutral-50 hover:bg-neutral-800/50 rounded-lg transition group">
33
+ <div>
34
+ <h3 class="fs-16 fw-6 dark:text-neutral-200 text-neutral-800">Live Chat</h3>
35
+ <p class="text-sm text-neutral-500 dark:text-neutral-200/80 text-neutral-800">Team, Invoices, Refunds, and Updates</p>
36
+ </div>
37
+ <svg class="w-5 h-5 text-neutral-400 group-hover:text-neutral-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
38
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
39
+ </svg>
40
+ </a>
41
+
42
+ <a href="#" class="flex items-center justify-between p-3 dark:bg-neutral-800 bg-neutral-50 hover:bg-neutral-800/50 rounded-lg transition group">
43
+ <div>
44
+ <h3 class="fs-16 fw-6 dark:text-neutral-200 text-neutral-800">AI Chat</h3>
45
+ <p class="text-sm text-neutral-500 dark:text-neutral-200/80 text-neutral-800">Team, Invoices, Refunds, and Updates</p>
46
+ </div>
47
+ <svg class="w-5 h-5 text-neutral-400 group-hover:text-neutral-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
48
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
49
+ </svg>
50
+ </a>
51
+
52
+ <a href="#" class="flex mb-2 items-center justify-between p-3 dark:bg-neutral-800 bg-gray-50 hover:bg-neutral-800/50 rounded-lg transition group">
53
+ <div>
54
+ <h3 class="fs-16 fw-6 dark:text-neutral-200 text-neutral-800">Support Chat</h3>
55
+ <p class="text-sm text-gray-500 dark:text-neutral-200/80 text-neutral-800">Team, Invoices, Refunds, and Updates</p>
56
+ </div>
57
+ <svg class="w-5 h-5 text-gray-400 group-hover:text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
58
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
59
+ </svg>
60
+ </a>
61
+ </div>
62
+ </div>
63
+
64
+ <div class="border-t border-neutral-700"></div>
File without changes
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { HomeComponent } from './home.component';
4
+
5
+ describe('HomeComponent', () => {
6
+ let component: HomeComponent;
7
+ let fixture: ComponentFixture<HomeComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [HomeComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(HomeComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,18 @@
1
+ import { ChangeDetectionStrategy, Component, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'app-home',
5
+ imports: [],
6
+ templateUrl: './home.component.html',
7
+ styleUrl: './home.component.scss',
8
+ standalone: true,
9
+ changeDetection: ChangeDetectionStrategy.OnPush,
10
+ encapsulation: ViewEncapsulation.None
11
+ })
12
+ export class HomeComponent {
13
+ @Output() navigate= new EventEmitter<number>();
14
+
15
+ navigateToTab(tabIndex: number) {
16
+ this.navigate.emit(tabIndex);
17
+ }
18
+ }
@@ -0,0 +1,2 @@
1
+ export * from './chat-widget/chat-widget.component'
2
+ export * from './support-buttons/support-buttons.component'
@@ -0,0 +1,119 @@
1
+ <div class="flex flex-col rounded-xl" [class]="noMessage ? 'max-h-[600px]' : 'h-[600px]'">
2
+ <div
3
+ class="flex items-center justify-between px-4 py-3 dark:bg-neutral-700/20 shadow-xl bg-neutral-50 hover:bg-neutral-800/50 rounded-xl">
4
+ <div class="flex items-center gap-3">
5
+ <button class="cursor-pointer" (click)="return(4)">
6
+ <svg class="w-5 h-5 text-neutral-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
7
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
8
+ </svg>
9
+ </button>
10
+ <img src="https://ui-avatars.com/api/?name=Costa+Quinn&background=0D8ABC&color=fff"
11
+ class="w-10 h-10 rounded-full" alt="Agent">
12
+ <div>
13
+ <h3 class="font-semibold text-neutral-800 dark:text-neutral-200 fs-16">AI Bot</h3>
14
+ <p class="text-green-300/80 fs-14">Online</p>
15
+ </div>
16
+ </div>
17
+ </div>
18
+
19
+
20
+ <div class="text-center h-full flex flex-col justify-center items-center relative animate-scale-in">
21
+ <h2 class="text-2xl font-bold text-gray-800 mb-2 dark:text-neutral-200">Hey Penny!</h2>
22
+ <p class="text-gray-600 text-sm dark:text-neutral-200/80">
23
+ You can ask me anything.
24
+ </p>
25
+ </div>
26
+
27
+
28
+ @if(noMessage) {
29
+ <div class="flex-1 overflow-y-auto px-4 py-6 space-y-4 hideScroll">
30
+ @for (message of messages; track $index) {
31
+ <div [class.flex-row-reverse]="message.sender === 'customer'" class="flex gap-3 items-start">
32
+
33
+ @if (message.sender === 'agent') {
34
+ <img src="https://ui-avatars.com/api/?name=Costa+Quinn&background=0D8ABC&color=fff"
35
+ class="w-8 h-8 rounded-full flex-shrink-0" alt="Avatar" />
36
+ }
37
+
38
+ <div [class.items-end]="message.sender === 'customer'" class="flex flex-col max-w-xs">
39
+
40
+ <div [class.bg-blue-600]="message.sender === 'customer'"
41
+ [class.text-white]="message.sender === 'customer'" [class.bg-white]="message.sender === 'agent'"
42
+ [class.text-gray-800]="message.sender === 'agent'" class="rounded-2xl px-4 py-2.5 shadow-sm">
43
+ <p class="text-sm whitespace-pre-wrap fs-16 ">{{ message.text }}</p>
44
+ </div>
45
+ <span class="text-sm text-neutral-300 mt-1 px-1">{{ message.time }}</span>
46
+ </div>
47
+ </div>
48
+ }
49
+
50
+
51
+
52
+ @if (isTyping) {
53
+ <div class="flex gap-3 items-start">
54
+ <img src="https://ui-avatars.com/api/?name=Costa+Quinn&background=0D8ABC&color=fff"
55
+ class="w-8 h-8 rounded-full" alt="Agent">
56
+ <div class="bg-white rounded-2xl px-4 py-3 shadow-sm">
57
+ <div class="flex gap-1">
58
+ <span class="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></span>
59
+ <span class="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style="animation-delay: 0.2s"></span>
60
+ <span class="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style="animation-delay: 0.4s"></span>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ }
65
+ </div>
66
+ }
67
+ <div>
68
+ <div class="flex flex-wrap justify-center gap-1.5 sm:gap-2 bg-transparent scroll-xcontainer">
69
+ @for (suggestion of suggestions; track $index) {
70
+ <button (click)="newMessage = suggestion; onSendMessage()" class="py-1.5 px-2.5 inline-flex items-center gap-x-1.5 text-sm bg-linear-to-tl from-blue-500 to-blue-800 text-white rounded-lg focus:outline-hidden ">
71
+ {{ suggestion }}
72
+ </button>
73
+ }
74
+ </div>
75
+ </div>
76
+
77
+ <div class="px-4">
78
+
79
+ <div class="flex justify-between items-center w-full py-2.5">
80
+ <div class="flex gap-2 w-full">
81
+ <button (click)="fileInput.click()"
82
+ class="text-gray-500 hover:text-gray-700 rounded-full hover:bg-gray-100">
83
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
84
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
85
+ d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" />
86
+ </svg>
87
+ </button>
88
+ <input #fileInput type="file" class="hidden" (change)="onFileSelect($event)">
89
+
90
+ <button class="text-gray-500 hover:text-gray-700 rounded-full hover:bg-gray-100">
91
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
92
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
93
+ d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
94
+ </svg>
95
+ </button>
96
+
97
+ <input [(ngModel)]="newMessage" (keyup.enter)="onSendMessage()" type="text"
98
+ placeholder="Type a message..."
99
+ class="flex-1 py-3 dark:text-white text-black rounded-md fs-16 focus:outline-none focus:ring-0 focus:ring-none w-full" />
100
+ </div>
101
+
102
+ <div class="flex gap-2 justify-end">
103
+ <button (click)="onSendMessage()" [disabled]="!newMessage.trim()"
104
+ class="bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed p-2">
105
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
106
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
107
+ d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
108
+ </svg>
109
+ </button>
110
+ <button class="text-gray-500 hover:text-gray-700 rounded-full hover:bg-gray-100">
111
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
112
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
113
+ d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" />
114
+ </svg>
115
+ </button>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </div>
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { MessageComponent } from './message.component';
4
+
5
+ describe('MessageComponent', () => {
6
+ let component: MessageComponent;
7
+ let fixture: ComponentFixture<MessageComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [MessageComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(MessageComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,48 @@
1
+ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+
4
+ @Component({
5
+ selector: 'app-message',
6
+ imports: [FormsModule],
7
+ templateUrl: './message.component.html',
8
+ styleUrl: './message.component.scss',
9
+ standalone: true,
10
+ changeDetection: ChangeDetectionStrategy.OnPush,
11
+ })
12
+ export class MessageComponent {
13
+ newMessage = '';
14
+ noMessage = false;
15
+ @Input() isTyping = false;
16
+ @Input() messages: any;
17
+ @Input() suggestions: string[] = ['Health', 'Learn', 'Technology', 'Science'];
18
+
19
+ @Output() sendMessage = new EventEmitter();
20
+ @Output() navigate= new EventEmitter<number>();
21
+
22
+ onSendMessage() {
23
+ if (this.newMessage.trim()) {
24
+ this.sendMessage.emit(this.newMessage);
25
+ this.newMessage = '';
26
+ this.noMessage = true
27
+ }
28
+ }
29
+
30
+ onFileSelect(event: any) {
31
+ const file = event.target.files[0];
32
+ if (file) {
33
+ console.log('File selected:', file.name);
34
+ // Handle file upload here
35
+ }
36
+ }
37
+
38
+ return(tabIndex:number) {
39
+ this.navigate.emit(tabIndex);
40
+ }
41
+
42
+ // private scrollToBottom(): void {
43
+ // if (this.messagesContainer) {
44
+ // const element = this.messagesContainer.nativeElement;
45
+ // element.scrollTop = element.scrollHeight;
46
+ // }
47
+ // }
48
+ }
@@ -0,0 +1,33 @@
1
+ <div class="bg-white rounded-lg h-[600px]">
2
+ <div class="confetti-container">
3
+ @for (confetti of confettiArray; track $index) {
4
+ <div
5
+ [style.left.%]="confetti.left"
6
+ [style.animation-delay.s]="confetti.delay"
7
+ [style.background-color]="confetti.color"
8
+ class="confetti">
9
+ </div>
10
+ }
11
+ </div>
12
+
13
+ <div class="p-4 text-center h-full flex flex-col justify-center items-center relative animate-scale-in">
14
+ <div class="mb-6 flex justify-center items-center">
15
+ <div class="w-16 h-16 bg-teal-100 rounded-full flex items-center justify-center animate-bounce-in">
16
+ <svg class="w-8 h-8 text-teal-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
17
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"/>
18
+ </svg>
19
+ </div>
20
+ </div>
21
+
22
+ <!-- Title -->
23
+ <h2 class="text-2xl font-bold text-gray-800 mb-4">Email Delivered!</h2>
24
+ <p class="text-gray-600 text-sm mb-2">
25
+ You're set on chatting with an online agent or ask your our AI robot your questions.
26
+ </p>
27
+
28
+ <button (click)="navigateToTab(2)" class="mt-6 bg-blue-600 text-white px-8 py-3 rounded-lg font-medium hover:bg-blue-700 transition">
29
+ Start a new chat
30
+ </button>
31
+
32
+ </div>
33
+ </div>
@@ -0,0 +1,65 @@
1
+ .confetti-container {
2
+ position: fixed;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ pointer-events: none;
8
+ overflow: hidden;
9
+ z-index: 51;
10
+ }
11
+
12
+ .confetti {
13
+ position: absolute;
14
+ width: 10px;
15
+ height: 10px;
16
+ top: -10%;
17
+ opacity: 0;
18
+ animation: confetti-fall 3s linear forwards;
19
+ }
20
+
21
+ @keyframes confetti-fall {
22
+ 0% {
23
+ top: -10%;
24
+ opacity: 1;
25
+ transform: translateX(0) rotateZ(0deg);
26
+ }
27
+ 100% {
28
+ top: 100%;
29
+ opacity: 0;
30
+ transform: translateX(100px) rotateZ(720deg);
31
+ }
32
+ }
33
+
34
+ @keyframes scale-in {
35
+ 0% {
36
+ transform: scale(0.7);
37
+ opacity: 0;
38
+ }
39
+ 100% {
40
+ transform: scale(1);
41
+ opacity: 1;
42
+ }
43
+ }
44
+
45
+ @keyframes bounce-in {
46
+ 0% {
47
+ transform: scale(0);
48
+ }
49
+ 50% {
50
+ transform: scale(1.2);
51
+ }
52
+ 100% {
53
+ transform: scale(1);
54
+ }
55
+ }
56
+
57
+ .animate-scale-in {
58
+ animation: scale-in 0.4s ease-out;
59
+ }
60
+
61
+ .animate-bounce-in {
62
+ animation: bounce-in 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
63
+ animation-delay: 0.2s;
64
+ animation-fill-mode: backwards;
65
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { SuccessMessageComponent } from './success-message.component';
4
+
5
+ describe('SuccessMessageComponent', () => {
6
+ let component: SuccessMessageComponent;
7
+ let fixture: ComponentFixture<SuccessMessageComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [SuccessMessageComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(SuccessMessageComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,34 @@
1
+ import { Component, ChangeDetectionStrategy, EventEmitter, Output, } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'app-success-message',
5
+ imports: [],
6
+ templateUrl: './success-message.component.html',
7
+ styleUrl: './success-message.component.scss',
8
+ standalone: true,
9
+ changeDetection: ChangeDetectionStrategy.OnPush,
10
+ })
11
+ export class SuccessMessageComponent {
12
+
13
+ @Output() navigate= new EventEmitter<number>();
14
+ confettiArray: Array<{left: number, delay: number, color: string}> = [];
15
+
16
+ ngOnInit() {
17
+ this.generateConfetti();
18
+ }
19
+
20
+ navigateToTab(tabIndex:number) {
21
+ this.navigate.emit(tabIndex);
22
+ }
23
+ generateConfetti() {
24
+ const colors = ['#10B981', '#3B82F6', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899'];
25
+
26
+ for (let i = 0; i < 50; i++) {
27
+ this.confettiArray.push({
28
+ left: Math.random() * 100,
29
+ delay: Math.random() * 2,
30
+ color: colors[Math.floor(Math.random() * colors.length)]
31
+ });
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,42 @@
1
+ <ul class="fab-options z-90 fixed bottom-25 right-5" [class]="cssClass">
2
+ <!-- <li>
3
+ <span class="fab-label bg-white text-neutral-950 dark:bg-neutral-800 dark:text-white">Chat with Aide on Whatsapp</span>
4
+ <a class=" bg-white text-green-600 dark:bg-neutral-800 dark:text-white btn-round btn-fab">
5
+ <div class="size-6">
6
+ <i class='fi fi-brands-whatsapp fs-20'></i>
7
+ </div>
8
+ </a>
9
+ </li>
10
+ <li>
11
+ <span class="fab-label bg-white text-neutral-950 dark:bg-neutral-800 dark:text-white">Chat with Aide on Telegram</span>
12
+ <a class=" bg-white text-blue-400 dark:bg-neutral-800 dark:text-white btn-round btn-fab">
13
+ <div class="size-6">
14
+ <i class='fi fi-brands-telegram fs-20'></i>
15
+ </div>
16
+ </a>
17
+ </li> -->
18
+ <li>
19
+ <span class="fab-label bg-white text-neutral-950 dark:bg-neutral-800 dark:text-white">Live Chat</span>
20
+ <a (click)="toggleLivechat()" class="bg-white text-neutral-950 dark:bg-neutral-800 dark:text-white btn-round btn-fab">
21
+ <div class="size-6">
22
+ <i class='fi fi-rr-robot fs-20'></i>
23
+ </div>
24
+ </a>
25
+ </li>
26
+ <!-- <li>
27
+ <span class="fab-label bg-white text-neutral-950 dark:bg-neutral-800 dark:text-white">Send us a mail</span>
28
+ <a class="bg-white text-neutral-950 dark:bg-neutral-800 dark:text-white btn-round btn-fab">
29
+ <div class="size-6">
30
+ <i class='fi fi-rr-envelope fs-20'></i>
31
+ </div>
32
+ </a>
33
+ </li> -->
34
+ </ul>
35
+
36
+ <button class="fixed bottom-5 right-5 main z-90 animated fadeInUp fs-20 bg-linear-to-tl from-blue-500 to-blue-800 text-white btn-round btn-fab btn-fab-button dark:bg-dark" (click)="toggleFab()" (keydown)="toggleFab()">
37
+ <div class="size-6">
38
+ <i class='fi fi-rr-comment fs-30 relative'></i>
39
+ </div>
40
+ </button>
41
+
42
+ <app-chat-widget [isOpen]="isOpen || false" />
@@ -0,0 +1,49 @@
1
+ :host {
2
+
3
+ .fadeIn {
4
+ opacity: 1 !important;
5
+ transform: scale(1) !important;
6
+ }
7
+
8
+ .fadeOut {
9
+ opacity: 0 !important;
10
+ transform: scale(0) !important;
11
+ }
12
+
13
+ .fab-options {
14
+ list-style-type: none;
15
+ opacity: 0;
16
+ transition: all 0.3s ease;
17
+ transform: scale(0);
18
+ transform-origin: 85% bottom;
19
+ li {
20
+ display: flex;
21
+ justify-content: flex-end;
22
+ padding: 5px;
23
+
24
+ .btn-fab {
25
+ width: 50px !important;
26
+ height: 50px !important;
27
+ box-shadow: 0 6px 20px rgba(0,0,0,0.2);
28
+ i {
29
+ position: relative !important;
30
+ top: 12px !important;
31
+ right: -15px !important;
32
+ // margin: 10px auto !important;
33
+ }
34
+ }
35
+
36
+ .fab-label {
37
+ padding: 2px 10px;
38
+ align-self: center;
39
+ user-select: none;
40
+ white-space: nowrap;
41
+ border-radius: 3px;
42
+ font-size: 13px;
43
+ font-weight: 400;
44
+ box-shadow: 0 6px 20px rgba(0,0,0,0.2);
45
+ margin-right: 10px;
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,21 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { SupportButtonsComponent } from './support-buttons.component';
4
+
5
+ describe('SupportButtonsComponent', () => {
6
+ let component: SupportButtonsComponent;
7
+ let fixture: ComponentFixture<SupportButtonsComponent>;
8
+
9
+ beforeEach(() => {
10
+ TestBed.configureTestingModule({
11
+ declarations: [SupportButtonsComponent]
12
+ });
13
+ fixture = TestBed.createComponent(SupportButtonsComponent);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+ });
@@ -0,0 +1,33 @@
1
+ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
2
+ import { ChatWidgetComponent } from '../chat-widget/chat-widget.component';
3
+ import { closeChat, toggleLivechat } from '../../utilities';
4
+
5
+ @Component({
6
+ selector: 'app-support-buttons',
7
+ templateUrl: './support-buttons.component.html',
8
+ styleUrls: ['./support-buttons.component.scss'],
9
+ standalone: true,
10
+ imports: [
11
+ ChatWidgetComponent
12
+ ],
13
+ changeDetection: ChangeDetectionStrategy.OnPush,
14
+ })
15
+ export class SupportButtonsComponent implements OnInit {
16
+ cssClass: 'fadeIn' | 'fadeOut' = 'fadeOut';
17
+ isOpen = false;
18
+
19
+ constructor() {}
20
+
21
+ ngOnInit(): void {
22
+ closeChat();
23
+ }
24
+
25
+ toggleFab() {
26
+ closeChat();
27
+ this.cssClass = this.cssClass === 'fadeIn' ? 'fadeOut' : 'fadeIn';
28
+ }
29
+
30
+ toggleLivechat() {
31
+ this.isOpen = toggleLivechat();
32
+ }
33
+ }