feat: enhance product and purchase components
- Added new components for handling purchase receipts and payment wrappers. - Updated product details view to include sales count and stock alerts. - Refactored invoice payment form to use a template for better structure. - Introduced confirmation dialog service for payment confirmations. - Improved state card component for better visual representation of orders. - Added loading indicators and error handling in various components. - Updated routes to include new purchase functionality for suppliers. - Enhanced stock alert component to visually indicate low stock levels.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
<p-confirmdialog #cd>
|
||||
<ng-template #headless let-message let-onAccept="onAccept" let-onReject="onReject">
|
||||
@if (message) {
|
||||
<div class="flex flex-col items-center p-8 bg-surface-0 dark:bg-surface-900 rounded">
|
||||
<div
|
||||
class="rounded-full bg-primary text-primary-contrast inline-flex justify-center items-center h-24 w-24 -mt-20"
|
||||
>
|
||||
<i class="pi pi-question text-5xl!"></i>
|
||||
</div>
|
||||
<span class="font-bold text-2xl block mb-2 mt-6">{{ message.header }}</span>
|
||||
<p class="mb-0">{{ message.message }}</p>
|
||||
<div class="flex items-center gap-2 mt-6">
|
||||
<p-button label="{{ acceptLabel }}" (onClick)="onAccept()" styleClass="w-32"></p-button>
|
||||
<p-button label="{{ rejectLabel }}" [outlined]="true" (onClick)="onReject()" styleClass="w-32"></p-button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</ng-template>
|
||||
</p-confirmdialog>
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core';
|
||||
import { ConfirmationService } from 'primeng/api';
|
||||
import { Button } from 'primeng/button';
|
||||
import { ConfirmDialog } from 'primeng/confirmdialog';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shared-confirmation-dialog',
|
||||
templateUrl: './confirmation-dialog.component.html',
|
||||
providers: [ConfirmationService],
|
||||
imports: [ConfirmDialog, Button],
|
||||
})
|
||||
export class ConfirmationDialogComponent implements OnDestroy {
|
||||
@Input() message!: string;
|
||||
@Input() header: string = 'تأیید عملیات';
|
||||
@Input() acceptLabel: string = 'بله';
|
||||
@Input() rejectLabel: string = 'خیر';
|
||||
@Output() onAccept = new EventEmitter<void>();
|
||||
@Output() onReject = new EventEmitter<void>();
|
||||
|
||||
constructor(private confirmationService: ConfirmationService) {}
|
||||
|
||||
show() {
|
||||
this.confirmationService.confirm({
|
||||
header: this.header,
|
||||
message: this.message,
|
||||
acceptLabel: this.acceptLabel,
|
||||
rejectLabel: this.rejectLabel,
|
||||
accept: () => {
|
||||
this.accept();
|
||||
},
|
||||
reject: () => {
|
||||
this.reject();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
accept() {
|
||||
this.onAccept.emit();
|
||||
}
|
||||
|
||||
reject() {
|
||||
this.onReject.emit();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
// Cleanup if needed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import {
|
||||
ApplicationRef,
|
||||
ComponentFactoryResolver,
|
||||
ComponentRef,
|
||||
Injectable,
|
||||
Injector,
|
||||
} from '@angular/core';
|
||||
import { ConfirmationDialogComponent } from './confirmation-dialog.component';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ConfirmationDialogService {
|
||||
private componentRef: ComponentRef<ConfirmationDialogComponent> | null = null;
|
||||
|
||||
constructor(
|
||||
private componentFactoryResolver: ComponentFactoryResolver,
|
||||
private appRef: ApplicationRef,
|
||||
private injector: Injector,
|
||||
) {}
|
||||
|
||||
confirm(options: {
|
||||
message: string;
|
||||
header?: string;
|
||||
acceptLabel?: string;
|
||||
rejectLabel?: string;
|
||||
accept?: () => void;
|
||||
reject?: () => void;
|
||||
}) {
|
||||
// Create the component dynamically
|
||||
const factory = this.componentFactoryResolver.resolveComponentFactory(
|
||||
ConfirmationDialogComponent,
|
||||
);
|
||||
this.componentRef = factory.create(this.injector);
|
||||
|
||||
// Set inputs
|
||||
this.componentRef.instance.message = options.message;
|
||||
if (options.header) this.componentRef.instance.header = options.header;
|
||||
if (options.acceptLabel) this.componentRef.instance.acceptLabel = options.acceptLabel;
|
||||
if (options.rejectLabel) this.componentRef.instance.rejectLabel = options.rejectLabel;
|
||||
|
||||
// Subscribe to outputs and close after
|
||||
if (options.accept) {
|
||||
this.componentRef.instance.onAccept.subscribe(() => {
|
||||
options.accept!();
|
||||
this.close();
|
||||
});
|
||||
} else {
|
||||
this.componentRef.instance.onAccept.subscribe(() => this.close());
|
||||
}
|
||||
if (options.reject) {
|
||||
this.componentRef.instance.onReject.subscribe(() => {
|
||||
options.reject!();
|
||||
this.close();
|
||||
});
|
||||
} else {
|
||||
this.componentRef.instance.onReject.subscribe(() => this.close());
|
||||
}
|
||||
|
||||
// Attach to the app
|
||||
this.appRef.attachView(this.componentRef.hostView);
|
||||
|
||||
// Append to body
|
||||
document.body.appendChild(this.componentRef.location.nativeElement);
|
||||
|
||||
// Trigger change detection and show
|
||||
this.componentRef.changeDetectorRef.detectChanges();
|
||||
this.componentRef.instance.show();
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.componentRef) {
|
||||
this.appRef.detachView(this.componentRef.hostView);
|
||||
this.componentRef.destroy();
|
||||
this.componentRef = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user