feat: optimize performance with lazy loading and change detection improvements
chore: update build configurations and remove unused styles fix: enhance user experience with loading indicators and improved asset management
This commit is contained in:
+10
-4
@@ -55,13 +55,13 @@
|
|||||||
"production": {
|
"production": {
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
"maximumError": "3MB",
|
"maximumError": "2.5MB",
|
||||||
"maximumWarning": "2MB",
|
"maximumWarning": "1.5MB",
|
||||||
"type": "initial"
|
"type": "initial"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"maximumError": "8kB",
|
"maximumError": "6kB",
|
||||||
"maximumWarning": "4kB",
|
"maximumWarning": "3kB",
|
||||||
"type": "anyComponentStyle"
|
"type": "anyComponentStyle"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -136,6 +136,12 @@
|
|||||||
},
|
},
|
||||||
"defaultConfiguration": "production",
|
"defaultConfiguration": "production",
|
||||||
"options": {
|
"options": {
|
||||||
|
"allowedCommonJsDependencies": [
|
||||||
|
"dayjs",
|
||||||
|
"dayjs/locale/fa",
|
||||||
|
"dayjs/plugin/relativeTime",
|
||||||
|
"flatpickr-wrap/dist/l10n/fa.js"
|
||||||
|
],
|
||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
"glob": "**/*",
|
"glob": "**/*",
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
||||||
"appData": {
|
"appData": {
|
||||||
"appVersion": "0.0.0",
|
"appVersion": "0.0.0",
|
||||||
"buildDate": "2026-05-04T18:58:47.135Z"
|
"buildDate": "2026-05-10T09:04:30.388Z"
|
||||||
},
|
},
|
||||||
"assetGroups": [
|
"assetGroups": [
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 524 KiB |
@@ -1,10 +1,11 @@
|
|||||||
import { Component, EventEmitter, inject, Output } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, EventEmitter, inject, Output } from '@angular/core';
|
||||||
import { Skeleton } from 'primeng/skeleton';
|
import { Skeleton } from 'primeng/skeleton';
|
||||||
import { PosLandingStore } from '../store/main.store';
|
import { PosLandingStore } from '../store/main.store';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-good-categories',
|
selector: 'pos-good-categories',
|
||||||
templateUrl: './categories.component.html',
|
templateUrl: './categories.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [Skeleton],
|
imports: [Skeleton],
|
||||||
})
|
})
|
||||||
export class PosGoodCategoriesComponent {
|
export class PosGoodCategoriesComponent {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (selectedGoodToAdd()) {
|
@defer (when showPayloadForm()) {
|
||||||
<pos-payload-form-dialog
|
<pos-payload-form-dialog
|
||||||
[(visible)]="showPayloadForm"
|
[(visible)]="showPayloadForm"
|
||||||
[good]="selectedGoodToAdd()!"
|
[good]="selectedGoodToAdd()!"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
||||||
import { SearchInputComponent } from '@/shared/components/search/search-input.component';
|
import { SearchInputComponent } from '@/shared/components/search/search-input.component';
|
||||||
import { Component, computed, inject, Input, signal } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, computed, inject, Input, signal } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { Divider } from 'primeng/divider';
|
import { Divider } from 'primeng/divider';
|
||||||
import { SelectButton } from 'primeng/selectbutton';
|
import { SelectButton } from 'primeng/selectbutton';
|
||||||
@@ -14,6 +14,7 @@ import { PayloadFormDialogComponent } from './payloads';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-goods',
|
selector: 'pos-goods',
|
||||||
templateUrl: './goods.component.html',
|
templateUrl: './goods.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [
|
imports: [
|
||||||
PosGoodCategoriesComponent,
|
PosGoodCategoriesComponent,
|
||||||
PosGoodsListViewComponent,
|
PosGoodsListViewComponent,
|
||||||
|
|||||||
@@ -6,9 +6,14 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
} @else {
|
} @else {
|
||||||
@for (good of goods(); track good.id) {
|
@for (good of visibleGoods(); track good.id) {
|
||||||
<div class="flex-1 bg-surface-card rounded-lg p-1 shadow-xs" (click)="addProduct(good)">
|
<div class="flex-1 bg-surface-card rounded-lg p-1 shadow-xs" (click)="addProduct(good)">
|
||||||
<img [src]="good.image_url || goodPlaceholder" class="w-full aspect-[1.3] object-cover rounded-md" />
|
<img
|
||||||
|
[src]="good.image_url || goodPlaceholder"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
class="w-full aspect-[1.3] object-cover rounded-md"
|
||||||
|
/>
|
||||||
<div class="mt-2 text-center">
|
<div class="mt-2 text-center">
|
||||||
<span class="text-lg font-bold text-center">
|
<span class="text-lg font-bold text-center">
|
||||||
{{ good.name }}
|
{{ good.name }}
|
||||||
@@ -25,3 +30,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@if (!loading() && hasMore()) {
|
||||||
|
<div class="flex justify-center mt-3">
|
||||||
|
<button pButton type="button" outlined (click)="loadMore()">نمایش کالاهای بیشتر</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
||||||
import { Component, computed, EventEmitter, inject, Output } from '@angular/core';
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
computed,
|
||||||
|
EventEmitter,
|
||||||
|
HostListener,
|
||||||
|
inject,
|
||||||
|
Output,
|
||||||
|
signal,
|
||||||
|
} from '@angular/core';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { Skeleton } from 'primeng/skeleton';
|
import { Skeleton } from 'primeng/skeleton';
|
||||||
import images from 'src/assets/images';
|
import images from 'src/assets/images';
|
||||||
@@ -8,6 +17,7 @@ import { PosLandingStore } from '../store/main.store';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-good-grid-view',
|
selector: 'pos-good-grid-view',
|
||||||
templateUrl: './grid-view.component.html',
|
templateUrl: './grid-view.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [ButtonDirective, Skeleton],
|
imports: [ButtonDirective, Skeleton],
|
||||||
})
|
})
|
||||||
export class PosGoodsGridViewComponent {
|
export class PosGoodsGridViewComponent {
|
||||||
@@ -15,6 +25,10 @@ export class PosGoodsGridViewComponent {
|
|||||||
@Output() onAdd = new EventEmitter<IGoodResponse>();
|
@Output() onAdd = new EventEmitter<IGoodResponse>();
|
||||||
|
|
||||||
goods = computed(() => this.store.filteredGoods());
|
goods = computed(() => this.store.filteredGoods());
|
||||||
|
private readonly pageSize = 80;
|
||||||
|
readonly renderLimit = signal(this.pageSize);
|
||||||
|
visibleGoods = computed(() => this.goods()?.slice(0, this.renderLimit()));
|
||||||
|
hasMore = computed(() => (this.goods()?.length || 0) > (this.visibleGoods()?.length || 0));
|
||||||
loading = computed(() => this.store.getGoodsLoading());
|
loading = computed(() => this.store.getGoodsLoading());
|
||||||
|
|
||||||
goodPlaceholder = images.placeholders.default;
|
goodPlaceholder = images.placeholders.default;
|
||||||
@@ -22,4 +36,15 @@ export class PosGoodsGridViewComponent {
|
|||||||
addProduct(good: IGoodResponse) {
|
addProduct(good: IGoodResponse) {
|
||||||
this.onAdd.emit(good);
|
this.onAdd.emit(good);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadMore() {
|
||||||
|
this.renderLimit.update((limit) => limit + this.pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:scroll')
|
||||||
|
onWindowScroll() {
|
||||||
|
if (!this.hasMore()) return;
|
||||||
|
const nearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 300;
|
||||||
|
if (nearBottom) this.loadMore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,21 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
} @else {
|
} @else {
|
||||||
@for (good of goods(); track good.id) {
|
@for (good of visibleGoods(); track good.id) {
|
||||||
<div class="flex items-center bg-surface-card rounded-lg p-1 shadow-xs gap-2">
|
<div class="flex items-center bg-surface-card rounded-lg p-1 shadow-xs gap-2">
|
||||||
<div class="grow flex items-center gap-2">
|
<div class="grow flex items-center gap-2">
|
||||||
<img [src]="good.image_url || goodPlaceholder" class="w-12 h-12 object-cover rounded-md" />
|
<img
|
||||||
|
[src]="good.image_url || goodPlaceholder"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
class="w-12 h-12 object-cover rounded-md"
|
||||||
|
/>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<span class="text-lg font-bold">
|
<span class="text-lg font-bold">
|
||||||
{{ good.name }}
|
{{ good.name }}
|
||||||
@if (!good.is_default_guild_good) {
|
@if (!good.is_default_guild_good) {
|
||||||
<small class="text-xs text-muted-color">*</small>
|
<small class="text-xs text-muted-color">*</small>
|
||||||
}
|
}
|
||||||
<!-- <small class="text-xs text-muted-color">({{ good.quantity }})</small> -->
|
|
||||||
</span>
|
</span>
|
||||||
<span class="text-sm text-muted-color">
|
<span class="text-sm text-muted-color">
|
||||||
{{ good.sku }}
|
{{ good.sku }}
|
||||||
@@ -24,10 +28,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="shrink-0 flex items-center justify-between gap-3">
|
<div class="shrink-0 flex items-center justify-between gap-3">
|
||||||
<!-- <span [appPriceMask]="good.salePrice" class="text-base font-bold"></span> -->
|
|
||||||
<button pButton type="button" icon="pi pi-plus" size="small" (click)="addGood(good)">انتخاب</button>
|
<button pButton type="button" icon="pi pi-plus" size="small" (click)="addGood(good)">انتخاب</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@if (hasMore()) {
|
||||||
|
<button pButton type="button" outlined class="mx-auto" (click)="loadMore()">نمایش کالاهای بیشتر</button>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
||||||
import { Component, computed, EventEmitter, inject, Output } from '@angular/core';
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
computed,
|
||||||
|
EventEmitter,
|
||||||
|
HostListener,
|
||||||
|
inject,
|
||||||
|
Output,
|
||||||
|
signal,
|
||||||
|
} from '@angular/core';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { Skeleton } from 'primeng/skeleton';
|
import { Skeleton } from 'primeng/skeleton';
|
||||||
import images from 'src/assets/images';
|
import images from 'src/assets/images';
|
||||||
@@ -8,6 +17,7 @@ import { PosLandingStore } from '../store/main.store';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-goods-list-view',
|
selector: 'pos-goods-list-view',
|
||||||
templateUrl: './list-view.component.html',
|
templateUrl: './list-view.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [ButtonDirective, Skeleton],
|
imports: [ButtonDirective, Skeleton],
|
||||||
})
|
})
|
||||||
export class PosGoodsListViewComponent {
|
export class PosGoodsListViewComponent {
|
||||||
@@ -15,6 +25,10 @@ export class PosGoodsListViewComponent {
|
|||||||
@Output() onAdd = new EventEmitter<IGoodResponse>();
|
@Output() onAdd = new EventEmitter<IGoodResponse>();
|
||||||
|
|
||||||
goods = computed(() => this.store.filteredGoods());
|
goods = computed(() => this.store.filteredGoods());
|
||||||
|
private readonly pageSize = 120;
|
||||||
|
readonly renderLimit = signal(this.pageSize);
|
||||||
|
visibleGoods = computed(() => this.goods()?.slice(0, this.renderLimit()));
|
||||||
|
hasMore = computed(() => (this.goods()?.length || 0) > (this.visibleGoods()?.length || 0));
|
||||||
loading = computed(() => this.store.getGoodsLoading());
|
loading = computed(() => this.store.getGoodsLoading());
|
||||||
|
|
||||||
goodPlaceholder = images.placeholders.default;
|
goodPlaceholder = images.placeholders.default;
|
||||||
@@ -22,4 +36,15 @@ export class PosGoodsListViewComponent {
|
|||||||
addGood(good: IGoodResponse) {
|
addGood(good: IGoodResponse) {
|
||||||
this.onAdd.emit(good);
|
this.onAdd.emit(good);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadMore() {
|
||||||
|
this.renderLimit.update((limit) => limit + this.pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:scroll')
|
||||||
|
onWindowScroll() {
|
||||||
|
if (!this.hasMore()) return;
|
||||||
|
const nearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 300;
|
||||||
|
if (nearBottom) this.loadMore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -2,6 +2,8 @@
|
|||||||
<div class="flex gap-3 items-center">
|
<div class="flex gap-3 items-center">
|
||||||
<img
|
<img
|
||||||
[src]="inOrderGood.good.image_url || placeholderImage"
|
[src]="inOrderGood.good.image_url || placeholderImage"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
class="w-24 h-24 rounded-md bg-surface-100 object-cover shrink-0 border border-surface-border"
|
class="w-24 h-24 rounded-md bg-surface-100 object-cover shrink-0 border border-surface-border"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-col grow justify-between overflow-hidden">
|
<div class="flex flex-col grow justify-between overflow-hidden">
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
import { PriceMaskDirective } from '@/shared/directives';
|
import { PriceMaskDirective } from '@/shared/directives';
|
||||||
import { enumTranslator } from '@/utils';
|
import { enumTranslator } from '@/utils';
|
||||||
import { Component, inject, Input, signal } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, inject, Input, signal } from '@angular/core';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import images from 'src/assets/images';
|
import images from 'src/assets/images';
|
||||||
import { IPosInOrderGood } from '../../models';
|
import { IPosInOrderGood } from '../../models';
|
||||||
@@ -10,6 +10,7 @@ import { PayloadFormDialogComponent } from '../payload-form.component';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-order-card-template',
|
selector: 'pos-order-card-template',
|
||||||
templateUrl: './order-card-template.component.html',
|
templateUrl: './order-card-template.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [ButtonDirective, PayloadFormDialogComponent, PriceMaskDirective],
|
imports: [ButtonDirective, PayloadFormDialogComponent, PriceMaskDirective],
|
||||||
})
|
})
|
||||||
export class OrderCardTemplateComponent {
|
export class OrderCardTemplateComponent {
|
||||||
|
|||||||
@@ -61,6 +61,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<pos-order-customer-dialog [(visible)]="isVisibleCustomerForm" (onSubmit)="submitCustomer()" />
|
@defer (when isVisibleCustomerForm()) {
|
||||||
|
<pos-order-customer-dialog [(visible)]="isVisibleCustomerForm" (onSubmit)="submitCustomer()" />
|
||||||
|
}
|
||||||
<!-- <pos-pre-invoice-dialog [(visible)]="isVisiblePreInvoiceForm" /> -->
|
<!-- <pos-pre-invoice-dialog [(visible)]="isVisiblePreInvoiceForm" /> -->
|
||||||
<pos-payment-form-dialog [(visible)]="isVisiblePaymentForm" (onSubmit)="submitPayment($event)" />
|
@defer (when isVisiblePaymentForm()) {
|
||||||
|
<pos-payment-form-dialog [(visible)]="isVisiblePaymentForm" (onSubmit)="submitPayment($event)" />
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// 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 { ICustomerResponse } from '@/modules/customers/models';
|
||||||
import { KeyValueComponent } from '@/shared/components';
|
import { KeyValueComponent } from '@/shared/components';
|
||||||
import { Component, computed, EventEmitter, inject, Output, signal } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, computed, EventEmitter, inject, Output, signal } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { Card } from 'primeng/card';
|
import { Card } from 'primeng/card';
|
||||||
@@ -17,6 +17,7 @@ import { POSOrderPriceInfoCardComponent } from './price-info-card.component';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-order-section',
|
selector: 'pos-order-section',
|
||||||
templateUrl: './order-section.component.html',
|
templateUrl: './order-section.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [
|
imports: [
|
||||||
ButtonDirective,
|
ButtonDirective,
|
||||||
POSOrderPriceInfoCardComponent,
|
POSOrderPriceInfoCardComponent,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { AmountPercentageInputComponent } from '@/shared/components/amountPercen
|
|||||||
import { TGoldKarat } from '@/shared/localEnum/constants/goldKarat';
|
import { TGoldKarat } from '@/shared/localEnum/constants/goldKarat';
|
||||||
import { formatWithCurrency } from '@/utils';
|
import { formatWithCurrency } from '@/utils';
|
||||||
import { Component, computed, EventEmitter, Output, signal } from '@angular/core';
|
import { Component, computed, EventEmitter, Output, signal } from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { SelectButton, SelectButtonChangeEvent } from 'primeng/selectbutton';
|
import { SelectButton, SelectButtonChangeEvent } from 'primeng/selectbutton';
|
||||||
@@ -71,35 +72,19 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
form.valueChanges.subscribe((value) => {
|
form.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
|
||||||
this.updateCalculateAmount(value as any);
|
this.updateCalculateAmount(value as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
form.controls.payload.controls.profit_amount.valueChanges.subscribe((value) => {
|
form.controls.payload.controls.profit_amount.valueChanges.pipe(takeUntilDestroyed()).subscribe(() => {
|
||||||
// if ((form.controls.discount_amount.value || 0) > (value || 0)) {
|
// if ((form.controls.discount_amount.value || 0) > (value || 0)) {
|
||||||
form.controls.discount_amount.setValue(0);
|
form.controls.discount_amount.setValue(0);
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
form.controls.payload.controls.profit_percentage.valueChanges.subscribe((value) => {
|
form.controls.payload.controls.profit_percentage.valueChanges.pipe(takeUntilDestroyed()).subscribe(() => {
|
||||||
form.controls.discount_amount.setValue(0);
|
form.controls.discount_amount.setValue(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
form.setValue({
|
|
||||||
unit_price: 200_000_000,
|
|
||||||
quantity: 2,
|
|
||||||
discount_amount: 0,
|
|
||||||
discount_percentage: 0,
|
|
||||||
payload: {
|
|
||||||
commission_amount: 0,
|
|
||||||
commission_percentage: 10,
|
|
||||||
wages_amount: 0,
|
|
||||||
wages_percentage: 10,
|
|
||||||
profit_amount: 0,
|
|
||||||
profit_percentage: 10,
|
|
||||||
karat: '18',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return form;
|
return form;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { InputComponent } from '@/shared/components';
|
|||||||
import { AmountPercentageInputComponent } from '@/shared/components/amountPercentageInput/amount-percentage-input.component';
|
import { AmountPercentageInputComponent } from '@/shared/components/amountPercentageInput/amount-percentage-input.component';
|
||||||
import { formatWithCurrency, getGoodUnitTypeProperties, UnitType } from '@/utils';
|
import { formatWithCurrency, getGoodUnitTypeProperties, UnitType } from '@/utils';
|
||||||
import { Component, computed, EventEmitter, Input, Output, signal } from '@angular/core';
|
import { Component, computed, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { Button } from 'primeng/button';
|
import { Button } from 'primeng/button';
|
||||||
import { IPosOrderItem, IStandardPayload } from '../../../models';
|
import { IPosOrderItem, IStandardPayload } from '../../../models';
|
||||||
@@ -34,7 +35,7 @@ export class PosStandardPayloadFormComponent extends AbstractForm<
|
|||||||
discount_percentage: [0, [Validators.min(0), Validators.max(100)]],
|
discount_percentage: [0, [Validators.min(0), Validators.max(100)]],
|
||||||
});
|
});
|
||||||
|
|
||||||
form.valueChanges.subscribe((value) => {
|
form.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
|
||||||
this.updateCalculateAmount(value as Partial<IPosOrderItem<IStandardPayload>>);
|
this.updateCalculateAmount(value as Partial<IPosOrderItem<IStandardPayload>>);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { SharedDialogComponent } from '@/shared/components/dialog/dialog.compone
|
|||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
import { UikitFieldComponent } from '@/uikit';
|
import { UikitFieldComponent } from '@/uikit';
|
||||||
import { Component, computed, inject, signal } from '@angular/core';
|
import { Component, computed, inject, signal } from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { Select } from 'primeng/select';
|
import { Select } from 'primeng/select';
|
||||||
@@ -74,7 +75,7 @@ export class PosPaymentFormDialogComponent extends AbstractFormDialog<IPayment,
|
|||||||
terminals: this.fb.array([this.fb.control(0)]),
|
terminals: this.fb.array([this.fb.control(0)]),
|
||||||
});
|
});
|
||||||
|
|
||||||
form.valueChanges.subscribe((value) => {
|
form.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
|
||||||
const terminalTotal =
|
const terminalTotal =
|
||||||
(value.terminals || []).reduce((acc, curr) => (acc || 0) + (curr || 0), 0) || 0;
|
(value.terminals || []).reduce((acc, curr) => (acc || 0) + (curr || 0), 0) || 0;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { AbstractIsMobileComponent } from '@/shared/abstractClasses/abstract-is-
|
|||||||
import { SharedDialogComponent } from '@/shared/components';
|
import { SharedDialogComponent } from '@/shared/components';
|
||||||
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
|
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
|
||||||
import { PriceMaskDirective } from '@/shared/directives';
|
import { PriceMaskDirective } from '@/shared/directives';
|
||||||
import { Component, computed, inject, signal } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { PosGoodsComponent } from '../components/goods.component';
|
import { PosGoodsComponent } from '../components/goods.component';
|
||||||
import { PosOrderSectionComponent } from '../components/order/order-section.component';
|
import { PosOrderSectionComponent } from '../components/order/order-section.component';
|
||||||
@@ -17,6 +17,7 @@ import { PosLandingStore } from '../store/main.store';
|
|||||||
selector: 'pos-landing',
|
selector: 'pos-landing',
|
||||||
templateUrl: './root.component.html',
|
templateUrl: './root.component.html',
|
||||||
host: { class: 'grow overflow-hidden' },
|
host: { class: 'grow overflow-hidden' },
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
|
||||||
imports: [
|
imports: [
|
||||||
PosGoodsComponent,
|
PosGoodsComponent,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
||||||
import { InputComponent } from '@/shared/components';
|
import { InputComponent } from '@/shared/components';
|
||||||
import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
@@ -28,7 +27,6 @@ import { IPosSaleInvoicesFilterDto } from '../models';
|
|||||||
ButtonDirective,
|
ButtonDirective,
|
||||||
EnumSelectComponent,
|
EnumSelectComponent,
|
||||||
InputComponent,
|
InputComponent,
|
||||||
UikitFlatpickrJalaliComponent,
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PosSaleInvoicesFilterDrawerComponent implements OnChanges {
|
export class PosSaleInvoicesFilterDrawerComponent implements OnChanges {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { BreadcrumbComponent } from '@/shared/components';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, computed, ContentChild, inject, Renderer2, TemplateRef } from '@angular/core';
|
import { Component, computed, ContentChild, inject, Renderer2, TemplateRef } from '@angular/core';
|
||||||
import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
||||||
import { ProgressSpinner } from 'primeng/progressspinner';
|
|
||||||
import { filter, Subscription } from 'rxjs';
|
import { filter, Subscription } from 'rxjs';
|
||||||
import { LayoutService } from '../service/layout.service';
|
import { LayoutService } from '../service/layout.service';
|
||||||
import { AppFooter } from './app.footer.component';
|
import { AppFooter } from './app.footer.component';
|
||||||
@@ -14,15 +13,7 @@ import { AppTopbar } from './app.topbar.component';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-layout',
|
selector: 'app-layout',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [CommonModule, AppTopbar, AppSidebar, RouterModule, AppFooter, BreadcrumbComponent],
|
||||||
CommonModule,
|
|
||||||
AppTopbar,
|
|
||||||
AppSidebar,
|
|
||||||
RouterModule,
|
|
||||||
AppFooter,
|
|
||||||
BreadcrumbComponent,
|
|
||||||
ProgressSpinner,
|
|
||||||
],
|
|
||||||
templateUrl: './app.layout.component.html',
|
templateUrl: './app.layout.component.html',
|
||||||
})
|
})
|
||||||
export class AppLayout {
|
export class AppLayout {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
@use "./flatpicker.css";
|
@use "./flatpicker.css";
|
||||||
@use "./layout/layout.scss";
|
@use "./layout/layout.scss";
|
||||||
@use "primeicons/primeicons.css";
|
@use "primeicons/primeicons.css";
|
||||||
@use "./demo/demo.scss";
|
|
||||||
@use "./rtlSupport.scss";
|
@use "./rtlSupport.scss";
|
||||||
@use "./customize.scss";
|
@use "./customize.scss";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user