feat: implement change password functionality with dialog and service integration

This commit is contained in:
2026-06-07 13:56:36 +03:30
parent cd09b09e3b
commit 2f67801700
9 changed files with 89 additions and 60 deletions
@@ -1,16 +1,14 @@
<shared-dialog <shared-dialog
header="ویرایش گذرواژه" header="تغییر گذرواژه"
[(visible)]="visible" [(visible)]="visible"
[modal]="true" [modal]="true"
[style]="{ width: '500px' }" [style]="{ width: '500px' }"
[closable]="true" [closable]="true"
(onHide)="close()" (onHide)="close()">
>
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4"> <form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
<shared-password-input <shared-password-input
[passwordControl]="form.controls.password" [passwordControl]="form.controls.password"
[confirmPasswordControl]="form.controls.confirmPassword" [confirmPasswordControl]="form.controls.confirmPassword" />
/>
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" /> <app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
</form> </form>
@@ -1,16 +1,14 @@
<shared-dialog <shared-dialog
header="ویرایش گذرواژه" header="تغییر گذرواژه"
[(visible)]="visible" [(visible)]="visible"
[modal]="true" [modal]="true"
[style]="{ width: '500px' }" [style]="{ width: '500px' }"
[closable]="true" [closable]="true"
(onHide)="close()" (onHide)="close()">
>
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4"> <form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
<shared-password-input <shared-password-input
[passwordControl]="form.controls.password" [passwordControl]="form.controls.password"
[confirmPasswordControl]="form.controls.confirmPassword" [confirmPasswordControl]="form.controls.confirmPassword" />
/>
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" /> <app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
</form> </form>
@@ -0,0 +1 @@
<shared-change-password-form-dialog [(visible)]="visible" [loading]="submitLoading()" (onSubmit)="submit($event)" />
@@ -0,0 +1,34 @@
import { ToastService } from '@/core/services/toast.service';
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
import { ChangePasswordFormDialogComponent } from '@/shared/components';
import { Component, inject, signal } from '@angular/core';
import { finalize } from 'rxjs';
import { IChangePasswordSubmitPayload } from '../modules/configs/components/changePassword/model';
import { PosChangePasswordService } from '../services/password';
@Component({
selector: 'pos-change-password',
templateUrl: 'change-password.component.html',
imports: [ChangePasswordFormDialogComponent],
})
export class PosChangePasswordComponent extends AbstractDialog {
private readonly service = inject(PosChangePasswordService);
private readonly toastService = inject(ToastService);
submitLoading = signal(false);
submit(payload: IChangePasswordSubmitPayload) {
this.submitLoading.set(true);
this.service
.changePassword(payload.password)
.pipe(finalize(() => this.submitLoading.set(false)))
.subscribe(() => {
this.toastService.success({
text: 'تغییر گذرواژه با موفقیت انجام شد.',
});
this.submitLoading.set(false);
this.close();
});
}
}
@@ -25,32 +25,7 @@
@if (loading()) { @if (loading()) {
<shared-page-loading /> <shared-page-loading />
} @else { } @else if (error()) {
<!-- <div class="w-svw h-svh bg-surface-ground flex flex-col gap-4 p-4"> -->
<!-- <div class="w-full flex items-center gap-4 shrink-0 justify-between">
<div class="flex gap-2 items-center">
@if (posInfo()) {
<div class="w-10 h-10">
<img [src]="placeholderLogo" alt="Logo" class="w-full h-full object-cover rounded-md bg-surface-card" />
</div>
<span class="text-lg font-bold">
{{ posInfo()?.name }} ({{ posInfo()?.complex!.name }} - {{ posInfo()?.businessActivity!.name }})
</span>
}
</div>
<div class="flex gap-2 items-center">
<div class="bg-surface-card px-3 rounded-md shadow-sm h-9 flex items-center">
<span [jalaliDate]="now" jalaliFormat="dddd YYYY/MM/DD" class="text-base"></span>
</div>
<div class="">
<p-menu #menu [model]="profileMenuItems" [popup]="true" />
<button pButton (click)="menu.toggle($event)" icon="pi pi-user" severity="contrast">
{{ posProfile()?.account?.username }}
</button>
</div>
</div>
</div> -->
@if (error()) {
@switch (error()?.status) { @switch (error()?.status) {
@case (412) { @case (412) {
<pos-choose-cards class="h-full" (onChoose)="onChoosePos()" /> <pos-choose-cards class="h-full" (onChoose)="onChoosePos()" />
@@ -68,9 +43,9 @@
</div> </div>
} }
} }
} @else { } @else {
<pos-main-menu-sidebar [(visible)]="mainMenuVisible" /> <pos-main-menu-sidebar [(visible)]="mainMenuVisible" />
<pos-change-password [(visible)]="changePasswordVisible" />
<router-outlet></router-outlet> <router-outlet></router-outlet>
}
<!-- </div> -->
} }
<!-- </div> -->
@@ -11,6 +11,7 @@ import { Menu } from 'primeng/menu';
import { finalize } from 'rxjs'; import { finalize } from 'rxjs';
import images from 'src/assets/images'; import images from 'src/assets/images';
import config from 'src/config'; import config from 'src/config';
import { PosChangePasswordComponent } from '../../components/change-password.component';
import { PosInfoStore, PosProfileStore } from '../../store'; import { PosInfoStore, PosProfileStore } from '../../store';
import { DeviceInfoStore } from '../../store/device.store'; import { DeviceInfoStore } from '../../store/device.store';
import { PosMainMenuSidebarComponent } from '../mainMenuSidebar/main-menu-sidebar.component'; import { PosMainMenuSidebarComponent } from '../mainMenuSidebar/main-menu-sidebar.component';
@@ -30,6 +31,7 @@ import { PosChooseCardsComponent } from './choose-pos.component';
CommonModule, CommonModule,
RouterLinkWithHref, RouterLinkWithHref,
RouterOutlet, RouterOutlet,
PosChangePasswordComponent,
], ],
}) })
export class PosPagesLayoutComponent { export class PosPagesLayoutComponent {
@@ -49,6 +51,7 @@ export class PosPagesLayoutComponent {
private readonly layoutService = inject(LayoutService); private readonly layoutService = inject(LayoutService);
mainMenuVisible = signal(false); mainMenuVisible = signal(false);
changePasswordVisible = signal(false);
readonly posProfileLoading = computed(() => this.posProfileStore.loading()); readonly posProfileLoading = computed(() => this.posProfileStore.loading());
readonly posProfile = computed(() => this.posProfileStore.entity()); readonly posProfile = computed(() => this.posProfileStore.entity());
@@ -67,12 +70,21 @@ export class PosPagesLayoutComponent {
this.authService.logout(); this.authService.logout();
}; };
showChangePasswordDialog = () => {
this.changePasswordVisible.set(true);
};
profileMenuItems: MenuItem[] = [ profileMenuItems: MenuItem[] = [
{ {
label: 'راهنمای سامانه', label: 'راهنمای سامانه',
icon: 'pi pi-question-circle', icon: 'pi pi-question-circle',
disabled: true, disabled: true,
}, },
{
label: 'تغییر گذرواژه',
icon: 'pi pi-key',
command: this.showChangePasswordDialog,
},
{ {
label: 'خروج', label: 'خروج',
icon: 'pi pi-sign-out', icon: 'pi pi-sign-out',
@@ -97,7 +109,7 @@ export class PosPagesLayoutComponent {
.pipe( .pipe(
finalize(() => { finalize(() => {
this.layoutService.changeFullPageLoading(false); this.layoutService.changeFullPageLoading(false);
}), })
) )
.subscribe(); .subscribe();
}, },
@@ -10,7 +10,6 @@
<pos-config-send-to-fiscal-activation-form class="w-full" /> <pos-config-send-to-fiscal-activation-form class="w-full" />
</div> </div>
</app-card-data> </app-card-data>
<pos-change-password-form class="w-full" />
<app-card-data cardTitle="تنظیمات پرینت صورت‌حساب" class="w-full"> <app-card-data cardTitle="تنظیمات پرینت صورت‌حساب" class="w-full">
<p-message variant="text" severity="info" icon="pi pi-info-circle"> <p-message variant="text" severity="info" icon="pi pi-info-circle">
هریک از موارد زیر را که می‌خواهید در چاپ صورت‌حساب‌ نمایش داده‌ شوند را انتخاب کنید هریک از موارد زیر را که می‌خواهید در چاپ صورت‌حساب‌ نمایش داده‌ شوند را انتخاب کنید
@@ -3,7 +3,6 @@ import { AppCardComponent } from '@/shared/components';
import { Component, computed, inject } from '@angular/core'; import { Component, computed, inject } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Message } from 'primeng/message'; import { Message } from 'primeng/message';
import { PosChangePasswordFormDialogComponent } from '../components/changePassword/form.component';
import { PosConfigGoldPriceFormComponent } from '../components/goldPrice/form.component'; import { PosConfigGoldPriceFormComponent } from '../components/goldPrice/form.component';
import { PosConfigPrintFormComponent } from '../components/print/form.component'; import { PosConfigPrintFormComponent } from '../components/print/form.component';
import { PosConfigRapidInvoiceFormComponent } from '../components/rapidInvoice/form.component'; import { PosConfigRapidInvoiceFormComponent } from '../components/rapidInvoice/form.component';
@@ -19,7 +18,6 @@ import { PosConfigSendToFiscalActivationFormComponent } from '../components/send
PosConfigGoldPriceFormComponent, PosConfigGoldPriceFormComponent,
PosConfigRapidInvoiceFormComponent, PosConfigRapidInvoiceFormComponent,
PosConfigSendToFiscalActivationFormComponent, PosConfigSendToFiscalActivationFormComponent,
PosChangePasswordFormDialogComponent,
], ],
}) })
export class PosConfigPageComponent { export class PosConfigPageComponent {
+14
View File
@@ -0,0 +1,14 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class PosChangePasswordService {
constructor(private readonly http: HttpClient) {}
changePassword(password: string): Observable<unknown> {
return this.http.put('/api/v1/pos/update-password', { password });
}
}