@aslaluroba/help-center 1.0.0

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 (63) hide show
  1. package/.editorconfig +17 -0
  2. package/README.md +76 -0
  3. package/angular.json +106 -0
  4. package/ng-package.json +29 -0
  5. package/package-lock.json +16479 -0
  6. package/package.json +62 -0
  7. package/postcss.config.js +6 -0
  8. package/proxy.conf.json +4 -0
  9. package/public/Shape.png +0 -0
  10. package/public/favicon.ico +0 -0
  11. package/public_api.ts +5 -0
  12. package/src/app/app.component.html +336 -0
  13. package/src/app/app.component.scss +0 -0
  14. package/src/app/app.component.spec.ts +29 -0
  15. package/src/app/app.component.ts +59 -0
  16. package/src/app/app.config.ts +47 -0
  17. package/src/app/app.routes.ts +3 -0
  18. package/src/app/chat/chat.component.html +102 -0
  19. package/src/app/chat/chat.component.ts +88 -0
  20. package/src/app/help-center-widget/help-center-widget.component.html +224 -0
  21. package/src/app/help-center-widget/help-center-widget.component.scss +427 -0
  22. package/src/app/help-center-widget/help-center-widget.component.spec.ts +23 -0
  23. package/src/app/help-center-widget/help-center-widget.component.ts +446 -0
  24. package/src/app/help-center-widget/help-center.module.ts +15 -0
  25. package/src/app/help-screen-data/help-screen-data.component.html +46 -0
  26. package/src/app/help-screen-data/help-screen-data.component.ts +83 -0
  27. package/src/app/language.service.ts +17 -0
  28. package/src/app/services/api.service.ts +89 -0
  29. package/src/app/services/help-center-config.service.ts +16 -0
  30. package/src/app/services/signalrService.service.ts +104 -0
  31. package/src/app/services/token.service.ts +44 -0
  32. package/src/app/shared/components/button/button.component.ts +81 -0
  33. package/src/app/shared/components/button/index.ts +1 -0
  34. package/src/app/shared/components/card/card.component.ts +106 -0
  35. package/src/app/shared/components/card/index.ts +1 -0
  36. package/src/app/shared/components/confirmation-dialog/confirmation-dialog.component.ts +40 -0
  37. package/src/app/shared/components/header/header.component.ts +119 -0
  38. package/src/app/shared/components/header/index.ts +1 -0
  39. package/src/app/shared/components/loading/loading.component.ts +14 -0
  40. package/src/app/shared/utils/class-utils.ts +9 -0
  41. package/src/app/transloco-loader.ts +12 -0
  42. package/src/assets/i18n/ar.json +17 -0
  43. package/src/assets/i18n/en.json +17 -0
  44. package/src/assets/icons/arrow-stripped-colored.svg +3 -0
  45. package/src/assets/icons/arrow-stripped.svg +3 -0
  46. package/src/assets/icons/chat.svg +4 -0
  47. package/src/assets/icons/close-circle.svg +3 -0
  48. package/src/assets/icons/menu.svg +3 -0
  49. package/src/assets/icons/person.svg +4 -0
  50. package/src/assets/icons/send.svg +3 -0
  51. package/src/assets/images/animatedLogo.gif +0 -0
  52. package/src/assets/images/seperator.svg +5 -0
  53. package/src/assets/images/stars.svg +7 -0
  54. package/src/assets/logo-primary.svg +6 -0
  55. package/src/assets/logo-white.svg +6 -0
  56. package/src/index.html +13 -0
  57. package/src/main.ts +5 -0
  58. package/src/styles.scss +43 -0
  59. package/tailwind.config.ts +175 -0
  60. package/transloco.config.ts +9 -0
  61. package/tsconfig.app.json +15 -0
  62. package/tsconfig.json +31 -0
  63. package/tsconfig.spec.json +15 -0
@@ -0,0 +1,16 @@
1
+ import { Injectable } from '@angular/core'
2
+
3
+ @Injectable({
4
+ providedIn: 'root'
5
+ })
6
+ export class HelpCenterConfigService {
7
+ private _apiBaseUrl: string = 'https://babylai.net/api'
8
+
9
+ setApiBaseUrl(url: string) {
10
+ this._apiBaseUrl = url
11
+ }
12
+
13
+ getApiBaseUrl(): string {
14
+ return this._apiBaseUrl
15
+ }
16
+ }
@@ -0,0 +1,104 @@
1
+ import { Injectable } from '@angular/core';
2
+ import * as signalR from '@microsoft/signalr';
3
+
4
+ @Injectable({
5
+ providedIn: 'root',
6
+ })
7
+ export class SignalRService {
8
+ private connection: signalR.HubConnection | null = null;
9
+ private isConnected = false;
10
+ private baseURL = 'http://localhost:5086'; // Replace with your API URL
11
+ private hubUrl = 'https://babylai.net'; // Replace with your SignalR hub URL
12
+
13
+ async startConnection(
14
+ sessionId: string,
15
+ apiKey: string,
16
+ onMessageReceived: (
17
+ message: string,
18
+ senderType: string,
19
+ needsAgent: boolean
20
+ ) => void
21
+ ): Promise<void> {
22
+ console.log('sessionId:', sessionId);
23
+
24
+ if (this.isConnected) return;
25
+
26
+ this.connection = new signalR.HubConnectionBuilder()
27
+ .withUrl(
28
+ `${this.hubUrl}/clientHub?access_token=${encodeURIComponent(apiKey)}`,
29
+ {
30
+ withCredentials: true,
31
+ transport:
32
+ signalR.HttpTransportType.WebSockets |
33
+ signalR.HttpTransportType.LongPolling,
34
+ headers: {
35
+ Authorization: `Bearer ${apiKey}`,
36
+ 'X-Requested-With': 'XMLHttpRequest',
37
+ 'X-SignalR-User-Agent':
38
+ 'Microsoft SignalR/8.0 (8.0.7; Unknown OS; Browser; Unknown Runtime Version)',
39
+ },
40
+ skipNegotiation: false,
41
+ accessTokenFactory: () => apiKey,
42
+ }
43
+ )
44
+ .withAutomaticReconnect()
45
+ .configureLogging(signalR.LogLevel.Information)
46
+ .build();
47
+
48
+ this.connection.on(
49
+ 'ReceiveMessage',
50
+ (message: string, senderType: string, needsAgent: boolean) => {
51
+ console.log(
52
+ 'Received message from SignalR:',
53
+ message,
54
+ senderType,
55
+ needsAgent
56
+ );
57
+ onMessageReceived(message, senderType, needsAgent);
58
+ }
59
+ );
60
+
61
+ try {
62
+ await this.connection.start();
63
+ console.log('SignalR connection started successfully.');
64
+
65
+ this.isConnected = true;
66
+ await this.joinGroup(sessionId);
67
+ console.log('SignalR group joined.');
68
+ } catch (error) {
69
+ console.error('Error connecting to SignalR', error);
70
+ this.isConnected = false;
71
+ }
72
+ }
73
+
74
+ async joinGroup(sessionId: string): Promise<void> {
75
+ if (this.connection) {
76
+ try {
77
+ console.log(`Attempting to join group with session ID: ${sessionId}`);
78
+ await this.connection.invoke('JoinGroup', sessionId);
79
+ console.log(`Joined group with session ID: ${sessionId}`);
80
+ } catch (error) {
81
+ console.error('Error joining SignalR group:', error);
82
+ }
83
+ }
84
+ }
85
+
86
+ async leaveGroup(sessionId: string): Promise<void> {
87
+ if (this.connection && this.isConnected) {
88
+ try {
89
+ await this.connection.invoke('LeaveGroup', sessionId);
90
+ console.log(`Left group with session ID: ${sessionId}`);
91
+ } catch (error) {
92
+ console.error('Error leaving SignalR group:', error);
93
+ }
94
+ }
95
+ }
96
+
97
+ async stopConnection(): Promise<void> {
98
+ if (this.connection && this.isConnected) {
99
+ await this.connection.stop();
100
+ this.isConnected = false;
101
+ console.log('SignalR disconnected.');
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,44 @@
1
+ import { Injectable } from '@angular/core'
2
+
3
+ export interface TokenResponse {
4
+ token: string
5
+ expiresIn: number
6
+ }
7
+
8
+ @Injectable({
9
+ providedIn: 'root'
10
+ })
11
+ export class TokenService {
12
+ private baseUrl: string | null = null
13
+
14
+ initializeService(baseUrl: string) {
15
+ this.baseUrl = baseUrl
16
+ }
17
+
18
+ async getToken(): Promise<TokenResponse> {
19
+ if (!this.baseUrl) {
20
+ throw new Error('Token service not initialized. Call initializeService first.')
21
+ }
22
+
23
+ try {
24
+ const response = await fetch(`${this.baseUrl}/Auth/client/get-babylai-token`, {
25
+ method: 'POST',
26
+ headers: {
27
+ 'Content-Type': 'application/json'
28
+ }
29
+ })
30
+
31
+ if (!response.ok) {
32
+ throw new Error('Failed to fetch token')
33
+ }
34
+
35
+ const data = await response.json()
36
+ return {
37
+ token: data.token,
38
+ expiresIn: data.expiresIn || 3600 // Default to 1 hour if not provided
39
+ }
40
+ } catch (error) {
41
+ throw new Error('Failed to get authentication token')
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,81 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import { Component, EventEmitter, Input, Output } from '@angular/core'
3
+ import { TranslocoModule } from '@jsverse/transloco'
4
+
5
+ type ButtonVariant = 'default' | 'icon-bg' | 'icon-only'
6
+ type ButtonType = 'button' | 'submit' | 'reset'
7
+
8
+ @Component({
9
+ selector: 'app-button',
10
+ standalone: true,
11
+ imports: [CommonModule, TranslocoModule],
12
+ template: `
13
+ <button [type]="type" [disabled]="disabled" [ngClass]="getButtonClasses()" (click)="onClick.emit($event)">
14
+ <ng-content></ng-content>
15
+ </button>
16
+ `
17
+ })
18
+ export class ButtonComponent {
19
+ @Input() variant: ButtonVariant = 'default'
20
+ @Input() type: ButtonType = 'button'
21
+ @Input() disabled = false
22
+ @Input() fullWidth = false
23
+ @Input() className = ''
24
+ @Output() onClick = new EventEmitter<MouseEvent>()
25
+
26
+ getButtonClasses(): string {
27
+ const baseClasses = 'babylai-cursor-pointer babylai-transition-all babylai-duration-200 '
28
+
29
+ const variantClasses = {
30
+ default: 'babylai-bg-primary babylai-text-white babylai-py-2 babylai-px-4 babylai-rounded-full hover:babylai-bg-primary-700',
31
+ 'icon-bg':
32
+ 'babylai-bg-primary babylai-text-white babylai-py-2 babylai-px-4 babylai-rounded-full babylai-w-12 babylai-h-12 babylai-flex babylai-items-center babylai-justify-center hover:babylai-bg-primary-700',
33
+ 'icon-only': 'babylai-bg-transparent babylai-border-none babylai-p-1 babylai-flex babylai-items-center babylai-justify-center'
34
+ }
35
+
36
+ const widthClass = this.fullWidth ? 'babylai-w-full' : ''
37
+ const disabledClass = this.disabled ? 'babylai-opacity-50 babylai-cursor-not-allowed' : ''
38
+
39
+ return `${baseClasses} ${variantClasses[this.variant]} ${widthClass} ${disabledClass} ${this.className}`
40
+ }
41
+ }
42
+
43
+ @Component({
44
+ selector: 'app-button-content',
45
+ standalone: true,
46
+ imports: [CommonModule],
47
+ template: ` <ng-content></ng-content> `
48
+ })
49
+ export class ButtonContentComponent {}
50
+
51
+ @Component({
52
+ selector: 'app-icon-button',
53
+ standalone: true,
54
+ imports: [CommonModule, ButtonComponent],
55
+ template: `
56
+ <app-button [variant]="'icon-bg'" [className]="className" [disabled]="disabled" (onClick)="onClick.emit($event)">
57
+ <ng-content></ng-content>
58
+ </app-button>
59
+ `
60
+ })
61
+ export class IconButtonComponent {
62
+ @Input() className = ''
63
+ @Input() disabled = false
64
+ @Output() onClick = new EventEmitter<MouseEvent>()
65
+ }
66
+
67
+ @Component({
68
+ selector: 'app-transparent-icon-button',
69
+ standalone: true,
70
+ imports: [CommonModule, ButtonComponent],
71
+ template: `
72
+ <app-button [variant]="'icon-only'" [className]="className" [disabled]="disabled" (onClick)="onClick.emit($event)">
73
+ <ng-content></ng-content>
74
+ </app-button>
75
+ `
76
+ })
77
+ export class TransparentIconButtonComponent {
78
+ @Input() className = ''
79
+ @Input() disabled = false
80
+ @Output() onClick = new EventEmitter<MouseEvent>()
81
+ }
@@ -0,0 +1 @@
1
+ export * from './button.component'
@@ -0,0 +1,106 @@
1
+ import { Component, Input, HostBinding, ViewEncapsulation, inject } from '@angular/core'
2
+ import { CommonModule } from '@angular/common'
3
+ import { cn } from '../../utils/class-utils'
4
+
5
+ @Component({
6
+ selector: 'app-card',
7
+ standalone: true,
8
+ imports: [CommonModule],
9
+ template: `<ng-content></ng-content>`,
10
+ encapsulation: ViewEncapsulation.None
11
+ })
12
+ export class CardComponent {
13
+ @Input() variant: 'default' | 'rounded' | 'shadowed' = 'default'
14
+ @Input() class = ''
15
+
16
+ @HostBinding('class')
17
+ get hostClasses(): string {
18
+ const variantStyles = {
19
+ default: 'babylai-rounded-xl babylai-border babylai-bg-card babylai-text-card-foreground babylai-shadow',
20
+ rounded: 'babylai-rounded-3xl babylai-bg-black-white-50 babylai-py-4 babylai-px-[24px] babylai-w-full babylai-block',
21
+ shadowed: 'babylai-rounded-xl babylai-border babylai-bg-card babylai-text-card-foreground babylai-shadow-lg'
22
+ }
23
+
24
+ return cn(variantStyles[this.variant], this.class)
25
+ }
26
+ }
27
+
28
+ @Component({
29
+ selector: 'app-card-header',
30
+ standalone: true,
31
+ imports: [CommonModule],
32
+ template: `<ng-content></ng-content>`,
33
+ encapsulation: ViewEncapsulation.None
34
+ })
35
+ export class CardHeaderComponent {
36
+ @Input() class = ''
37
+
38
+ @HostBinding('class')
39
+ get hostClasses(): string {
40
+ return cn('babylai-flex babylai-flex-col babylai-space-y-1.5 babylai-p-6', this.class)
41
+ }
42
+ }
43
+
44
+ @Component({
45
+ selector: 'app-card-title',
46
+ standalone: true,
47
+ imports: [CommonModule],
48
+ template: `<ng-content></ng-content>`,
49
+ encapsulation: ViewEncapsulation.None
50
+ })
51
+ export class CardTitleComponent {
52
+ @Input() class = ''
53
+
54
+ @HostBinding('class')
55
+ get hostClasses(): string {
56
+ return cn('babylai-font-semibold babylai-leading-none babylai-tracking-tight', this.class)
57
+ }
58
+ }
59
+
60
+ @Component({
61
+ selector: 'app-card-description',
62
+ standalone: true,
63
+ imports: [CommonModule],
64
+ template: `<ng-content></ng-content>`,
65
+ encapsulation: ViewEncapsulation.None
66
+ })
67
+ export class CardDescriptionComponent {
68
+ @Input() class = ''
69
+
70
+ @HostBinding('class')
71
+ get hostClasses(): string {
72
+ return cn('babylai-text-sm babylai-text-muted-foreground', this.class)
73
+ }
74
+ }
75
+
76
+ @Component({
77
+ selector: 'app-card-content',
78
+ standalone: true,
79
+ imports: [CommonModule],
80
+ template: `<ng-content></ng-content>`,
81
+ encapsulation: ViewEncapsulation.None
82
+ })
83
+ export class CardContentComponent {
84
+ @Input() class = ''
85
+
86
+ @HostBinding('class')
87
+ get hostClasses(): string {
88
+ return cn('babylai-p-0 babylai-pt-0', this.class)
89
+ }
90
+ }
91
+
92
+ @Component({
93
+ selector: 'app-card-footer',
94
+ standalone: true,
95
+ imports: [CommonModule],
96
+ template: `<ng-content></ng-content>`,
97
+ encapsulation: ViewEncapsulation.None
98
+ })
99
+ export class CardFooterComponent {
100
+ @Input() class = ''
101
+
102
+ @HostBinding('class')
103
+ get hostClasses(): string {
104
+ return cn('babylai-flex babylai-items-center babylai-p-6 babylai-pt-0', this.class)
105
+ }
106
+ }
@@ -0,0 +1 @@
1
+ export * from './card.component'
@@ -0,0 +1,40 @@
1
+ import { Component, Input, Output, EventEmitter } from '@angular/core'
2
+ import { CommonModule } from '@angular/common'
3
+ import { ButtonComponent } from '../button'
4
+ import { TranslocoModule } from '@jsverse/transloco'
5
+
6
+ @Component({
7
+ selector: 'app-confirmation-dialog',
8
+ standalone: true,
9
+ imports: [CommonModule, ButtonComponent, TranslocoModule],
10
+ template: `
11
+ <div
12
+ class="babylai-absolute babylai-inset-0 babylai-bg-black/50 babylai-z-[10] babylai-flex babylai-items-center babylai-justify-center babylai-rounded-3xl"
13
+ >
14
+ <div class="babylai-bg-white babylai-rounded-2xl babylai-p-6 babylai-max-w-sm babylai-w-full babylai-mx-4">
15
+ <h3 class="babylai-text-xl babylai-font-bold babylai-mb-2">{{ title }}</h3>
16
+ <p class="babylai-text-gray-600 babylai-mb-6">{{ body }}</p>
17
+ <div class="babylai-flex babylai-gap-3 babylai-justify-end">
18
+ <app-button
19
+ variant="default"
20
+ className="!babylai-bg-transparent !babylai-text-primary !babylai-border !babylai-border-primary hover:!babylai-bg-primary/10"
21
+ (click)="onCancel.emit()"
22
+ >
23
+ {{ cancelText }}
24
+ </app-button>
25
+ <app-button variant="default" (click)="onConfirm.emit()">
26
+ {{ confirmText }}
27
+ </app-button>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ `
32
+ })
33
+ export class ConfirmationDialogComponent {
34
+ @Input() title: string = ''
35
+ @Input() body: string = ''
36
+ @Input() confirmText: string = 'Confirm'
37
+ @Input() cancelText: string = 'Cancel'
38
+ @Output() onConfirm = new EventEmitter<void>()
39
+ @Output() onCancel = new EventEmitter<void>()
40
+ }
@@ -0,0 +1,119 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core'
3
+ import { TranslocoModule } from '@jsverse/transloco'
4
+ import { ButtonComponent } from '../button'
5
+
6
+ type HeaderType = 'standard' | 'minimal'
7
+
8
+ @Component({
9
+ selector: 'app-header',
10
+ standalone: true,
11
+ imports: [CommonModule, TranslocoModule, ButtonComponent],
12
+ template: `
13
+ <div class="babylai-p-4 babylai-flex babylai-items-center babylai-justify-between">
14
+ <app-button *ngIf="showBackButton" variant="icon-bg" className="!babylai-bg-black-white-50" (click)="onBack.emit()">
15
+ <img
16
+ src="/icons/arrow-stripped-colored.svg"
17
+ alt="Back"
18
+ class="babylai-w-6 babylai-h-6"
19
+ [ngClass]="{ 'babylai-rotate-180': language === 'ar' }"
20
+ />
21
+ </app-button>
22
+ <img *ngIf="showLogo" [src]="logoSrc" [alt]="logoAlt" class="babylai-w-10 babylai-h-10" />
23
+ <app-button *ngIf="!showBackButton" variant="icon-only" (click)="onClose.emit()">
24
+ <img src="/icons/close-circle.svg" alt="Close" class="babylai-w-10 babylai-h-10" />
25
+ </app-button>
26
+ </div>
27
+ `
28
+ })
29
+ export class HeaderComponent {
30
+ @Input() headerType: HeaderType = 'standard'
31
+ @Input() showBackButton = false
32
+ @Input() showLogo = true
33
+ @Input() logoSrc = '/logo-white.svg'
34
+ @Input() logoAlt = 'BabylAI Logo'
35
+ @Input() language = 'en'
36
+ @Output() onBack = new EventEmitter<void>()
37
+ @Output() onClose = new EventEmitter<void>()
38
+ }
39
+
40
+ @Component({
41
+ selector: 'app-chat-header',
42
+ standalone: true,
43
+ imports: [CommonModule, TranslocoModule, ButtonComponent],
44
+ template: `
45
+ <div
46
+ class="babylai-p-4 babylai-flex babylai-items-center babylai-justify-between babylai-bg-black-white-50 babylai-rounded-t-3xl babylai-relative"
47
+ >
48
+ <div class="babylai-flex babylai-items-center babylai-gap-2">
49
+ <app-button
50
+ variant="icon-bg"
51
+ className="!babylai-bg-primary-500/10 babylai-w-8 babylai-h-8 !babylai-p-2 hover:!babylai-bg-primary-700/10"
52
+ (click)="onBack.emit()"
53
+ >
54
+ <img
55
+ src="/icons/arrow-stripped-colored.svg"
56
+ alt="Back"
57
+ class="babylai-w-full babylai-h-full"
58
+ [ngClass]="{ 'babylai-rotate-180': language === 'ar' }"
59
+ />
60
+ </app-button>
61
+ <div class="babylai-relative" data-menu-container>
62
+ <app-button
63
+ variant="icon-bg"
64
+ className="!babylai-bg-primary-500/10 babylai-w-8 babylai-h-8 !babylai-p-2 hover:!babylai-bg-primary-700/10"
65
+ (click)="$event.stopPropagation(); isMenuOpen = !isMenuOpen"
66
+ >
67
+ <img
68
+ src="/icons/menu.svg"
69
+ alt="Menu"
70
+ class="babylai-w-full babylai-h-full"
71
+ [ngClass]="{ 'babylai-rotate-180': language === 'ar' }"
72
+ />
73
+ </app-button>
74
+ <div
75
+ *ngIf="isMenuOpen"
76
+ class="babylai-absolute babylai-mt-2 babylai-w-48 babylai-rounded-md babylai-shadow-lg babylai-bg-white babylai-ring-1 babylai-ring-black babylai-ring-opacity-5 babylai-z-50"
77
+ [ngClass]="{ 'babylai-right-0': language === 'ar', 'babylai-left-0': language === 'en' }"
78
+ >
79
+ <div class="babylai-py-1">
80
+ <button
81
+ (click)="onClose.emit(); isMenuOpen = false"
82
+ class="babylai-block babylai-w-full babylai-text-left babylai-px-4 babylai-py-2 babylai-text-sm babylai-text-gray-700 hover:babylai-bg-gray-100"
83
+ [ngClass]="{ 'babylai-text-left': language === 'en', 'babylai-text-right': language === 'ar' }"
84
+ >
85
+ {{ 'EndChat' | transloco }}
86
+ </button>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ <div
92
+ class="babylai-flex babylai-items-center babylai-gap-1 babylai-absolute babylai-left-1/2 babylai-transform babylai--translate-x-1/2"
93
+ >
94
+ <img src="/logo-primary.svg" [alt]="logoAlt" class="babylai-w-10 babylai-h-10" />
95
+ <p class="babylai-text-base babylai-font-bold babylai-text-black-white-600">{{ 'BabylAI' | transloco }}</p>
96
+ </div>
97
+ </div>
98
+ `
99
+ })
100
+ export class ChatHeaderComponent {
101
+ isMenuOpen = false
102
+ @Input() showBackButton = false
103
+ @Input() showLogo = true
104
+ @Input() logoSrc = '/logo-white.svg'
105
+ @Input() logoAlt = 'BabylAI Logo'
106
+ @Input() language = 'en'
107
+ @Output() onBack = new EventEmitter<void>()
108
+ @Output() onClose = new EventEmitter<void>()
109
+
110
+ @HostListener('document:click', ['$event'])
111
+ onDocumentClick(event: MouseEvent) {
112
+ const target = event.target as HTMLElement
113
+ // Check if the click target is either the menu button or inside the menu
114
+ const menuContainer = target.closest('[data-menu-container]')
115
+ if (!menuContainer && this.isMenuOpen) {
116
+ this.isMenuOpen = false
117
+ }
118
+ }
119
+ }
@@ -0,0 +1 @@
1
+ export * from './header.component'
@@ -0,0 +1,14 @@
1
+ import { Component } from '@angular/core'
2
+
3
+ @Component({
4
+ selector: 'app-loading',
5
+ template: `
6
+ <div
7
+ class="babylai-flex babylai-flex-col babylai-items-center babylai-justify-center babylai-w-full babylai-h-full babylai-py-16 md:babylai-py-28"
8
+ >
9
+ <img src="/images/animatedLogo.gif" alt="Animated Logo" class="babylai-w-20 babylai-h-20" />
10
+ </div>
11
+ `,
12
+ standalone: true
13
+ })
14
+ export class LoadingComponent {}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Utility function to conditionally join CSS class names
3
+ */
4
+ import { clsx, type ClassValue } from 'clsx'
5
+ import { twMerge } from 'tailwind-merge'
6
+
7
+ export function cn(...inputs: ClassValue[]) {
8
+ return twMerge(clsx(inputs))
9
+ }
@@ -0,0 +1,12 @@
1
+ import { inject, Injectable } from '@angular/core'
2
+ import { Translation, TranslocoLoader } from '@jsverse/transloco'
3
+ import { HttpClient } from '@angular/common/http'
4
+
5
+ @Injectable({ providedIn: 'root' })
6
+ export class TranslocoHttpLoader implements TranslocoLoader {
7
+ private http = inject(HttpClient)
8
+
9
+ getTranslation(lang: string) {
10
+ return this.http.get<Translation>(`/i18n/${lang}.json`)
11
+ }
12
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "ChatIntroMessage": "دردش مع BabylAI 🚀",
3
+ "BabylaiTitle": "BabylAI",
4
+ "BabylaiDescription": "مرحبا! 👋 أنا BabylAI، هنا لتساعدك.",
5
+ "ChatNow": "دردش الآن",
6
+ "TryBableAI": "جرب BabylAI مجانا 🎉",
7
+ "ContactUs": "تواصل معنا, دعنا نتحدث! 💬",
8
+ "PickTopicTitle": "اختر موضوع للبدء",
9
+ "BabylAI": "BabylAI",
10
+ "ChatPlaceholder": "اكتب رسالتك...",
11
+ "PoweredByBabylAI": "مدعوم من BabylAI",
12
+ "EndChat": "إنهاء الدردشة",
13
+ "LeavingDialogTitle": "هل تغادر بالفعل؟ 👋",
14
+ "LeavingDialogBody": "لا تقلق، يمكنك العودة في أي وقت. نحن دائماً هنا إذا كنت بحاجة إلى مساعدة أو لديك أسئلة.",
15
+ "Confirm": "تأكيد",
16
+ "Cancel": "إلغاء"
17
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "ChatIntroMessage": "Chat with BabylAI 🚀",
3
+ "BabylaiTitle": "BabylAI",
4
+ "BabylaiDescription": "Hey there! 👋 I'm BabylAI, here to assist you.",
5
+ "ChatNow": "Chat Now",
6
+ "TryBableAI": "Try BabylAI for Free 🎉",
7
+ "ContactUs": "Contact us, Let's Talk! 💬",
8
+ "PickTopicTitle": "Pick a Topic to Get Started",
9
+ "BabylAI": "BabylAI",
10
+ "ChatPlaceholder": "Type your message...",
11
+ "PoweredByBabylAI": "Powered by BabylAI",
12
+ "EndChat": "End Chat",
13
+ "LeavingDialogTitle": "Leaving so soon? 👋",
14
+ "LeavingDialogBody": "Don't worry, you can come back anytime. We're always here if you need help or have questions.",
15
+ "Confirm": "Confirm",
16
+ "Cancel": "Cancel"
17
+ }
@@ -0,0 +1,3 @@
1
+ <svg width="8" height="16" viewBox="0 0 8 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M7 15L1 8L2.5 6.25M7 1L5 3.333" stroke="#7A1CAC" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="9" height="16" viewBox="0 0 9 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M1.5 0.999998L7.5 8L6 9.75M1.5 15L3.5 12.667" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M17.5 3.83801C15.9806 2.95874 14.2555 2.49712 12.5 2.50001C6.977 2.50001 2.5 6.97701 2.5 12.5C2.5 14.1 2.876 15.612 3.543 16.953C3.721 17.309 3.78 17.716 3.677 18.101L3.082 20.327C3.02307 20.5473 3.02312 20.7792 3.08216 20.9995C3.14119 21.2198 3.25712 21.4206 3.41831 21.5819C3.57951 21.7432 3.7803 21.8593 4.00053 21.9184C4.22075 21.9776 4.45267 21.9778 4.673 21.919L6.899 21.323C7.28538 21.2254 7.69414 21.2727 8.048 21.456C9.43095 22.1446 10.9551 22.502 12.5 22.5C18.023 22.5 22.5 18.023 22.5 12.5C22.5 10.679 22.013 8.97001 21.162 7.50001" stroke="white" stroke-width="2" stroke-linecap="round"/>
3
+ <path d="M8.5 12.5H8.509M12.491 12.5H12.5M16.491 12.5H16.5" stroke="white" stroke-width="2.66667" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M33.8568 21.1458L21.1484 33.8541M21.1484 21.1458L33.8568 33.8541M14.7943 5.48404C18.6562 3.24921 23.0407 2.07593 27.5026 2.08329C41.5402 2.08329 52.9193 13.4623 52.9193 27.5C52.9193 41.5376 41.5402 52.9166 27.5026 52.9166C13.465 52.9166 2.08594 41.5376 2.08594 27.5C2.08594 22.8716 3.32373 18.5279 5.48669 14.7916" stroke="white" stroke-width="3" stroke-linecap="round"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="14" height="4" viewBox="0 0 14 4" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M3.25 1.8269C3.25 2.22473 3.09196 2.60626 2.81066 2.88756C2.52936 3.16887 2.14782 3.3269 1.75 3.3269C1.35218 3.3269 0.970644 3.16887 0.68934 2.88756C0.408035 2.60626 0.25 2.22473 0.25 1.8269C0.25 1.42908 0.408035 1.04755 0.68934 0.766244C0.970644 0.48494 1.35218 0.326904 1.75 0.326904C2.14782 0.326904 2.52936 0.48494 2.81066 0.766244C3.09196 1.04755 3.25 1.42908 3.25 1.8269ZM8.5 1.8269C8.5 2.22473 8.34196 2.60626 8.06066 2.88756C7.77936 3.16887 7.39782 3.3269 7 3.3269C6.60218 3.3269 6.22064 3.16887 5.93934 2.88756C5.65804 2.60626 5.5 2.22473 5.5 1.8269C5.5 1.42908 5.65804 1.04755 5.93934 0.766244C6.22064 0.48494 6.60218 0.326904 7 0.326904C7.39782 0.326904 7.77936 0.48494 8.06066 0.766244C8.34196 1.04755 8.5 1.42908 8.5 1.8269ZM13.75 1.8269C13.75 2.22473 13.592 2.60626 13.3107 2.88756C13.0294 3.16887 12.6478 3.3269 12.25 3.3269C11.8522 3.3269 11.4706 3.16887 11.1893 2.88756C10.908 2.60626 10.75 2.22473 10.75 1.8269C10.75 1.42908 10.908 1.04755 11.1893 0.766244C11.4706 0.48494 11.8522 0.326904 12.25 0.326904C12.6478 0.326904 13.0294 0.48494 13.3107 0.766244C13.592 1.04755 13.75 1.42908 13.75 1.8269Z" fill="#AD49E1"/>
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="12" height="14" viewBox="0 0 12 14" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M5.99479 5.66658C7.46755 5.66658 8.66146 4.47268 8.66146 2.99992C8.66146 1.52716 7.46755 0.333252 5.99479 0.333252C4.52203 0.333252 3.32812 1.52716 3.32812 2.99992C3.32812 4.47268 4.52203 5.66658 5.99479 5.66658Z" fill="#AD49E1"/>
3
+ <path d="M11.3307 10.6665C11.3307 12.3232 11.3307 13.6665 5.9974 13.6665C0.664062 13.6665 0.664062 12.3232 0.664062 10.6665C0.664062 9.00984 3.05206 7.6665 5.9974 7.6665C8.94273 7.6665 11.3307 9.00984 11.3307 10.6665Z" fill="#AD49E1"/>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M18.2346 2.68609C18.6666 1.49109 17.5086 0.33309 16.3136 0.76609L1.70855 6.04809C0.509554 6.48209 0.364554 8.11809 1.46755 8.75709L6.12955 11.4561L10.2926 7.29309C10.4812 7.11093 10.7338 7.01014 10.996 7.01242C11.2582 7.01469 11.509 7.11986 11.6944 7.30527C11.8798 7.49068 11.9849 7.74149 11.9872 8.00369C11.9895 8.26589 11.8887 8.51849 11.7066 8.70709L7.54355 12.8701L10.2436 17.5321C10.8816 18.6351 12.5176 18.4891 12.9516 17.2911L18.2346 2.68609Z" fill="white"/>
3
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="327" height="14" viewBox="0 0 327 14" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <line x1="132.5" y1="7.5" y2="7.5" stroke="#AD49E1"/>
3
+ <path d="M162.891 0.464864C162.892 0.460907 162.893 0.458928 162.893 0.458012C163.067 -0.152671 163.933 -0.152671 164.107 0.458012C164.107 0.458928 164.108 0.460907 164.109 0.464864C164.112 0.475291 164.113 0.480505 164.115 0.4854C164.924 3.34287 167.157 5.57619 170.015 6.38539C170.019 6.38678 170.025 6.38825 170.035 6.39119C170.039 6.3923 170.041 6.39286 170.042 6.39312C170.653 6.56727 170.653 7.43274 170.042 7.60688C170.041 7.60714 170.039 7.6077 170.035 7.60881C170.025 7.61175 170.019 7.61322 170.015 7.61461C167.157 8.42381 164.924 10.6571 164.115 13.5146C164.113 13.5195 164.112 13.5247 164.109 13.5351C164.108 13.5391 164.107 13.5411 164.107 13.542C163.933 14.1527 163.067 14.1527 162.893 13.542C162.893 13.5411 162.892 13.5391 162.891 13.5351C162.888 13.5247 162.887 13.5195 162.885 13.5146C162.076 10.6571 159.843 8.42381 156.985 7.61461C156.981 7.61322 156.975 7.61175 156.965 7.60881C156.961 7.6077 156.959 7.60714 156.958 7.60688C156.347 7.43274 156.347 6.56727 156.958 6.39312C156.959 6.39286 156.961 6.3923 156.965 6.39119C156.975 6.38825 156.981 6.38678 156.985 6.38539C159.843 5.57619 162.076 3.34287 162.885 0.4854C162.887 0.480505 162.888 0.475291 162.891 0.464864Z" fill="#AD49E1"/>
4
+ <line x1="327" y1="7.5" x2="194.5" y2="7.5" stroke="#AD49E1"/>
5
+ </svg>