aril 1.0.39 → 1.0.41

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 (59) hide show
  1. package/esm2022/http/src/serviceStateMethods.mjs +6 -2
  2. package/esm2022/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.mjs +211 -0
  3. package/esm2022/theme/layout/app/favorite-pages/favorite-pages.service.mjs +55 -0
  4. package/esm2022/theme/layout/app/favorite-pages/modals/add-edit-favorite-modal/add-edit-favorite-modal.component.mjs +129 -0
  5. package/esm2022/theme/layout/app/history/history-sidebar.component.mjs +128 -0
  6. package/esm2022/theme/layout/app/history/history.service.mjs +146 -0
  7. package/esm2022/theme/layout/app/layout/app.layout.component.mjs +9 -3
  8. package/esm2022/theme/layout/app/profileSidebar/app.profilesidebar.component.mjs +100 -8
  9. package/esm2022/theme/layout/app/profileSidebar/modals/change-password-modal/change-password-modal.component.mjs +142 -0
  10. package/esm2022/theme/layout/app/profileSidebar/modals/edit-profile-modal/edit-profile-modal.component.mjs +123 -0
  11. package/esm2022/theme/layout/app/profileSidebar/profile.service.mjs +42 -0
  12. package/esm2022/theme/layout/app/site-map/site-map-sidebar.component.mjs +161 -0
  13. package/esm2022/theme/layout/app/topbar/app.topbar.component.mjs +23 -5
  14. package/esm2022/theme/layout/service/app.layout.service.mjs +13 -1
  15. package/fesm2022/aril-http.mjs +5 -1
  16. package/fesm2022/aril-http.mjs.map +1 -1
  17. package/fesm2022/aril-theme-layout.mjs +1197 -75
  18. package/fesm2022/aril-theme-layout.mjs.map +1 -1
  19. package/package.json +84 -83
  20. package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.d.ts +42 -0
  21. package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.html +106 -0
  22. package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.scss +181 -0
  23. package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.ts +253 -0
  24. package/theme/layout/app/favorite-pages/favorite-pages.service.d.ts +54 -0
  25. package/theme/layout/app/favorite-pages/favorite-pages.service.ts +87 -0
  26. package/theme/layout/app/favorite-pages/modals/add-edit-favorite-modal/add-edit-favorite-modal.component.d.ts +36 -0
  27. package/theme/layout/app/favorite-pages/modals/add-edit-favorite-modal/add-edit-favorite-modal.component.html +27 -0
  28. package/theme/layout/app/favorite-pages/modals/add-edit-favorite-modal/add-edit-favorite-modal.component.ts +165 -0
  29. package/theme/layout/app/history/history-sidebar.component.d.ts +30 -0
  30. package/theme/layout/app/history/history-sidebar.component.html +88 -0
  31. package/theme/layout/app/history/history-sidebar.component.scss +191 -0
  32. package/theme/layout/app/history/history-sidebar.component.ts +139 -0
  33. package/theme/layout/app/history/history.service.d.ts +36 -0
  34. package/theme/layout/app/history/history.service.ts +182 -0
  35. package/theme/layout/app/layout/app.layout.component.html +3 -0
  36. package/theme/layout/app/layout/app.layout.component.ts +7 -1
  37. package/theme/layout/app/profileSidebar/app.profilesidebar.component.d.ts +17 -2
  38. package/theme/layout/app/profileSidebar/app.profilesidebar.component.html +107 -135
  39. package/theme/layout/app/profileSidebar/app.profilesidebar.component.scss +152 -0
  40. package/theme/layout/app/profileSidebar/app.profilesidebar.component.ts +114 -7
  41. package/theme/layout/app/profileSidebar/modals/change-password-modal/change-password-modal.component.d.ts +30 -0
  42. package/theme/layout/app/profileSidebar/modals/change-password-modal/change-password-modal.component.html +46 -0
  43. package/theme/layout/app/profileSidebar/modals/change-password-modal/change-password-modal.component.scss +28 -0
  44. package/theme/layout/app/profileSidebar/modals/change-password-modal/change-password-modal.component.ts +178 -0
  45. package/theme/layout/app/profileSidebar/modals/edit-profile-modal/edit-profile-modal.component.d.ts +27 -0
  46. package/theme/layout/app/profileSidebar/modals/edit-profile-modal/edit-profile-modal.component.html +76 -0
  47. package/theme/layout/app/profileSidebar/modals/edit-profile-modal/edit-profile-modal.component.ts +141 -0
  48. package/theme/layout/app/profileSidebar/profile.service.d.ts +67 -0
  49. package/theme/layout/app/profileSidebar/profile.service.ts +89 -0
  50. package/theme/layout/app/site-map/site-map-sidebar.component.d.ts +37 -0
  51. package/theme/layout/app/site-map/site-map-sidebar.component.html +118 -0
  52. package/theme/layout/app/site-map/site-map-sidebar.component.scss +189 -0
  53. package/theme/layout/app/site-map/site-map-sidebar.component.ts +189 -0
  54. package/theme/layout/app/topbar/app.topbar.component.d.ts +7 -1
  55. package/theme/layout/app/topbar/app.topbar.component.html +37 -17
  56. package/theme/layout/app/topbar/app.topbar.component.scss +188 -12
  57. package/theme/layout/app/topbar/app.topbar.component.ts +29 -7
  58. package/theme/layout/service/app.layout.service.d.ts +6 -0
  59. package/theme/layout/service/app.layout.service.ts +19 -1
@@ -2,150 +2,122 @@
2
2
  [(visible)]="visible"
3
3
  position="right"
4
4
  [transitionOptions]="'.3s cubic-bezier(0, 0, 0.2, 1)'"
5
- styleClass="layout-profile-sidebar w-full sm:w-25rem">
6
- <div class="flex flex-column mx-auto md:mx-0">
7
- <span class="mb-2 font-semibold">Hoşgeldiniz</span>
8
- <span class="text-color-secondary font-medium mb-5">{{username}}</span>
5
+ styleClass="layout-profile-sidebar w-full sm:w-30rem">
6
+ <ng-template pTemplate="header">
7
+ <div class="flex align-items-center gap-2" *transloco="let t; read: 'profileSidebar'">
8
+ <span class="font-bold">{{ t('personalInfo') }}</span>
9
+ </div>
10
+ </ng-template>
9
11
 
10
- <ul class="list-none m-0 p-0">
11
- <!-- <li>
12
- <a
13
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
14
- <span>
15
- <i class="pi pi-user text-xl text-primary"></i>
16
- </span>
17
- <div class="ml-3">
18
- <span class="mb-2 font-semibold">Profile</span>
19
- <p class="text-color-secondary m-0">Lorem ipsum date visale</p>
12
+ @if (userProfile()) {
13
+ <div class="profile-content" *transloco="let t; read: 'profileSidebar'">
14
+ <!-- Personal Information -->
15
+ <div class="info-section">
16
+ <div class="info-items">
17
+ <div class="info-item">
18
+ <i class="pi pi-user info-icon"></i>
19
+ <div class="info-content">
20
+ <span class="info-label">{{ t('fullName') }}</span>
21
+ <span class="info-value">{{ userProfile()?.firstName }} {{ userProfile()?.lastName }}</span>
22
+ </div>
20
23
  </div>
21
- </a>
22
- </li>
23
- <li>
24
- <a
25
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
26
- <span>
27
- <i class="pi pi-user text-xl text-primary"></i>
28
- </span>
29
- <div class="ml-3">
30
- <span class="mb-2 font-semibold">Billing</span>
31
- <p class="text-color-secondary m-0">Amet mimin mıollit</p>
32
- </div>
33
- </a>
34
- </li>
35
- <li>
36
- <a
37
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
38
- <span>
39
- <i class="pi pi-cog text-xl text-primary"></i>
40
- </span>
41
- <div class="ml-3">
42
- <span class="mb-2 font-semibold">Settings</span>
43
- <p class="text-color-secondary m-0">Exercitation veniam</p>
44
- </div>
45
- </a>
46
- </li> -->
47
- <li (click)="logout()">
48
- <a
49
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
50
- <span>
51
- <i class="pi pi-power-off text-xl text-primary"></i>
52
- </span>
53
- <div class="ml-3" >
54
- <span class="mb-2 font-semibold">Çıkış</span>
55
- </div>
56
- </a>
57
- </li>
58
- </ul>
59
- </div>
60
24
 
61
- <!-- <div class="flex flex-column mt-5 mx-auto md:mx-0">
62
- <span class="mb-2 font-semibold">Notifications</span>
63
- <span class="text-color-secondary font-medium mb-5">You have 3 notifications</span>
64
-
65
- <ul class="list-none m-0 p-0">
66
- <li>
67
- <a
68
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
69
- <span>
70
- <i class="pi pi-comment text-xl text-primary"></i>
71
- </span>
72
- <div class="ml-3">
73
- <span class="mb-2 font-semibold">Your post has new comments</span>
74
- <p class="text-color-secondary m-0">5 min ago</p>
25
+ <div class="info-item">
26
+ <i class="pi pi-id-card info-icon"></i>
27
+ <div class="info-content">
28
+ <span class="info-label">{{ t('tcNumber') }}</span>
29
+ <span class="info-value">{{ userProfile()?.tckn || '' }}</span>
30
+ </div>
75
31
  </div>
76
- </a>
77
- </li>
78
- <li>
79
- <a
80
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
81
- <span>
82
- <i class="pi pi-trash text-xl text-primary"></i>
83
- </span>
84
- <div class="ml-3">
85
- <span class="mb-2 font-semibold">Your post has been deleted</span>
86
- <p class="text-color-secondary m-0">15min ago</p>
32
+
33
+ <div class="info-item">
34
+ <i class="pi pi-envelope info-icon"></i>
35
+ <div class="info-content">
36
+ <span class="info-label">{{ t('email') }}</span>
37
+ <span class="info-value">{{ userProfile()?.email || '' }}</span>
38
+ </div>
87
39
  </div>
88
- </a>
89
- </li>
90
- <li>
91
- <a
92
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
93
- <span>
94
- <i class="pi pi-folder text-xl text-primary"></i>
95
- </span>
96
- <div class="ml-3">
97
- <span class="mb-2 font-semibold">Post has been updated</span>
98
- <p class="text-color-secondary m-0">3h ago</p>
40
+
41
+ <div class="info-item">
42
+ <i class="pi pi-phone info-icon"></i>
43
+ <div class="info-content">
44
+ <span class="info-label">{{ t('phone') }}</span>
45
+ <span class="info-value">{{ userProfile()?.phone || '' }}</span>
46
+ </div>
99
47
  </div>
100
- </a>
101
- </li>
102
- </ul>
103
- </div> -->
104
48
 
105
- <!-- <div class="flex flex-column mt-5 mx-auto md:mx-0">
106
- <span class="mb-2 font-semibold">Messages</span>
107
- <span class="text-color-secondary font-medium mb-5">You have new messages</span>
49
+ <div class="info-item">
50
+ <i class="pi pi-at info-icon"></i>
51
+ <div class="info-content">
52
+ <span class="info-label">{{ t('username') }}</span>
53
+ <span class="info-value">{{ userProfile()?.userName }}</span>
54
+ </div>
55
+ </div>
108
56
 
109
- <ul class="list-none m-0 p-0">
110
- <li>
111
- <a
112
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
113
- <span>
114
- <img src="assets/demo/images/avatar/circle/avatar-m-8.png" alt="Avatar" class="w-2rem h-2rem" />
115
- </span>
116
- <div class="ml-3">
117
- <span class="mb-2 font-semibold">James Robinson</span>
118
- <p class="text-color-secondary m-0">10 min ago</p>
57
+ <div class="info-item">
58
+ <i class="pi pi-check-circle info-icon"></i>
59
+ <div class="info-content">
60
+ <span class="info-label">{{ t('accountStatus') }}</span>
61
+ <span class="info-value status" [class.active]="userProfile()?.enabled">
62
+ {{ userProfile()?.enabled ? t('active') : t('inactive') }}
63
+ </span>
64
+ </div>
119
65
  </div>
120
- <p-tag value="3" class="ml-auto"></p-tag>
121
- </a>
122
- </li>
123
- <li>
124
- <a
125
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
126
- <span>
127
- <img src="assets/demo/images/avatar/circle/avatar-f-8.png" alt="Avatar" class="w-2rem h-2rem" />
128
- </span>
129
- <div class="ml-3">
130
- <span class="mb-2 font-semibold">Mary Watson</span>
131
- <p class="text-color-secondary m-0">15min ago</p>
66
+
67
+ <div class="info-item">
68
+ <i class="pi pi-user info-icon"></i>
69
+ <div class="info-content">
70
+ <span class="info-label">{{ t('systemUser') }}</span>
71
+ <span class="info-value status" [class.active]="userProfile()?.systemUser">
72
+ {{ userProfile()?.systemUser ? t('yes') : t('no') }}
73
+ </span>
74
+ </div>
132
75
  </div>
133
- <p-tag value="1" class="ml-auto"></p-tag>
134
- </a>
135
- </li>
136
- <li>
137
- <a
138
- class="cursor-pointer flex surface-border mb-3 p-3 align-items-center border-1 surface-border border-round hover:surface-hover transition-colors transition-duration-150">
139
- <span>
140
- <img src="assets/demo/images/avatar/circle/avatar-f-4.png" alt="Avatar" class="w-2rem h-2rem" />
141
- </span>
142
- <div class="ml-3">
143
- <span class="mb-2 font-semibold">Aisha Webb</span>
144
- <p class="text-color-secondary m-0">3h ago</p>
76
+
77
+ <div class="info-item">
78
+ <i class="pi pi-building info-icon"></i>
79
+ <div class="info-content">
80
+ <span class="info-label">{{ t('clientSystemUser') }}</span>
81
+ <span class="info-value">{{ userProfile()?.clientOfSystemUser }}</span>
82
+ </div>
145
83
  </div>
146
- <p-tag value="2" class="ml-auto"></p-tag>
147
- </a>
148
- </li>
149
- </ul>
150
- </div> -->
84
+ </div>
85
+ </div>
86
+ </div>
87
+ }
88
+
89
+ <!-- Fixed Action Buttons -->
90
+ @if (userProfile()) {
91
+ <div class="action-buttons-container grid p-fluid" *transloco="let t; read: 'profileSidebar'">
92
+ <div class="col-12 flex justify-content-between align-items-center">
93
+ <aril-button
94
+ [label]="t('editProfile')"
95
+ icon="USER_EDIT"
96
+ color="primary"
97
+ [outlined]="true"
98
+ size="sm"
99
+ class="col-6"
100
+ (clickEvent)="editProfile()">
101
+ </aril-button>
102
+ <aril-button
103
+ [label]="t('changePassword')"
104
+ icon="KEY"
105
+ color="secondary"
106
+ [outlined]="true"
107
+ size="sm"
108
+ class="col-6"
109
+ (clickEvent)="changePassword()">
110
+ </aril-button>
111
+ </div>
112
+ <aril-button
113
+ [label]="t('logout')"
114
+ icon="SIGN_OUT"
115
+ color="danger"
116
+ [outlined]="false"
117
+ size="sm"
118
+ class="col-12"
119
+ (clickEvent)="logout()">
120
+ </aril-button>
121
+ </div>
122
+ }
151
123
  </p-sidebar>
@@ -0,0 +1,152 @@
1
+ // Modern Profile Sidebar - Matching App UI
2
+ :host {
3
+ .layout-profile-sidebar {
4
+ .p-sidebar-content {
5
+ padding: 0;
6
+ background: var(--surface-0, #ffffff);
7
+ color: var(--text-color, #333);
8
+ height: 100vh;
9
+ overflow-y: auto;
10
+ position: relative;
11
+ }
12
+ }
13
+
14
+ // Content Section
15
+ .profile-content {
16
+ padding: 1rem 0.75rem;
17
+ padding-bottom: 12rem;
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 1.25rem;
21
+ }
22
+
23
+ // Fixed Action Buttons Container - Sadece sidebar içinde
24
+ .action-buttons-container {
25
+ width: 100%;
26
+ position: absolute;
27
+ bottom: 0;
28
+ left: 0;
29
+ right: 0;
30
+ background: var(--surface-0, #ffffff);
31
+ border-top: 1px solid var(--surface-border, #e2e8f0);
32
+ padding: 1rem 0.75rem;
33
+ z-index: 300;
34
+ }
35
+
36
+ // Info Sections - Modern Flat Design
37
+ .info-section {
38
+ .section-title {
39
+ font-size: 1.25rem;
40
+ font-weight: 500;
41
+ color: var(--text-color-secondary, #64748b);
42
+ margin: 0 0 1rem 0;
43
+ padding-bottom: 0.5rem;
44
+ border-bottom: 1px solid var(--surface-border, #e2e8f0);
45
+ display: flex;
46
+ align-items: center;
47
+ gap: 0.5rem;
48
+ text-transform: uppercase;
49
+ letter-spacing: 0.5px;
50
+
51
+ i {
52
+ color: var(--text-color-secondary, #64748b);
53
+ font-size: 1rem;
54
+ }
55
+ }
56
+
57
+ .info-items {
58
+ display: flex;
59
+ flex-direction: column;
60
+ gap: 0;
61
+ }
62
+
63
+ .info-item {
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 0.75rem;
67
+ padding: 0.75rem 0;
68
+ border-bottom: 1px solid var(--surface-border, #f1f5f9);
69
+
70
+ &:last-child {
71
+ border-bottom: none;
72
+ }
73
+
74
+ .info-icon {
75
+ color: var(--text-color-secondary, #64748b);
76
+ font-size: 1rem;
77
+ flex-shrink: 0;
78
+ width: 1.25rem;
79
+ text-align: center;
80
+ }
81
+
82
+ .info-content {
83
+ flex: 1;
84
+ display: flex;
85
+ flex-direction: column;
86
+ gap: 0.25rem;
87
+
88
+ .info-label {
89
+ font-size: 0.95rem;
90
+ color: var(--text-color-secondary, #64748b);
91
+ font-weight: 500;
92
+ line-height: 1;
93
+ }
94
+
95
+ .info-value {
96
+ font-size: 0.95rem;
97
+ color: var(--text-color, #1e293b);
98
+ font-weight: 400;
99
+ line-height: 1.3;
100
+
101
+ &.status {
102
+ display: inline-flex;
103
+ align-items: center;
104
+ padding: 0.25rem 0.75rem;
105
+ border-radius: 16px;
106
+ font-size: 0.8rem;
107
+ font-weight: 600;
108
+ text-transform: uppercase;
109
+ letter-spacing: 0.025em;
110
+ width: fit-content;
111
+ background: var(--red-100, #fee2e2);
112
+ color: var(--red-700, #b91c1c);
113
+ border: 1px solid var(--red-200, #fecaca);
114
+
115
+ &.active {
116
+ background: var(--green-100, #dcfce7);
117
+ color: var(--green-700, #15803d);
118
+ border: 1px solid var(--green-200, #bbf7d0);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ }
126
+
127
+ // Responsive Design
128
+ @media (max-width: 768px) {
129
+ .profile-content {
130
+ padding: 0.875rem 0.65rem;
131
+ padding-bottom: 11rem;
132
+ gap: 1rem;
133
+ }
134
+
135
+ .action-buttons-container {
136
+ padding: 0.875rem 0.65rem;
137
+
138
+ .action-buttons-vertical {
139
+ gap: 0.65rem;
140
+ }
141
+
142
+ .action-buttons-horizontal {
143
+ gap: 0.4rem;
144
+ }
145
+ }
146
+
147
+ .info-item {
148
+ padding: 0.65rem 0;
149
+ }
150
+ }
151
+
152
+ }
@@ -1,23 +1,86 @@
1
- import { Component } from '@angular/core';
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, OnInit, effect, signal } from '@angular/core';
3
+ import { toSignal } from '@angular/core/rxjs-interop';
2
4
 
5
+ import { AvatarModule } from 'primeng/avatar';
6
+ import { ButtonModule } from 'primeng/button';
7
+ import { ChipModule } from 'primeng/chip';
8
+ import { DialogService } from 'primeng/dynamicdialog';
3
9
  import { SidebarModule } from 'primeng/sidebar';
10
+ import { SkeletonModule } from 'primeng/skeleton';
4
11
  import { TagModule } from 'primeng/tag';
5
12
 
6
-
13
+ import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
7
14
  import { KeycloakService } from 'keycloak-angular';
15
+ import { Subject, switchMap } from 'rxjs';
16
+
17
+ import { ButtonComponent } from 'aril/ui/button';
18
+
8
19
  import { LayoutService } from '../../service/app.layout.service';
20
+ import { ChangePasswordModalComponent } from './modals/change-password-modal/change-password-modal.component';
21
+ import { EditProfileModalComponent } from './modals/edit-profile-modal/edit-profile-modal.component';
22
+ import { GetUserRequestDTO, ProfileService, UserResponseDTO } from './profile.service';
9
23
 
10
24
  @Component({
11
25
  standalone: true,
12
26
  selector: 'app-profilemenu',
13
- imports: [SidebarModule, TagModule],
14
- templateUrl: './app.profilesidebar.component.html'
27
+ imports: [
28
+ CommonModule,
29
+ SidebarModule,
30
+ TagModule,
31
+ ButtonModule,
32
+ SkeletonModule,
33
+ AvatarModule,
34
+ ChipModule,
35
+ TranslocoModule,
36
+ ButtonComponent
37
+ ],
38
+ templateUrl: './app.profilesidebar.component.html',
39
+ styleUrls: ['./app.profilesidebar.component.scss'],
40
+ providers: [DialogService]
15
41
  })
16
- export class AppProfileSidebarComponent {
42
+ export class AppProfileSidebarComponent implements OnInit {
17
43
  username: string;
44
+ userProfile = signal<UserResponseDTO | null>(null);
45
+
46
+ private subjects = {
47
+ getUser: new Subject<GetUserRequestDTO>()
48
+ };
49
+
50
+ getUserService = toSignal(this.subjects.getUser.pipe(switchMap((data) => this.profileService.getUser(data))));
18
51
 
19
- constructor(public layoutService: LayoutService,private readonly keycloak:KeycloakService) {
52
+ constructor(
53
+ public layoutService: LayoutService,
54
+ private readonly keycloak: KeycloakService,
55
+ private readonly profileService: ProfileService,
56
+ private readonly dialogService: DialogService,
57
+ private readonly translocoService: TranslocoService
58
+ ) {
20
59
  this.username = this.keycloak.getUsername();
60
+ this.initializeEffects();
61
+ }
62
+
63
+ ngOnInit(): void {
64
+ this.loadUserProfile();
65
+ }
66
+
67
+ private initializeEffects(): void {
68
+ effect(
69
+ () => {
70
+ const service = this.getUserService();
71
+ if (service?.response) {
72
+ this.userProfile.set(service.response);
73
+ }
74
+ },
75
+ { allowSignalWrites: true }
76
+ );
77
+ }
78
+
79
+ private loadUserProfile(): void {
80
+ const userId = this.keycloak.getKeycloakInstance().idTokenParsed?.sub;
81
+ if (userId) {
82
+ this.subjects.getUser.next({ id: userId });
83
+ }
21
84
  }
22
85
 
23
86
  get visible(): boolean {
@@ -26,9 +89,53 @@ export class AppProfileSidebarComponent {
26
89
 
27
90
  set visible(_val: boolean) {
28
91
  this.layoutService.state.profileSidebarVisible = _val;
92
+ if (_val && !this.userProfile()) {
93
+ this.loadUserProfile();
94
+ }
29
95
  }
30
96
 
31
- logout() {
97
+ logout(): void {
32
98
  this.keycloak.logout();
33
99
  }
100
+
101
+ editProfile(): void {
102
+ if (!this.userProfile()) return;
103
+
104
+ const ref = this.dialogService.open(EditProfileModalComponent, {
105
+ header: this.translocoService.translate('profileSidebar.editProfile'),
106
+ width: '600px',
107
+ height: 'auto',
108
+ modal: true,
109
+ maximizable: false,
110
+ closable: true,
111
+ data: {
112
+ userProfile: this.userProfile()
113
+ }
114
+ });
115
+
116
+ ref.onClose.subscribe((result) => {
117
+ if (result?.status === 'success') {
118
+ this.loadUserProfile();
119
+ }
120
+ });
121
+ }
122
+
123
+ changePassword(): void {
124
+ const userId = this.keycloak.getKeycloakInstance().idTokenParsed?.sub;
125
+ if (!userId) return;
126
+
127
+ const ref = this.dialogService.open(ChangePasswordModalComponent, {
128
+ header: this.translocoService.translate('profileSidebar.changePassword'),
129
+ width: '500px',
130
+ height: 'auto',
131
+ modal: true,
132
+ maximizable: false,
133
+ closable: true,
134
+ data: {
135
+ userId: userId
136
+ }
137
+ });
138
+
139
+ ref.onClose.subscribe();
140
+ }
34
141
  }
@@ -0,0 +1,30 @@
1
+ import { AbstractControl, FormBuilder, FormGroup, ValidationErrors } from '@angular/forms';
2
+ import { MessageService } from 'primeng/api';
3
+ import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
4
+ import { TranslocoService } from '@ngneat/transloco';
5
+ import { ProfileService } from '../../profile.service';
6
+ import * as i0 from "@angular/core";
7
+ export declare class PasswordValidators {
8
+ static passwordMatchValidator: (passwordFormGroup: FormGroup) => (control: AbstractControl) => ValidationErrors | null;
9
+ static minLength(length: number): (control: AbstractControl) => ValidationErrors | null;
10
+ static required(control: AbstractControl): ValidationErrors | null;
11
+ }
12
+ export declare class ChangePasswordModalComponent {
13
+ private readonly formBuilder;
14
+ private readonly dialogRef;
15
+ private readonly dialogConfig;
16
+ private readonly profileService;
17
+ private readonly translocoService;
18
+ private readonly messageService;
19
+ passwordForm: FormGroup;
20
+ userId: string;
21
+ private subjects;
22
+ resetPasswordService: import("@angular/core").Signal<import("../../../../../../../../dist/http").ServiceResponse<any> | undefined>;
23
+ constructor(formBuilder: FormBuilder, dialogRef: DynamicDialogRef, dialogConfig: DynamicDialogConfig, profileService: ProfileService, translocoService: TranslocoService, messageService: MessageService);
24
+ initializeForm(): void;
25
+ getErrorMessage(controlName: string): string;
26
+ submit(): void;
27
+ cancel(): void;
28
+ static ɵfac: i0.ɵɵFactoryDeclaration<ChangePasswordModalComponent, never>;
29
+ static ɵcmp: i0.ɵɵComponentDeclaration<ChangePasswordModalComponent, "ng-component", never, {}, {}, never, never, true, never>;
30
+ }
@@ -0,0 +1,46 @@
1
+ <div class="change-password-modal" *transloco="let t; read: 'profileSidebar'">
2
+ <aril-form [formGroup]="passwordForm">
3
+ <aril-field [label]="t('newPassword')" [cols]="{ xl: 12, lg: 12, md: 12, sm: 12 }" [markAsRequired]="true">
4
+ <p-password
5
+ formControlName="newPassword"
6
+ [placeholder]="t('newPassword')"
7
+ [feedback]="false"
8
+ [toggleMask]="true"
9
+ styleClass="w-full"
10
+ [pTooltip]="passwordForm.get('newPassword')?.invalid && passwordForm.get('newPassword')?.touched ? getErrorMessage('newPassword') : ''"
11
+ tooltipPosition="top"
12
+ tooltipStyleClass="tooltipErrorMessage">
13
+ </p-password>
14
+ </aril-field>
15
+
16
+ <aril-field [label]="t('confirmPassword')" [cols]="{ xl: 12, lg: 12, md: 12, sm: 12 }" [markAsRequired]="true">
17
+ <p-password
18
+ formControlName="confirmPassword"
19
+ [placeholder]="t('confirmPassword')"
20
+ [feedback]="false"
21
+ [toggleMask]="true"
22
+ styleClass="w-full"
23
+ [pTooltip]="passwordForm.get('confirmPassword')?.invalid && passwordForm.get('confirmPassword')?.touched ? getErrorMessage('confirmPassword') : ''"
24
+ tooltipPosition="top"
25
+ tooltipStyleClass="tooltipErrorMessage">
26
+ </p-password>
27
+ </aril-field>
28
+
29
+ <div class="col-12 flex justify-content-end mt-4 gap-2">
30
+ <aril-button
31
+ color="danger"
32
+ [label]="t('cancel')"
33
+ [outlined]="true"
34
+ icon="TIMES"
35
+ (clickEvent)="cancel()">
36
+ </aril-button>
37
+ <aril-button
38
+ color="success"
39
+ [label]="t('save')"
40
+ [raised]="false"
41
+ icon="CHECK"
42
+ (clickEvent)="submit()">
43
+ </aril-button>
44
+ </div>
45
+ </aril-form>
46
+ </div>
@@ -0,0 +1,28 @@
1
+ .change-password-modal {
2
+
3
+ :host ::ng-deep {
4
+ .p-password.ng-invalid.ng-touched .p-inputtext {
5
+ border-color: var(--red-500, #ef4444);
6
+ box-shadow: 0 0 0 1px var(--red-500, #ef4444);
7
+ }
8
+
9
+ .p-password.ng-valid.ng-touched .p-inputtext {
10
+ border-color: var(--green-500, #22c55e);
11
+ box-shadow: 0 0 0 1px var(--green-500, #22c55e);
12
+ }
13
+
14
+ .tooltipErrorMessage {
15
+ background-color: var(--red-500, #ef4444) !important;
16
+ color: white !important;
17
+ font-size: 0.75rem !important;
18
+ font-weight: 500 !important;
19
+ border-radius: 4px !important;
20
+ padding: 0.5rem 0.75rem !important;
21
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
22
+ }
23
+
24
+ .tooltipErrorMessage .p-tooltip-arrow {
25
+ border-top-color: var(--red-500, #ef4444) !important;
26
+ }
27
+ }
28
+ }