feat: Enhance customer and inventory components with new features and improvements
This commit is contained in:
@@ -1,4 +1,11 @@
|
|||||||
<p-dialog header="فرم مشتری" [(visible)]="visible" [modal]="true" [style]="{ width: '600px' }" [closable]="true">
|
<p-dialog
|
||||||
|
header="فرم مشتری"
|
||||||
|
[(visible)]="visible"
|
||||||
|
[modal]="true"
|
||||||
|
[style]="{ width: '600px', zIndex: '100000' }"
|
||||||
|
appendTo="body"
|
||||||
|
[closable]="true"
|
||||||
|
>
|
||||||
<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.firstName" name="firstName" />
|
<app-input label="نام" [control]="form.controls.firstName" name="firstName" />
|
||||||
<app-input label="نام خانوادگی" [control]="form.controls.lastName" name="lastName" />
|
<app-input label="نام خانوادگی" [control]="form.controls.lastName" name="lastName" />
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<uikit-field label="مشتری" [control]="control" [showLabel]="showLabel" [showErrors]="showErrors">
|
<uikit-field label="مشتری" [control]="control" [showLabel]="showLabel" [showErrors]="showErrors">
|
||||||
<p-select
|
<p-select
|
||||||
|
[loading]="loading()"
|
||||||
[options]="items()"
|
[options]="items()"
|
||||||
optionLabel="name"
|
optionLabel="fullName"
|
||||||
[optionValue]="selectOptionValue"
|
[optionValue]="selectOptionValue"
|
||||||
placeholder="انتخاب مشتری"
|
placeholder="انتخاب مشتری"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
@@ -9,5 +10,21 @@
|
|||||||
[filter]="true"
|
[filter]="true"
|
||||||
appendTo="body"
|
appendTo="body"
|
||||||
>
|
>
|
||||||
|
@if (canInsert) {
|
||||||
|
<ng-template #footer>
|
||||||
|
<div class="p-3">
|
||||||
|
<p-button
|
||||||
|
label="افزودن مشتری جدید"
|
||||||
|
fluid
|
||||||
|
severity="secondary"
|
||||||
|
text
|
||||||
|
size="small"
|
||||||
|
icon="pi pi-plus"
|
||||||
|
(onClick)="onOpenForm()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
}
|
||||||
</p-select>
|
</p-select>
|
||||||
|
<customer-form [(visible)]="isOpenFormDialog" (onSubmit)="refresh()" />
|
||||||
</uikit-field>
|
</uikit-field>
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ import { AbstractSelectComponent } from '@/shared/components';
|
|||||||
import { UikitFieldComponent } from '@/uikit';
|
import { UikitFieldComponent } from '@/uikit';
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { Button } from 'primeng/button';
|
||||||
import { Select } from 'primeng/select';
|
import { Select } from 'primeng/select';
|
||||||
import { ICustomerResponse } from '../../models';
|
import { ICustomerResponse } from '../../models';
|
||||||
import { CustomersService } from '../../services/main.service';
|
import { CustomersService } from '../../services/main.service';
|
||||||
|
import { CustomerFormComponent } from '../form.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'customers-select-field',
|
selector: 'customers-select-field',
|
||||||
templateUrl: './select.component.html',
|
templateUrl: './select.component.html',
|
||||||
imports: [ReactiveFormsModule, Select, UikitFieldComponent],
|
imports: [ReactiveFormsModule, Select, UikitFieldComponent, Button, CustomerFormComponent],
|
||||||
})
|
})
|
||||||
export class CustomersSelectComponent extends AbstractSelectComponent<ICustomerResponse> {
|
export class CustomersSelectComponent extends AbstractSelectComponent<ICustomerResponse> {
|
||||||
constructor(private service: CustomersService) {
|
constructor(private service: CustomersService) {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { IPaginatedResponse } from '@/core/models/service.model';
|
import { IPaginatedResponse } from '@/core/models/service.model';
|
||||||
|
import { getFullName } from '@/utils';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { map, Observable } from 'rxjs';
|
||||||
import { CUSTOMERS_API_ROUTES } from '../constants';
|
import { CUSTOMERS_API_ROUTES } from '../constants';
|
||||||
import { ICustomerRawResponse, ICustomerRequest, ICustomerResponse } from '../models';
|
import { ICustomerRawResponse, ICustomerRequest, ICustomerResponse } from '../models';
|
||||||
|
|
||||||
@@ -12,11 +13,22 @@ export class CustomersService {
|
|||||||
private apiRoutes = CUSTOMERS_API_ROUTES;
|
private apiRoutes = CUSTOMERS_API_ROUTES;
|
||||||
|
|
||||||
getAll(): Observable<IPaginatedResponse<ICustomerResponse>> {
|
getAll(): Observable<IPaginatedResponse<ICustomerResponse>> {
|
||||||
return this.http.get<IPaginatedResponse<ICustomerRawResponse>>(this.apiRoutes.list());
|
return this.http.get<IPaginatedResponse<ICustomerRawResponse>>(this.apiRoutes.list()).pipe(
|
||||||
|
map((res) => {
|
||||||
|
return {
|
||||||
|
meta: res.meta,
|
||||||
|
data: res.data.map((item) => ({ ...item, fullName: getFullName(item) })),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSingle(customerId: string): Observable<ICustomerResponse> {
|
getSingle(customerId: string): Observable<ICustomerResponse> {
|
||||||
return this.http.get<ICustomerRawResponse>(this.apiRoutes.single(customerId));
|
return this.http.get<ICustomerRawResponse>(this.apiRoutes.single(customerId)).pipe(
|
||||||
|
map((res) => {
|
||||||
|
return { ...res, fullName: getFullName(res) };
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(data: ICustomerRequest): Observable<ICustomerResponse> {
|
create(data: ICustomerRequest): Observable<ICustomerResponse> {
|
||||||
|
|||||||
@@ -32,7 +32,9 @@
|
|||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ movement.receiptId }}</td>
|
<td>{{ movement.receiptId }}</td>
|
||||||
<td><catalog-movement-reference-tag [type]="movement.info.referenceType" /></td>
|
<td>
|
||||||
|
<catalog-movement-reference-tag [type]="movement.info.referenceType" [movementType]="movement.info.type" />
|
||||||
|
</td>
|
||||||
<td>{{ movement.count }}</td>
|
<td>{{ movement.count }}</td>
|
||||||
<td>{{ movement.info.quantity }}</td>
|
<td>{{ movement.info.quantity }}</td>
|
||||||
<td><span [appPriceMask]="movement.info.totalCost"></span></td>
|
<td><span [appPriceMask]="movement.info.totalCost"></span></td>
|
||||||
|
|||||||
@@ -95,7 +95,6 @@
|
|||||||
@if (!form.controls.fromInventory.value) {
|
@if (!form.controls.fromInventory.value) {
|
||||||
<div class="text-center text-gray-500 py-10">لطفا انبار مبدا را انتخاب کنید</div>
|
<div class="text-center text-gray-500 py-10">لطفا انبار مبدا را انتخاب کنید</div>
|
||||||
} @else {
|
} @else {
|
||||||
{{ form.controls.items.value.length }}
|
|
||||||
<p-table [value]="form.controls.items.controls" class="w-full">
|
<p-table [value]="form.controls.items.controls" class="w-full">
|
||||||
<ng-template #header>
|
<ng-template #header>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -107,13 +106,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>{{ item.controls.product.value?.name }}</td>
|
<td>{{ item.controls.product.value?.name }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<app-uikit-counter [min]="1" [max]="10" [control]="item.controls.count" />
|
||||||
pInputText
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
[max]="item.controls.product.value?.quantity"
|
|
||||||
[formControl]="form.controls.items.at(rowIndex).controls.count"
|
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
import { InputComponent } from '@/shared/components';
|
import { InputComponent } from '@/shared/components';
|
||||||
import { UikitFieldComponent } from '@/uikit';
|
import { UikitCounterComponent, UikitFieldComponent } from '@/uikit';
|
||||||
import { Component, inject, signal } from '@angular/core';
|
import { Component, inject, signal } from '@angular/core';
|
||||||
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
@@ -32,6 +32,7 @@ import { InventoriesSelectComponent } from '../select/select.component';
|
|||||||
TableModule,
|
TableModule,
|
||||||
InputText,
|
InputText,
|
||||||
ButtonDirective,
|
ButtonDirective,
|
||||||
|
UikitCounterComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class InventoriesTransferFormComponent {
|
export class InventoriesTransferFormComponent {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Maybe } from '@/core';
|
|||||||
import { KeyValueComponent } from '@/shared/components';
|
import { KeyValueComponent } from '@/shared/components';
|
||||||
import { DetailsInfoCardComponent } from '@/shared/components/detailsInfoCard/details-info-card.component';
|
import { DetailsInfoCardComponent } from '@/shared/components/detailsInfoCard/details-info-card.component';
|
||||||
import { PriceMaskDirective } from '@/shared/directives';
|
import { PriceMaskDirective } from '@/shared/directives';
|
||||||
|
import { formatWithCurrency } from '@/utils';
|
||||||
import { Component, inject, signal } from '@angular/core';
|
import { Component, inject, signal } from '@angular/core';
|
||||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||||
import { Button, ButtonDirective } from 'primeng/button';
|
import { Button, ButtonDirective } from 'primeng/button';
|
||||||
@@ -83,7 +84,7 @@ export class InventoryComponent {
|
|||||||
{
|
{
|
||||||
icon: 'pi pi-dollar',
|
icon: 'pi pi-dollar',
|
||||||
label: 'ارزش کلی کالاهای موجود',
|
label: 'ارزش کلی کالاهای موجود',
|
||||||
value: this.data()?.availableProductsCost,
|
value: formatWithCurrency(this.data()?.availableProductsCost || 0),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
<div class="bg-surface-card w-md shrink-0 h-full overflow-hidden rounded-xl p-4 pb-0 flex flex-col">
|
<div class="bg-surface-card w-md shrink-0 h-full overflow-hidden rounded-xl p-4 pb-0 flex flex-col">
|
||||||
<div class="shrink-0 sticky top-0">
|
<div class="shrink-0 sticky top-0">
|
||||||
<customers-select-field [canInsert]="true" />
|
<customers-select-field
|
||||||
|
[canInsert]="true"
|
||||||
|
[value]="selectedCustomer()"
|
||||||
|
(valueChange)="updateCustomer($event)"
|
||||||
|
[isFullDataOptionValue]="true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="grow overflow-auto flex flex-col">
|
<div class="grow overflow-auto flex flex-col">
|
||||||
@@ -61,7 +66,7 @@
|
|||||||
<app-uikit-counter
|
<app-uikit-counter
|
||||||
[min]="1"
|
[min]="1"
|
||||||
[max]="inOrderProduct.maxQuantity"
|
[max]="inOrderProduct.maxQuantity"
|
||||||
[value]="inOrderProduct.quantity"
|
[value]="inOrderProduct.count"
|
||||||
(valueChange)="updateInOrderProductQuantity(inOrderProduct.productId, $event)"
|
(valueChange)="updateInOrderProductQuantity(inOrderProduct.productId, $event)"
|
||||||
></app-uikit-counter>
|
></app-uikit-counter>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,7 +81,15 @@
|
|||||||
<div class="flex flex-col sticky bottom-0 py-2">
|
<div class="flex flex-col sticky bottom-0 py-2">
|
||||||
<pos-order-price-info-card />
|
<pos-order-price-info-card />
|
||||||
<div class="grid grid-cols grid-cols-2 sticky bottom-0 gap-2 pt-4">
|
<div class="grid grid-cols grid-cols-2 sticky bottom-0 gap-2 pt-4">
|
||||||
<button pButton type="button" label="ثبت سفارش" severity="primary" icon="pi pi-check" class="w-full"></button>
|
<button
|
||||||
|
pButton
|
||||||
|
type="button"
|
||||||
|
label="ثبت سفارش"
|
||||||
|
severity="primary"
|
||||||
|
icon="pi pi-check"
|
||||||
|
class="w-full"
|
||||||
|
(click)="submit()"
|
||||||
|
></button>
|
||||||
<button pButton type="button" label="لغو" outlined icon="pi pi-times" class="w-full"></button>
|
<button pButton type="button" label="لغو" outlined icon="pi pi-times" class="w-full"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { Maybe } from '@/core';
|
||||||
import { CustomersSelectComponent } from '@/modules/customers/components/select/select.component';
|
import { CustomersSelectComponent } from '@/modules/customers/components/select/select.component';
|
||||||
|
import { ICustomerResponse } from '@/modules/customers/models';
|
||||||
import { PriceMaskDirective } from '@/shared/directives';
|
import { PriceMaskDirective } from '@/shared/directives';
|
||||||
import { UikitCounterComponent } from '@/uikit';
|
import { UikitCounterComponent } from '@/uikit';
|
||||||
import { Component, computed, signal } from '@angular/core';
|
import { Component, computed, signal } from '@angular/core';
|
||||||
@@ -25,13 +27,15 @@ import { POSOrderPriceInfoCardComponent } from './price-info-card.component';
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PosOrderCardComponent {
|
export class PosOrderCardComponent {
|
||||||
constructor(private store: POSStore) {}
|
constructor(private store: POSStore) {
|
||||||
|
this.selectedCustomer.set(this.store.selectedCustomer());
|
||||||
|
}
|
||||||
|
|
||||||
placeholderImage = images.placeholders.default;
|
placeholderImage = images.placeholders.default;
|
||||||
|
|
||||||
inOrderProducts = computed(() => this.store.inOrderProducts());
|
inOrderProducts = computed(() => this.store.inOrderProducts());
|
||||||
|
|
||||||
value = signal(0);
|
selectedCustomer = signal<Maybe<ICustomerResponse>>(null);
|
||||||
|
|
||||||
removeProductFromOrder(productId: number) {
|
removeProductFromOrder(productId: number) {
|
||||||
this.store.removeFromInOrderProducts(productId);
|
this.store.removeFromInOrderProducts(productId);
|
||||||
@@ -41,8 +45,10 @@ export class PosOrderCardComponent {
|
|||||||
this.store.updateInOrderProductQuantity(productId, quantity);
|
this.store.updateInOrderProductQuantity(productId, quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInOrderProductFee(productId: number, $event: Event, prevFee: string) {
|
updateInOrderProductFee(productId: number, $event: Event, prevFee: number) {
|
||||||
const fee = $event.target ? String(($event.target as HTMLInputElement).ariaValueNow) : prevFee;
|
const fee = $event.target
|
||||||
|
? parseFloat(($event.target as HTMLInputElement).ariaValueNow || prevFee.toString())
|
||||||
|
: prevFee;
|
||||||
|
|
||||||
this.store.updateInOrderProductFee(productId, fee);
|
this.store.updateInOrderProductFee(productId, fee);
|
||||||
}
|
}
|
||||||
@@ -50,4 +56,12 @@ export class PosOrderCardComponent {
|
|||||||
clearOrderList() {
|
clearOrderList() {
|
||||||
this.store.resetInOrderProducts();
|
this.store.resetInOrderProducts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateCustomer(customer: Maybe<ICustomerResponse>) {
|
||||||
|
this.store.setSelectedCustomer(customer);
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
this.store.submitOrder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
<p-card class="border border-surface-border">
|
<p-card class="border border-surface-border">
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between items-center">
|
||||||
<span>جمع قیمت</span>
|
<span>جمع قیمت</span>
|
||||||
<span [appPriceMask]="priceInfo().totalAmount"></span>
|
@if (priceInfo().totalAmount == priceInfo().totalBaseAmount) {
|
||||||
|
<span [appPriceMask]="priceInfo().totalAmount"></span>
|
||||||
|
} @else {
|
||||||
|
<div class="flex flex-col items-end">
|
||||||
|
<span class="line-through text-muted-color text-xs" [appPriceMask]="priceInfo().totalBaseAmount"></span>
|
||||||
|
<span [appPriceMask]="priceInfo().totalAmount"></span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between items-center">
|
||||||
<span>مالیات (۱۰٪)</span>
|
<span>مالیات (۱۰٪)</span>
|
||||||
<span [appPriceMask]="priceInfo().taxAmount"></span>
|
<span [appPriceMask]="priceInfo().taxAmount"></span>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="flex justify-between font-bold text-lg">
|
<div class="flex justify-between items-center font-bold text-lg">
|
||||||
<span>مجموع کل</span>
|
<span>مجموع کل</span>
|
||||||
<span [appPriceMask]="priceInfo().payableAmount"></span>
|
<span [appPriceMask]="priceInfo().payableAmount"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ export const POS_API_ROUTES = {
|
|||||||
info: () => `${baseUrl}`,
|
info: () => `${baseUrl}`,
|
||||||
stock: () => `${baseUrl}/stock`,
|
stock: () => `${baseUrl}/stock`,
|
||||||
productCategories: () => `${baseUrl}/product-categories`,
|
productCategories: () => `${baseUrl}/product-categories`,
|
||||||
|
submitOrder: () => `${baseUrl}/orders/create`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ interface ICategorySummary {
|
|||||||
|
|
||||||
export interface IPosOrderItem {
|
export interface IPosOrderItem {
|
||||||
productId: number;
|
productId: number;
|
||||||
quantity: number;
|
count: number;
|
||||||
fee: string;
|
fee: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPosInOrderProduct extends IPosOrderItem {
|
export interface IPosInOrderProduct extends IPosOrderItem {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { POS_API_ROUTES } from '../constants';
|
|||||||
import {
|
import {
|
||||||
IPosInfoRawResponse,
|
IPosInfoRawResponse,
|
||||||
IPosInfoResponse,
|
IPosInfoResponse,
|
||||||
|
IPosOrderRequest,
|
||||||
IPosProductCategoriesRawResponse,
|
IPosProductCategoriesRawResponse,
|
||||||
IPosProductCategoriesResponse,
|
IPosProductCategoriesResponse,
|
||||||
IPosStockRawResponse,
|
IPosStockRawResponse,
|
||||||
@@ -31,4 +32,8 @@ export class PosService {
|
|||||||
this.apiRoutes.productCategories(),
|
this.apiRoutes.productCategories(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
submitOrder(payload: IPosOrderRequest): Observable<any> {
|
||||||
|
return this.http.post<any>(this.apiRoutes.submitOrder(), payload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
|
import { ICustomerResponse } from '@/modules/customers/models';
|
||||||
import { computed, Injectable, signal } from '@angular/core';
|
import { computed, Injectable, signal } from '@angular/core';
|
||||||
import { map } from 'rxjs';
|
import { map } from 'rxjs';
|
||||||
import { IPosInfoResponse, IPosProductCategoriesResponse, IPosStockResponse } from '../models';
|
import { IPosInfoResponse, IPosProductCategoriesResponse, IPosStockResponse } from '../models';
|
||||||
@@ -14,6 +15,7 @@ interface IPosState {
|
|||||||
productCategories: Maybe<IPosProductCategoriesResponse[]>;
|
productCategories: Maybe<IPosProductCategoriesResponse[]>;
|
||||||
activeProductCategory: Maybe<number>;
|
activeProductCategory: Maybe<number>;
|
||||||
inOrderProducts: IPosInOrderProduct[];
|
inOrderProducts: IPosInOrderProduct[];
|
||||||
|
selectedCustomer: Maybe<ICustomerResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const INITIAL_POS_STATE: IPosState = {
|
export const INITIAL_POS_STATE: IPosState = {
|
||||||
@@ -25,6 +27,7 @@ export const INITIAL_POS_STATE: IPosState = {
|
|||||||
productCategories: null,
|
productCategories: null,
|
||||||
activeProductCategory: null,
|
activeProductCategory: null,
|
||||||
inOrderProducts: [],
|
inOrderProducts: [],
|
||||||
|
selectedCustomer: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
@Injectable({ providedIn: 'any' })
|
@Injectable({ providedIn: 'any' })
|
||||||
@@ -41,6 +44,7 @@ export class POSStore {
|
|||||||
readonly productCategories = computed(() => this.state$().productCategories);
|
readonly productCategories = computed(() => this.state$().productCategories);
|
||||||
readonly getProductCategoriesLoading = computed(() => this.state$().getProductCategoriesLoading);
|
readonly getProductCategoriesLoading = computed(() => this.state$().getProductCategoriesLoading);
|
||||||
readonly activeProductCategory = computed(() => this.state$().activeProductCategory);
|
readonly activeProductCategory = computed(() => this.state$().activeProductCategory);
|
||||||
|
readonly selectedCustomer = computed(() => this.state$().selectedCustomer);
|
||||||
readonly activatedCategoryProducts = computed(() => {
|
readonly activatedCategoryProducts = computed(() => {
|
||||||
if (this.activeProductCategory() === 0) {
|
if (this.activeProductCategory() === 0) {
|
||||||
return this.state$().stock;
|
return this.state$().stock;
|
||||||
@@ -52,14 +56,14 @@ export class POSStore {
|
|||||||
|
|
||||||
readonly orderPricingInfo = computed(() => {
|
readonly orderPricingInfo = computed(() => {
|
||||||
const totalAmount = this.inOrderProducts().reduce(
|
const totalAmount = this.inOrderProducts().reduce(
|
||||||
(acc, curr) => acc + parseFloat(curr.fee) * curr.quantity,
|
(acc, curr) => acc + curr.fee * curr.count,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
const taxAmount = totalAmount * 0.1;
|
const taxAmount = totalAmount * 0.1;
|
||||||
return {
|
return {
|
||||||
totalItems: this.inOrderProducts().reduce((acc, curr) => acc + curr.quantity, 0),
|
totalItems: this.inOrderProducts().reduce((acc, curr) => acc + curr.count, 0),
|
||||||
totalBaseAmount: this.inOrderProducts().reduce(
|
totalBaseAmount: this.inOrderProducts().reduce(
|
||||||
(acc, curr) => acc + parseFloat(curr.product.salePrice) * curr.quantity,
|
(acc, curr) => acc + parseFloat(curr.product.salePrice) * curr.count,
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
totalAmount,
|
totalAmount,
|
||||||
@@ -156,7 +160,7 @@ export class POSStore {
|
|||||||
if (this.state$().inOrderProducts.some((p) => p.productId === productId)) {
|
if (this.state$().inOrderProducts.some((p) => p.productId === productId)) {
|
||||||
this.updateInOrderProductQuantity(
|
this.updateInOrderProductQuantity(
|
||||||
productId,
|
productId,
|
||||||
this.state$().inOrderProducts.find((p) => p.productId === productId)!.quantity + 1,
|
this.state$().inOrderProducts.find((p) => p.productId === productId)!.count + 1,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -165,8 +169,8 @@ export class POSStore {
|
|||||||
{
|
{
|
||||||
product,
|
product,
|
||||||
productId: product.id,
|
productId: product.id,
|
||||||
quantity: 1,
|
count: 1,
|
||||||
fee: product.salePrice,
|
fee: parseFloat(product.salePrice),
|
||||||
maxQuantity: productStock.quantity,
|
maxQuantity: productStock.quantity,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -190,7 +194,7 @@ export class POSStore {
|
|||||||
} else {
|
} else {
|
||||||
const updatedProducts = inOrderProducts.map((p) => {
|
const updatedProducts = inOrderProducts.map((p) => {
|
||||||
if (p.productId === productId) {
|
if (p.productId === productId) {
|
||||||
return { ...p, quantity: Math.min(quantity, p.maxQuantity) };
|
return { ...p, count: Math.min(quantity, p.maxQuantity) };
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
});
|
});
|
||||||
@@ -198,7 +202,7 @@ export class POSStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInOrderProductFee(productId: number, fee: string) {
|
updateInOrderProductFee(productId: number, fee: number) {
|
||||||
const inOrderProducts = this.state$().inOrderProducts;
|
const inOrderProducts = this.state$().inOrderProducts;
|
||||||
|
|
||||||
if (inOrderProducts.some((p) => p.productId === productId)) {
|
if (inOrderProducts.some((p) => p.productId === productId)) {
|
||||||
@@ -215,4 +219,22 @@ export class POSStore {
|
|||||||
resetInOrderProducts() {
|
resetInOrderProducts() {
|
||||||
this.setState({ inOrderProducts: [] });
|
this.setState({ inOrderProducts: [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSelectedCustomer(customer: Maybe<ICustomerResponse>) {
|
||||||
|
console.log(customer);
|
||||||
|
|
||||||
|
this.setState({ selectedCustomer: customer });
|
||||||
|
}
|
||||||
|
|
||||||
|
submitOrder() {
|
||||||
|
const orderPayload = {
|
||||||
|
customerId: this.selectedCustomer()?.id,
|
||||||
|
items: this.inOrderProducts()?.map((item) => ({
|
||||||
|
productId: item.productId,
|
||||||
|
count: item.count,
|
||||||
|
fee: item.fee,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
this.service.submitOrder(orderPayload).subscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
header="فرم برند کالا"
|
header="فرم برند کالا"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
[style]="{ width: '500px' }"
|
[style]="{ width: '500px', zIndex: '10000' }"
|
||||||
[closable]="true"
|
[closable]="true"
|
||||||
appendTo="body"
|
appendTo="body"
|
||||||
>
|
>
|
||||||
|
|||||||
+4
-3
@@ -28,19 +28,20 @@ export class PurchaseReceiptProductRowComponent {
|
|||||||
|
|
||||||
@Output() onRemove = new EventEmitter<void>();
|
@Output() onRemove = new EventEmitter<void>();
|
||||||
|
|
||||||
editMode = signal(false);
|
editMode = signal(true);
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.purchaseItemControl?.controls.product.valueChanges.subscribe((res) => {
|
||||||
|
this.purchaseItemControl?.controls.fee.setValue(Number(res?.salePrice) || 0);
|
||||||
|
});
|
||||||
this.purchaseItemControl?.controls.count.valueChanges.subscribe(() => {
|
this.purchaseItemControl?.controls.count.valueChanges.subscribe(() => {
|
||||||
this.updateTotal();
|
this.updateTotal();
|
||||||
});
|
});
|
||||||
this.purchaseItemControl?.controls.fee.valueChanges.subscribe(() => {
|
this.purchaseItemControl?.controls.fee.valueChanges.subscribe(() => {
|
||||||
this.updateTotal();
|
this.updateTotal();
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('purchase item control', this.purchaseItemControl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTotal() {
|
updateTotal() {
|
||||||
|
|||||||
+12
-12
@@ -6,9 +6,9 @@
|
|||||||
<div class="grid grid-cols-2 gap-4 border-b border-surface-700 pb-4">
|
<div class="grid grid-cols-2 gap-4 border-b border-surface-700 pb-4">
|
||||||
<div class="grid grid-cols-1 gap-2">
|
<div class="grid grid-cols-1 gap-2">
|
||||||
<div class="w-full flex items-center gap-2 h-10">
|
<div class="w-full flex items-center gap-2 h-10">
|
||||||
<span [class]="formIsSubmitted() && form.controls.inventory.invalid ? ' text-error' : 'text-muted-color'"
|
<span [class]="formIsSubmitted() && form.controls.inventory.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
>انبار:</span
|
انبار:
|
||||||
>
|
</span>
|
||||||
<shared-inline-edit>
|
<shared-inline-edit>
|
||||||
<ng-template #data>
|
<ng-template #data>
|
||||||
<span class="font-bold">{{ form.controls.inventory.value?.name || "وارد نشده" }}</span>
|
<span class="font-bold">{{ form.controls.inventory.value?.name || "وارد نشده" }}</span>
|
||||||
@@ -24,9 +24,9 @@
|
|||||||
</shared-inline-edit>
|
</shared-inline-edit>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2 h-10">
|
<div class="w-full flex items-center gap-2 h-10">
|
||||||
<span [class]="formIsSubmitted() && form.controls.supplier.invalid ? ' text-error' : 'text-muted-color'"
|
<span [class]="formIsSubmitted() && form.controls.supplier.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
>تامین کننده:</span
|
تامین کننده:
|
||||||
>
|
</span>
|
||||||
<shared-inline-edit>
|
<shared-inline-edit>
|
||||||
<ng-template #data>
|
<ng-template #data>
|
||||||
<span class="font-bold">{{ form.controls.supplier.value?.fullname || "وارد نشده" }}</span>
|
<span class="font-bold">{{ form.controls.supplier.value?.fullname || "وارد نشده" }}</span>
|
||||||
@@ -46,9 +46,9 @@
|
|||||||
<div class="">
|
<div class="">
|
||||||
<div class="flex flex-col gap-2 max-w-xs items-end ms-auto w-full">
|
<div class="flex flex-col gap-2 max-w-xs items-end ms-auto w-full">
|
||||||
<div class="w-full flex items-center gap-2 h-10">
|
<div class="w-full flex items-center gap-2 h-10">
|
||||||
<span [class]="formIsSubmitted() && form.controls.code.invalid ? ' text-error' : 'text-muted-color'"
|
<span [class]="formIsSubmitted() && form.controls.code.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
>شماره رسید:</span
|
شماره رسید:
|
||||||
>
|
</span>
|
||||||
<shared-inline-edit>
|
<shared-inline-edit>
|
||||||
<ng-template #data>
|
<ng-template #data>
|
||||||
<span class="font-bold">{{ form.controls.code.value || "وارد نشده" }}</span>
|
<span class="font-bold">{{ form.controls.code.value || "وارد نشده" }}</span>
|
||||||
@@ -59,9 +59,9 @@
|
|||||||
</shared-inline-edit>
|
</shared-inline-edit>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2 h-10">
|
<div class="w-full flex items-center gap-2 h-10">
|
||||||
<span [class]="formIsSubmitted() && form.controls.buyAt.invalid ? ' text-error' : 'text-muted-color'"
|
<span [class]="formIsSubmitted() && form.controls.buyAt.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
>تاریخ رسید:</span
|
تاریخ رسید:
|
||||||
>
|
</span>
|
||||||
<shared-inline-edit>
|
<shared-inline-edit>
|
||||||
<ng-template #data>
|
<ng-template #data>
|
||||||
<span class="font-bold">{{ form.controls.buyAt.value || "وارد نشده" }}</span>
|
<span class="font-bold">{{ form.controls.buyAt.value || "وارد نشده" }}</span>
|
||||||
|
|||||||
+22
-16
@@ -12,6 +12,7 @@ import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, inject, Input, signal } from '@angular/core';
|
import { Component, 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 { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { Card } from 'primeng/card';
|
import { Card } from 'primeng/card';
|
||||||
import { TableModule } from 'primeng/table';
|
import { TableModule } from 'primeng/table';
|
||||||
@@ -91,22 +92,22 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
] as IColumn[];
|
] as IColumn[];
|
||||||
|
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
totalAmount: [300000, [Validators.required, Validators.min(0)]],
|
totalAmount: [0, [Validators.required, Validators.min(0)]],
|
||||||
code: ['122132', [Validators.required]],
|
code: ['', [Validators.required]],
|
||||||
isSettled: [false],
|
isSettled: [false],
|
||||||
buyAt: ['2025-12-01', Validators.required],
|
buyAt: [dayjs().calendar('jalali').format('YYYY/MM/DD'), Validators.required],
|
||||||
description: [''],
|
description: [''],
|
||||||
products: this.fb.array([
|
products: this.fb.array([
|
||||||
this.fb.group({
|
this.fb.group({
|
||||||
product: [{ id: 1 } as Maybe<IProductResponse>, [Validators.required]],
|
product: [null as Maybe<IProductResponse>, [Validators.required]],
|
||||||
count: [2, [Validators.required, Validators.min(1)]],
|
count: [0, [Validators.required, Validators.min(1)]],
|
||||||
fee: [150000, [Validators.required, Validators.min(0)]],
|
fee: [0, [Validators.required, Validators.min(0)]],
|
||||||
description: [''],
|
description: [''],
|
||||||
total: [300000, [Validators.required, Validators.min(0)]],
|
total: [0, [Validators.required, Validators.min(0)]],
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
inventory: [{ id: 2 } as Maybe<IInventorySummaryResponse>, [Validators.required]],
|
inventory: [null as Maybe<IInventorySummaryResponse>, [Validators.required]],
|
||||||
supplier: [{ id: 1 } as Maybe<ISupplierResponse>, [Validators.required]],
|
supplier: [null as Maybe<ISupplierResponse>, [Validators.required]],
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -114,6 +115,8 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
this.form.controls.products.valueChanges.subscribe((products) => {
|
this.form.controls.products.valueChanges.subscribe((products) => {
|
||||||
|
console.log('first');
|
||||||
|
|
||||||
let totalAmount = 0;
|
let totalAmount = 0;
|
||||||
products.forEach((p: any) => {
|
products.forEach((p: any) => {
|
||||||
totalAmount += p.total || 0;
|
totalAmount += p.total || 0;
|
||||||
@@ -126,14 +129,17 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.formIsSubmitted.set(false);
|
this.formIsSubmitted.set(false);
|
||||||
|
this.form.controls.products.controls.pop();
|
||||||
if (this.product) {
|
if (this.product) {
|
||||||
this.form.controls.products.at(0).setValue({
|
this.form.controls.products.setValue([
|
||||||
product: this.product,
|
{
|
||||||
count: 0,
|
product: this.product,
|
||||||
fee: 0,
|
count: 0,
|
||||||
description: '',
|
fee: 0,
|
||||||
total: 0,
|
description: '',
|
||||||
});
|
total: 0,
|
||||||
|
},
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
import { Tag } from 'primeng/tag';
|
import { Tag } from 'primeng/tag';
|
||||||
|
import { MovementType } from '../movementTypes';
|
||||||
import { MovementReferenceType } from './types';
|
import { MovementReferenceType } from './types';
|
||||||
import { getMovementReferenceTypeColor, getMovementReferenceTypeText } from './utils';
|
import { getMovementReferenceTypeColor, getMovementReferenceTypeText } from './utils';
|
||||||
|
|
||||||
@@ -10,10 +11,11 @@ import { getMovementReferenceTypeColor, getMovementReferenceTypeText } from './u
|
|||||||
})
|
})
|
||||||
export class CatalogMovementReferenceTagComponent {
|
export class CatalogMovementReferenceTagComponent {
|
||||||
@Input() type!: MovementReferenceType;
|
@Input() type!: MovementReferenceType;
|
||||||
|
@Input() movementType?: MovementType;
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
get text() {
|
get text() {
|
||||||
return getMovementReferenceTypeText(this.type);
|
return getMovementReferenceTypeText(this.type, this.movementType);
|
||||||
}
|
}
|
||||||
get color() {
|
get color() {
|
||||||
return getMovementReferenceTypeColor(this.type);
|
return getMovementReferenceTypeColor(this.type);
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { TagSeverity } from '@/core/models/tag';
|
import { TagSeverity } from '@/core/models/tag';
|
||||||
|
import { MovementType } from '../movementTypes';
|
||||||
import { MovementReferenceType } from './types';
|
import { MovementReferenceType } from './types';
|
||||||
|
|
||||||
export const getMovementReferenceTypeText = (movementType: MovementReferenceType): string => {
|
export const getMovementReferenceTypeText = (
|
||||||
|
movementType: MovementReferenceType,
|
||||||
|
type?: MovementType,
|
||||||
|
): string => {
|
||||||
switch (movementType) {
|
switch (movementType) {
|
||||||
case MovementReferenceType.PURCHASE:
|
case MovementReferenceType.PURCHASE:
|
||||||
return 'خرید';
|
return 'خرید';
|
||||||
@@ -10,6 +14,12 @@ export const getMovementReferenceTypeText = (movementType: MovementReferenceType
|
|||||||
case MovementReferenceType.ADJUSTMENT:
|
case MovementReferenceType.ADJUSTMENT:
|
||||||
return 'تعدیل';
|
return 'تعدیل';
|
||||||
case MovementReferenceType.INVENTORY_TRANSFER:
|
case MovementReferenceType.INVENTORY_TRANSFER:
|
||||||
|
if (type === MovementType.IN) {
|
||||||
|
return 'دریافت از انبار دیگر';
|
||||||
|
} else {
|
||||||
|
return 'ارسال به انبار دیگر';
|
||||||
|
}
|
||||||
|
default:
|
||||||
return 'انتقال بین انبارها';
|
return 'انتقال بین انبارها';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
import { Component, Input, signal } from '@angular/core';
|
import { Component, Input, model, signal } from '@angular/core';
|
||||||
import { FormControl } from '@angular/forms';
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
export interface ISelectItem {
|
export interface ISelectItem {
|
||||||
@@ -12,7 +12,7 @@ export interface ISelectItem {
|
|||||||
template: '',
|
template: '',
|
||||||
})
|
})
|
||||||
export abstract class AbstractSelectComponent<T = ISelectItem> {
|
export abstract class AbstractSelectComponent<T = ISelectItem> {
|
||||||
@Input() control!: FormControl<Maybe<number | T>>;
|
@Input() control = new FormControl<Maybe<number | T>>(null);
|
||||||
@Input() canInsert: boolean = false;
|
@Input() canInsert: boolean = false;
|
||||||
@Input() showLabel: boolean = true;
|
@Input() showLabel: boolean = true;
|
||||||
@Input() showErrors: boolean = true;
|
@Input() showErrors: boolean = true;
|
||||||
@@ -22,20 +22,29 @@ export abstract class AbstractSelectComponent<T = ISelectItem> {
|
|||||||
loading = signal(false);
|
loading = signal(false);
|
||||||
items = signal<Maybe<T[]>>(null);
|
items = signal<Maybe<T[]>>(null);
|
||||||
isOpenFormDialog = signal(false);
|
isOpenFormDialog = signal(false);
|
||||||
|
value = model<Maybe<T>>(null);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
if (this.value()) {
|
||||||
|
this.control.setValue(this.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.control.valueChanges.subscribe((val) => {
|
||||||
|
this.value.set(val as Maybe<T>);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
abstract getData(): void;
|
abstract getData(): void;
|
||||||
// abstract getLabel(): string;
|
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.getData();
|
this.getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenForm() {
|
onOpenForm() {
|
||||||
// Override in subclass if needed
|
this.isOpenFormDialog.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
get selectOptionValue() {
|
get selectOptionValue() {
|
||||||
if (!this.control) return undefined;
|
|
||||||
if (this.isFullDataOptionValue) {
|
if (this.isFullDataOptionValue) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="text-center!">{{ i + 1 }}</td>
|
<td class="text-center!">{{ i + 1 }}</td>
|
||||||
<td class="text-center!" [jalaliDate]="item.createdAt"></td>
|
<td class="text-center!" [jalaliDate]="item.createdAt"></td>
|
||||||
<td class="text-center!"><catalog-movement-reference-tag [type]="item.referenceType" /></td>
|
<td class="text-center!">
|
||||||
|
<catalog-movement-reference-tag [type]="item.referenceType" [movementType]="item.type" />
|
||||||
|
</td>
|
||||||
<td class="text-center!">{{ item.referenceId || "-" }}</td>
|
<td class="text-center!">{{ item.referenceId || "-" }}</td>
|
||||||
<td class="text-center!">{{ item.supplier?.name || "-" }}</td>
|
<td class="text-center!">{{ item.supplier?.name || "-" }}</td>
|
||||||
<td class="text-center!">{{ item.inventory.name || "-" }}</td>
|
<td class="text-center!">{{ item.inventory.name || "-" }}</td>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
ViewChild,
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import flatpickr from 'flatpickr-wrap';
|
import flatpickr from 'flatpickr-wrap';
|
||||||
import { BaseOptions } from 'flatpickr-wrap/dist/types/options';
|
import { BaseOptions } from 'flatpickr-wrap/dist/types/options';
|
||||||
import { InputTextModule } from 'primeng/inputtext';
|
import { InputTextModule } from 'primeng/inputtext';
|
||||||
@@ -40,6 +41,7 @@ export class UikitFlatpickrJalaliComponent implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.fpInstance = flatpickr(this.wrapperRef.nativeElement, {
|
this.fpInstance = flatpickr(this.wrapperRef.nativeElement, {
|
||||||
...this.options,
|
...this.options,
|
||||||
|
now: dayjs().calendar('jalali').format('YYYY/MM/DD'),
|
||||||
altInputClass: 'p-inputtext w-full',
|
altInputClass: 'p-inputtext w-full',
|
||||||
onChange: (selectedDates: Date[], dateStr: string) => {
|
onChange: (selectedDates: Date[], dateStr: string) => {
|
||||||
this.valueChange.emit(dateStr);
|
this.valueChange.emit(dateStr);
|
||||||
|
|||||||
Reference in New Issue
Block a user