feat(purchases): implement purchase receipt functionality with form and receipt template

- Added `ProductPurchaseComponent` to handle product purchases.
- Created `PurchaseReceiptTemplateComponent` for displaying purchase receipt details.
- Developed `PurchaseFormComponent` for managing purchase form inputs and submission.
- Introduced `ProductChargeRowFormComponent` and `ProductChargeRowFormFieldsComponent` for handling product charge rows in the form.
- Implemented `PurchaseReceiptProductRowComponent` for displaying individual product rows in the receipt.
- Established API routes for purchase operations in `apiRoutes`.
- Integrated suppliers and inventories selection components.
- Added utility functions for converting prices to Persian alphabet.
- Created a utility for generating full names from name parts.
- Enhanced form validation and submission handling in the purchase form.
- Updated styles and templates for improved UI/UX.
This commit is contained in:
2025-12-09 20:17:00 +03:30
parent abf53bac03
commit 50bc9a4632
77 changed files with 1807 additions and 18834 deletions
+1
View File
@@ -1,6 +1,7 @@
export * from './breadcrumb.component';
export * from './card-data.component';
export * from './inlineConfirmation/inline-confirmation.component';
export * from './inlineEdit/inline-edit.component';
export * from './input/input.component';
export * from './key-value.component/key-value.component';
export * from './table-action-row.component';
@@ -0,0 +1,22 @@
<div class="flex items-stretch gap-2">
<div class="shrink-0 flex items-center">
@if (editMode()) {
<ng-container [ngTemplateOutlet]="field"></ng-container>
} @else {
<ng-container [ngTemplateOutlet]="data"></ng-container>
}
</div>
<div class="relative shrink-0">
<div class="static end-0 top-0">
<button
pButton
size="small"
type="button"
[icon]="'pi ' + (editMode() ? 'pi-times' : 'pi-pencil')"
text
severity="secondary"
(click)="toggleEditMode()"
></button>
</div>
</div>
</div>
@@ -0,0 +1,20 @@
import { CommonModule } from '@angular/common';
import { Component, ContentChild, signal, TemplateRef } from '@angular/core';
import { ButtonDirective } from 'primeng/button';
@Component({
selector: 'shared-inline-edit',
templateUrl: './inline-edit.component.html',
imports: [CommonModule, ButtonDirective],
})
export class InlineEditComponent {
constructor() {}
editMode = signal<boolean>(false);
@ContentChild('data', { static: true }) data?: TemplateRef<any>;
@ContentChild('field', { static: true }) field?: TemplateRef<any>;
toggleEditMode() {
this.editMode.set(!this.editMode());
}
}
@@ -1,4 +1,4 @@
<uikit-field [label]="label" [name]="name" [control]="control">
<uikit-field [label]="label" [name]="name" [control]="control" [showLabel]="!!label" [showErrors]="showErrors">
@if (type === "switch") {
<p-toggleSwitch [formControl]="control" />
} @else {
@@ -23,6 +23,7 @@ export class InputComponent {
@Input() disabled = false;
@Input() size?: 'small' | 'large';
@Input() autocomplete?: string = 'off';
@Input() showErrors = false;
@Output() valueChange = new EventEmitter<string>();
onInput(ev: Event) {
@@ -17,14 +17,14 @@ import { SkeletonModule } from 'primeng/skeleton';
import { TableModule } from 'primeng/table';
import { TableActionRowComponent } from '../table-action-row.component';
export interface IColumn {
field: string;
export interface IColumn<T = any> {
field: T extends object ? keyof T | string : string;
header: string;
width?: string;
minWidth?: string;
canCopy?: boolean;
type?: 'text' | 'price' | 'boolean' | 'date';
customDataModel?: TemplateRef<any> | ((item: any) => string | number | boolean);
customDataModel?: TemplateRef<any> | ((item: T) => string | number | boolean);
}
@Component({
@@ -120,7 +120,7 @@ export class PageDataListComponent<I> {
if (column.customDataModel) {
return this.renderCustom(column, item);
}
const data = item[field];
const data = item[String(field)];
switch (column.type) {
case 'date':
if (!data) return '-';
@@ -20,6 +20,6 @@
/>
}
@if (showDetails) {
<p-button size="small" icon="pi pi-chevron-left" variant="outlined" (click)="details.emit()" title="جزئیات" />
<p-button size="small" icon="pi pi-chevron-left" (click)="details.emit()" title="جزئیات" />
}
</td>