Refactor nested column definitions and improve license info handling
- Updated column definitions in various components to use `nestedOption` instead of `nestedPath` for better clarity and consistency. - Removed commented-out license status checks and related UI elements from the layout component. - Simplified license info interface by removing unnecessary properties. - Enhanced consumer accounts and business activities components to display additional license information. - Adjusted form components to conditionally include fields based on selected device type. - Improved the handling of discount calculations in the gold payload form component. - Added new fields for branch code in complex components and adjusted related views. - Cleaned up unused console logs in form data utility.
This commit is contained in:
@@ -44,7 +44,9 @@ export class ConsumerSaleInvoiceSharedComponent {
|
|||||||
field: 'name',
|
field: 'name',
|
||||||
header: 'عنوان',
|
header: 'عنوان',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'good.name',
|
nestedOption: {
|
||||||
|
path: 'good.name',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'unit_price',
|
field: 'unit_price',
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[closable]="true"
|
[closable]="true"
|
||||||
(onHide)="close()"
|
(onHide)="close()"
|
||||||
>
|
>
|
||||||
@if (!licenseStatus()) {
|
<!-- @if (!licenseStatus()) {
|
||||||
<p-message severity="warn" [closable]="false" variant="text" icon="pi pi-info-circle" class="mb-5">
|
<p-message severity="warn" [closable]="false" variant="text" icon="pi pi-info-circle" class="mb-5">
|
||||||
برای کاربر شما لایسنسی در نظر گرفته نشده است. برای پیگیری با پشتیبانی تماس بگیرید.
|
برای کاربر شما لایسنسی در نظر گرفته نشده است. برای پیگیری با پشتیبانی تماس بگیرید.
|
||||||
</p-message>
|
</p-message>
|
||||||
@@ -21,5 +21,5 @@
|
|||||||
<app-key-value label="انقضای لایسنس" [value]="license()?.expires_at!" type="date" />
|
<app-key-value label="انقضای لایسنس" [value]="license()?.expires_at!" type="date" />
|
||||||
<app-key-value label="ارایه شده توسط" [value]="license()?.partner?.name || 'برند نرمافزار'" />
|
<app-key-value label="ارایه شده توسط" [value]="license()?.partner?.name || 'برند نرمافزار'" />
|
||||||
</div>
|
</div>
|
||||||
}
|
} -->
|
||||||
</p-dialog>
|
</p-dialog>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
import { KeyValueComponent } from '@/shared/components';
|
import { KeyValueComponent } from '@/shared/components';
|
||||||
import { getLicenseStatus } from '@/utils';
|
import { Component, inject } from '@angular/core';
|
||||||
import { Component, computed, inject } from '@angular/core';
|
|
||||||
import { Dialog } from 'primeng/dialog';
|
import { Dialog } from 'primeng/dialog';
|
||||||
import { Message } from 'primeng/message';
|
import { Message } from 'primeng/message';
|
||||||
import { ConsumerStore } from '../store/main.store';
|
import { ConsumerStore } from '../store/main.store';
|
||||||
@@ -14,7 +13,7 @@ import { ConsumerStore } from '../store/main.store';
|
|||||||
export class ConsumerLicenseInfoDialogComponent extends AbstractDialog {
|
export class ConsumerLicenseInfoDialogComponent extends AbstractDialog {
|
||||||
private readonly store = inject(ConsumerStore);
|
private readonly store = inject(ConsumerStore);
|
||||||
|
|
||||||
license = computed(() => this.store.entity()?.license_info);
|
// license = computed(() => this.store.entity()?.license_info);
|
||||||
|
|
||||||
licenseStatus = computed(() => getLicenseStatus(getLicenseStatus(this.license()?.expires_at)));
|
// licenseStatus = computed(() => getLicenseStatus(getLicenseStatus(this.license()?.expires_at)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,13 @@ export const columns: IColumn[] = [
|
|||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'serial', header: 'شماره سریال' },
|
{ field: 'serial', header: 'شماره سریال' },
|
||||||
{ field: 'pos_type', header: 'نوع دستگاه' },
|
{ field: 'pos_type', header: 'نوع دستگاه' },
|
||||||
{ field: 'device', header: 'دستگاه', type: 'nested', nestedPath: 'device.name' },
|
{ field: 'device', header: 'دستگاه', type: 'nested', nestedOption: { path: 'device.name' } },
|
||||||
{ field: 'provider', header: 'ارایهدهنده', type: 'nested', nestedPath: 'provider.name' },
|
{
|
||||||
|
field: 'provider',
|
||||||
|
header: 'ارایهدهنده',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'provider.name' },
|
||||||
|
},
|
||||||
{ field: 'status', header: 'وضعیت' },
|
{ field: 'status', header: 'وضعیت' },
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<ng-template #topBarMoreAction>
|
<!-- <ng-template #topBarMoreAction>
|
||||||
@if (licenseStatus() === "ACTIVE") {
|
@if (licenseStatus() === "ACTIVE") {
|
||||||
<p-button outlined severity="success" size="small" (click)="showLicenseInfo()">لایسنس فعال</p-button>
|
<p-button outlined severity="success" size="small" (click)="showLicenseInfo()">لایسنس فعال</p-button>
|
||||||
} @else if (licenseStatus() === "EXPIRED") {
|
} @else if (licenseStatus() === "EXPIRED") {
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<i class="pi pi-question-circle" pButtonIcon></i>
|
<i class="pi pi-question-circle" pButtonIcon></i>
|
||||||
</p-button>
|
</p-button>
|
||||||
}
|
}
|
||||||
</ng-template>
|
</ng-template> -->
|
||||||
|
|
||||||
<consumer-license-info-dialog [(visible)]="visibleLicenseInfo" />
|
<consumer-license-info-dialog [(visible)]="visibleLicenseInfo" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { LayoutService } from '@/layout/service/layout.service';
|
import { LayoutService } from '@/layout/service/layout.service';
|
||||||
import { getLicenseStatus } from '@/utils';
|
import { Component, inject, signal, TemplateRef, ViewChild } from '@angular/core';
|
||||||
import { Component, computed, inject, signal, TemplateRef, ViewChild } from '@angular/core';
|
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { Button, ButtonIcon } from 'primeng/button';
|
import { Button, ButtonIcon } from 'primeng/button';
|
||||||
import { ConsumerLicenseInfoDialogComponent } from '../components/license-info-dialog.component';
|
import { ConsumerLicenseInfoDialogComponent } from '../components/license-info-dialog.component';
|
||||||
@@ -20,9 +19,9 @@ export class LayoutComponent {
|
|||||||
|
|
||||||
visibleLicenseInfo = signal(false);
|
visibleLicenseInfo = signal(false);
|
||||||
|
|
||||||
licenseStatus = computed(() =>
|
// licenseStatus = computed(() =>
|
||||||
getLicenseStatus(getLicenseStatus(this.store.entity()?.license_info?.expires_at)),
|
// getLicenseStatus(getLicenseStatus(this.store.entity()?.license_info?.expires_at)),
|
||||||
);
|
// );
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.layoutService.setMenuItems(CONSUMER_MENU_ITEMS);
|
this.layoutService.setMenuItems(CONSUMER_MENU_ITEMS);
|
||||||
|
|||||||
-10
@@ -5,15 +5,5 @@ export interface IConsumerInfoRawResponse {
|
|||||||
mobile_number: string;
|
mobile_number: string;
|
||||||
status: string;
|
status: string;
|
||||||
fullname: string;
|
fullname: string;
|
||||||
license_info: LicenseInfo;
|
|
||||||
}
|
}
|
||||||
export interface IConsumerInfoResponse extends IConsumerInfoRawResponse {}
|
export interface IConsumerInfoResponse extends IConsumerInfoRawResponse {}
|
||||||
|
|
||||||
interface LicenseInfo {
|
|
||||||
id: string;
|
|
||||||
starts_at: string;
|
|
||||||
expires_at: string;
|
|
||||||
partner: {
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -20,9 +20,19 @@ export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
|
|||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = [
|
this.columns = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'username', header: 'نام کاربری', type: 'nested', nestedPath: 'account.username' },
|
{
|
||||||
|
field: 'username',
|
||||||
|
header: 'نام کاربری',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'account.username' },
|
||||||
|
},
|
||||||
{ field: 'role', header: 'نقش' },
|
{ field: 'role', header: 'نقش' },
|
||||||
{ field: 'status', header: 'وضعیت', type: 'nested', nestedPath: 'account.status' },
|
{
|
||||||
|
field: 'status',
|
||||||
|
header: 'وضعیت',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'account.status' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
+1
@@ -22,6 +22,7 @@ export class ConsumerComplexListComponent extends AbstractList<IComplexResponse>
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
|
{ field: 'branch_code', header: 'کد شعبه' },
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
+6
-1
@@ -23,7 +23,12 @@ export class ConsumerComplexGoodsListComponent extends AbstractList<IConsumerCom
|
|||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'sku', header: 'شناسهی عمومی' },
|
{ field: 'sku', header: 'شناسهی عمومی' },
|
||||||
{ field: 'category', header: 'دستهبندی', type: 'nested', nestedPath: 'category.name' },
|
{
|
||||||
|
field: 'category',
|
||||||
|
header: 'دستهبندی',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'category.name' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
@@ -21,7 +21,24 @@ export class ConsumerBusinessActivityListComponent extends AbstractList<IBusines
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'guild', header: 'صنف', type: 'nested', nestedPath: 'guild.name' },
|
{ field: 'guild', header: 'صنف', type: 'nested', nestedOption: { path: 'guild.name' } },
|
||||||
|
{
|
||||||
|
field: 'license_info',
|
||||||
|
header: 'محدودیت کاربر',
|
||||||
|
customDataModel(item) {
|
||||||
|
const licenseInfo = (item as IBusinessActivityResponse).license_info;
|
||||||
|
if (!licenseInfo) {
|
||||||
|
return 'بدون مجوز';
|
||||||
|
}
|
||||||
|
return `${licenseInfo.accounts_limit} کاربر`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'license_info',
|
||||||
|
header: 'انقضای مجوز',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'license_info.expires_at', type: 'date' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ export interface IBusinessActivityRawResponse {
|
|||||||
name: string;
|
name: string;
|
||||||
economic_code: string;
|
economic_code: string;
|
||||||
guild: ISummary;
|
guild: ISummary;
|
||||||
|
created_at: string;
|
||||||
|
license_info: LicenseInfo;
|
||||||
}
|
}
|
||||||
export interface IBusinessActivityResponse extends IBusinessActivityRawResponse {}
|
export interface IBusinessActivityResponse extends IBusinessActivityRawResponse {}
|
||||||
|
|
||||||
@@ -12,3 +14,10 @@ export interface IBusinessActivityRequest {
|
|||||||
economic_code: string;
|
economic_code: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LicenseInfo {
|
||||||
|
id: string;
|
||||||
|
starts_at: string;
|
||||||
|
expires_at: string;
|
||||||
|
accounts_limit: number;
|
||||||
|
}
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="grid grid-cols-3 gap-4 items-center">
|
<div class="grid grid-cols-3 gap-4 items-center">
|
||||||
<app-key-value label="عنوان" [value]="complex()?.name" />
|
<app-key-value label="عنوان" [value]="complex()?.name" />
|
||||||
|
<app-key-value label="کد شعبه" [value]="complex()?.branch_code" />
|
||||||
<app-key-value label="آدرس" [value]="complex()?.address" />
|
<app-key-value label="آدرس" [value]="complex()?.address" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ export class ConsumerCustomerSaleInvoiceListComponent extends AbstractList<ICust
|
|||||||
field: 'account',
|
field: 'account',
|
||||||
header: 'ایجاد شده توسط',
|
header: 'ایجاد شده توسط',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.account.username',
|
nestedOption: { path: 'account.account.username' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'invoice_date',
|
field: 'invoice_date',
|
||||||
|
|||||||
@@ -39,13 +39,13 @@ export class ConsumerPosListComponent extends AbstractList<IPosResponse> {
|
|||||||
field: 'complex.business_activity',
|
field: 'complex.business_activity',
|
||||||
header: 'عنوان کسب و کار',
|
header: 'عنوان کسب و کار',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'complex.business_activity.name',
|
nestedOption: { path: 'complex.business_activity.name' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'complex',
|
field: 'complex',
|
||||||
header: 'عنوان شعبه',
|
header: 'عنوان شعبه',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'complex.name',
|
nestedOption: { path: 'complex.name' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'customAction',
|
field: 'customAction',
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export class ConsumerSaleInvoiceListComponent extends AbstractList<IConsumerSale
|
|||||||
field: 'account',
|
field: 'account',
|
||||||
header: 'ایجاد شده توسط',
|
header: 'ایجاد شده توسط',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.account.username',
|
nestedOption: { path: 'account.account.username' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'invoice_date',
|
field: 'invoice_date',
|
||||||
|
|||||||
@@ -20,9 +20,19 @@ export class PartnerAccountsComponent extends AbstractList<IAccountResponse> {
|
|||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = [
|
this.columns = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'username', header: 'نام کاربری', type: 'nested', nestedPath: 'account.username' },
|
{
|
||||||
|
field: 'username',
|
||||||
|
header: 'نام کاربری',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'account.username' },
|
||||||
|
},
|
||||||
{ field: 'role', header: 'نقش' },
|
{ field: 'role', header: 'نقش' },
|
||||||
{ field: 'status', header: 'وضعیت', type: 'nested', nestedPath: 'account.status' },
|
{
|
||||||
|
field: 'status',
|
||||||
|
header: 'وضعیت',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'account.status' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
@@ -20,17 +20,17 @@ export class ConsumerAccountListComponent extends AbstractList<IConsumerAccountR
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{
|
{
|
||||||
field: 'username',
|
field: 'account',
|
||||||
header: 'نام کاربری',
|
header: 'نام کاربری',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.username',
|
nestedOption: { path: 'account.username' },
|
||||||
},
|
},
|
||||||
{ field: 'role', header: 'نوع حساب' },
|
{ field: 'role', header: 'نوع حساب' },
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
header: 'وضعیت',
|
header: 'وضعیت',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.status',
|
nestedOption: { path: 'account.status' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
|
|||||||
+18
-1
@@ -22,7 +22,24 @@ export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessA
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'guild', header: 'صنف', type: 'nested', nestedPath: 'name' },
|
{ field: 'guild', header: 'صنف', type: 'nested', nestedOption: { path: 'guild.name' } },
|
||||||
|
{
|
||||||
|
field: 'license_info',
|
||||||
|
header: 'محدودیت کاربر',
|
||||||
|
customDataModel(item) {
|
||||||
|
const licenseInfo = (item as IBusinessActivityResponse).license_info;
|
||||||
|
if (!licenseInfo) {
|
||||||
|
return 'بدون مجوز';
|
||||||
|
}
|
||||||
|
return `${licenseInfo.accounts_limit} کاربر`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'license_info',
|
||||||
|
header: 'انقضای مجوز',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'license_info.expires_at', type: 'date' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
>
|
>
|
||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<app-input label="عنوان" [control]="form.controls.name" name="name" />
|
<app-input label="عنوان" [control]="form.controls.name" name="name" />
|
||||||
<app-input label="سریال دستگاه" [control]="form.controls.serial" name="serial" />
|
|
||||||
<!-- <app-input label="مدل دستگاه" [control]="form.controls.model" name="model" /> -->
|
<!-- <app-input label="مدل دستگاه" [control]="form.controls.model" name="model" /> -->
|
||||||
<app-enum-select [control]="form.controls.pos_type" type="posType" name="pos_type" />
|
<app-enum-select [control]="form.controls.pos_type" type="posType" name="pos_type" />
|
||||||
@if (form.controls.pos_type.value === "PSP") {
|
@if (form.controls.pos_type.value === "PSP") {
|
||||||
|
<app-input label="سریال دستگاه" [control]="form.controls.serial" name="serial" />
|
||||||
<catalog-device-select [control]="form.controls.device_id" />
|
<catalog-device-select [control]="form.controls.device_id" />
|
||||||
<catalog-provider-select [control]="form.controls.provider_id" />
|
<catalog-provider-select [control]="form.controls.provider_id" />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IP
|
|||||||
});
|
});
|
||||||
form.controls.pos_type.valueChanges.subscribe((value) => {
|
form.controls.pos_type.valueChanges.subscribe((value) => {
|
||||||
if (value === 'PSP') {
|
if (value === 'PSP') {
|
||||||
|
form.addControl(
|
||||||
|
'serial',
|
||||||
|
this.fb.control<string>(this.initialValues?.serial ?? '', {
|
||||||
|
nonNullable: true,
|
||||||
|
validators: [Validators.required],
|
||||||
|
}),
|
||||||
|
);
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'device_id',
|
'device_id',
|
||||||
this.fb.control<string>(this.initialValues?.device?.id ?? '', {
|
this.fb.control<string>(this.initialValues?.device?.id ?? '', {
|
||||||
@@ -58,6 +65,8 @@ export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IP
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
form.removeControl('serial');
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
form.removeControl('device_id');
|
form.removeControl('device_id');
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -24,10 +24,15 @@ export class ConsumerPosesComponent extends AbstractList<IPosResponse> {
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'serial', header: 'شماره سریال' },
|
{ field: 'serial_number', header: 'شماره سریال' },
|
||||||
{ field: 'device', header: 'دستگاه', type: 'nested', nestedPath: 'device.name' },
|
{ field: 'device', header: 'دستگاه', type: 'nested', nestedOption: { path: 'device.name' } },
|
||||||
{ field: 'pos_type', header: 'نوع دستگاه' },
|
{ field: 'pos_type', header: 'نوع دستگاه' },
|
||||||
{ field: 'provider', header: 'ارایهدهنده', type: 'nested', nestedPath: 'provider.name' },
|
{
|
||||||
|
field: 'provider',
|
||||||
|
header: 'ارایهدهنده',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'provider.name' },
|
||||||
|
},
|
||||||
{ field: 'status', header: 'وضعیت' },
|
{ field: 'status', header: 'وضعیت' },
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
|
|||||||
+10
-1
@@ -1,10 +1,12 @@
|
|||||||
import ISummary from '@/core/models/summary';
|
import ISummary from '@/core/models/summary';
|
||||||
|
|
||||||
export interface IBusinessActivityRawResponse {
|
export interface IBusinessActivityRawResponse {
|
||||||
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
economic_code: string;
|
economic_code: string;
|
||||||
guild: ISummary;
|
guild: ISummary;
|
||||||
id: string;
|
created_at: string;
|
||||||
|
license_info: LicenseInfo;
|
||||||
}
|
}
|
||||||
export interface IBusinessActivityResponse extends IBusinessActivityRawResponse {}
|
export interface IBusinessActivityResponse extends IBusinessActivityRawResponse {}
|
||||||
|
|
||||||
@@ -13,3 +15,10 @@ export interface IBusinessActivityRequest {
|
|||||||
economic_code: string;
|
economic_code: string;
|
||||||
guild_id: string;
|
guild_id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LicenseInfo {
|
||||||
|
id: string;
|
||||||
|
starts_at: string;
|
||||||
|
expires_at: string;
|
||||||
|
accounts_limit: number;
|
||||||
|
}
|
||||||
|
|||||||
+2
@@ -5,6 +5,8 @@
|
|||||||
<app-key-value label="عنوان" [value]="businessActivity()?.name" />
|
<app-key-value label="عنوان" [value]="businessActivity()?.name" />
|
||||||
<app-key-value label="کد اقتصادی" [value]="businessActivity()?.economic_code" />
|
<app-key-value label="کد اقتصادی" [value]="businessActivity()?.economic_code" />
|
||||||
<app-key-value label="صنف" [value]="businessActivity()?.guild?.name" />
|
<app-key-value label="صنف" [value]="businessActivity()?.guild?.name" />
|
||||||
|
<app-key-value label="تاریخ انقضای مجوز" [value]="businessActivity()?.license_info?.expires_at" type="date" />
|
||||||
|
<app-key-value label="تعداد کاربران مجاز" [value]="businessActivity()?.license_info?.accounts_limit" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</app-card-data>
|
</app-card-data>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="grid grid-cols-3 gap-4 items-center">
|
<div class="grid grid-cols-3 gap-4 items-center">
|
||||||
<app-key-value label="عنوان" [value]="complex()?.name" />
|
<app-key-value label="عنوان" [value]="complex()?.name" />
|
||||||
|
<app-key-value label="کد شعبه" [value]="complex()?.branch_code" />
|
||||||
<app-key-value label="آدرس" [value]="complex()?.address" />
|
<app-key-value label="آدرس" [value]="complex()?.address" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,25 +6,6 @@
|
|||||||
<app-key-value label="نام مشتری" [value]="consumer()?.fullname" />
|
<app-key-value label="نام مشتری" [value]="consumer()?.fullname" />
|
||||||
<app-key-value label="شماره موبایل" [value]="consumer()?.mobile_number" />
|
<app-key-value label="شماره موبایل" [value]="consumer()?.mobile_number" />
|
||||||
<app-key-value label="وضعیت" [value]="consumer()?.status" />
|
<app-key-value label="وضعیت" [value]="consumer()?.status" />
|
||||||
@if (licenseStatus() === "EXPIRED") {
|
|
||||||
<app-key-value label="وضعیت لایسنس">
|
|
||||||
<p-button size="small" outlined severity="warn" (onClick)="openLicenseForm()">
|
|
||||||
منقضی شده در <span [jalaliDate]="license()!.expires_at"></span>
|
|
||||||
</p-button>
|
|
||||||
</app-key-value>
|
|
||||||
<!-- <app-key-value label="ارایه شده توسط" [value]="license()?.partner?.name || 'برند نرمافزار'" /> -->
|
|
||||||
} @else if (licenseStatus() === "ACTIVE") {
|
|
||||||
<app-key-value label="وضعیت لایسنس">
|
|
||||||
<p-button size="small" outlined severity="success" (onClick)="openLicenseForm()">
|
|
||||||
تا تاریخ <span [jalaliDate]="license()!.expires_at"></span>
|
|
||||||
</p-button>
|
|
||||||
</app-key-value>
|
|
||||||
<!-- <app-key-value label="ارایه شده توسط" [value]="license()?.partner?.name || 'برند نرمافزار'" /> -->
|
|
||||||
} @else {
|
|
||||||
<app-key-value label="وضعیت لایسنس">
|
|
||||||
<p-button size="small" outlined severity="danger" (onClick)="openLicenseForm()"> ارایه نشده </p-button>
|
|
||||||
</app-key-value>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</app-card-data>
|
</app-card-data>
|
||||||
@@ -39,13 +20,4 @@
|
|||||||
[initialValues]="consumer() || undefined"
|
[initialValues]="consumer() || undefined"
|
||||||
(onSubmit)="getData()"
|
(onSubmit)="getData()"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<partner-consumer-license-form
|
|
||||||
[(visible)]="visibleLicenseForm"
|
|
||||||
[editMode]="!!license()?.id"
|
|
||||||
[consumerId]="consumerId()"
|
|
||||||
[licenseId]="license()?.id"
|
|
||||||
[initialValues]="license() || undefined"
|
|
||||||
(onSubmit)="getData()"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,12 +34,21 @@
|
|||||||
<app-amount-percentage-input
|
<app-amount-percentage-input
|
||||||
[percentageControl]="form.controls.discount_percentage"
|
[percentageControl]="form.controls.discount_percentage"
|
||||||
[amountControl]="form.controls.discount_amount"
|
[amountControl]="form.controls.discount_amount"
|
||||||
[baseAmount]="baseTotalAmount()"
|
[baseAmount]="baseAmountForDiscountCalculation()"
|
||||||
[minAmount]="0"
|
[minAmount]="0"
|
||||||
[maxAmount]="baseTotalAmount()"
|
[maxAmount]="baseAmountForDiscountCalculation()"
|
||||||
name="discount"
|
name="discount"
|
||||||
label="تخفیف"
|
label="تخفیف"
|
||||||
|
>
|
||||||
|
<ng-template #labelSuffix>
|
||||||
|
<p-selectButton
|
||||||
|
[options]="discountTypeItems"
|
||||||
|
optionLabel="label"
|
||||||
|
optionValue="value"
|
||||||
|
(onChange)="changeDiscountCalculation($event)"
|
||||||
/>
|
/>
|
||||||
|
</ng-template>
|
||||||
|
</app-amount-percentage-input>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="flex flex-col gap-4 justify-center w-full">
|
<div class="flex flex-col gap-4 justify-center w-full">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { formatWithCurrency } from '@/utils';
|
|||||||
import { Component, EventEmitter, Output, signal } from '@angular/core';
|
import { Component, EventEmitter, Output, signal } from '@angular/core';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { Button } from 'primeng/button';
|
import { Button } from 'primeng/button';
|
||||||
|
import { SelectButton, SelectButtonChangeEvent } from 'primeng/selectbutton';
|
||||||
import { IGoldPayload, IPosOrderItem } from '../../../models';
|
import { IGoldPayload, IPosOrderItem } from '../../../models';
|
||||||
import { PosFormDialogAmountCardTemplateComponent } from '../form-dialog-amount-card-template.component';
|
import { PosFormDialogAmountCardTemplateComponent } from '../form-dialog-amount-card-template.component';
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ import { PosFormDialogAmountCardTemplateComponent } from '../form-dialog-amount-
|
|||||||
EnumSelectComponent,
|
EnumSelectComponent,
|
||||||
Button,
|
Button,
|
||||||
PosFormDialogAmountCardTemplateComponent,
|
PosFormDialogAmountCardTemplateComponent,
|
||||||
|
SelectButton,
|
||||||
AmountPercentageInputComponent,
|
AmountPercentageInputComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -29,9 +31,22 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
@Output() onSubmitForm = new EventEmitter<IGoldPayload>();
|
@Output() onSubmitForm = new EventEmitter<IGoldPayload>();
|
||||||
@Output() onChangeTotalAmount = new EventEmitter<number>();
|
@Output() onChangeTotalAmount = new EventEmitter<number>();
|
||||||
|
|
||||||
|
readonly discountTypeItems = [
|
||||||
|
{
|
||||||
|
label: 'از سود',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'از کل',
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
discountType = signal<number>(1);
|
||||||
unitWithQuantity = signal<number>(0);
|
unitWithQuantity = signal<number>(0);
|
||||||
totalAmountBeforeProfit = signal<number>(0);
|
totalAmountBeforeProfit = signal<number>(0);
|
||||||
baseTotalAmount = signal<number>(0);
|
baseTotalAmount = signal<number>(0);
|
||||||
|
baseAmountForDiscountCalculation = signal<number>(0);
|
||||||
taxAmount = signal<number>(0);
|
taxAmount = signal<number>(0);
|
||||||
totalAmount = signal<number>(0);
|
totalAmount = signal<number>(0);
|
||||||
|
|
||||||
@@ -94,7 +109,7 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
|
|
||||||
updateCalculateAmount(payload: Partial<IPosOrderItem<any>>) {
|
updateCalculateAmount(payload: Partial<IPosOrderItem<any>>) {
|
||||||
const commissionAmount = Number(payload.payload?.commission_amount ?? '0');
|
const commissionAmount = Number(payload.payload?.commission_amount ?? '0');
|
||||||
const wageAmount = Number(payload.payload?.wages ?? '0');
|
const wageAmount = Number(payload.payload?.wages_amount ?? '0');
|
||||||
const discountAmount = Number(payload.discount_amount ?? '0');
|
const discountAmount = Number(payload.discount_amount ?? '0');
|
||||||
const profitAmount = Number(payload.payload?.profit_amount ?? '0');
|
const profitAmount = Number(payload.payload?.profit_amount ?? '0');
|
||||||
const unitPrice = Number(payload.unit_price ?? '0');
|
const unitPrice = Number(payload.unit_price ?? '0');
|
||||||
@@ -103,6 +118,8 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
const unitWithQuantity = unitPrice * quantity;
|
const unitWithQuantity = unitPrice * quantity;
|
||||||
const totalAmountBeforeProfit = unitWithQuantity + wageAmount + commissionAmount;
|
const totalAmountBeforeProfit = unitWithQuantity + wageAmount + commissionAmount;
|
||||||
const baseTotalAmount = totalAmountBeforeProfit + profitAmount;
|
const baseTotalAmount = totalAmountBeforeProfit + profitAmount;
|
||||||
|
const baseAmountForDiscountCalculation =
|
||||||
|
this.discountType() === 1 ? profitAmount : baseTotalAmount;
|
||||||
const taxAmount = (profitAmount + commissionAmount + wageAmount - discountAmount) * 0.1;
|
const taxAmount = (profitAmount + commissionAmount + wageAmount - discountAmount) * 0.1;
|
||||||
const totalAmount = baseTotalAmount - discountAmount + taxAmount;
|
const totalAmount = baseTotalAmount - discountAmount + taxAmount;
|
||||||
|
|
||||||
@@ -111,6 +128,7 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
this.baseTotalAmount.set(baseTotalAmount);
|
this.baseTotalAmount.set(baseTotalAmount);
|
||||||
this.taxAmount.set(taxAmount);
|
this.taxAmount.set(taxAmount);
|
||||||
this.totalAmount.set(totalAmount);
|
this.totalAmount.set(totalAmount);
|
||||||
|
this.baseAmountForDiscountCalculation.set(baseAmountForDiscountCalculation);
|
||||||
|
|
||||||
this.onChangeTotalAmount.emit(totalAmount);
|
this.onChangeTotalAmount.emit(totalAmount);
|
||||||
}
|
}
|
||||||
@@ -121,4 +139,10 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
}
|
}
|
||||||
return `(${formatWithCurrency(amount)})`;
|
return `(${formatWithCurrency(amount)})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeDiscountCalculation($event: SelectButtonChangeEvent) {
|
||||||
|
this.discountType.set($event.value);
|
||||||
|
|
||||||
|
this.updateCalculateAmount(this.form.value as any);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ export class ConsumerAccountListComponent extends AbstractList<IConsumerAccountR
|
|||||||
field: 'username',
|
field: 'username',
|
||||||
header: 'نام کاربری',
|
header: 'نام کاربری',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.username',
|
nestedOption: { path: 'account.username' },
|
||||||
},
|
},
|
||||||
{ field: 'role', header: 'نوع حساب' },
|
{ field: 'role', header: 'نوع حساب' },
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
header: 'وضعیت',
|
header: 'وضعیت',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.status',
|
nestedOption: { path: 'account.status' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessA
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'guild', header: 'صنف', type: 'nested', nestedPath: 'name' },
|
{ field: 'guild', header: 'صنف', type: 'nested', nestedOption: { path: 'guild.name' } },
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
@@ -24,10 +24,15 @@ export class ConsumerPosesComponent extends AbstractList<IPosResponse> {
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'serial', header: 'شماره سریال' },
|
{ field: 'serial_number', header: 'شماره سریال' },
|
||||||
{ field: 'device', header: 'دستگاه', type: 'nested', nestedPath: 'device.name' },
|
{ field: 'device', header: 'دستگاه', type: 'nested', nestedOption: { path: 'device.name' } },
|
||||||
{ field: 'pos_type', header: 'نوع دستگاه' },
|
{ field: 'pos_type', header: 'نوع دستگاه' },
|
||||||
{ field: 'provider', header: 'ارایهدهنده', type: 'nested', nestedPath: 'provider.name' },
|
{
|
||||||
|
field: 'provider',
|
||||||
|
header: 'ارایهدهنده',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'provider.name' },
|
||||||
|
},
|
||||||
{ field: 'status', header: 'وضعیت' },
|
{ field: 'status', header: 'وضعیت' },
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="grid grid-cols-3 gap-4 items-center">
|
<div class="grid grid-cols-3 gap-4 items-center">
|
||||||
<app-key-value label="عنوان" [value]="complex()?.name" />
|
<app-key-value label="عنوان" [value]="complex()?.name" />
|
||||||
|
<app-key-value label="کد شعبه" [value]="complex()?.branch_code" />
|
||||||
<app-key-value label="آدرس" [value]="complex()?.address" />
|
<app-key-value label="آدرس" [value]="complex()?.address" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,12 @@ export class DevicesComponent extends AbstractList<IDeviceResponse> {
|
|||||||
this.columns = [
|
this.columns = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'brand', header: 'برند دستگاه', type: 'nested', nestedPath: 'name' },
|
{
|
||||||
|
field: 'brand',
|
||||||
|
header: 'برند دستگاه',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'brand.name' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
@@ -21,7 +21,12 @@ export class GuildGoodsListComponent extends AbstractList<IGuildGoodsResponse> {
|
|||||||
{ field: 'image_url', header: 'تصویر', type: 'thumbnail' },
|
{ field: 'image_url', header: 'تصویر', type: 'thumbnail' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
{ field: 'sku', header: 'شناسهی عمومی' },
|
{ field: 'sku', header: 'شناسهی عمومی' },
|
||||||
{ field: 'category', header: 'دستهبندی', type: 'nested', nestedPath: 'category.name' },
|
{
|
||||||
|
field: 'category',
|
||||||
|
header: 'دستهبندی',
|
||||||
|
type: 'nested',
|
||||||
|
nestedOption: { path: 'category.name' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ export class ConsumerAccountListComponent extends AbstractList<IPartnerAccountRe
|
|||||||
field: 'username',
|
field: 'username',
|
||||||
header: 'نام کاربری',
|
header: 'نام کاربری',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.username',
|
nestedOption: { path: 'account.username' },
|
||||||
},
|
},
|
||||||
{ field: 'role', header: 'نوع حساب' },
|
{ field: 'role', header: 'نوع حساب' },
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
header: 'وضعیت',
|
header: 'وضعیت',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedPath: 'account.status',
|
nestedOption: { path: 'account.status' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
|
|||||||
+11
@@ -5,6 +5,17 @@
|
|||||||
[showLabel]="!!label"
|
[showLabel]="!!label"
|
||||||
[showErrors]="showErrors"
|
[showErrors]="showErrors"
|
||||||
>
|
>
|
||||||
|
@if (labelSuffix) {
|
||||||
|
<ng-template #labelView>
|
||||||
|
<div class="flex gap-1 items-center">
|
||||||
|
<uikit-label [name]="name">
|
||||||
|
{{ preparedLabel() }}
|
||||||
|
</uikit-label>
|
||||||
|
<ng-container [ngTemplateOutlet]="labelSuffix"></ng-container>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
}
|
||||||
|
|
||||||
<p-inputgroup>
|
<p-inputgroup>
|
||||||
@if (selectedType.value === "amount") {
|
@if (selectedType.value === "amount") {
|
||||||
<p-inputnumber
|
<p-inputnumber
|
||||||
|
|||||||
+16
-2
@@ -1,8 +1,18 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
import { ToastService } from '@/core/services/toast.service';
|
import { ToastService } from '@/core/services/toast.service';
|
||||||
import { UikitFieldComponent } from '@/uikit';
|
import { UikitFieldComponent, UikitLabelComponent } from '@/uikit';
|
||||||
import { formatWithCurrency } from '@/utils';
|
import { formatWithCurrency } from '@/utils';
|
||||||
import { Component, EventEmitter, inject, Input, Output, signal } from '@angular/core';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ContentChild,
|
||||||
|
EventEmitter,
|
||||||
|
inject,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
signal,
|
||||||
|
TemplateRef,
|
||||||
|
} from '@angular/core';
|
||||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { InputGroup } from 'primeng/inputgroup';
|
import { InputGroup } from 'primeng/inputgroup';
|
||||||
import { InputGroupAddon } from 'primeng/inputgroupaddon';
|
import { InputGroupAddon } from 'primeng/inputgroupaddon';
|
||||||
@@ -27,6 +37,8 @@ interface IAmountPercentageInputSelect {
|
|||||||
InputText,
|
InputText,
|
||||||
Select,
|
Select,
|
||||||
InputNumberModule,
|
InputNumberModule,
|
||||||
|
CommonModule,
|
||||||
|
UikitLabelComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AmountPercentageInputComponent {
|
export class AmountPercentageInputComponent {
|
||||||
@@ -52,6 +64,8 @@ export class AmountPercentageInputComponent {
|
|||||||
@Output() onTypeChange = new EventEmitter<TAmountPercentageInput>();
|
@Output() onTypeChange = new EventEmitter<TAmountPercentageInput>();
|
||||||
@Output() blur = new EventEmitter<void>();
|
@Output() blur = new EventEmitter<void>();
|
||||||
|
|
||||||
|
@ContentChild('labelSuffix', { static: false }) labelSuffix!: TemplateRef<any> | null;
|
||||||
|
|
||||||
private readonly toastService = inject(ToastService);
|
private readonly toastService = inject(ToastService);
|
||||||
|
|
||||||
readonly typeSelectOptions: IAmountPercentageInputSelect[] = [
|
readonly typeSelectOptions: IAmountPercentageInputSelect[] = [
|
||||||
|
|||||||
@@ -22,14 +22,19 @@ import { TableModule } from 'primeng/table';
|
|||||||
import { KeyValueComponent } from '../key-value.component/key-value.component';
|
import { KeyValueComponent } from '../key-value.component/key-value.component';
|
||||||
import { TableActionRowComponent } from '../table-action-row.component';
|
import { TableActionRowComponent } from '../table-action-row.component';
|
||||||
|
|
||||||
|
type TDataType = 'simple' | 'price' | 'boolean' | 'date' | 'nested' | 'index' | 'id' | 'thumbnail';
|
||||||
export interface IColumn<T = any> {
|
export interface IColumn<T = any> {
|
||||||
field: T extends object ? keyof T | string : string;
|
field: T extends object ? keyof T | string : string;
|
||||||
header: string;
|
header: string;
|
||||||
width?: string;
|
width?: string;
|
||||||
minWidth?: string;
|
minWidth?: string;
|
||||||
canCopy?: boolean;
|
canCopy?: boolean;
|
||||||
type?: 'simple' | 'price' | 'boolean' | 'date' | 'nested' | 'index' | 'id' | 'thumbnail';
|
type?: TDataType;
|
||||||
nestedPath?: string;
|
|
||||||
|
nestedOption?: {
|
||||||
|
path: string;
|
||||||
|
type?: TDataType;
|
||||||
|
};
|
||||||
thumbnailOptions?: {
|
thumbnailOptions?: {
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
deletable: boolean;
|
deletable: boolean;
|
||||||
@@ -179,13 +184,24 @@ export class PageDataListComponent<I> {
|
|||||||
getCell(item: Record<string, any>, column: IColumn): any {
|
getCell(item: Record<string, any>, column: IColumn): any {
|
||||||
if (!item || !column) return '';
|
if (!item || !column) return '';
|
||||||
try {
|
try {
|
||||||
const { field } = column;
|
let { field, type } = column;
|
||||||
|
|
||||||
if (column.customDataModel) {
|
if (column.customDataModel) {
|
||||||
return this.renderCustom(column, item);
|
return this.renderCustom(column, item);
|
||||||
}
|
}
|
||||||
const data = item[String(field)];
|
|
||||||
switch (column.type) {
|
let data = item[String(field)];
|
||||||
|
if (column.type === 'nested') {
|
||||||
|
const path = column.nestedOption?.path;
|
||||||
|
if (!path) return '-';
|
||||||
|
data = path
|
||||||
|
.split('.')
|
||||||
|
.reduce((obj, key) => (obj && obj[key] !== undefined ? obj[key] : null), item);
|
||||||
|
type = column.nestedOption?.type || 'simple';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type) {
|
||||||
|
switch (type) {
|
||||||
case 'id':
|
case 'id':
|
||||||
if (!data) return '-';
|
if (!data) return '-';
|
||||||
return `${data.slice(0, 5)}...${data.slice(data.length - 5, data.length)}`;
|
return `${data.slice(0, 5)}...${data.slice(data.length - 5, data.length)}`;
|
||||||
@@ -196,19 +212,10 @@ export class PageDataListComponent<I> {
|
|||||||
return data ? 'بله' : 'خیر';
|
return data ? 'بله' : 'خیر';
|
||||||
case 'price':
|
case 'price':
|
||||||
return formatWithCurrency(data, false, 'ریال');
|
return formatWithCurrency(data, false, 'ریال');
|
||||||
case 'nested': {
|
|
||||||
const path = column.nestedPath;
|
|
||||||
if (!path) return '-';
|
|
||||||
const nestedData = path
|
|
||||||
.split('.')
|
|
||||||
.reduce((obj, key) => (obj && obj[key] !== undefined ? obj[key] : null), item);
|
|
||||||
|
|
||||||
return nestedData || '-';
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (data === undefined || data === null) {
|
if (data === undefined || data === null) {
|
||||||
return '-';
|
return '-';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,13 @@
|
|||||||
<ng-template #fieldTemplate>
|
<ng-template #fieldTemplate>
|
||||||
@if (showLabel) {
|
@if (showLabel) {
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
|
@if (labelView) {
|
||||||
|
<ng-container [ngTemplateOutlet]="labelView"> </ng-container>
|
||||||
|
} @else {
|
||||||
<uikit-label [name]="name" [invalid]="!!invalid || hasError">
|
<uikit-label [name]="name" [invalid]="!!invalid || hasError">
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</uikit-label>
|
</uikit-label>
|
||||||
|
}
|
||||||
<ng-container [ngTemplateOutlet]="contentTemplate" />
|
<ng-container [ngTemplateOutlet]="contentTemplate" />
|
||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FormErrorsService } from '@/core/services/form-errors.service';
|
import { FormErrorsService } from '@/core/services/form-errors.service';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, Input, inject } from '@angular/core';
|
import { Component, ContentChild, Input, TemplateRef, inject } from '@angular/core';
|
||||||
import { AbstractControl } from '@angular/forms';
|
import { AbstractControl } from '@angular/forms';
|
||||||
import { MessageModule } from 'primeng/message';
|
import { MessageModule } from 'primeng/message';
|
||||||
import { UikitLabelComponent } from './uikit-label.component';
|
import { UikitLabelComponent } from './uikit-label.component';
|
||||||
@@ -25,6 +25,8 @@ export class UikitFieldComponent {
|
|||||||
@Input() showErrors: boolean = true;
|
@Input() showErrors: boolean = true;
|
||||||
@Input() showLabel: boolean = true;
|
@Input() showLabel: boolean = true;
|
||||||
|
|
||||||
|
@ContentChild('labelView', { static: false }) labelView!: TemplateRef<any> | null;
|
||||||
|
|
||||||
private errorsService = inject(FormErrorsService);
|
private errorsService = inject(FormErrorsService);
|
||||||
|
|
||||||
get hasError(): boolean {
|
get hasError(): boolean {
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ export function buildFormData(
|
|||||||
): FormData {
|
): FormData {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
console.log(formGroup);
|
|
||||||
console.log(formGroup.controls);
|
|
||||||
|
|
||||||
Object.keys(formGroup.controls).forEach((key) => {
|
Object.keys(formGroup.controls).forEach((key) => {
|
||||||
const control = formGroup.get(key);
|
const control = formGroup.get(key);
|
||||||
if (control && control.value !== null && control.value !== undefined) {
|
if (control && control.value !== null && control.value !== undefined) {
|
||||||
|
|||||||
Reference in New Issue
Block a user