feat: refactor dialog components to use light-bottomsheet for improved UX

- Replaced SharedDialogComponent with SharedLightBottomsheetComponent in customer-dialog, order-submitted-dialog, payment form-dialog, and pre-invoice-dialog components.
- Updated styles and properties for light-bottomsheet to enhance responsiveness and usability.
- Modified payload form components to use measure units instead of unit types for better clarity.
- Adjusted form controls to use consistent naming conventions for amounts and percentages.
- Enhanced support for overlay options in select components to manage z-index dynamically.
- Improved support for RTL layouts in input groups and other components.
This commit is contained in:
2026-05-13 13:44:33 +03:30
parent dba960c454
commit 42b8476b96
39 changed files with 396 additions and 143 deletions
@@ -31,14 +31,14 @@
}
</ul>
</div>
<div class="mt-auto">
<hr class="mb-4 mx-4 border-t border-0 border-surface" />
@if (isPwaBuild) {
@if (isPwaBuild) {
<div class="mt-auto">
<hr class="mb-4 mx-4 border-t border-0 border-surface" />
<div class="px-6 pb-6 text-sm text-muted-color">
نسخه برنامه : <span class="font-semibold">{{ appVersion }}</span>
</div>
}
</div>
</div>
}
</div>
</ng-template>
</p-drawer>
@@ -53,7 +53,7 @@ export class PosMainMenuSidebarComponent extends AbstractDialog {
icon: 'pi pi-fw pi-cog',
},
{
label: 'درباره ما',
label: 'درباره نرم‌افزار',
routerLink: posAboutNamedRoutes.about.meta.pagePath!(),
icon: 'pi pi-fw pi-info-circle',
},
@@ -2,15 +2,7 @@ import { AuthService } from '@/core';
import { LayoutService } from '@/layout/service/layout.service';
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
import { CommonModule } from '@angular/common';
import {
AfterViewInit,
Component,
TemplateRef,
ViewChild,
computed,
inject,
signal,
} from '@angular/core';
import { Component, TemplateRef, ViewChild, computed, inject, signal } from '@angular/core';
import { RouterLinkWithHref, RouterOutlet } from '@angular/router';
import { MenuItem } from 'primeng/api';
import { Button, ButtonDirective } from 'primeng/button';
@@ -38,7 +30,7 @@ import { PosChooseCardsComponent } from './choose-pos.component';
RouterOutlet,
],
})
export class PosPagesLayoutComponent implements AfterViewInit {
export class PosPagesLayoutComponent {
constructor() {}
// private readonly nativeBridgeService = inject(NativeBridgeService);
@@ -118,9 +110,6 @@ export class PosPagesLayoutComponent implements AfterViewInit {
ngOnInit() {
this.layoutService.changeIsFullPage(true);
}
ngAfterViewInit() {
this.layoutService.setTopbarStartSlot(this.topbarStart);
this.layoutService.setTopbarCenterSlot(this.topbarCenter);
this.layoutService.setTopbarEndSlot(this.topbarEnd);
+1 -2
View File
@@ -1,5 +1,4 @@
import ISummary from '@/core/models/summary';
import { UnitType } from '@/utils';
export interface IGoodRawResponse {
id: string;
@@ -10,7 +9,7 @@ export interface IGoodRawResponse {
name: string;
};
category: ISummary;
unit_type: UnitType;
measure_unit: ISummary;
pricing_model: string;
description?: string;
image_url: string;
@@ -1,6 +1,55 @@
<div class="w-full h-full min-h-[60svh] flex items-center justify-center p-4">
<div class="text-center">
<h2 class="text-xl font-semibold mb-2">درباره سیستم</h2>
<p class="text-muted-color">این صفحه به زودی تکمیل می شود.</p>
</div>
<div class="w-full min-h-[60svh] p-4 md:p-6">
<section class="mx-auto max-w-3xl overflow-hidden rounded-2xl border border-surface-200 bg-white">
<div class="bg-gradient-to-l from-emerald-50 via-teal-50 to-cyan-50 p-5 md:p-7">
<p class="mb-2 inline-flex items-center rounded-full bg-white px-3 py-1 text-xs font-semibold text-emerald-700">
{{ brandingInfo.appTitle }}
</p>
<span class="block mb-4 text-xl font-bold text-surface-900 md:text-3xl">درباره نسخه تیس</span>
<p class="mt-3 max-w-2xl text-sm leading-7 text-surface-700 md:text-base">
این نسخه برای استفاده روزانه روی دستگاه های PSP بهینه شده است تا عملیات ثبت و صدور صورتحساب‌‌های مالیاتی با سرعت
بالاتر، پایداری بیشتر و تجربه کاربری ساده تر انجام شود.
</p>
</div>
<div class="grid gap-3 p-4 md:grid-cols-3 md:gap-4 md:p-6">
<!-- <article class="rounded-xl border border-surface-200 bg-surface-50 p-4">
<h2 class="mb-2 text-sm font-bold text-surface-900">پایداری در وب ویو</h2>
<p class="text-sm leading-6 text-surface-700">
رفتار رابط کاربری برای محیط WebView تنظیم شده تا روی سخت افزارهای ضعیف تر هم اجرای روان تری داشته باشد.
</p>
</article> -->
<article class="rounded-xl border border-surface-200 bg-surface-50 p-4">
<span class="block mb-4 text-xl font-bold text-surface-900">تمرکز بر سرعت عملیات</span>
<p class="text-sm leading-6 text-surface-700">
مسیرهای کلیدی مانند انتخاب کالا، ورود مقادیر و ثبت نهایی برای کاهش تاخیر و افزایش سرعت کاربر بهینه شده اند.
</p>
</article>
<article class="rounded-xl border border-surface-200 bg-surface-50 p-4">
<span class="block mb-4 text-xl font-bold text-surface-900">سازگار با سناریوهای فروش</span>
<p class="text-sm leading-6 text-surface-700">
طراحی این نسخه بر مبنای سناریوهای واقعی فروشگاه انجام شده تا اپراتور با کمترین کلیک فرآیند را تکمیل کند.
</p>
</article>
</div>
<div class="mx-4 mb-4 rounded-xl border border-surface-200 bg-surface-50 p-4 md:mx-6">
<div class="flex flex-wrap items-center justify-between gap-3">
<div class="text-sm text-surface-700">
نسخه برنامه:
<span class="font-semibold text-surface-900">{{ appVersion() }}</span>
</div>
<button pButton type="button" [outlined]="!hasUpdate()" [disabled]="isCheckingUpdate()" (click)="onUpdateCtaClick()">
{{ updateCtaLabel() }}
</button>
</div>
</div>
<div class="border-t border-surface-200 bg-surface-50 px-4 py-4 md:px-6">
<p class="text-xs leading-6 text-surface-600 md:text-sm">
در صورت نیاز به راهنمایی بیشتر، به صفحه‌ی راهنمای استفاده مراجعه کنید یا با پشتیبانی تماس بگیرید.
</p>
</div>
</section>
</div>
@@ -1,7 +1,87 @@
import { Component } from '@angular/core';
import { brandingConfig } from '@/branding/branding.config';
import { Component, computed, inject, signal } from '@angular/core';
import { SwUpdate, VersionReadyEvent } from '@angular/service-worker';
import { ButtonDirective } from 'primeng/button';
import { filter } from 'rxjs';
@Component({
selector: 'pos-about-page',
templateUrl: './root.component.html',
imports: [ButtonDirective],
})
export class PosAboutPageComponent {}
export class PosAboutPageComponent {
private readonly swUpdate = inject(SwUpdate);
brandingInfo = brandingConfig;
appVersion = signal('0.0.0');
isPwaBuild = this.swUpdate.isEnabled;
isCheckingUpdate = signal(false);
hasUpdate = signal(false);
isUpdated = signal(false);
updateCtaLabel = computed(() => {
if (!this.isPwaBuild) return 'به روزرسانی فقط در نسخه PWA';
if (this.isUpdated()) return 'به روز است';
if (this.hasUpdate()) return 'به روزرسانی برنامه';
if (this.isCheckingUpdate()) return 'در حال بررسی...';
return 'بررسی به روزرسانی';
});
ngOnInit() {
if (!this.isPwaBuild) return;
this.loadVersion();
this.swUpdate.versionUpdates
.pipe(filter((event): event is VersionReadyEvent => event.type === 'VERSION_READY'))
.subscribe((event) => {
const appData = event.latestVersion.appData as { appVersion?: string } | undefined;
this.appVersion.set(appData?.appVersion || this.appVersion());
this.hasUpdate.set(true);
this.isUpdated.set(false);
});
}
async onUpdateCtaClick() {
if (!this.isPwaBuild || this.isCheckingUpdate()) return;
if (this.hasUpdate()) {
await this.applyUpdate();
return;
}
await this.checkForUpdate();
}
private async checkForUpdate() {
this.isCheckingUpdate.set(true);
this.isUpdated.set(false);
try {
const hasUpdate = await this.swUpdate.checkForUpdate();
this.hasUpdate.set(hasUpdate);
this.isUpdated.set(!hasUpdate);
} finally {
this.isCheckingUpdate.set(false);
}
}
private async applyUpdate() {
this.isCheckingUpdate.set(true);
try {
await this.swUpdate.activateUpdate();
this.isUpdated.set(true);
this.hasUpdate.set(false);
window.location.reload();
} finally {
this.isCheckingUpdate.set(false);
}
}
private loadVersion() {
fetch('/ngsw.json')
.then((res) => res.json())
.then((data: { appData?: { appVersion?: string } }) => {
this.appVersion.set(data?.appData?.appVersion || this.appVersion());
})
.catch(() => {});
}
}
@@ -1,4 +1,9 @@
<shared-dialog [(visible)]="visible" header="اطلاعات مشتری" [modal]="true" [style]="{ width: '560px' }">
<shared-light-bottomsheet
[(visible)]="visible"
header="اطلاعات مشتری"
[modal]="true"
[style]="{ 'max-height': '90svh', height: 'auto' }"
>
<div class="card p-2! flex justify-center">
<p-selectbutton [options]="customerTypes" [(ngModel)]="selectedCustomerType" optionValue="value">
<ng-template #item let-item>
@@ -13,4 +18,4 @@
} @else if (selectedCustomerType() === "LEGAL") {
<pos-customer-legal-form (onSubmit)="onSubmitCustomer()" (onClose)="close()" />
}
</shared-dialog>
</shared-light-bottomsheet>
@@ -1,5 +1,5 @@
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
import { SharedLightBottomsheetComponent } from '@/shared/components/dialog/light-bottomsheet.component';
import { CustomerType } from '@/shared/localEnum/constants/customerTypes';
import { Component, EventEmitter, inject, Output, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
@@ -13,7 +13,7 @@ import { CustomerUnknownFormComponent } from './unknown/form.component';
selector: 'pos-order-customer-dialog',
templateUrl: './customer-dialog.component.html',
imports: [
SharedDialogComponent,
SharedLightBottomsheetComponent,
CustomerIndividualFormComponent,
FormsModule,
CustomerLegalFormComponent,
@@ -16,7 +16,7 @@
</span>
</div>
<span class="text-sm text-ellipsis text-nowrap overflow-hidden">
{{ inOrderGood.quantity }} {{ enumTranslator(inOrderGood.good.unit_type) }}
{{ inOrderGood.quantity }} {{ inOrderGood.good.measure_unit.name }}
</span>
</div>
@if (!inOrderGood.discount_amount) {
@@ -53,9 +53,11 @@
</div>
</div>
<pos-payload-form-dialog
[(visible)]="visible"
[good]="inOrderGood.good"
[initialValues]="inOrderGood"
[orderItemId]="inOrderGood.id"
/>
@if (visible()) {
<pos-payload-form-dialog
[(visible)]="visible"
[good]="inOrderGood.good"
[initialValues]="inOrderGood"
[orderItemId]="inOrderGood.id"
/>
}
@@ -1,8 +1,8 @@
<shared-dialog
<shared-light-bottomsheet
[(visible)]="visible"
header="ثبت موفقیت‌آمیز"
[modal]="true"
[style]="{ width: '420px' }"
[style]="{ 'max-height': '90svh', height: 'auto' }"
[closable]="true"
(onHide)="close()"
>
@@ -15,4 +15,4 @@
<button pButton type="button" outlined (click)="sendInvoice()">ارسال به سامانه مودیان</button>
<button pButton type="button" outlined (click)="openOrderDetails()">جزئیات</button>
</div>
</shared-dialog>
</shared-light-bottomsheet>
@@ -2,7 +2,7 @@ import { NativeBridgeService } from '@/core/services';
import { ToastService } from '@/core/services/toast.service';
import { PosInfoStore } from '@/domains/pos/store';
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
import { SharedDialogComponent } from '@/shared/components';
import { SharedLightBottomsheetComponent } from '@/shared/components/dialog/light-bottomsheet.component';
import { formatJalali } from '@/utils';
import { Component, computed, inject, Input, signal } from '@angular/core';
import { Router } from '@angular/router';
@@ -15,7 +15,7 @@ import { IPosOrderResponse } from '../../models';
@Component({
selector: 'pos-order-submitted-dialog',
templateUrl: 'order-submitted-dialog.component.html',
imports: [SharedDialogComponent, ButtonDirective],
imports: [SharedLightBottomsheetComponent, ButtonDirective],
})
export class PosOrderSubmittedDialogComponent extends AbstractDialog {
@Input({ required: true }) invoice!: IPosOrderResponse;
@@ -12,7 +12,7 @@
} @else if (isStandardMode()) {
<pos-standard-payload-form
[initialValues]="standardPayload()"
[unitType]="good.unit_type"
[measureUnit]="good.measure_unit"
[editMode]="editMode()"
(onSubmit)="submit($event)"
/>
@@ -6,7 +6,7 @@
<app-amount-percentage-input
[percentageControl]="form.controls.payload.controls.wages_percentage"
[amountControl]="form.controls.payload.controls.wages_amount"
[amountControl]="form.controls.payload.controls.wages"
[baseAmount]="unitWithQuantity()"
[minAmount]="0"
[maxAmount]="unitWithQuantity()"
@@ -15,7 +15,7 @@
/>
<app-amount-percentage-input
[percentageControl]="form.controls.payload.controls.commission_percentage"
[amountControl]="form.controls.payload.controls.commission_amount"
[amountControl]="form.controls.payload.controls.commission"
[baseAmount]="unitWithQuantity()"
[minAmount]="0"
[maxAmount]="unitWithQuantity()"
@@ -24,7 +24,7 @@
/>
<app-amount-percentage-input
[percentageControl]="form.controls.payload.controls.profit_percentage"
[amountControl]="form.controls.payload.controls.profit_amount"
[amountControl]="form.controls.payload.controls.profit"
[baseAmount]="totalAmountBeforeProfit()"
[minAmount]="0"
[maxAmount]="totalAmountBeforeProfit()"
@@ -35,7 +35,7 @@
<app-amount-percentage-input
[percentageControl]="form.controls.discount_percentage"
[amountControl]="form.controls.discount_amount"
[amountControl]="form.controls.discount"
[baseAmount]="baseAmountForDiscountCalculation()"
[minAmount]="0"
[maxAmount]="baseAmountForDiscountCalculation()"
@@ -59,7 +59,7 @@
<pos-form-dialog-amount-card-template
[totalAmount]="totalAmount()"
[baseTotalAmount]="baseTotalAmount()"
[discountAmount]="form.controls.discount_amount.value || 0"
[discountAmount]="form.controls.discount.value || 0"
[taxAmount]="taxAmount()"
/>
<button pButton class="sm:w-auto w-full" (click)="submit()">{{ preparedCTAText() }}</button>
@@ -31,6 +31,17 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
IPosOrderItem<IGoldPayload>,
IPosOrderItem<IGoldPayload>
> {
override defaultValues: Partial<IPosOrderItem<IGoldPayload>> = {
unit_price: 200_000_000,
quantity: 2,
payload: {
commission: 10_000,
wages: 10_000,
profit: 10_000,
karat: '18' as TGoldKarat,
} as any,
};
@Output() onSubmitForm = new EventEmitter<IGoldPayload>();
@Output() onChangeTotalAmount = new EventEmitter<number>();
@@ -59,14 +70,14 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
const form = this.fb.group({
unit_price: [this.initialValues?.unit_price || 0, [Validators.required]],
quantity: [this.initialValues?.quantity || 0, [Validators.required, greaterThanValidator(0)]],
discount_amount: [this.initialValues?.discount || 0],
discount: [this.initialValues?.discount || 0],
discount_percentage: [0, [Validators.max(100), Validators.min(0)]],
payload: this.fb.group({
commission_amount: [this.initialValues?.payload?.commission || 0, [Validators.required]],
commission: [this.initialValues?.payload?.commission || 0, [Validators.required]],
commission_percentage: [0, [Validators.required, Validators.max(100), Validators.min(0)]],
wages_amount: [this.initialValues?.payload?.wages || 0, [Validators.required]],
wages: [this.initialValues?.payload?.wages || 0, [Validators.required]],
wages_percentage: [0, [Validators.required, Validators.max(100), Validators.min(0)]],
profit_amount: [this.initialValues?.payload?.profit || 0, [Validators.required]],
profit: [this.initialValues?.payload?.profit || 0, [Validators.required]],
profit_percentage: [0, [Validators.required, Validators.max(100), Validators.min(0)]],
karat: [this.initialValues?.payload?.karat || '', [Validators.required]],
}),
@@ -76,17 +87,15 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
this.updateCalculateAmount(value as any);
});
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, { emitEvent: false });
// }
});
form.controls.payload.controls.profit.valueChanges.pipe(takeUntilDestroyed()).subscribe(() => {
// if ((form.controls.discount_amount.value || 0) > (value || 0)) {
form.controls.discount.setValue(0, { emitEvent: false });
// }
});
form.controls.payload.controls.profit_percentage.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(() => {
form.controls.discount_amount.setValue(0, { emitEvent: false });
form.controls.discount.setValue(0, { emitEvent: false });
});
return form;
@@ -101,19 +110,19 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
base_total_amount: this.baseTotalAmount(),
tax_amount: this.taxAmount(),
payload: {
commission: this.form.controls.payload.controls.commission_amount.value || 0,
commission: this.form.controls.payload.controls.commission.value || 0,
karat: this.form.controls.payload.controls.karat.value as TGoldKarat,
profit: this.form.controls.payload.controls.profit_amount.value || 0,
wages: this.form.controls.payload.controls.wages_amount.value || 0,
profit: this.form.controls.payload.controls.profit.value || 0,
wages: this.form.controls.payload.controls.wages.value || 0,
},
});
}
updateCalculateAmount(payload: Partial<IPosOrderItem<any>>) {
const commissionAmount = Number(payload.payload?.commission_amount ?? '0');
const wageAmount = Number(payload.payload?.wages_amount ?? '0');
const discountAmount = Number(payload.discount_amount ?? '0');
const profitAmount = Number(payload.payload?.profit_amount ?? '0');
const commissionAmount = Number(payload.payload?.commission ?? '0');
const wageAmount = Number(payload.payload?.wages ?? '0');
const discountAmount = Number(payload.discount ?? '0');
const profitAmount = Number(payload.payload?.profit ?? '0');
const unitPrice = Number(payload.unit_price ?? '0');
const quantity = Number(payload.quantity ?? '0');
@@ -3,9 +3,9 @@
<app-input
[control]="form.controls.quantity"
name="quantity"
[label]="preparedFormVisuals().quantityLabel"
[label]="measureUnit.name"
type="number"
[suffix]="preparedFormVisuals().quantitySymbolText"
[suffix]="measureUnit.name"
[min]="0"
/>
@@ -1,7 +1,8 @@
import ISummary from '@/core/models/summary';
import { AbstractForm } from '@/shared/abstractClasses';
import { InputComponent } from '@/shared/components';
import { AmountPercentageInputComponent } from '@/shared/components/amountPercentageInput/amount-percentage-input.component';
import { formatWithCurrency, getGoodUnitTypeProperties, UnitType } from '@/utils';
import { formatWithCurrency } 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';
@@ -24,7 +25,7 @@ export class PosStandardPayloadFormComponent extends AbstractForm<
IPosOrderItem<IStandardPayload>,
IPosOrderItem<IStandardPayload>
> {
@Input({ required: true }) unitType!: UnitType;
@Input({ required: true }) measureUnit!: ISummary;
@Output() onChangeTotalAmount = new EventEmitter<number>();
private readonly initialForm = () => {
@@ -53,8 +54,6 @@ export class PosStandardPayloadFormComponent extends AbstractForm<
});
}
preparedFormVisuals = computed(() => getGoodUnitTypeProperties(this.unitType));
baseTotalAmount = signal<number>(0);
totalAmount = signal<number>(0);
discountAmount = signal<number>(0);
@@ -1,8 +1,8 @@
<shared-dialog
<shared-light-bottomsheet
[(visible)]="visible"
header="اطلاعات پرداخت"
[modal]="true"
[style]="{ width: '500px' }"
[style]="{ 'max-height': '90svh', height: 'auto' }"
[closable]="true"
(onHide)="close()"
>
@@ -71,4 +71,4 @@
/>
</form>
</div>
</shared-dialog>
</shared-light-bottomsheet>
@@ -3,7 +3,7 @@ import { NativeBridgeService } from '@/core/services';
import { ToastService } from '@/core/services/toast.service';
import { AbstractFormDialog } from '@/shared/abstractClasses';
import { InputComponent, KeyValueComponent } from '@/shared/components';
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
import { SharedLightBottomsheetComponent } from '@/shared/components/dialog/light-bottomsheet.component';
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
import { UikitFieldComponent } from '@/uikit';
import { Component, computed, inject, signal } from '@angular/core';
@@ -27,7 +27,7 @@ import { PosLandingStore } from '../../store/main.store';
FormFooterActionsComponent,
KeyValueComponent,
ButtonDirective,
SharedDialogComponent,
SharedLightBottomsheetComponent,
Select,
UikitFieldComponent,
],
@@ -1,11 +1,11 @@
<shared-dialog
<shared-light-bottomsheet
[(visible)]="visible"
header="پیش فاکتور"
[modal]="true"
[style]="{ width: '500px' }"
[style]="{ 'max-height': '90svh', height: 'auto' }"
[closable]="true"
(onHide)="close()"
>
<form [formGroup]="form"></form>
<uikit-datepicker [control]="form.controls.invoiceDate" label="تاریخ فاکتور" />
</shared-dialog>
</shared-light-bottomsheet>
@@ -1,14 +1,14 @@
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
import { SharedLightBottomsheetComponent } from '@/shared/components/dialog/light-bottomsheet.component';
import { UikitFlatpickrJalaliComponent } from '@/uikit';
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { PosLandingStore } from '../store/main.store';
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
@Component({
selector: 'pos-pre-invoice-dialog',
templateUrl: './pre-invoice-dialog.component.html',
imports: [SharedDialogComponent, UikitFlatpickrJalaliComponent, ReactiveFormsModule],
imports: [SharedLightBottomsheetComponent, UikitFlatpickrJalaliComponent, ReactiveFormsModule],
})
export class PosPreInvoiceDialogComponent extends AbstractDialog {
private readonly store = inject(PosLandingStore);
@@ -1,5 +1,5 @@
import ISummary from '@/core/models/summary';
import { IGoodResponse } from '@/domains/pos/models/good.io';
import { UnitType } from '@/utils';
import { TPosOrderGoodPayload } from './payload';
export interface IPosOrderItem<T = TPosOrderGoodPayload> {
@@ -7,7 +7,7 @@ export interface IPosOrderItem<T = TPosOrderGoodPayload> {
quantity: number;
total_amount: number;
discount_amount: number;
unit_type: UnitType;
measure_unit: ISummary;
good_id?: string;
service_id?: string;
notes?: string;
@@ -221,7 +221,7 @@ export class PosLandingStore {
items: this.inOrderGoods().map(({ good, ...rest }) => ({
...rest,
good_id: good.id,
unit_type: good.unit_type,
measure_unit: good.measure_unit,
})),
invoice_date: new Date().toISOString(),
payments: this.payments(),
@@ -34,17 +34,11 @@
</div>
</button>
}
<shared-dialog
[(visible)]="showInvoiceBottomSheet"
position="bottom"
[modal]="true"
[closable]="true"
header="فاکتور"
>
<shared-light-bottomsheet [(visible)]="showInvoiceBottomSheet" [modal]="true" [closable]="true" header="فاکتور">
@if (showInvoiceBottomSheet()) {
<pos-order-section (onAddMoreGoods)="closeInvoiceBottomSheet()" (onSuccess)="onSuccessSubmit($event)" />
}
</shared-dialog>
</shared-light-bottomsheet>
@if (responseInvoice()) {
<pos-order-submitted-dialog [(visible)]="isVisibleSuccessDialog" [invoice]="responseInvoice()!" />
@@ -2,7 +2,7 @@
import { Maybe } from '@/core';
import { PosInfoStore } from '@/domains/pos/store/pos.store';
import { AbstractIsMobileComponent } from '@/shared/abstractClasses/abstract-is-mobile';
import { SharedDialogComponent } from '@/shared/components';
import { SharedLightBottomsheetComponent } from '@/shared/components/dialog/light-bottomsheet.component';
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
import { PriceMaskDirective } from '@/shared/directives';
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';
@@ -24,7 +24,7 @@ import { PosLandingStore } from '../store/main.store';
PosOrderSectionComponent,
PageLoadingComponent,
PriceMaskDirective,
SharedDialogComponent,
SharedLightBottomsheetComponent,
ButtonDirective,
PosOrderSubmittedDialogComponent,
],
@@ -1,6 +1,47 @@
<div class="w-full h-full min-h-[60svh] flex items-center justify-center p-4">
<div class="text-center">
<h2 class="text-xl font-semibold mb-2">پشتیبانی</h2>
<p class="text-muted-color">این صفحه به زودی تکمیل می شود.</p>
</div>
<div class="w-full min-h-[60svh] p-4 md:p-6">
<section class="mx-auto max-w-3xl overflow-hidden rounded-2xl border border-surface-200 bg-white">
<div class="bg-gradient-to-l from-sky-50 via-cyan-50 to-teal-50 p-5 md:p-7">
<h1 class="text-2xl font-bold text-surface-900 md:text-3xl">پشتیبانی تیس</h1>
<p class="mt-3 max-w-2xl text-sm leading-7 text-surface-700 md:text-base">
در صورت بروز مشکل در ثبت سفارش، صدور صورتحساب یا تنظیمات دستگاه، تیم پشتیبانی آماده پاسخگویی است. لطفا هنگام
تماس، نام پایانه و شماره سریال دستگاه را همراه داشته باشید.
</p>
</div>
<div class="grid gap-3 p-4 md:grid-cols-2 md:gap-4 md:p-6">
<article class="rounded-xl border border-surface-200 bg-surface-50 p-4">
<h2 class="mb-3 text-sm font-bold text-surface-900">شماره های تماس مستقیم</h2>
<ul class="space-y-2 text-sm text-surface-700">
<li class="flex items-center justify-between gap-2">
<span>واحد پشتیبانی 1</span>
<a class="font-semibold text-primary" href="tel:02191012345" dir="ltr">021-91012345</a>
</li>
<li class="flex items-center justify-between gap-2">
<span>واحد پشتیبانی 2</span>
<a class="font-semibold text-primary" href="tel:02191012346" dir="ltr">021-91012346</a>
</li>
<li class="flex items-center justify-between gap-2">
<span>پاسخگویی اضطراری</span>
<a class="font-semibold text-primary" href="tel:09121234567" dir="ltr">0912-123-4567</a>
</li>
</ul>
</article>
<article class="rounded-xl border border-surface-200 bg-surface-50 p-4">
<h2 class="mb-3 text-sm font-bold text-surface-900">راهنمای سریع قبل از تماس</h2>
<ul class="space-y-2 text-sm leading-6 text-surface-700">
<li>اتصال اینترنت دستگاه را بررسی کنید.</li>
<li>یک بار برنامه را ببندید و دوباره اجرا کنید.</li>
<li>در صفحه درباره نرم افزار، نسخه برنامه را اعلام کنید.</li>
<li>در صورت خطا، متن خطا یا تصویر آن را برای پشتیبانی ارسال کنید.</li>
</ul>
</article>
</div>
<div class="border-t border-surface-200 bg-surface-50 px-4 py-4 md:px-6">
<p class="text-xs leading-6 text-surface-600 md:text-sm">
ساعات پاسخگویی: شنبه تا چهارشنبه 8:30 تا 17:30 و پنجشنبه 8:30 تا 13:00
</p>
</div>
</section>
</div>