@unifylib/ui-lib 1.0.3 → 1.1.3

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 (155) hide show
  1. package/ng-package.json +7 -7
  2. package/package.json +14 -12
  3. package/src/lib/base-model/SearchStrConfig.ts +12 -12
  4. package/src/lib/base-model/api-response.ts +23 -23
  5. package/src/lib/base-model/audit-log-entry.ts +7 -7
  6. package/src/lib/base-model/button-action-settings.ts +29 -25
  7. package/src/lib/base-model/column-def.model.ts +34 -34
  8. package/src/lib/base-model/do-action-request.ts +11 -11
  9. package/src/lib/base-model/feature-item.ts +9 -0
  10. package/src/lib/base-model/field-action.ts +7 -7
  11. package/src/lib/base-model/field-filter.model.ts +7 -14
  12. package/src/lib/base-model/field-info.ts +102 -98
  13. package/src/lib/base-model/field-predicate.model.ts +7 -7
  14. package/src/lib/base-model/filter-request.ts +27 -27
  15. package/src/lib/base-model/filter.model.ts +49 -49
  16. package/src/lib/base-model/get-items-list.ts +24 -24
  17. package/src/lib/base-model/index.ts +11 -11
  18. package/src/lib/base-model/items-total.model.ts +12 -0
  19. package/src/lib/base-model/line-item.model.ts +18 -0
  20. package/src/lib/base-model/lookupItem.ts +21 -21
  21. package/src/lib/base-model/null-snackmessage.ts +9 -9
  22. package/src/lib/base-model/page-info.ts +54 -51
  23. package/src/lib/base-model/report-request.model.ts +33 -33
  24. package/src/lib/base-model/response-envelop.model.ts +15 -15
  25. package/src/lib/base-model/snack-message.model.ts +14 -14
  26. package/src/lib/base-model/snackmessage-interface.ts +7 -7
  27. package/src/lib/base-model/table-column.interface.ts +29 -29
  28. package/src/lib/base-model/table-page-user-action.interface.ts +33 -33
  29. package/src/lib/base-model/workflow/workflow-steps.model.ts +9 -9
  30. package/src/lib/base-model/workflow/workflow.model.ts +52 -52
  31. package/src/lib/components/action-comment/action-comment.component.css +52 -0
  32. package/src/lib/components/action-comment/action-comment.component.html +47 -0
  33. package/src/lib/components/{rejection-comment → action-comment}/action-comment.component.spec.ts +23 -23
  34. package/src/lib/components/{rejection-comment → action-comment}/action-comment.component.ts +102 -86
  35. package/src/lib/components/action-confirmation/action-confirmation.component.css +46 -34
  36. package/src/lib/components/action-confirmation/action-confirmation.component.html +32 -18
  37. package/src/lib/components/action-confirmation/action-confirmation.component.spec.ts +23 -23
  38. package/src/lib/components/action-confirmation/action-confirmation.component.ts +58 -58
  39. package/src/lib/components/activity-report-form/activity-report-form.component.html +110 -109
  40. package/src/lib/components/activity-report-form/activity-report-form.component.scss +69 -0
  41. package/src/lib/components/activity-report-form/activity-report-form.component.spec.ts +25 -25
  42. package/src/lib/components/activity-report-form/activity-report-form.component.ts +616 -605
  43. package/src/lib/components/advanced-filter/field-filter/field-filter.component.html +8 -0
  44. package/src/lib/components/advanced-filter/field-filter/field-filter.component.scss +0 -0
  45. package/src/lib/components/advanced-filter/field-filter/field-filter.component.spec.ts +25 -0
  46. package/src/lib/components/advanced-filter/field-filter/field-filter.component.ts +55 -0
  47. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.html +36 -0
  48. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.scss +130 -0
  49. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.spec.ts +25 -0
  50. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.ts +186 -0
  51. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.css +51 -51
  52. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.html +23 -23
  53. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.spec.ts +23 -23
  54. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.ts +69 -69
  55. package/src/lib/components/audit-log-list/audit-log.component.html +26 -23
  56. package/src/lib/components/audit-log-list/audit-log.component.scss +50 -0
  57. package/src/lib/components/audit-log-list/audit-log.component.spec.ts +25 -25
  58. package/src/lib/components/audit-log-list/audit-log.component.ts +114 -116
  59. package/src/lib/components/auto-complete/auto-complete.component.css +55 -14
  60. package/src/lib/components/auto-complete/auto-complete.component.html +45 -29
  61. package/src/lib/components/auto-complete/auto-complete.component.spec.ts +23 -23
  62. package/src/lib/components/auto-complete/auto-complete.component.ts +331 -330
  63. package/src/lib/components/base-form/base-form.component.html +59 -58
  64. package/src/lib/components/base-form/base-form.component.scss +68 -0
  65. package/src/lib/components/base-form/base-form.component.spec.ts +25 -25
  66. package/src/lib/components/base-form/base-form.component.ts +323 -305
  67. package/src/lib/components/base-form-canvas/base-form-canvas.component.css +196 -22
  68. package/src/lib/components/base-form-canvas/base-form-canvas.component.html +1095 -1006
  69. package/src/lib/components/base-form-canvas/base-form-canvas.component.spec.ts +23 -23
  70. package/src/lib/components/base-form-canvas/base-form-canvas.component.ts +680 -573
  71. package/src/lib/components/base-input-dialog/base-input-dialog.component.css +67 -0
  72. package/src/lib/components/base-input-dialog/base-input-dialog.component.html +47 -42
  73. package/src/lib/components/base-input-dialog/base-input-dialog.component.spec.ts +23 -23
  74. package/src/lib/components/base-input-dialog/base-input-dialog.component.ts +77 -78
  75. package/src/lib/components/base-table/base-table.component.html +268 -242
  76. package/src/lib/components/base-table/base-table.component.scss +140 -31
  77. package/src/lib/components/base-table/base-table.component.spec.ts +25 -25
  78. package/src/lib/components/base-table/base-table.component.ts +621 -568
  79. package/src/lib/components/button-actions/button-actions.component.html +27 -28
  80. package/src/lib/components/button-actions/button-actions.component.scss +101 -6
  81. package/src/lib/components/button-actions/button-actions.component.spec.ts +23 -23
  82. package/src/lib/components/button-actions/button-actions.component.ts +70 -72
  83. package/src/lib/components/editable-base-table/editable-base-table.component.html +337 -372
  84. package/src/lib/components/editable-base-table/editable-base-table.component.scss +126 -44
  85. package/src/lib/components/editable-base-table/editable-base-table.component.spec.ts +25 -25
  86. package/src/lib/components/editable-base-table/editable-base-table.component.ts +579 -570
  87. package/src/lib/components/equation-builder/equation-builder.component.css +39 -0
  88. package/src/lib/components/equation-builder/equation-builder.component.html +31 -31
  89. package/src/lib/components/equation-builder/equation-builder.component.spec.ts +23 -23
  90. package/src/lib/components/equation-builder/equation-builder.component.ts +119 -121
  91. package/src/lib/components/item-line-editor/item-line-editor.component.html +102 -0
  92. package/src/lib/components/item-line-editor/item-line-editor.component.scss +152 -0
  93. package/src/lib/components/item-line-editor/item-line-editor.component.spec.ts +23 -0
  94. package/src/lib/components/item-line-editor/item-line-editor.component.ts +306 -0
  95. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.css +19 -11
  96. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.html +38 -38
  97. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.spec.ts +23 -23
  98. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.ts +315 -317
  99. package/src/lib/components/paginator/paginator.component.css +65 -25
  100. package/src/lib/components/paginator/paginator.component.html +30 -34
  101. package/src/lib/components/paginator/paginator.component.ts +87 -94
  102. package/src/lib/components/report-details-dialog/report-details-dialog.component.css +17 -17
  103. package/src/lib/components/report-details-dialog/report-details-dialog.component.html +16 -16
  104. package/src/lib/components/report-details-dialog/report-details-dialog.component.spec.ts +23 -23
  105. package/src/lib/components/report-details-dialog/report-details-dialog.component.ts +111 -113
  106. package/src/lib/components/report-form/report-form.component.html +92 -94
  107. package/src/lib/components/report-form/report-form.component.scss +51 -0
  108. package/src/lib/components/report-form/report-form.component.spec.ts +25 -25
  109. package/src/lib/components/report-form/report-form.component.ts +599 -588
  110. package/src/lib/components/search-bar/search-bar.component.html +51 -62
  111. package/src/lib/components/search-bar/search-bar.component.scss +63 -8
  112. package/src/lib/components/search-bar/search-bar.component.spec.ts +25 -25
  113. package/src/lib/components/search-bar/search-bar.component.ts +68 -70
  114. package/src/lib/components/section-form-canvas/section-form-canvas.component.html +43 -0
  115. package/src/lib/components/section-form-canvas/section-form-canvas.component.scss +81 -0
  116. package/src/lib/components/section-form-canvas/section-form-canvas.component.spec.ts +23 -0
  117. package/src/lib/components/section-form-canvas/section-form-canvas.component.ts +67 -0
  118. package/src/lib/components/shared/action-button/action-button.component.html +12 -0
  119. package/src/lib/components/shared/action-button/action-button.component.scss +45 -0
  120. package/src/lib/components/shared/action-button/action-button.component.ts +51 -0
  121. package/src/lib/components/shared/action-card/action-card.component.html +78 -0
  122. package/src/lib/components/shared/action-card/action-card.component.scss +238 -0
  123. package/src/lib/components/shared/action-card/action-card.component.ts +56 -0
  124. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.css +135 -54
  125. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.html +36 -22
  126. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.spec.ts +23 -23
  127. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.ts +71 -45
  128. package/src/lib/components/shared-list/shared-list.component.html +17 -17
  129. package/src/lib/components/shared-list/shared-list.component.spec.ts +23 -23
  130. package/src/lib/components/shared-list/shared-list.component.ts +53 -53
  131. package/src/lib/components/snackbar-static/snackbar-static.component.html +20 -0
  132. package/src/lib/components/snackbar-static/snackbar-static.component.scss +135 -0
  133. package/src/lib/components/snackbar-static/snackbar-static.component.ts +26 -0
  134. package/src/lib/components/title-bar/title-bar.component.html +35 -31
  135. package/src/lib/components/title-bar/title-bar.component.scss +126 -23
  136. package/src/lib/components/title-bar/title-bar.component.spec.ts +23 -23
  137. package/src/lib/components/title-bar/title-bar.component.ts +126 -119
  138. package/src/lib/services/backend-service.ts +287 -286
  139. package/src/lib/services/index.ts +3 -3
  140. package/src/lib/services/top-panel.ts +17 -17
  141. package/src/lib/services/trigger-form.service.ts +11 -11
  142. package/src/lib/share-module/shared-module.ts +10 -10
  143. package/src/lib/utils/base-utils.ts +102 -102
  144. package/src/lib/validators/date-range-validator.ts +31 -31
  145. package/src/lib/validators/index.ts +3 -3
  146. package/src/lib/validators/match-list.validator.ts +10 -10
  147. package/src/lib/validators/multi-email-validator.ts +15 -15
  148. package/src/public-api.ts +29 -21
  149. package/tsconfig.lib.json +15 -15
  150. package/tsconfig.lib.prod.json +11 -11
  151. package/tsconfig.spec.json +15 -15
  152. package/src/lib/components/rejection-comment/action-comment.component.css +0 -33
  153. package/src/lib/components/rejection-comment/action-comment.component.html +0 -46
  154. package/src/lib/styles/invoiceq-theme.scss +0 -252
  155. package/src/lib/styles/styles.scss +0 -1723
@@ -0,0 +1,51 @@
1
+ import { Component, EventEmitter, Input, Output, inject, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { MatIconModule } from '@angular/material/icon';
4
+ import { TranslateModule, TranslateService } from '@ngx-translate/core';
5
+ import { Subject, takeUntil, startWith } from 'rxjs';
6
+
7
+ @Component({
8
+ selector: 'lib-action-button',
9
+ standalone: true,
10
+ imports: [
11
+ CommonModule,
12
+ MatIconModule,
13
+ TranslateModule
14
+ ],
15
+ templateUrl: './action-button.component.html',
16
+ styleUrl: './action-button.component.scss'
17
+ })
18
+ export class ActionButtonComponent implements OnInit, OnDestroy {
19
+ private readonly translateService = inject(TranslateService);
20
+ private readonly destroy$ = new Subject<void>();
21
+
22
+ @Input() buttonText: string = '';
23
+ @Input() buttonTextKey?: string;
24
+ @Input() buttonGradient: string = 'linear-gradient(90deg, #E4C9D0 0%, #8A1538 100%)';
25
+ @Input() id?: string;
26
+ @Output() buttonClick = new EventEmitter<void>();
27
+
28
+ get isArabic(): boolean {
29
+ const currentLang = this.translateService.currentLang
30
+ || this.translateService.defaultLang
31
+ || this.translateService.getBrowserLang()
32
+ || 'en';
33
+ return currentLang === 'ar';
34
+ }
35
+
36
+ ngOnInit(): void {
37
+ this.translateService.onLangChange
38
+ .pipe(takeUntil(this.destroy$))
39
+ .subscribe(() => {
40
+ });
41
+ }
42
+
43
+ ngOnDestroy(): void {
44
+ this.destroy$.next();
45
+ this.destroy$.complete();
46
+ }
47
+
48
+ onButtonClick(): void {
49
+ this.buttonClick.emit();
50
+ }
51
+ }
@@ -0,0 +1,78 @@
1
+ <div class="action-card"
2
+ [class.extended-variant]="variant === 'extended'"
3
+ [style.--top-border-gradient]="topBorderGradient || buttonGradient"
4
+ [style.--top-border-height]="topBorderHeight + 'px'"
5
+ [style.border-right-color]="borderRightColor || borderColor"
6
+ [style.border-bottom-color]="borderBottomColor || borderColor"
7
+ [style.border-left-color]="borderLeftColor || borderColor">
8
+ <div class="card-content" [class.extended-content]="variant === 'extended'">
9
+ <div class="main-content" [class.extended-main]="variant === 'extended'">
10
+ <div class="header-section" [class.extended-header]="variant === 'extended'">
11
+ <div class="header-top-wrapper" *ngIf="variant === 'default'">
12
+ <div class="icon-wrapper"
13
+ [style.color]="iconColor"
14
+ [style.width.px]="iconSize"
15
+ [style.height.px]="iconSize">
16
+ <img *ngIf="iconSvg" [src]="iconSvg" alt="" class="icon-svg" [style.width.px]="iconSize" [style.height.px]="iconSize" />
17
+ <mat-icon *ngIf="!iconSvg && icon" [style.font-size.px]="iconSize" [style.width.px]="iconSize" [style.height.px]="iconSize">{{ icon }}</mat-icon>
18
+ </div>
19
+ <div class="header-top">
20
+ <h2 class="card-title">
21
+ <span *ngIf="titleKey">{{ titleKey | translate }}</span>
22
+ <span *ngIf="!titleKey">{{ title }}</span>
23
+ </h2>
24
+ </div>
25
+ </div>
26
+ <div class="icon-wrapper"
27
+ *ngIf="variant === 'extended'"
28
+ [style.color]="iconColor"
29
+ [style.width.px]="iconSize"
30
+ [style.height.px]="iconSize">
31
+ <img *ngIf="iconSvg" [src]="iconSvg" alt="" class="icon-svg" [style.width.px]="iconSize" [style.height.px]="iconSize" />
32
+ <mat-icon *ngIf="!iconSvg && icon" [style.font-size.px]="iconSize" [style.width.px]="iconSize" [style.height.px]="iconSize">{{ icon }}</mat-icon>
33
+ </div>
34
+ <div class="title-description-wrapper" *ngIf="variant === 'extended'">
35
+ <h2 class="card-title">
36
+ <span *ngIf="titleKey">{{ titleKey | translate }}</span>
37
+ <span *ngIf="!titleKey">{{ title }}</span>
38
+ </h2>
39
+ <p class="card-description">
40
+ <span *ngIf="descriptionKey">{{ descriptionKey | translate }}</span>
41
+ <span *ngIf="!descriptionKey">{{ description }}</span>
42
+ </p>
43
+ </div>
44
+ <p class="card-description" *ngIf="variant === 'default'">
45
+ <span *ngIf="descriptionKey">{{ descriptionKey | translate }}</span>
46
+ <span *ngIf="!descriptionKey">{{ description }}</span>
47
+ </p>
48
+ </div>
49
+ <lib-action-button
50
+ [buttonText]="buttonText"
51
+ [buttonTextKey]="buttonTextKey"
52
+ [buttonGradient]="buttonGradient"
53
+ (buttonClick)="onButtonClick()">
54
+ </lib-action-button>
55
+ <div class="features-divider" *ngIf="showDivider && features && features.length > 0"></div>
56
+
57
+ <div class="features-section" *ngIf="features && features.length > 0">
58
+ <h3 class="features-heading" *ngIf="featuresHeading || featuresHeadingKey">
59
+ <span *ngIf="featuresHeadingKey">{{ featuresHeadingKey | translate }}</span>
60
+ <span *ngIf="!featuresHeadingKey">{{ featuresHeading }}</span>
61
+ </h3>
62
+ <div class="feature-item" *ngFor="let feature of features">
63
+ <mat-icon class="feature-check-icon" [style.color]="featureCheckIconColor || iconColor">check_circle</mat-icon>
64
+ <span class="feature-text">
65
+ <span *ngIf="feature.textKey">{{ feature.textKey | translate }}</span>
66
+ <span *ngIf="!feature.textKey">{{ feature.text }}</span>
67
+ </span>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ <div class="decorative-icon-wrapper" *ngIf="variant === 'default' && (icon || iconSvg)">
72
+ <div class="decorative-icon">
73
+ <img *ngIf="iconSvg" [src]="iconSvg" alt="" class="decorative-icon-svg" [style.filter]="'opacity(0.3)'" />
74
+ <mat-icon *ngIf="!iconSvg && icon" [style.color]="decorativeIconColor">{{ icon }}</mat-icon>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ </div>
@@ -0,0 +1,238 @@
1
+ .action-card {
2
+ background-color: var(--grayscale-surface-default, #ffffff);
3
+ border-right: 1px solid;
4
+ border-bottom: 1px solid;
5
+ border-left: 1px solid;
6
+ border-radius: 16px;
7
+ width: 100%;
8
+ height: 100%;
9
+ min-height: 247px;
10
+ position: relative;
11
+ overflow: hidden;
12
+
13
+
14
+ &::before {
15
+ content: '';
16
+ position: absolute;
17
+ top: 0;
18
+ left: 0;
19
+ right: 0;
20
+ height: var(--top-border-height, 12px);
21
+ background: var(--top-border-gradient, var(--button-gradient, linear-gradient(90deg, #E4C9D0 0%, #8A1538 100%)));
22
+ border-radius: 16px 16px 0 0;
23
+ z-index: 1;
24
+ }
25
+
26
+ &.extended-variant {
27
+ min-height: 572px;
28
+ }
29
+ }
30
+
31
+ .card-content {
32
+ display: flex;
33
+ gap: 8px;
34
+ align-items: flex-start;
35
+ padding: 16px 20px;
36
+ height: 100%;
37
+ position: relative;
38
+ overflow: hidden;
39
+ box-sizing: border-box;
40
+
41
+ &.extended-content {
42
+ padding: 20px;
43
+ gap: 0;
44
+ }
45
+ }
46
+
47
+ .main-content {
48
+ flex: 1 1 0;
49
+ display: flex;
50
+ flex-direction: column;
51
+ gap: 64px;
52
+ min-width: 0;
53
+ min-height: 0;
54
+
55
+ &.extended-main {
56
+ gap: 24px;
57
+ }
58
+ }
59
+
60
+ .header-section {
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: 12px;
64
+ width: 100%;
65
+ height: 83px;
66
+
67
+ &.extended-header {
68
+ height: auto;
69
+ gap: 20px;
70
+ }
71
+ }
72
+
73
+ .header-top-wrapper {
74
+ display: flex;
75
+ flex-direction: row;
76
+ gap: 12px;
77
+ align-items: flex-start;
78
+ width: 100%;
79
+ }
80
+
81
+ .header-top {
82
+ display: flex;
83
+ gap: 8px;
84
+ align-items: flex-start;
85
+ flex: 1;
86
+ }
87
+
88
+ .title-description-wrapper {
89
+ display: flex;
90
+ flex-direction: column;
91
+ gap: 16px;
92
+ width: 100%;
93
+ }
94
+
95
+ .icon-wrapper {
96
+ flex-shrink: 0;
97
+ width: 40px;
98
+ height: 40px;
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ overflow: hidden;
103
+
104
+ mat-icon {
105
+ font-size: 40px;
106
+ width: 40px;
107
+ height: 40px;
108
+ }
109
+
110
+ .icon-svg {
111
+ width: 40px;
112
+ height: 40px;
113
+ object-fit: contain;
114
+ }
115
+ }
116
+
117
+ .card-title {
118
+ font-family: 'lusail-bold', sans-serif;
119
+ font-weight: 700;
120
+ font-size: 24px !important;
121
+ line-height: 1.2;
122
+ color: #222222;
123
+ margin: 0;
124
+ height: 40px;
125
+ display: flex;
126
+ align-items: flex-end;
127
+ justify-content: flex-start;
128
+ flex: 1;
129
+ }
130
+
131
+ .extended-variant .card-title {
132
+ color: #000000;
133
+ height: auto;
134
+ }
135
+
136
+ .card-description {
137
+ font-family: 'lusail-regular', sans-serif;
138
+ font-weight: 400;
139
+ font-size: 20px !important;
140
+ line-height: 1.2;
141
+ color: #888888;
142
+ margin: 0;
143
+ height: 40px;
144
+ display: flex;
145
+ align-items: center;
146
+ }
147
+
148
+ .extended-variant .card-description {
149
+ font-family: 'lusail-light', sans-serif;
150
+ font-weight: 300;
151
+ height: auto;
152
+ }
153
+
154
+ .decorative-icon-wrapper {
155
+ position: relative;
156
+ width: 153px;
157
+ height: 211px;
158
+ flex-shrink: 0;
159
+ }
160
+
161
+ .decorative-icon {
162
+ position: absolute;
163
+ left: 0;
164
+ top: 43px;
165
+ width: 144px;
166
+ height: 152px;
167
+ opacity: 0.3;
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ pointer-events: none;
172
+ overflow: hidden;
173
+
174
+ mat-icon {
175
+ font-size: 152px;
176
+ width: 144px;
177
+ height: 152px;
178
+ }
179
+
180
+ .decorative-icon-svg {
181
+ width: 144px;
182
+ height: 152px;
183
+ object-fit: contain;
184
+ }
185
+ }
186
+
187
+ .features-divider {
188
+ width: 100%;
189
+ height: 1px;
190
+ background-color: #e9e9e9;
191
+ margin: 0;
192
+ }
193
+
194
+ .features-section {
195
+ display: flex;
196
+ flex-direction: column;
197
+ gap: 24px;
198
+ width: 100%;
199
+
200
+ .feature-item:not(:last-child) {
201
+ margin-bottom: 0;
202
+ }
203
+ }
204
+
205
+ .features-heading {
206
+ font-family: 'lusail-bold', sans-serif;
207
+ font-weight: 700;
208
+ font-size: 20px !important;
209
+ line-height: 1.2;
210
+ color: #2e2e2e;
211
+ margin: 0 0 0 0;
212
+ padding: 0;
213
+ }
214
+
215
+ .feature-item {
216
+ display: flex;
217
+ gap: 20px;
218
+ align-items: center;
219
+ width: 100%;
220
+ padding: 0;
221
+ margin: 0;
222
+ }
223
+
224
+ .feature-check-icon {
225
+ font-size: 24px !important;
226
+ width: 24px;
227
+ height: 24px;
228
+ flex-shrink: 0;
229
+ }
230
+
231
+ .feature-text {
232
+ font-family: 'lusail-light', sans-serif;
233
+ font-weight: 300;
234
+ font-size: 20px !important;
235
+ line-height: 1.2;
236
+ color: #2e2e2e;
237
+ flex: 1;
238
+ }
@@ -0,0 +1,56 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { MatIconModule } from '@angular/material/icon';
4
+ import { TranslateModule } from '@ngx-translate/core';
5
+ import { ActionButtonComponent } from '../action-button/action-button.component';
6
+
7
+ export interface FeatureItem {
8
+ text?: string;
9
+ textKey?: string;
10
+ }
11
+
12
+ @Component({
13
+ selector: 'lib-action-card',
14
+ standalone: true,
15
+ imports: [
16
+ CommonModule,
17
+ MatIconModule,
18
+ TranslateModule,
19
+ ActionButtonComponent
20
+ ],
21
+ templateUrl: './action-card.component.html',
22
+ styleUrl: './action-card.component.scss'
23
+ })
24
+ export class ActionCardComponent {
25
+
26
+ @Input() icon: string = '';
27
+ @Input() iconSvg?: string;
28
+ @Input() title: string = '';
29
+ @Input() description: string = '';
30
+ @Input() buttonText: string = '';
31
+ @Input() buttonTextKey?: string;
32
+ @Input() titleKey?: string;
33
+ @Input() descriptionKey?: string;
34
+ @Input() iconColor: string = '#8A1538';
35
+ @Input() borderColor: string = '#d1d1d1';
36
+ @Input() borderLeftColor?: string;
37
+ @Input() borderRightColor?: string;
38
+ @Input() borderBottomColor?: string;
39
+ @Input() topBorderColor?: string;
40
+ @Input() topBorderGradient?: string;
41
+ @Input() buttonGradient: string = 'linear-gradient(90deg, #E4C9D0 0%, #8A1538 100%)';
42
+ @Input() decorativeIconColor: string = 'rgba(209, 203, 216, 1)';
43
+ @Input() featureCheckIconColor?: string;
44
+ @Input() variant: 'default' | 'extended' = 'default';
45
+ @Input() iconSize: number = 40;
46
+ @Input() features?: FeatureItem[];
47
+ @Input() featuresHeading?: string;
48
+ @Input() featuresHeadingKey?: string;
49
+ @Input() showDivider: boolean = false;
50
+ @Input() topBorderHeight: number = 12;
51
+ @Output() buttonClick = new EventEmitter<void>();
52
+
53
+ onButtonClick(): void {
54
+ this.buttonClick.emit();
55
+ }
56
+ }
@@ -1,54 +1,135 @@
1
- .attachment-uploader {
2
- display: flex;
3
- align-items: center;
4
- justify-content: flex-start; /* <== Ensures buttons align left*/
5
- gap: 10px;
6
- flex-wrap: wrap;
7
-
8
-
9
- .upload-button {
10
- display: flex;
11
- align-items: center;
12
- gap: 8px;
13
- padding: 10px 18px;
14
- border-radius: 8px;
15
- font-weight: 500;
16
- transition: all 0.3s ease;
17
- min-width: 200px;
18
- text-align: left;
19
- overflow: hidden;
20
- text-overflow: ellipsis;
21
- white-space: nowrap;
22
-
23
- mat-icon {
24
- font-size: 20px;
25
- }
26
- }
27
-
28
- .clear-button {
29
- background-color: transparent;
30
- border: none;
31
- color: #d32f2f;
32
- transition: color 0.2s ease;
33
- padding: 4px;
34
-
35
- &:hover {
36
- color: #b71c1c;
37
- }
38
-
39
- mat-icon {
40
- font-size: 20px;
41
- }
42
- }
43
-
44
- .hidden-input {
45
- display: none;
46
- }
47
- }
48
-
49
- .icon-design {
50
- display: flex;
51
- align-items: center;
52
- cursor: pointer;
53
-
54
- }
1
+ .attachment-uploader {
2
+ background-color: var(--background-color);
3
+ border: 1px dashed #b7b7b7;
4
+ border-radius: 8px;
5
+ position: relative;
6
+ width: 100%;
7
+ transition: all 0.3s ease;
8
+ cursor: pointer;
9
+
10
+ &.drag-over {
11
+ border-color: var(--primary-color-3nd);
12
+ background-color: var(--selected-hover);
13
+ }
14
+ }
15
+
16
+ .upload-content {
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: center;
20
+ justify-content: center;
21
+ gap: 8px;
22
+ padding: 24px;
23
+ min-height: 200px;
24
+ }
25
+
26
+ .upload-icon {
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ margin-bottom: 8px;
31
+
32
+ mat-icon {
33
+ font-size: 48px;
34
+ width: 48px;
35
+ height: 48px;
36
+ color: #888888;
37
+ }
38
+ }
39
+
40
+ .main-text {
41
+ font-family: 'Lusail', sans-serif;
42
+ font-size: 16px;
43
+ font-weight: 500;
44
+ line-height: 1.2;
45
+ color: #000000;
46
+ margin: 0;
47
+ text-align: center;
48
+ }
49
+
50
+ .info-text {
51
+ font-family: 'Lusail', sans-serif;
52
+ font-size: 14px;
53
+ font-weight: 300;
54
+ line-height: 1.2;
55
+ color: #888888;
56
+ margin: 0;
57
+ text-align: center;
58
+ }
59
+
60
+ .browse-button {
61
+ margin-top: 8px;
62
+ border: 1px solid var(--primary-color-3nd);
63
+ border-radius: 8px;
64
+ background-color: var(--background-color);
65
+ color: var(--primary-color-3nd);
66
+ font-family: 'Lusail', sans-serif;
67
+ font-size: 16px;
68
+ font-weight: 500;
69
+ padding: 8px 16px;
70
+ transition: all 0.2s ease;
71
+
72
+ &:hover {
73
+ background-color: var(--selected-hover);
74
+ }
75
+ }
76
+
77
+ .selected-file {
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: space-between;
81
+ padding: 12px 16px;
82
+ background-color: var(--background-color);
83
+ border-top: 1px solid #e0e0e0;
84
+ border-radius: 0 0 8px 8px;
85
+ }
86
+
87
+ .file-info {
88
+ display: flex;
89
+ align-items: center;
90
+ gap: 8px;
91
+ flex: 1;
92
+ min-width: 0;
93
+ }
94
+
95
+ .file-icon {
96
+ color: #888888;
97
+ font-size: 24px;
98
+ width: 24px;
99
+ height: 24px;
100
+ flex-shrink: 0;
101
+ }
102
+
103
+ .file-name {
104
+ font-family: 'Lusail', sans-serif;
105
+ font-size: 14px;
106
+ font-weight: 400;
107
+ color: #000000;
108
+ overflow: hidden;
109
+ text-overflow: ellipsis;
110
+ white-space: nowrap;
111
+ }
112
+
113
+ .clear-button {
114
+ background-color: transparent;
115
+ border: none;
116
+ color: #d32f2f;
117
+ transition: color 0.2s ease;
118
+ padding: 4px;
119
+ flex-shrink: 0;
120
+
121
+ &:hover {
122
+ color: #b71c1c;
123
+ background-color: transparent;
124
+ }
125
+
126
+ mat-icon {
127
+ font-size: 20px;
128
+ width: 20px;
129
+ height: 20px;
130
+ }
131
+ }
132
+
133
+ .hidden-input {
134
+ display: none;
135
+ }
@@ -1,22 +1,36 @@
1
- <div class="attachment-uploader">
2
- <button mat-raised-button
3
- [color]="selectedFile ? 'accent' : 'primary'"
4
- class="upload-button"
5
- (click)="triggerAttachmentUpload()">
6
- <div class="icon-design">
7
- <mat-icon>attach_file</mat-icon>
8
- <span *ngIf="!selectedFile">{{ 'uploadAttachment' | translate }}</span>
9
- <span *ngIf="selectedFile">{{ selectedFile.name }}</span>
10
- </div>
11
- </button>
12
-
13
- <button *ngIf="selectedFile"
14
- mat-icon-button
15
- class="clear-button"
16
- (click)="clearFile()"
17
- matTooltip="Remove file">
18
- <mat-icon>close</mat-icon>
19
- </button>
20
-
21
- <input #fileUpload type="file" class="hidden-input" (change)="uploadFileToServer()" />
22
- </div>
1
+ <div class="attachment-uploader"
2
+ [class.drag-over]="isDragOver"
3
+ (dragover)="onDragOver($event)"
4
+ (dragleave)="onDragLeave($event)"
5
+ (drop)="onDrop($event)">
6
+ <div class="upload-content">
7
+ <div class="upload-icon">
8
+ <mat-icon>upload_file</mat-icon>
9
+ </div>
10
+
11
+ <p class="main-text">{{ 'attachmentUploader.dragAndDrop' | translate }}</p>
12
+
13
+ <p class="info-text">{{ 'attachmentUploader.fileInfo' | translate }}</p>
14
+
15
+ <button mat-stroked-button
16
+ class="browse-button"
17
+ (click)="triggerAttachmentUpload()">
18
+ {{ 'attachmentUploader.browseFiles' | translate }}
19
+ </button>
20
+ </div>
21
+
22
+ <div *ngIf="selectedFile" class="selected-file">
23
+ <div class="file-info">
24
+ <mat-icon class="file-icon">description</mat-icon>
25
+ <span class="file-name">{{ selectedFile.name }}</span>
26
+ </div>
27
+ <button mat-icon-button
28
+ class="clear-button"
29
+ (click)="clearFile()"
30
+ matTooltip="{{ 'attachmentUploader.removeFile' | translate }}">
31
+ <mat-icon>close</mat-icon>
32
+ </button>
33
+ </div>
34
+
35
+ <input #fileUpload type="file" class="hidden-input" (change)="uploadFileToServer()" />
36
+ </div>