feat: implement invoice payments component and integrate with supplier invoices

This commit is contained in:
2025-12-29 10:14:28 +03:30
parent 2583bc7ad5
commit 85a9c8714d
24 changed files with 268 additions and 47 deletions
@@ -63,8 +63,6 @@ export class CardexFiltersComponent {
this.store.setDefaultInventory(inventory); this.store.setDefaultInventory(inventory);
} }
setDefaultProduct(product: IProductResponse) { setDefaultProduct(product: IProductResponse) {
console.log('setDefaultProduct');
this.store.setDefaultProduct(product); this.store.setDefaultProduct(product);
} }
} }
+27 -14
View File
@@ -17,6 +17,7 @@ export interface CardexState extends PaginatedState<ICardexResponse> {
selectedProduct: Maybe<ICardexProductSummary>; selectedProduct: Maybe<ICardexProductSummary>;
variant: 'inventory' | 'product' | 'general'; variant: 'inventory' | 'product' | 'general';
canChangeVariant: boolean; canChangeVariant: boolean;
cardexTitle: string;
} }
@Injectable({ @Injectable({
@@ -63,6 +64,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
selectedProduct: null, selectedProduct: null,
variant: 'general', variant: 'general',
canChangeVariant: true, canChangeVariant: true,
cardexTitle: 'کاردکس',
}); });
this.initial(); this.initial();
} }
@@ -70,18 +72,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
readonly filters = computed(() => this._state().filters); readonly filters = computed(() => this._state().filters);
readonly variant = computed(() => this._state().variant); readonly variant = computed(() => this._state().variant);
readonly canChangeVariant = computed(() => this._state().canChangeVariant); readonly canChangeVariant = computed(() => this._state().canChangeVariant);
readonly cardexTitle = computed(() => { readonly cardexTitle = computed(() => this._state().cardexTitle);
switch (this._state().variant) {
case 'product':
return `کاردکس کالای ${this._state().selectedProduct?.name}`;
case 'inventory':
return `کاردکس انبار ${this._state().selectedInventory?.name}`;
default:
return `کاردکس ${this._state().selectedProduct ? 'کالای ' + this._state().selectedProduct?.name : ''} ${
this._state().selectedInventory ? 'در انبار ' + this._state().selectedInventory?.name : ''
}`;
}
});
/** /**
* Reset state to initial values * Reset state to initial values
@@ -109,6 +100,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
selectedProduct: null, selectedProduct: null,
variant: 'general', variant: 'general',
canChangeVariant: this.state().canChangeVariant, canChangeVariant: this.state().canChangeVariant,
cardexTitle: 'کاردکس',
}); });
} }
@@ -155,8 +147,6 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
updateFilter(filters: ICardexRequestPayload) { updateFilter(filters: ICardexRequestPayload) {
this.updateVariant(); this.updateVariant();
console.log('filters');
console.log(filters);
const cleanedFilters = this.validateFilters() || {}; const cleanedFilters = this.validateFilters() || {};
this.router this.router
@@ -169,6 +159,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
console.log(err); console.log(err);
}); });
this.patchState({ filters }); this.patchState({ filters });
this.updateCardexTitle();
} }
setProduct(product: Maybe<ICardexProductSummary>) { setProduct(product: Maybe<ICardexProductSummary>) {
@@ -184,10 +175,12 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
setDefaultInventory(inventory: ICardexInventorySummary) { setDefaultInventory(inventory: ICardexInventorySummary) {
this.patchState({ selectedInventory: inventory }); this.patchState({ selectedInventory: inventory });
this.updateCardexTitle();
} }
setDefaultProduct(product: ICardexProductSummary) { setDefaultProduct(product: ICardexProductSummary) {
this.patchState({ selectedProduct: product }); this.patchState({ selectedProduct: product });
this.updateCardexTitle();
} }
private updateVariant() { private updateVariant() {
@@ -201,7 +194,27 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
} else if (productIsSelected) { } else if (productIsSelected) {
variant = 'product'; variant = 'product';
} }
this.updateCardexTitle();
this.patchState({ variant }); this.patchState({ variant });
} }
updateCardexTitle() {
let title = '';
switch (this._state().variant) {
case 'product':
title = `کاردکس کالای ${this._state().selectedProduct?.name}`;
break;
case 'inventory':
title = `کاردکس انبار ${this._state().selectedInventory?.name}`;
break;
default:
title = `کاردکس ${this._state().selectedProduct ? 'کالای ' + this._state().selectedProduct?.name : ''} ${
this._state().selectedInventory ? 'در انبار ' + this._state().selectedInventory?.name : ''
}`;
break;
}
this.patchState({ cardexTitle: title });
}
} }
@@ -29,6 +29,10 @@ export class InventoryBankAccountSelectComponent extends AbstractSelectComponent
constructor(private service: InventoryBankAccountsService) { constructor(private service: InventoryBankAccountsService) {
super(); super();
}
ngOnInit() {
console.log(this.inventoryId);
this.getData(); this.getData();
} }
@@ -1,15 +1,7 @@
import { NamedRoutes } from '@/core'; import { NamedRoutes } from '@/core';
import { Routes } from '@angular/router'; import { Routes } from '@angular/router';
export type TInventoriesRouteNames = export const inventoriesNamedRoutes: NamedRoutes<any> = {
| 'inventories'
| 'inventory'
| 'transfer'
| 'products'
| 'productCardex'
| 'posAccounts';
export const inventoriesNamedRoutes: NamedRoutes<TInventoriesRouteNames> = {
inventories: { inventories: {
path: 'inventories', path: 'inventories',
loadComponent: () => import('../../views/list.component').then((m) => m.InventoriesComponent), loadComponent: () => import('../../views/list.component').then((m) => m.InventoriesComponent),
@@ -65,6 +57,17 @@ export const inventoriesNamedRoutes: NamedRoutes<TInventoriesRouteNames> = {
pagePath: () => '/inventories/:inventoryId/pos-accounts', pagePath: () => '/inventories/:inventoryId/pos-accounts',
}, },
}, },
}; purchase: {
path: 'inventories/:inventoryId/purchase',
loadComponent: () =>
import('../../views/purchase.component').then((m) => m.InventoryPurchaseComponent),
meta: {
title: 'ثبت خرید در انبار',
pagePath: () => '/inventories/:inventoryId/purchase',
},
},
} as const;
export type TInventoriesRouteNames = keyof typeof inventoriesNamedRoutes;
export const INVENTORIES_ROUTES: Routes = Object.values(inventoriesNamedRoutes); export const INVENTORIES_ROUTES: Routes = Object.values(inventoriesNamedRoutes);
@@ -21,3 +21,24 @@ export interface IInventoryBankAccountRequest extends IBankAccountsRequest {}
export interface IInventoryAssignBankAccountRequest { export interface IInventoryAssignBankAccountRequest {
bankAccountId: number; bankAccountId: number;
} }
export interface IBankAccountSummary {
branch: Branch;
accountNumber: string;
cardNumber: string;
name: string;
id: number;
iban: string;
}
interface Branch {
id: number;
name: string;
bank: Bank;
}
interface Bank {
id: number;
name: string;
shortName: string;
}
@@ -43,10 +43,13 @@ export class InventoryStore extends EntityStore<IInventoryDetailResponse, Invent
this.patchState({ loading: true }); this.patchState({ loading: true });
this.service.getSingle(inventoryId).subscribe({ this.service.getSingle(inventoryId).subscribe({
next: (res) => { next: (res) => {
console.log('first');
this.patchState({ this.patchState({
entities: { [res.id]: res }, entities: { [res.id]: res },
loading: false, loading: false,
}); });
console.log(this.entities());
}, },
error: (err) => { error: (err) => {
this.patchState({ loading: false, error: err }); this.patchState({ loading: false, error: err });
@@ -0,0 +1,4 @@
@if (loading()) {
} @else {
<purchase-receipt-template [inventory]="inventory()" />
}
@@ -0,0 +1,22 @@
import { PurchaseReceiptTemplateComponent } from '@/modules/purchases/components';
import { Component, computed, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { InventoryStore } from '../store/inventory.store';
@Component({
selector: 'app-inventory-purchase',
templateUrl: './purchase.component.html',
imports: [PurchaseReceiptTemplateComponent],
})
export class InventoryPurchaseComponent {
private readonly route = inject(ActivatedRoute);
private readonly store = inject(InventoryStore);
inventoryId = this.route.snapshot.paramMap.get('inventoryId')!;
inventory = computed(() => this.store.entities()[this.inventoryId]);
loading = this.store.loading;
constructor() {
this.store.getSingle(this.inventoryId);
}
}
@@ -14,14 +14,19 @@
icon="pi pi-plus" icon="pi pi-plus"
[routerLink]="['/inventories', inventoryId, 'pos-accounts']" [routerLink]="['/inventories', inventoryId, 'pos-accounts']"
></button> ></button>
<button pButton type="button" label="افزایش موجودی" icon="pi pi-plus"></button> <button
<!-- [routerLink]="['/inventories', inventoryId, 'purchase']" --> pButton
type="button"
label="افزایش موجودی"
icon="pi pi-plus"
[routerLink]="['/inventories', inventoryId, 'purchase']"
></button>
<button <button
pButton pButton
type="button" type="button"
label="انتقال کالا" label="انتقال کالا"
icon="pi pi-plus" icon="pi pi-plus"
[routerLink]="['/inventories', inventoryId, 'transfer']" [routerLink]="['/inventories', 'transfer']"
></button> ></button>
<button pButton type="button" label="ویرایش" icon="pi pi-pencil"></button> <button pButton type="button" label="ویرایش" icon="pi pi-pencil"></button>
<!-- [routerLink]="['/inventories', inventoryId, 'update']" --> <!-- [routerLink]="['/inventories', inventoryId, 'update']" -->
@@ -151,8 +151,8 @@
<span class="font-bold" [appPriceMask]="totalAmount"></span> <span class="font-bold" [appPriceMask]="totalAmount"></span>
</div> </div>
<div class="flex justify-between"> <div class="flex justify-between">
<span>مالیات (۹٪):</span> <span>مالیات (۱۰٪):</span>
<span class="font-bold" [appPriceMask]="totalAmount * 0.09"></span> <span class="font-bold" [appPriceMask]="totalAmount * 0.1"></span>
</div> </div>
</div> </div>
</td> </td>
@@ -161,12 +161,12 @@
<td [attr.colspan]="6" class="p-0! border-none!"> <td [attr.colspan]="6" class="p-0! border-none!">
<div class="w-full flex items-center gap-2 py-10 border-surface-700 border-t-4"> <div class="w-full flex items-center gap-2 py-10 border-surface-700 border-t-4">
<span>مبلغ قابل پرداخت:</span> <span>مبلغ قابل پرداخت:</span>
<span [appPriceAlphabet]="totalAmount + totalAmount * 0.09" class="font-bold text-lg"></span> <span [appPriceAlphabet]="totalAmount + totalAmount * 0.1" class="font-bold text-lg"></span>
</div> </div>
</td> </td>
<td [attr.colspan]="2" class="p-0! border-none!"> <td [attr.colspan]="2" class="p-0! border-none!">
<div class="flex h-full items-center justify-end py-10 px-2 border-surface-700 border-t-4 border-r"> <div class="flex h-full items-center justify-end py-10 px-2 border-surface-700 border-t-4 border-r">
<span [appPriceMask]="totalAmount + totalAmount * 0.09" class="text-xl font-bold"></span> <span [appPriceMask]="totalAmount + totalAmount * 0.1" class="text-xl font-bold"></span>
</div> </div>
</td> </td>
</tr> </tr>
@@ -10,7 +10,7 @@ import { IColumn } from '@/shared/components/pageDataList/page-data-list.compone
import { PriceAlphabetDirective, PriceMaskDirective } from '@/shared/directives'; import { PriceAlphabetDirective, PriceMaskDirective } from '@/shared/directives';
import { UikitFlatpickrJalaliComponent } from '@/uikit'; import { UikitFlatpickrJalaliComponent } from '@/uikit';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component, inject, Input, signal } from '@angular/core'; import { Component, effect, inject, Input, signal } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { ButtonDirective } from 'primeng/button'; import { ButtonDirective } from 'primeng/button';
@@ -130,6 +130,15 @@ export class PurchaseReceiptTemplateComponent {
this.form.controls.paidAmount.setValue(0); this.form.controls.paidAmount.setValue(0);
} }
}); });
effect(() => {
if (this.inventory) {
this.form.controls.inventory.setValue(this.inventory);
}
if (this.supplier) {
this.form.controls.supplier.setValue(this.supplier);
}
});
} }
formIsSubmitted = signal(false); formIsSubmitted = signal(false);
@@ -0,0 +1,5 @@
<app-page-data-list [items]="items()" [columns]="columns" [loading]="loading()" pageTitle="پرداخت‌های فاکتور">
<ng-template #paymentMethodTpl let-item>
<app-catalog-payment-method-type-tag [type]="item.paymentMethod" />
</ng-template>
</app-page-data-list>
@@ -0,0 +1,75 @@
import { CatalogPaymentMethodTypeTagComponent } from '@/shared/catalog/paymentMethodTypes';
import {
IColumn,
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { Component, Input, signal, TemplateRef, ViewChild } from '@angular/core';
import { IInvoicePaymentResponse } from '../../models/invoices.io';
import { SupplierInvoicesService } from '../../services';
@Component({
selector: 'app-invoice-payments',
templateUrl: './payments.component.html',
imports: [PageDataListComponent, CatalogPaymentMethodTypeTagComponent],
})
export class InvoicePaymentsComponent {
@Input() supplierId!: string;
@Input() invoiceId!: string;
@ViewChild('paymentMethodTpl', { static: true }) paymentMethodTpl!: TemplateRef<any>;
constructor(private readonly service: SupplierInvoicesService) {}
columns = [] as IColumn[];
ngOnInit() {
console.log(this.invoiceId);
this.columns = [
{
field: 'index',
header: 'ردیف',
type: 'index',
},
{
field: 'code',
header: 'شناسه پرداخت',
},
{
field: 'amount',
header: 'مبلغ پرداختی',
type: 'price',
},
{
field: 'paymentMethod',
header: 'روش پرداخت',
customDataModel: this.paymentMethodTpl,
},
{
field: 'bankAccount',
header: 'حساب بانکی',
customDataModel: (item: IInvoicePaymentResponse) =>
`${item.bankAccount.name} - بانک ${item.bankAccount.branch.bank.name} - شعبه ${item.bankAccount.branch.name}`,
},
{
field: 'payedAt',
header: 'تاریخ پرداخت',
type: 'date',
},
];
this.getData();
}
items = signal<IInvoicePaymentResponse[]>([]);
loading = signal(false);
getData() {
this.loading.set(true);
return this.service.getPayments(this.supplierId!, this.invoiceId!).subscribe({
next: (res) => {
this.items.set(res.data);
this.loading.set(false);
},
error: (err) => {
this.loading.set(false);
},
});
}
}
@@ -4,7 +4,7 @@
<span class="text-xl font-bold">دفتر کل تامین‌کننده</span> <span class="text-xl font-bold">دفتر کل تامین‌کننده</span>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
@if (showViewAllCTA) { @if (showViewAllCTA) {
<button pButton outlined [routerLink]="['/suppliers', supplierId, 'ledger']">مشاهده‌ی تمامی تراکنش‌ها</button> <button pButton outlined [routerLink]="['/suppliers', supplierId, 'ledger']">مشاهده‌ی دفتر کل</button>
} }
<button pButton outlined icon="pi pi-refresh" [loading]="loading()" (click)="getAll()"></button> <button pButton outlined icon="pi pi-refresh" [loading]="loading()" (click)="getAll()"></button>
</div> </div>
@@ -33,7 +33,7 @@
<ng-template pTemplate="emptymessage"> <ng-template pTemplate="emptymessage">
<tr> <tr>
<td colspan="7" class="text-center! p-10!">هیچ فاکتوری ثبت نشده است.</td> <td colspan="7" class="text-center! p-10!">هیچ رکوردی ثبت نشده است.</td>
</tr> </tr>
</ng-template> </ng-template>
</p-table> </p-table>
@@ -4,5 +4,7 @@ export const SUPPLIER_INVOICES_API_ROUTES = (_baseUrl: string) => {
list: (supplierId: string) => `${baseUrl(supplierId)}`, list: (supplierId: string) => `${baseUrl(supplierId)}`,
single: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}`, single: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}`,
pay: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}/pay`, pay: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}/pay`,
invoicePayments: (supplierId: string, invoiceId: string) =>
`${baseUrl(supplierId)}/${invoiceId}/payments`,
}; };
}; };
@@ -1,8 +1,9 @@
import ISummary from '@/core/models/summary'; import ISummary from '@/core/models/summary';
import { IBankAccountSummary } from '@/modules/inventories/models';
import { PurchaseReceiptStatus } from '@/shared/catalog'; import { PurchaseReceiptStatus } from '@/shared/catalog';
import { PaymentMethodType } from '@/shared/catalog/paymentMethodTypes'; import { PaymentMethodType } from '@/shared/catalog/paymentMethodTypes';
import { PaymentType } from '@/shared/catalog/paymentTypes'; import { PaymentType } from '@/shared/catalog/paymentTypes';
import { ISupplierReceiptItemSummary } from './types'; import { IReceiptInfo, ISupplierReceiptItemSummary } from './types';
export interface ISupplierInvoicesRawResponse { export interface ISupplierInvoicesRawResponse {
id: number; id: number;
@@ -37,3 +38,18 @@ export interface IPayRawResponse {
description?: string; description?: string;
} }
export interface IPayResponse extends IPayRawResponse {} export interface IPayResponse extends IPayRawResponse {}
export interface IInvoicePaymentRawResponse {
id: number;
amount: string;
paymentMethod: string;
type: string;
bankAccountId: number;
payedAt: string;
description: null;
createdAt: string;
receipt: IReceiptInfo;
bankAccount: IBankAccountSummary;
}
export interface IInvoicePaymentResponse extends IInvoicePaymentRawResponse {}
+16
View File
@@ -1,3 +1,5 @@
import ISummary from '@/core/models/summary';
export interface IReceiptsOverview { export interface IReceiptsOverview {
totalPayment: string; totalPayment: string;
count: number; count: number;
@@ -19,3 +21,17 @@ export interface ISupplierReceiptItemSummary {
sku: string; sku: string;
}; };
} }
export interface IReceiptInfo {
id: number;
code: string;
totalAmount: string;
paidAmount: string;
description: string;
createdAt: string;
updatedAt: string;
status: string;
supplierId: number;
inventoryId: number;
inventory: ISummary;
}
@@ -4,6 +4,8 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { SUPPLIERS_API_ROUTES } from '../constants'; import { SUPPLIERS_API_ROUTES } from '../constants';
import { import {
IInvoicePaymentRawResponse,
IInvoicePaymentResponse,
IPayRawResponse, IPayRawResponse,
IPayRequestPayload, IPayRequestPayload,
IPayResponse, IPayResponse,
@@ -36,4 +38,13 @@ export class SupplierInvoicesService {
): Observable<IPayResponse> { ): Observable<IPayResponse> {
return this.http.post<IPayRawResponse>(this.apiRoutes.pay(supplierId, invoiceId), payload); return this.http.post<IPayRawResponse>(this.apiRoutes.pay(supplierId, invoiceId), payload);
} }
getPayments(
supplierId: string,
invoiceId: string,
): Observable<IPaginatedResponse<IInvoicePaymentResponse>> {
return this.http.get<IPaginatedResponse<IInvoicePaymentRawResponse>>(
this.apiRoutes.invoicePayments(supplierId, invoiceId),
);
}
} }
@@ -21,6 +21,7 @@
</app-key-value> </app-key-value>
</div> </div>
</div> </div>
<app-invoice-payments [supplierId]="supplierId" [invoiceId]="invoiceId" />
@if (invoice() && supplier()) { @if (invoice() && supplier()) {
<app-supplier-invoice-pay-form <app-supplier-invoice-pay-form
[(visible)]="showPayForm" [(visible)]="showPayForm"
@@ -5,6 +5,7 @@ import { Component, computed, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { ButtonDirective } from 'primeng/button'; import { ButtonDirective } from 'primeng/button';
import { SupplierInvoicePayFormComponent } from '../components/invoices/pay-form.component'; import { SupplierInvoicePayFormComponent } from '../components/invoices/pay-form.component';
import { InvoicePaymentsComponent } from '../components/invoices/payments.component';
import { SupplierInvoiceStore, SupplierStore } from '../store'; import { SupplierInvoiceStore, SupplierStore } from '../store';
@Component({ @Component({
@@ -16,6 +17,7 @@ import { SupplierInvoiceStore, SupplierStore } from '../store';
CatalogPurchaseReceiptStatusTagComponent, CatalogPurchaseReceiptStatusTagComponent,
ButtonDirective, ButtonDirective,
SupplierInvoicePayFormComponent, SupplierInvoicePayFormComponent,
InvoicePaymentsComponent,
], ],
}) })
export class SupplierInvoiceComponent { export class SupplierInvoiceComponent {
@@ -27,6 +29,7 @@ export class SupplierInvoiceComponent {
this.supplierStore.getSingle(this.supplierId); this.supplierStore.getSingle(this.supplierId);
this.store.supplierId = this.supplierId; this.store.supplierId = this.supplierId;
this.store.getSingle(this.invoiceId); this.store.getSingle(this.invoiceId);
console.log(this.supplierId);
} }
supplierId = this.route.snapshot.params['supplierId']; supplierId = this.route.snapshot.params['supplierId'];
@@ -1,14 +1,16 @@
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<app-inner-pages-header [pageTitle]="pageTitle()" [backRoute]="['/suppliers', supplierId]" /> <app-inner-pages-header [pageTitle]="pageTitle()" [backRoute]="['/suppliers', supplierId]" />
<div class="inline-flex items-center gap-5"> <div class="inline-flex items-center gap-5">
<div class=""> @if (supplier()) {
<app-key-value label="شماره تماس" [value]="supplier()?.mobileNumber" /> <div class="">
</div> <app-key-value label="شماره تماس" [value]="supplier().mobileNumber" />
</div>
}
</div> </div>
<div class="mt-5"> <div class="mt-5">
<div class="grid grid-cols-4 gap-4"> <div class="grid grid-cols-4 gap-4">
@for (item of topBarCardDetails; track $index) { @for (item of topBarCardDetails; track $index) {
<details-info-card [icon]="item.icon" [label]="item.label" [value]="item.value?.toString() || ''" /> <details-info-card [icon]="item.icon" [label]="item.label" [value]="item.value.toString() || ''" />
} }
</div> </div>
</div> </div>
@@ -1,5 +1,4 @@
import { Maybe } from '@/core'; import { Maybe } from '@/core';
import { PriceMaskDirective } from '@/shared/directives';
import { UikitFieldComponent } from '@/uikit/uikit-field.component'; import { UikitFieldComponent } from '@/uikit/uikit-field.component';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Component, EventEmitter, Input, Output } from '@angular/core';
@@ -20,7 +19,6 @@ import { ToggleSwitch } from 'primeng/toggleswitch';
InputGroupModule, InputGroupModule,
UikitFieldComponent, UikitFieldComponent,
ToggleSwitch, ToggleSwitch,
PriceMaskDirective,
InputGroupAddon, InputGroupAddon,
InputNumberModule, InputNumberModule,
], ],
@@ -41,7 +41,15 @@
<ng-template #header let-columns> <ng-template #header let-columns>
<tr> <tr>
@for (col of columns; track col.header) { @for (col of columns; track col.header) {
<th [style]="{ width: col.width, minWidth: col.minWidth }">{{ col.header }}</th> <th
[style]="
col.type === 'index'
? { width: '3rem', minWidth: '3rem' }
: { width: col.width, minWidth: col.minWidth }
"
>
{{ col.header }}
</th>
} }
@if (actionsCount()) { @if (actionsCount()) {
<th type="th" [style]="{ width: `${actionsCount() * 2 + (actionsCount() - 1) * 0.25}rem` }"></th> <th type="th" [style]="{ width: `${actionsCount() * 2 + (actionsCount() - 1) * 0.25}rem` }"></th>
@@ -49,11 +57,13 @@
</tr> </tr>
</ng-template> </ng-template>
<ng-template #body let-item> <ng-template #body let-item let-i="rowIndex">
<tr> <tr>
@for (col of columns; track col.field) { @for (col of columns; track col.field) {
<td> <td>
@if (getTemplate(col)) { @if (col.type === "index") {
{{ i * (currentPage || 1) + 1 }}
} @else if (getTemplate(col)) {
<ng-container <ng-container
[ngTemplateOutlet]="getTemplate(col)" [ngTemplateOutlet]="getTemplate(col)"
[ngTemplateOutletContext]="{ $implicit: item }" [ngTemplateOutletContext]="{ $implicit: item }"
@@ -24,7 +24,7 @@ export interface IColumn<T = any> {
width?: string; width?: string;
minWidth?: string; minWidth?: string;
canCopy?: boolean; canCopy?: boolean;
type?: 'text' | 'price' | 'boolean' | 'date' | 'nested'; type?: 'text' | 'price' | 'boolean' | 'date' | 'nested' | 'index';
nestedPath?: string; nestedPath?: string;
customDataModel?: TemplateRef<any> | ((item: T) => string | number | boolean); customDataModel?: TemplateRef<any> | ((item: T) => string | number | boolean);
} }