diff --git a/angular.json b/angular.json index 1a1d548..7790e20 100644 --- a/angular.json +++ b/angular.json @@ -55,13 +55,13 @@ "production": { "budgets": [ { - "maximumError": "3MB", - "maximumWarning": "2MB", + "maximumError": "2.5MB", + "maximumWarning": "1.5MB", "type": "initial" }, { - "maximumError": "8kB", - "maximumWarning": "4kB", + "maximumError": "6kB", + "maximumWarning": "3kB", "type": "anyComponentStyle" } ], @@ -136,6 +136,12 @@ }, "defaultConfiguration": "production", "options": { + "allowedCommonJsDependencies": [ + "dayjs", + "dayjs/locale/fa", + "dayjs/plugin/relativeTime", + "flatpickr-wrap/dist/l10n/fa.js" + ], "assets": [ { "glob": "**/*", diff --git a/ngsw-config.json b/ngsw-config.json index 5325311..074fee2 100644 --- a/ngsw-config.json +++ b/ngsw-config.json @@ -2,7 +2,7 @@ "$schema": "./node_modules/@angular/service-worker/config/schema.json", "appData": { "appVersion": "0.0.0", - "buildDate": "2026-05-04T18:58:47.135Z" + "buildDate": "2026-05-10T09:04:30.388Z" }, "assetGroups": [ { diff --git a/public-tis/branding/login.webp b/public-tis/branding/login.webp deleted file mode 100644 index 6e0ecb5..0000000 Binary files a/public-tis/branding/login.webp and /dev/null differ diff --git a/src/app/domains/pos/modules/landing/components/categories.component.ts b/src/app/domains/pos/modules/landing/components/categories.component.ts index 55798cd..dc4cd23 100644 --- a/src/app/domains/pos/modules/landing/components/categories.component.ts +++ b/src/app/domains/pos/modules/landing/components/categories.component.ts @@ -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 { PosLandingStore } from '../store/main.store'; @Component({ selector: 'pos-good-categories', templateUrl: './categories.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, imports: [Skeleton], }) export class PosGoodCategoriesComponent { diff --git a/src/app/domains/pos/modules/landing/components/goods.component.html b/src/app/domains/pos/modules/landing/components/goods.component.html index caccbe3..0fcb068 100644 --- a/src/app/domains/pos/modules/landing/components/goods.component.html +++ b/src/app/domains/pos/modules/landing/components/goods.component.html @@ -36,7 +36,7 @@ } - @if (selectedGoodToAdd()) { + @defer (when showPayloadForm()) { } } @else { - @for (good of goods(); track good.id) { + @for (good of visibleGoods(); track good.id) {
- +
{{ good.name }} @@ -25,3 +30,8 @@ } }
+@if (!loading() && hasMore()) { +
+ +
+} diff --git a/src/app/domains/pos/modules/landing/components/grid-view.component.ts b/src/app/domains/pos/modules/landing/components/grid-view.component.ts index 41ab119..f81f620 100644 --- a/src/app/domains/pos/modules/landing/components/grid-view.component.ts +++ b/src/app/domains/pos/modules/landing/components/grid-view.component.ts @@ -1,5 +1,14 @@ 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 { Skeleton } from 'primeng/skeleton'; import images from 'src/assets/images'; @@ -8,6 +17,7 @@ import { PosLandingStore } from '../store/main.store'; @Component({ selector: 'pos-good-grid-view', templateUrl: './grid-view.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, imports: [ButtonDirective, Skeleton], }) export class PosGoodsGridViewComponent { @@ -15,6 +25,10 @@ export class PosGoodsGridViewComponent { @Output() onAdd = new EventEmitter(); 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()); goodPlaceholder = images.placeholders.default; @@ -22,4 +36,15 @@ export class PosGoodsGridViewComponent { addProduct(good: IGoodResponse) { 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(); + } } diff --git a/src/app/domains/pos/modules/landing/components/list-view.component.html b/src/app/domains/pos/modules/landing/components/list-view.component.html index 1b0c217..6415ed3 100644 --- a/src/app/domains/pos/modules/landing/components/list-view.component.html +++ b/src/app/domains/pos/modules/landing/components/list-view.component.html @@ -6,17 +6,21 @@
} } @else { - @for (good of goods(); track good.id) { + @for (good of visibleGoods(); track good.id) {
- +
{{ good.name }} @if (!good.is_default_guild_good) { * } - {{ good.sku }} @@ -24,10 +28,12 @@
-
} + @if (hasMore()) { + + } } diff --git a/src/app/domains/pos/modules/landing/components/list-view.component.ts b/src/app/domains/pos/modules/landing/components/list-view.component.ts index 32d205a..6473798 100644 --- a/src/app/domains/pos/modules/landing/components/list-view.component.ts +++ b/src/app/domains/pos/modules/landing/components/list-view.component.ts @@ -1,5 +1,14 @@ 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 { Skeleton } from 'primeng/skeleton'; import images from 'src/assets/images'; @@ -8,6 +17,7 @@ import { PosLandingStore } from '../store/main.store'; @Component({ selector: 'pos-goods-list-view', templateUrl: './list-view.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, imports: [ButtonDirective, Skeleton], }) export class PosGoodsListViewComponent { @@ -15,6 +25,10 @@ export class PosGoodsListViewComponent { @Output() onAdd = new EventEmitter(); 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()); goodPlaceholder = images.placeholders.default; @@ -22,4 +36,15 @@ export class PosGoodsListViewComponent { addGood(good: IGoodResponse) { 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(); + } } diff --git a/src/app/domains/pos/modules/landing/components/order/order-card-template.component.html b/src/app/domains/pos/modules/landing/components/order/order-card-template.component.html index 461edd0..b5437b6 100644 --- a/src/app/domains/pos/modules/landing/components/order/order-card-template.component.html +++ b/src/app/domains/pos/modules/landing/components/order/order-card-template.component.html @@ -2,6 +2,8 @@
diff --git a/src/app/domains/pos/modules/landing/components/order/order-card-template.component.ts b/src/app/domains/pos/modules/landing/components/order/order-card-template.component.ts index 32bae4f..51f1f59 100644 --- a/src/app/domains/pos/modules/landing/components/order/order-card-template.component.ts +++ b/src/app/domains/pos/modules/landing/components/order/order-card-template.component.ts @@ -1,6 +1,6 @@ import { PriceMaskDirective } from '@/shared/directives'; 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 images from 'src/assets/images'; import { IPosInOrderGood } from '../../models'; @@ -10,6 +10,7 @@ import { PayloadFormDialogComponent } from '../payload-form.component'; @Component({ selector: 'pos-order-card-template', templateUrl: './order-card-template.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, imports: [ButtonDirective, PayloadFormDialogComponent, PriceMaskDirective], }) export class OrderCardTemplateComponent { diff --git a/src/app/domains/pos/modules/landing/components/order/order-section.component.html b/src/app/domains/pos/modules/landing/components/order/order-section.component.html index 424c024..30f16e8 100644 --- a/src/app/domains/pos/modules/landing/components/order/order-section.component.html +++ b/src/app/domains/pos/modules/landing/components/order/order-section.component.html @@ -61,6 +61,10 @@
- +@defer (when isVisibleCustomerForm()) { + +} - +@defer (when isVisiblePaymentForm()) { + +} diff --git a/src/app/domains/pos/modules/landing/components/order/order-section.component.ts b/src/app/domains/pos/modules/landing/components/order/order-section.component.ts index 30f3abb..d33cd74 100644 --- a/src/app/domains/pos/modules/landing/components/order/order-section.component.ts +++ b/src/app/domains/pos/modules/landing/components/order/order-section.component.ts @@ -1,7 +1,7 @@ // import { CustomersSelectComponent } from '@/modules/customers/components/select/select.component'; // import { ICustomerResponse } from '@/modules/customers/models'; 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 { ButtonDirective } from 'primeng/button'; import { Card } from 'primeng/card'; @@ -17,6 +17,7 @@ import { POSOrderPriceInfoCardComponent } from './price-info-card.component'; @Component({ selector: 'pos-order-section', templateUrl: './order-section.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, imports: [ ButtonDirective, POSOrderPriceInfoCardComponent, diff --git a/src/app/domains/pos/modules/landing/components/payloads/gold/form.component.ts b/src/app/domains/pos/modules/landing/components/payloads/gold/form.component.ts index 8f36792..4c9a3ed 100644 --- a/src/app/domains/pos/modules/landing/components/payloads/gold/form.component.ts +++ b/src/app/domains/pos/modules/landing/components/payloads/gold/form.component.ts @@ -6,6 +6,7 @@ import { AmountPercentageInputComponent } from '@/shared/components/amountPercen import { TGoldKarat } from '@/shared/localEnum/constants/goldKarat'; import { formatWithCurrency } from '@/utils'; import { Component, computed, EventEmitter, Output, signal } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { ButtonDirective } from 'primeng/button'; 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); }); - 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)) { 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.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; }; diff --git a/src/app/domains/pos/modules/landing/components/payloads/standard/form.component.ts b/src/app/domains/pos/modules/landing/components/payloads/standard/form.component.ts index ac7f3fd..b243a90 100644 --- a/src/app/domains/pos/modules/landing/components/payloads/standard/form.component.ts +++ b/src/app/domains/pos/modules/landing/components/payloads/standard/form.component.ts @@ -3,6 +3,7 @@ import { InputComponent } from '@/shared/components'; import { AmountPercentageInputComponent } from '@/shared/components/amountPercentageInput/amount-percentage-input.component'; import { formatWithCurrency, getGoodUnitTypeProperties, UnitType } from '@/utils'; import { Component, computed, EventEmitter, Input, Output, signal } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ReactiveFormsModule, Validators } from '@angular/forms'; import { Button } from 'primeng/button'; import { IPosOrderItem, IStandardPayload } from '../../../models'; @@ -34,7 +35,7 @@ export class PosStandardPayloadFormComponent extends AbstractForm< discount_percentage: [0, [Validators.min(0), Validators.max(100)]], }); - form.valueChanges.subscribe((value) => { + form.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => { this.updateCalculateAmount(value as Partial>); }); diff --git a/src/app/domains/pos/modules/landing/components/payment/form-dialog.component.ts b/src/app/domains/pos/modules/landing/components/payment/form-dialog.component.ts index 96d6d28..861ec13 100644 --- a/src/app/domains/pos/modules/landing/components/payment/form-dialog.component.ts +++ b/src/app/domains/pos/modules/landing/components/payment/form-dialog.component.ts @@ -7,6 +7,7 @@ import { SharedDialogComponent } from '@/shared/components/dialog/dialog.compone import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component'; import { UikitFieldComponent } from '@/uikit'; import { Component, computed, inject, signal } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { ButtonDirective } from 'primeng/button'; import { Select } from 'primeng/select'; @@ -74,7 +75,7 @@ export class PosPaymentFormDialogComponent extends AbstractFormDialog { + form.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => { const terminalTotal = (value.terminals || []).reduce((acc, curr) => (acc || 0) + (curr || 0), 0) || 0; diff --git a/src/app/domains/pos/modules/landing/views/root.component.ts b/src/app/domains/pos/modules/landing/views/root.component.ts index e0b370b..045fa15 100644 --- a/src/app/domains/pos/modules/landing/views/root.component.ts +++ b/src/app/domains/pos/modules/landing/views/root.component.ts @@ -5,7 +5,7 @@ import { AbstractIsMobileComponent } from '@/shared/abstractClasses/abstract-is- import { SharedDialogComponent } from '@/shared/components'; import { PageLoadingComponent } from '@/shared/components/page-loading.component'; 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 { PosGoodsComponent } from '../components/goods.component'; import { PosOrderSectionComponent } from '../components/order/order-section.component'; @@ -17,6 +17,7 @@ import { PosLandingStore } from '../store/main.store'; selector: 'pos-landing', templateUrl: './root.component.html', host: { class: 'grow overflow-hidden' }, + changeDetection: ChangeDetectionStrategy.OnPush, imports: [ PosGoodsComponent, diff --git a/src/app/domains/pos/modules/saleInvoices/components/filter-drawer.component.ts b/src/app/domains/pos/modules/saleInvoices/components/filter-drawer.component.ts index cc79b53..aa1ec03 100644 --- a/src/app/domains/pos/modules/saleInvoices/components/filter-drawer.component.ts +++ b/src/app/domains/pos/modules/saleInvoices/components/filter-drawer.component.ts @@ -1,6 +1,5 @@ import { EnumSelectComponent } from '@/shared/apiEnum/select.component'; import { InputComponent } from '@/shared/components'; -import { UikitFlatpickrJalaliComponent } from '@/uikit'; import { Component, EventEmitter, @@ -28,7 +27,6 @@ import { IPosSaleInvoicesFilterDto } from '../models'; ButtonDirective, EnumSelectComponent, InputComponent, - UikitFlatpickrJalaliComponent, ], }) export class PosSaleInvoicesFilterDrawerComponent implements OnChanges { diff --git a/src/app/layout/default/app.layout.component.ts b/src/app/layout/default/app.layout.component.ts index e51509b..bae744d 100644 --- a/src/app/layout/default/app.layout.component.ts +++ b/src/app/layout/default/app.layout.component.ts @@ -4,7 +4,6 @@ import { BreadcrumbComponent } from '@/shared/components'; import { CommonModule } from '@angular/common'; import { Component, computed, ContentChild, inject, Renderer2, TemplateRef } from '@angular/core'; import { NavigationEnd, Router, RouterModule } from '@angular/router'; -import { ProgressSpinner } from 'primeng/progressspinner'; import { filter, Subscription } from 'rxjs'; import { LayoutService } from '../service/layout.service'; import { AppFooter } from './app.footer.component'; @@ -14,15 +13,7 @@ import { AppTopbar } from './app.topbar.component'; @Component({ selector: 'app-layout', standalone: true, - imports: [ - CommonModule, - AppTopbar, - AppSidebar, - RouterModule, - AppFooter, - BreadcrumbComponent, - ProgressSpinner, - ], + imports: [CommonModule, AppTopbar, AppSidebar, RouterModule, AppFooter, BreadcrumbComponent], templateUrl: './app.layout.component.html', }) export class AppLayout { diff --git a/src/assets/styles.scss b/src/assets/styles.scss index 24fcb6e..1f789a5 100644 --- a/src/assets/styles.scss +++ b/src/assets/styles.scss @@ -5,7 +5,6 @@ @use "./flatpicker.css"; @use "./layout/layout.scss"; @use "primeicons/primeicons.css"; -@use "./demo/demo.scss"; @use "./rtlSupport.scss"; @use "./customize.scss";