@corp-products/ui-components 3.2.7 → 3.2.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.
- package/ng-package.json +7 -0
- package/package.json +22 -36
- package/src/enums/date-formatter.ts +21 -0
- package/src/helper/date-handler.ts +142 -0
- package/src/lib/app-accordion/app-accordion.component.html +15 -0
- package/src/lib/app-accordion/app-accordion.component.scss +0 -0
- package/src/lib/app-accordion/app-accordion.component.spec.ts +21 -0
- package/src/lib/app-accordion/app-accordion.component.ts +21 -0
- package/src/lib/app-accordion/index.ts +2 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.component.html +7 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.component.scss +25 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.component.ts +140 -0
- package/src/lib/app-breadcrumb/app-breadcrumb.interface.ts +15 -0
- package/src/lib/app-button/app-button.component.html +7 -0
- package/src/lib/app-button/app-button.component.scss +0 -0
- package/src/lib/app-button/app-button.component.ts +14 -0
- package/src/lib/app-button/app-button.ts +15 -0
- package/src/lib/app-button/index.ts +2 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.html +22 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.scss +39 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.spec.ts +21 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.component.ts +43 -0
- package/src/lib/app-dropdown-menu/app-dropdown-menu.ts +17 -0
- package/src/lib/app-dropdown-menu/index.ts +2 -0
- package/src/lib/app-dropdown-menu/menu-popup.pipe.ts +18 -0
- package/src/lib/app-header/app-header.component.html +26 -0
- package/src/lib/app-header/app-header.component.scss +0 -0
- package/src/lib/app-header/app-header.component.ts +43 -0
- package/src/lib/app-side-menu/app-side-menu.component.html +20 -0
- package/src/lib/app-side-menu/app-side-menu.component.ts +28 -0
- package/src/lib/app-side-menu/routes-names.ts +28 -0
- package/src/lib/app-side-menu/side-menu-items.ts +45 -0
- package/src/lib/app-side-menu/side-menu.ts +12 -0
- package/src/lib/app-tabs/app-tab.interface.ts +27 -0
- package/src/lib/app-tabs/app-tabs.component.html +37 -0
- package/src/lib/app-tabs/app-tabs.component.scss +103 -0
- package/src/lib/app-tabs/app-tabs.component.spec.ts +21 -0
- package/src/lib/app-tabs/app-tabs.component.ts +67 -0
- package/src/lib/app-tabs/index.ts +2 -0
- package/src/lib/bottom-sheet/bottom-sheet.component.html +18 -0
- package/src/lib/bottom-sheet/bottom-sheet.component.scss +31 -0
- package/src/lib/bottom-sheet/bottom-sheet.component.ts +26 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.html +37 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.scss +0 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.spec.ts +22 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.component.ts +64 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.interface.ts +13 -0
- package/src/lib/confirmation-dialog/confirmation-dialog.service.ts +34 -0
- package/src/lib/dual-calender/date-picker-switcher/date-picker-switcher.component.html +27 -0
- package/src/lib/dual-calender/date-picker-switcher/date-picker-switcher.component.scss +22 -0
- package/src/lib/dual-calender/date-picker-switcher/date-picker-switcher.component.ts +64 -0
- package/src/lib/dual-calender/dual-calendar.component.html +31 -0
- package/src/lib/dual-calender/dual-calendar.component.scss +229 -0
- package/src/lib/dual-calender/dual-calendar.component.ts +107 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.html +10 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.scss +0 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.spec.ts +21 -0
- package/src/lib/dual-calender/gregorian-calendar/gregorian-calendar.component.ts +59 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.html +10 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.scss +0 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.spec.ts +21 -0
- package/src/lib/dual-calender/hijri-calendar/hijri-calendar.component.ts +59 -0
- package/src/lib/dual-calender/services/gregorian-i18n.service.ts +123 -0
- package/src/lib/dual-calender/services/islamic-i18n.service.ts +119 -0
- package/src/lib/dual-calender/utils/date-i18n.utils.ts +58 -0
- package/src/lib/dynamic-form/dynamic-form.component.html +86 -0
- package/src/lib/dynamic-form/dynamic-form.component.scss +0 -0
- package/src/lib/dynamic-form/dynamic-form.component.spec.ts +21 -0
- package/src/lib/dynamic-form/dynamic-form.component.ts +58 -0
- package/src/lib/dynamic-form/dynamic-form.interface.ts +94 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.component.html +32 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.component.scss +3 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.component.ts +82 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.config.ts +31 -0
- package/src/lib/dynamic-side-bar-v2/dynamic-sidebar.service.ts +41 -0
- package/src/lib/form-components/@utils/form-utils.ts +12 -0
- package/src/lib/form-components/@utils/validations/error-keys.enum.ts +24 -0
- package/src/lib/form-components/@utils/validations/form-validation.service.ts +68 -0
- package/src/lib/form-components/@utils/validations/index.ts +3 -0
- package/src/lib/form-components/@utils/validations/validation-message.pipe.ts +24 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.html +35 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.scss +7 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.spec.ts +21 -0
- package/src/lib/form-components/components/auto-complete/auto-complete.component.ts +57 -0
- package/src/lib/form-components/components/base-input.component.ts +35 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.html +41 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.scss +16 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.spec.ts +21 -0
- package/src/lib/form-components/components/date-picker/date-picker.component.ts +54 -0
- package/src/lib/form-components/components/input/input.component.html +63 -0
- package/src/lib/form-components/components/input/input.component.scss +41 -0
- package/src/lib/form-components/components/input/input.component.spec.ts +21 -0
- package/src/lib/form-components/components/input/input.component.ts +45 -0
- package/src/lib/form-components/components/select/select.component.html +111 -0
- package/src/lib/form-components/components/select/select.component.scss +43 -0
- package/src/lib/form-components/components/select/select.component.spec.ts +21 -0
- package/src/lib/form-components/components/select/select.component.ts +56 -0
- package/src/lib/form-components/components/select-button/select-button.component.html +21 -0
- package/src/lib/form-components/components/select-button/select-button.component.scss +0 -0
- package/src/lib/form-components/components/select-button/select-button.component.spec.ts +21 -0
- package/src/lib/form-components/components/select-button/select-button.component.ts +22 -0
- package/src/lib/form-components/components/switcher/switch.component.html +5 -0
- package/src/lib/form-components/components/switcher/switch.component.scss +0 -0
- package/src/lib/form-components/components/switcher/switch.component.spec.ts +21 -0
- package/src/lib/form-components/components/switcher/switch.component.ts +25 -0
- package/src/lib/form-components/index.ts +9 -0
- package/src/lib/form-components/interfaces/index.ts +1 -0
- package/src/lib/form-components/interfaces/label-value.ts +4 -0
- package/src/lib/ico-moon-icon/ico-moon-icon.component.ts +23 -0
- package/src/lib/read-more/read-more.component.html +17 -0
- package/src/lib/read-more/read-more.component.scss +0 -0
- package/src/lib/read-more/read-more.component.spec.ts +21 -0
- package/src/lib/read-more/read-more.component.ts +21 -0
- package/src/lib/side-bar/side-bar.component.html +24 -0
- package/src/lib/side-bar/side-bar.component.scss +22 -0
- package/src/lib/side-bar/side-bar.component.spec.ts +21 -0
- package/src/lib/side-bar/side-bar.component.ts +33 -0
- package/src/lib/side-bar-dynamic/data-injector.pipe.ts +15 -0
- package/src/lib/side-bar-dynamic/dynamic-sidebar.service.ts +116 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.html +42 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.scss +5 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.spec.ts +21 -0
- package/src/lib/side-bar-dynamic/side-bar-dynamic.component.ts +37 -0
- package/src/lib/side-bar-dynamic/side-bar-utils.ts +30 -0
- package/src/lib/side-bar-dynamic/sidebar-config.ts +48 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.html +20 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.scss +0 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.spec.ts +21 -0
- package/src/lib/user-autocomplete-card/user-autocomplete-card.component.ts +21 -0
- package/src/lib/user-info/user-info.component.html +10 -0
- package/src/lib/user-info/user-info.component.ts +11 -0
- package/src/public-api.ts +26 -0
- package/tsconfig.lib.json +18 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +14 -0
- package/fesm2022/corp-products-ui-components.mjs +0 -1409
- package/fesm2022/corp-products-ui-components.mjs.map +0 -1
- package/index.d.ts +0 -623
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {Params} from "@angular/router";
|
|
2
|
+
import {AppButtonIconPos} from "../app-button";
|
|
3
|
+
|
|
4
|
+
export interface DropdownMenuItem {
|
|
5
|
+
title: string;
|
|
6
|
+
routerLink?: string;
|
|
7
|
+
queryParams?: Params;
|
|
8
|
+
callback?: () => void;
|
|
9
|
+
icon?: string;
|
|
10
|
+
show?: boolean;
|
|
11
|
+
// TODO: add type
|
|
12
|
+
permissionKey?: string;
|
|
13
|
+
permissionAction?: string;
|
|
14
|
+
iconPosition?: AppButtonIconPos;
|
|
15
|
+
textColor?: DropdownTextColor;
|
|
16
|
+
}
|
|
17
|
+
export type DropdownTextColor = 'white' | 'purple' | 'green';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
import {DropdownTextColor} from "./app-dropdown-menu";
|
|
3
|
+
|
|
4
|
+
@Pipe({
|
|
5
|
+
name: 'popupTextColorClass',
|
|
6
|
+
standalone: true,
|
|
7
|
+
pure: true
|
|
8
|
+
})
|
|
9
|
+
export class MenuPopupTextColorPipe implements PipeTransform {
|
|
10
|
+
transform(color?: DropdownTextColor): string {
|
|
11
|
+
switch (color) {
|
|
12
|
+
case 'white': return 'text-white';
|
|
13
|
+
case 'purple': return 'text-purple-500';
|
|
14
|
+
case 'green': return 'text-green-500';
|
|
15
|
+
default: return 'text-white';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<div class="px-10 flex justify-between items-center bg-white shadow-md py-3 h-16">
|
|
2
|
+
<div class="d-flex md:hidden w-fit">
|
|
3
|
+
<!-- Burger Icon for Mobile -->
|
|
4
|
+
<app-button icon="font-icon-burger-icon text-[25px]" size="large" variant="text"
|
|
5
|
+
(clickEmitter)="toggleMenu.emit()"/>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="d-flex items-center justify-content-between gap-1">
|
|
8
|
+
<app-button
|
|
9
|
+
*hasPermissions="[PermissionsActions.CREATE];key: UserPermissionsEnum.BOD"
|
|
10
|
+
iconPos="right" icon="font-icon-plus" (clickEmitter)="createButtonClicked.emit()"
|
|
11
|
+
[title]="'actions.create' | translate"/>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="flex items-center gap-1">
|
|
15
|
+
@if (userInfo) {
|
|
16
|
+
<div class="flex flex-col items-end justify-center">
|
|
17
|
+
<p class="text-sm">{{ userInfo.userName }}</p>
|
|
18
|
+
<p class="text-gray-500 mb-0 text-[10px]">{{ userInfo.email }}</p>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<img src="assets/images/user-placeholder.jpg" class="w-9 h-9 object-cover rounded-full" alt=""/>
|
|
22
|
+
}
|
|
23
|
+
<p-menu #menu [model]="items" [popup]="true"></p-menu>
|
|
24
|
+
<button (click)="menu.toggle($event)" class="mb-2"><i class="font-icon-Vector text-[6px]"></i></button>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
import { RouterModule } from '@angular/router';
|
|
3
|
+
import { TranslatePipe } from '@ngx-translate/core';
|
|
4
|
+
import { MenuItem } from 'primeng/api';
|
|
5
|
+
import { Menu } from 'primeng/menu';
|
|
6
|
+
import { AppButtonComponent } from '../app-button';
|
|
7
|
+
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'app-header',
|
|
10
|
+
templateUrl: './app-header.component.html',
|
|
11
|
+
styleUrl: './app-header.component.scss',
|
|
12
|
+
standalone: true,
|
|
13
|
+
imports: [RouterModule, AppButtonComponent, Menu, TranslatePipe],
|
|
14
|
+
encapsulation: ViewEncapsulation.None,
|
|
15
|
+
})
|
|
16
|
+
export class AppHeaderComponent {
|
|
17
|
+
@Output() createButtonClicked = new EventEmitter();
|
|
18
|
+
@Output() toggleMenu = new EventEmitter<boolean>();
|
|
19
|
+
@Input() userInfo: any;
|
|
20
|
+
items: MenuItem[] | undefined = [
|
|
21
|
+
{
|
|
22
|
+
items: [
|
|
23
|
+
{
|
|
24
|
+
label: 'خــــروج',
|
|
25
|
+
command: () => this.logout(),
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
// UserPermissionsEnum = UserPermissionsEnum;
|
|
31
|
+
// PermissionsActions = PermissionsActions;
|
|
32
|
+
|
|
33
|
+
logout(): void {
|
|
34
|
+
// this.authService
|
|
35
|
+
// .logoutFromSSO()
|
|
36
|
+
// .pipe(
|
|
37
|
+
// finalize(() => {
|
|
38
|
+
// this.authService.clearAuth();
|
|
39
|
+
// })
|
|
40
|
+
// )
|
|
41
|
+
// .subscribe();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<nav
|
|
2
|
+
[ngClass]="{ 'max-w-0 md:max-w-[500px]': !isOpen, 'max-w-[500px]': isOpen }"
|
|
3
|
+
class="md:flex h-100 bg-primary flex text-white flex-col py-2 text-center gap-y-10 transition-all w-24 hover:md:w-48 duration-500">
|
|
4
|
+
<a [routerLink]="'/'"><i class="font-icon-STC-Logo text-[20px] pt-4 block px-4"></i></a>
|
|
5
|
+
<ul class="flex flex-col flex-grow">
|
|
6
|
+
@for (item of filteredMenu; track $index) {
|
|
7
|
+
<li>
|
|
8
|
+
<a
|
|
9
|
+
[routerLinkActive]="'bg-primary_dark border-secondary'"
|
|
10
|
+
[routerLink]="item.link"
|
|
11
|
+
class="flex flex-col py-3 px-4 border-r-2 border-primary transition-all hover:bg-primary_dark hover:border-secondary">
|
|
12
|
+
<i [class]="item.icon + ' text-[17px] mb-1'"></i>
|
|
13
|
+
<span class="text-[10px] truncate">{{ item.label }}</span>
|
|
14
|
+
</a>
|
|
15
|
+
</li>
|
|
16
|
+
}
|
|
17
|
+
</ul>
|
|
18
|
+
|
|
19
|
+
<a href="#"><i class="font-icon-setting text-[20px] pb-4 block px-4"></i></a>
|
|
20
|
+
</nav>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Component, inject, Input, OnInit, ViewEncapsulation } from "@angular/core";
|
|
2
|
+
import { RouterModule } from "@angular/router";
|
|
3
|
+
import { SideMenuItem } from "./side-menu";
|
|
4
|
+
import { BASE_SIDE_MENU_ITEMS } from "./side-menu-items";
|
|
5
|
+
import { NgClass } from "@angular/common";
|
|
6
|
+
@Component({
|
|
7
|
+
selector: "app-side-menu",
|
|
8
|
+
standalone: true,
|
|
9
|
+
imports: [RouterModule, NgClass],
|
|
10
|
+
templateUrl: "./app-side-menu.component.html",
|
|
11
|
+
encapsulation: ViewEncapsulation.None
|
|
12
|
+
})
|
|
13
|
+
export class AppSideMenuComponent implements OnInit {
|
|
14
|
+
@Input() isOpen!: boolean;
|
|
15
|
+
menuItems: SideMenuItem[] = BASE_SIDE_MENU_ITEMS;
|
|
16
|
+
//permissionsService = inject(PermissionsService);
|
|
17
|
+
filteredMenu: SideMenuItem[];
|
|
18
|
+
|
|
19
|
+
ngOnInit(): void {
|
|
20
|
+
this.filteredMenu = this.menuItems.filter((item) => {
|
|
21
|
+
if (!item.permissionKey) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
// return this.permissionsService.checkKeyHasPermission(item.permissionKey as UserPermissionsEnum, PermissionsActions.VIEW);
|
|
25
|
+
return;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { RouteNameItem } from "./side-menu";
|
|
2
|
+
|
|
3
|
+
export const ROUTES_NAME: RouteNameItem = {
|
|
4
|
+
board: {
|
|
5
|
+
name: '/board-page',
|
|
6
|
+
},
|
|
7
|
+
users: {
|
|
8
|
+
name: '/users',
|
|
9
|
+
},
|
|
10
|
+
// reports: {
|
|
11
|
+
// name: '/reports',
|
|
12
|
+
// },
|
|
13
|
+
meetings: {
|
|
14
|
+
name: '/meeting-page',
|
|
15
|
+
},
|
|
16
|
+
// tasks: {
|
|
17
|
+
// name: '/tasks',
|
|
18
|
+
// },
|
|
19
|
+
// imported: {
|
|
20
|
+
// name: '/imported',
|
|
21
|
+
// },
|
|
22
|
+
// exported: {
|
|
23
|
+
// name: '/exported',
|
|
24
|
+
// },
|
|
25
|
+
// board: {
|
|
26
|
+
// name: '/board',
|
|
27
|
+
// },
|
|
28
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ROUTES_NAME } from './routes-names';
|
|
2
|
+
import { SideMenuItem } from './side-menu';
|
|
3
|
+
|
|
4
|
+
export const BASE_SIDE_MENU_ITEMS: SideMenuItem[] = [
|
|
5
|
+
{
|
|
6
|
+
label: 'الإجتماعات',
|
|
7
|
+
icon: 'font-icon-menu-board',
|
|
8
|
+
link: ROUTES_NAME['meetings'].name
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
label: 'اللجان و المجالس',
|
|
12
|
+
icon: 'font-icon-people',
|
|
13
|
+
link: ROUTES_NAME['board'].name
|
|
14
|
+
},
|
|
15
|
+
// {
|
|
16
|
+
// label: 'المستخدمين',
|
|
17
|
+
// icon: 'font-icon-profile-2user',
|
|
18
|
+
// link: ROUTES_NAME['users'].name,
|
|
19
|
+
// },
|
|
20
|
+
// {
|
|
21
|
+
// label: 'الإجتماعات',
|
|
22
|
+
// icon: 'font-icon-menu-board',
|
|
23
|
+
// link: ROUTES_NAME['meetings'].name,
|
|
24
|
+
// },
|
|
25
|
+
// {
|
|
26
|
+
// label: 'مهامي',
|
|
27
|
+
// icon: 'font-icon-task-square',
|
|
28
|
+
// link: ROUTES_NAME['tasks'].name,
|
|
29
|
+
// },
|
|
30
|
+
// {
|
|
31
|
+
// label: 'الوارد',
|
|
32
|
+
// icon: 'font-icon-directbox-receive',
|
|
33
|
+
// link: ROUTES_NAME['imported'].name,
|
|
34
|
+
// },
|
|
35
|
+
// {
|
|
36
|
+
// label: 'الصادر',
|
|
37
|
+
// icon: 'font-icon-directbox-send',
|
|
38
|
+
// link: ROUTES_NAME['exported'].name,
|
|
39
|
+
// },
|
|
40
|
+
// {
|
|
41
|
+
// label: 'التقارير',
|
|
42
|
+
// icon: 'font-icon-status-up',
|
|
43
|
+
// link: ROUTES_NAME['reports'].name,
|
|
44
|
+
// },
|
|
45
|
+
];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TemplateRef } from "@angular/core";
|
|
2
|
+
|
|
3
|
+
interface Tab {
|
|
4
|
+
title: string;
|
|
5
|
+
iconName?: string;
|
|
6
|
+
iconPathCount?: number;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
count?: number;
|
|
9
|
+
permissionKey?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RoutedTab extends Tab {
|
|
13
|
+
link: string;
|
|
14
|
+
}
|
|
15
|
+
export interface TemplateTab<T = unknown> extends Tab {
|
|
16
|
+
contentTemplate: TemplateRef<unknown>;
|
|
17
|
+
queryParamValue?: T;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export type AppTabs = ({
|
|
22
|
+
isRouted: true;
|
|
23
|
+
items: RoutedTab[];
|
|
24
|
+
} | {
|
|
25
|
+
isRouted: false;
|
|
26
|
+
items: TemplateTab[];
|
|
27
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
@if (tabs && tabs.items.length) {
|
|
2
|
+
<div [class]="tabsStyle + (responsive ? ' full-width' : '') + ' tabs-container'">
|
|
3
|
+
<p-tabs [value]="selectedTabIndex() || activeTabIndex" scrollable>
|
|
4
|
+
<p-tablist>
|
|
5
|
+
|
|
6
|
+
@for (tab of tabs.items; let i = $index; track i) {
|
|
7
|
+
<p-tab [value]="i" [routerLink]="tabs.isRouted ? $any(tab).link : null" [disabled]="tab.disabled"
|
|
8
|
+
(click)="onTabChange(i)">
|
|
9
|
+
@if (tab.iconName) {
|
|
10
|
+
<app-ico-moon-card [iconClass]="'text-[17px]'" [iconName]="tab.iconName"
|
|
11
|
+
[iconPathCount]="tab.iconPathCount || 0" />
|
|
12
|
+
}
|
|
13
|
+
<span>{{ tab.title | translate }}
|
|
14
|
+
@if (tab.count || tab.count === 0) {
|
|
15
|
+
<p-badge [value]="getTabCount(tab.count)" severity="secondary" />
|
|
16
|
+
}
|
|
17
|
+
</span>
|
|
18
|
+
</p-tab>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
</p-tablist>
|
|
22
|
+
|
|
23
|
+
<p-tabpanels>
|
|
24
|
+
@if (tabs.isRouted) {
|
|
25
|
+
<router-outlet></router-outlet>
|
|
26
|
+
} @else {
|
|
27
|
+
@for (tab of tabs.items; let i = $index; track i) {
|
|
28
|
+
<p-tabpanel [value]="i">
|
|
29
|
+
<ng-container [ngTemplateOutlet]="tab.contentTemplate"></ng-container>
|
|
30
|
+
</p-tabpanel>
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
</p-tabpanels>
|
|
35
|
+
</p-tabs>
|
|
36
|
+
</div>
|
|
37
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
.tabs-container {
|
|
2
|
+
&.full-width {
|
|
3
|
+
.p-tabs .p-tablist-tab-list .p-tab {
|
|
4
|
+
@apply flex-grow flex justify-center max-w-[50%];
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.p-tabs {
|
|
9
|
+
.p-tablist-tab-list {
|
|
10
|
+
@apply relative;
|
|
11
|
+
|
|
12
|
+
&:after {
|
|
13
|
+
@apply content-[''] w-full h-[3px] bg-purple-800/5 absolute bottom-0 right-0 z-[1];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.p-tab {
|
|
17
|
+
@apply text-sm text-gray-400 font-normal text-[16px] border-b-[4px] border-transparent z-[2];
|
|
18
|
+
|
|
19
|
+
&:not(.p-tab-active) {
|
|
20
|
+
app-ico-moon-card {
|
|
21
|
+
@apply grayscale;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.p-tablist-active-bar {
|
|
29
|
+
@apply hidden;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.p-tabpanels.p-component {
|
|
33
|
+
@apply mt-5 rounded-lg;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&.basic {
|
|
38
|
+
.p-tabs {
|
|
39
|
+
.p-tablist-tab-list {
|
|
40
|
+
@apply bg-transparent;
|
|
41
|
+
|
|
42
|
+
.p-tab {
|
|
43
|
+
&.p-tab-active {
|
|
44
|
+
@apply text-primary border-primary;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&.primary_light {
|
|
52
|
+
.p-tabs {
|
|
53
|
+
.p-tablist-tab-list {
|
|
54
|
+
.p-tab {
|
|
55
|
+
@apply rounded-t-lg text-[14px];
|
|
56
|
+
|
|
57
|
+
&.p-tab-active {
|
|
58
|
+
@apply bg-purple-800/5 font-semibold text-primary border-primary;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&.primary {
|
|
66
|
+
.p-tabs {
|
|
67
|
+
.p-tablist-tab-list {
|
|
68
|
+
&:after {
|
|
69
|
+
@apply bg-purple-800/5;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.p-tab {
|
|
73
|
+
@apply rounded-t-lg text-[14px];
|
|
74
|
+
|
|
75
|
+
&.p-tab-active {
|
|
76
|
+
@apply bg-primary font-semibold text-white border-secondary;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
[dir='rtl'] {
|
|
85
|
+
.p-tabs .p-tablist{
|
|
86
|
+
.p-iconwrapper {
|
|
87
|
+
@apply rotate-180deg;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.p-tablist-next-button {
|
|
91
|
+
@apply right-auto left-0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.p-tablist-prev-button {
|
|
95
|
+
@apply right-0 left-auto;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// TODO : CHECK
|
|
101
|
+
// .p-tabpanels.p-component {
|
|
102
|
+
// @apply mt-5 rounded-[1.5rem];
|
|
103
|
+
// }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { AppTabsComponent } from './app-tabs.component';
|
|
3
|
+
|
|
4
|
+
describe('AppTabsComponent', () => {
|
|
5
|
+
let component: AppTabsComponent;
|
|
6
|
+
let fixture: ComponentFixture<AppTabsComponent>;
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
await TestBed.configureTestingModule({
|
|
10
|
+
imports: [AppTabsComponent],
|
|
11
|
+
}).compileComponents();
|
|
12
|
+
|
|
13
|
+
fixture = TestBed.createComponent(AppTabsComponent);
|
|
14
|
+
component = fixture.componentInstance;
|
|
15
|
+
fixture.detectChanges();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should create', () => {
|
|
19
|
+
expect(component).toBeTruthy();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, inject, Input, model, OnInit, ViewEncapsulation } from '@angular/core';
|
|
3
|
+
import { TabsModule } from 'primeng/tabs';
|
|
4
|
+
import { AppTabs } from './app-tab.interface';
|
|
5
|
+
import { IcoMoonIconComponent } from '../ico-moon-icon/ico-moon-icon.component';
|
|
6
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
7
|
+
import { ActivatedRoute, NavigationEnd, Router, RouterLink, RouterOutlet } from '@angular/router';
|
|
8
|
+
import { filter } from 'rxjs';
|
|
9
|
+
import { BadgeModule } from 'primeng/badge';
|
|
10
|
+
|
|
11
|
+
@Component({
|
|
12
|
+
selector: 'app-tabs',
|
|
13
|
+
standalone: true,
|
|
14
|
+
encapsulation: ViewEncapsulation.None,
|
|
15
|
+
imports: [
|
|
16
|
+
CommonModule,
|
|
17
|
+
TabsModule,
|
|
18
|
+
RouterLink,
|
|
19
|
+
RouterOutlet,
|
|
20
|
+
IcoMoonIconComponent,
|
|
21
|
+
TranslateModule,
|
|
22
|
+
BadgeModule,
|
|
23
|
+
],
|
|
24
|
+
templateUrl: './app-tabs.component.html',
|
|
25
|
+
styleUrl: './app-tabs.component.scss',
|
|
26
|
+
})
|
|
27
|
+
export class AppTabsComponent implements OnInit {
|
|
28
|
+
@Input() tabs: AppTabs;
|
|
29
|
+
@Input() tabsStyle: 'basic' | 'primary_light' | 'primary' = 'basic';
|
|
30
|
+
@Input() responsive = false;
|
|
31
|
+
@Input() twoDigitCount: boolean;
|
|
32
|
+
selectedTabIndex = model<number>(0);
|
|
33
|
+
activeTabIndex = 0;
|
|
34
|
+
private router = inject(Router);
|
|
35
|
+
private route = inject(ActivatedRoute);
|
|
36
|
+
|
|
37
|
+
ngOnInit(): void {
|
|
38
|
+
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(() => {
|
|
39
|
+
this.updateActiveTab();
|
|
40
|
+
});
|
|
41
|
+
// to be refactor
|
|
42
|
+
this.updateActiveTab();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Updates the active tab index based on the current route
|
|
46
|
+
private updateActiveTab(): void {
|
|
47
|
+
if (!this.tabs.isRouted) return;
|
|
48
|
+
const currentUrl = this.router.url;
|
|
49
|
+
const matchingTabIndex = this.tabs.items.findIndex((tab) => currentUrl.includes(tab.link));
|
|
50
|
+
this.activeTabIndex = matchingTabIndex !== -1 ? matchingTabIndex : 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
onTabChange(index: number): void {
|
|
54
|
+
this.selectedTabIndex.set(index);
|
|
55
|
+
|
|
56
|
+
if (!this.tabs.isRouted) return;
|
|
57
|
+
const selectedTab = this.tabs.items[index];
|
|
58
|
+
if (selectedTab && !selectedTab.disabled) {
|
|
59
|
+
this.router.navigate([selectedTab.link], { relativeTo: this.route });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getTabCount(count: number): string {
|
|
64
|
+
if (!count) return '0';
|
|
65
|
+
return this.twoDigitCount && count > 99 ? '99+' : count.toString();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<p-drawer
|
|
2
|
+
(onHide)="hideBottomSheet()"
|
|
3
|
+
(onShow)="onShow.emit($event)"
|
|
4
|
+
[(visible)]="show"
|
|
5
|
+
[closable]="false"
|
|
6
|
+
[ngClass]="{ show: show }"
|
|
7
|
+
[position]="'bottom'"
|
|
8
|
+
appendTo="body"
|
|
9
|
+
>
|
|
10
|
+
<ng-template pTemplate="header">
|
|
11
|
+
<div class="band"></div>
|
|
12
|
+
</ng-template>
|
|
13
|
+
@if (contentTemplate) {
|
|
14
|
+
<ng-template pTemplate="content">
|
|
15
|
+
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
|
|
16
|
+
</ng-template>
|
|
17
|
+
}
|
|
18
|
+
</p-drawer>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
.sidebar {
|
|
2
|
+
&.show {
|
|
3
|
+
@apply min-w-[550px];
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.band{
|
|
8
|
+
background-color: #DFE0E6;
|
|
9
|
+
width: 40px;
|
|
10
|
+
height: 4px;
|
|
11
|
+
border-radius: 24px;
|
|
12
|
+
display: block;
|
|
13
|
+
}
|
|
14
|
+
.p-drawer-header , .p-drawer-footer{
|
|
15
|
+
background-color: var(--gray-100);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.p-drawer-header{
|
|
19
|
+
--p-drawer-header-padding: 0.75rem var(--p-overlay-modal-padding);
|
|
20
|
+
font-weight: 500;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
color: #090D0F;
|
|
23
|
+
font-size: 20px;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.p-drawer-content{
|
|
29
|
+
padding: 0px !important;
|
|
30
|
+
margin: 0px !important;
|
|
31
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { NgClass, NgTemplateOutlet } from "@angular/common";
|
|
2
|
+
import { Component, EventEmitter, Input, Output, TemplateRef, ViewEncapsulation } from "@angular/core";
|
|
3
|
+
import { PrimeTemplate } from "primeng/api";
|
|
4
|
+
import { Drawer } from "primeng/drawer";
|
|
5
|
+
import { TooltipModule } from "primeng/tooltip";
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: "app-bottom-sheet",
|
|
9
|
+
standalone: true,
|
|
10
|
+
imports: [PrimeTemplate, Drawer, NgClass, NgTemplateOutlet, TooltipModule],
|
|
11
|
+
templateUrl: "./bottom-sheet.component.html",
|
|
12
|
+
styleUrl: "./bottom-sheet.component.scss",
|
|
13
|
+
encapsulation: ViewEncapsulation.None
|
|
14
|
+
})
|
|
15
|
+
export class BottomSheetComponent {
|
|
16
|
+
@Input() show = false;
|
|
17
|
+
@Input() contentTemplate!: TemplateRef<unknown>;
|
|
18
|
+
|
|
19
|
+
@Output() onHide = new EventEmitter<boolean>();
|
|
20
|
+
@Output() onShow = new EventEmitter<boolean>();
|
|
21
|
+
|
|
22
|
+
hideBottomSheet() {
|
|
23
|
+
this.show = false;
|
|
24
|
+
this.onHide.emit(false);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
@if (dynamicDialogConfig.data) {
|
|
2
|
+
<div class="confirmation-dialog">
|
|
3
|
+
<div class="dialog-wrapper">
|
|
4
|
+
@if (dynamicDialogConfig.data) {
|
|
5
|
+
<div class="confirmation-dialog__content my-4">
|
|
6
|
+
@if (dynamicDialogConfig.data.dialogIcon) {
|
|
7
|
+
<em [class]="dynamicDialogConfig.data.dialogIcon"></em>
|
|
8
|
+
}
|
|
9
|
+
<p class="confirmation-dialog__message text-xl mb-2">
|
|
10
|
+
{{ dynamicDialogConfig.data.message }}
|
|
11
|
+
</p>
|
|
12
|
+
@if (dynamicDialogConfig.data.hint) {
|
|
13
|
+
<p class="confirmation-dialog__hint font-normal text-base">
|
|
14
|
+
{{ dynamicDialogConfig.data.hint }}
|
|
15
|
+
</p>
|
|
16
|
+
}
|
|
17
|
+
@if (dynamicDialogConfig.data.inputForm) {
|
|
18
|
+
<app-dynamic-form [dynamicFormData]="dialogFormData"></app-dynamic-form>
|
|
19
|
+
}
|
|
20
|
+
</div>
|
|
21
|
+
}
|
|
22
|
+
<div class="confirmation-dialog__actions flex gap-2 mt-4">
|
|
23
|
+
<app-button [title]="dynamicDialogConfig.data?.confirmLabel || ('actions.confirm' | translate)"
|
|
24
|
+
[disabled]="!!(dialogFormData && dialogFormData.formGroup?.invalid)" [severity]="'primary'"
|
|
25
|
+
[id]="dynamicDialogConfig.data.confirmBtnId" [icon]="dynamicDialogConfig.data.confirmBtnIcon || ''"
|
|
26
|
+
[label]="dynamicDialogConfig.data.confirmBtnLabel"
|
|
27
|
+
[iconPos]="dynamicDialogConfig.data.confirmBtnPosition || 'left'" [styleClass]="'confirmation-btn'"
|
|
28
|
+
(click)="submit()" />
|
|
29
|
+
<app-button [title]="dynamicDialogConfig.data?.closeLabel || ('actions.cancel' | translate)"
|
|
30
|
+
[severity]="'primary'" variant="outlined" [label]="dynamicDialogConfig.data.cancelBtnLabel"
|
|
31
|
+
[id]="dynamicDialogConfig.data.cancelBtnId" [styleClass]="'cancel-btn confirmation-btn cancel-btn'"
|
|
32
|
+
(click)="close()" />
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
|
2
|
+
|
|
3
|
+
import { ConfirmationDialogComponent } from "./confirmation-dialog.component";
|
|
4
|
+
|
|
5
|
+
describe("SharedConfirmDialogComponent", () => {
|
|
6
|
+
let component: ConfirmationDialogComponent;
|
|
7
|
+
let fixture: ComponentFixture<ConfirmationDialogComponent>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
imports: [ConfirmationDialogComponent]
|
|
12
|
+
}).compileComponents();
|
|
13
|
+
|
|
14
|
+
fixture = TestBed.createComponent(ConfirmationDialogComponent);
|
|
15
|
+
component = fixture.componentInstance;
|
|
16
|
+
fixture.detectChanges();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should create", () => {
|
|
20
|
+
expect(component).toBeTruthy();
|
|
21
|
+
});
|
|
22
|
+
});
|