create light bottomsheet drawer for gold payload
This commit is contained in:
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
||||||
"appData": {
|
"appData": {
|
||||||
"appVersion": "0.0.4",
|
"appVersion": "0.0.9",
|
||||||
"buildDate": "2026-05-11T16:11:59.783Z",
|
"buildDate": "2026-05-13T06:42:17.700Z",
|
||||||
"buildNumber": 4
|
"buildNumber": 9
|
||||||
},
|
},
|
||||||
"assetGroups": [
|
"assetGroups": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<shared-dialog
|
<shared-light-bottomsheet
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[header]="preparedTitle()"
|
[header]="preparedTitle()"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
[style]="{ width: '500px' }"
|
[style]="{ 'max-height': '90svh', height: 'auto' }"
|
||||||
[closable]="true"
|
[closable]="true"
|
||||||
(onHide)="close()"
|
(onHide)="close()"
|
||||||
>
|
>
|
||||||
@@ -18,4 +18,4 @@
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</shared-dialog>
|
</shared-light-bottomsheet>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
import { IGoodResponse } from '@/domains/pos/models/good.io';
|
||||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
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 { Component, computed, EventEmitter, inject, Input, Output, signal } from '@angular/core';
|
import { Component, computed, EventEmitter, inject, Input, Output, signal } from '@angular/core';
|
||||||
import { IGoldPayload, IPosOrderItem, IStandardPayload, TPosOrderGoodPayload } from '../models';
|
import { IGoldPayload, IPosOrderItem, IStandardPayload, TPosOrderGoodPayload } from '../models';
|
||||||
import { PosLandingStore } from '../store/main.store';
|
import { PosLandingStore } from '../store/main.store';
|
||||||
@@ -10,7 +10,7 @@ import { PosStandardPayloadFormComponent } from './payloads/standard/form.compon
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-payload-form-dialog',
|
selector: 'pos-payload-form-dialog',
|
||||||
templateUrl: './payload-form.component.html',
|
templateUrl: './payload-form.component.html',
|
||||||
imports: [PosGoldPayloadFormComponent, SharedDialogComponent, PosStandardPayloadFormComponent],
|
imports: [PosGoldPayloadFormComponent, SharedLightBottomsheetComponent, PosStandardPayloadFormComponent],
|
||||||
})
|
})
|
||||||
export class PayloadFormDialogComponent extends AbstractDialog {
|
export class PayloadFormDialogComponent extends AbstractDialog {
|
||||||
@Input({ required: true }) good!: IGoodResponse;
|
@Input({ required: true }) good!: IGoodResponse;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
@if (formVisible()) {
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<app-input [control]="form.controls.unit_price" name="unit_price" label="قیمت پایه هر گرم" type="price" />
|
<app-input [control]="form.controls.unit_price" name="unit_price" label="قیمت پایه هر گرم" type="price" />
|
||||||
@@ -66,4 +65,3 @@
|
|||||||
<button pButton class="sm:w-auto w-full" (click)="submit()">{{ preparedCTAText() }}</button>
|
<button pButton class="sm:w-auto w-full" (click)="submit()">{{ preparedCTAText() }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
baseAmountForDiscountCalculation = signal<number>(0);
|
baseAmountForDiscountCalculation = signal<number>(0);
|
||||||
taxAmount = signal<number>(0);
|
taxAmount = signal<number>(0);
|
||||||
totalAmount = signal<number>(0);
|
totalAmount = signal<number>(0);
|
||||||
formVisible = signal<boolean>(false);
|
|
||||||
|
|
||||||
preparedCTAText = computed(() => (this.editMode ? 'اعمال ویرایش' : 'افزودن به لیست خرید'));
|
preparedCTAText = computed(() => (this.editMode ? 'اعمال ویرایش' : 'افزودن به لیست خرید'));
|
||||||
|
|
||||||
@@ -95,16 +94,6 @@ export class PosGoldPayloadFormComponent extends AbstractForm<
|
|||||||
|
|
||||||
form = this.initialForm();
|
form = this.initialForm();
|
||||||
|
|
||||||
override ngAfterViewInit(): void {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.formVisible.set(true);
|
|
||||||
if (this.editMode) {
|
|
||||||
this.form.patchValue(this.initialValues || {}, { emitEvent: false });
|
|
||||||
this.updateCalculateAmount(this.form.value as any);
|
|
||||||
}
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
override submitForm(payload: IPosOrderItem) {
|
override submitForm(payload: IPosOrderItem) {
|
||||||
this.onSubmit.emit({
|
this.onSubmit.emit({
|
||||||
...payload,
|
...payload,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
pButton
|
pButton
|
||||||
class="sticky! bottom-0 inset-x-0 w-full right-0 z-1200 border-t border-surface-border bg-surface-0 px-4 py-3 shadow-[0_-4px_16px_rgba(0,0,0,0.08)] md:hidden! rounded-b-none!"
|
class="sticky! bottom-0 inset-x-0 w-full right-0 z-1200 border-t border-surface-border bg-surface-0 px-4 py-3 shadow-[0_-4px_16px_rgba(0,0,0,0.08)] md:hidden! rounded-b-none!"
|
||||||
[style.paddingBottom]="'calc(0.75rem + env(safe-area-inset-bottom))'"
|
[style.paddingBottom]="'calc(0.75rem + {{env(safe-area-inset-bottom)}})'"
|
||||||
(click)="openInvoiceBottomSheet()"
|
(click)="openInvoiceBottomSheet()"
|
||||||
>
|
>
|
||||||
<div class="mx-auto flex w-full max-w-3xl items-center justify-between">
|
<div class="mx-auto flex w-full max-w-3xl items-center justify-between">
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export abstract class AbstractForm<
|
|||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngOnInit() {
|
||||||
this.form.reset(this.initialValues ?? this.defaultValues);
|
this.form.reset(this.initialValues ?? this.defaultValues);
|
||||||
// Object.entries(this.form.controls).forEach(([key, control]) => {
|
// Object.entries(this.form.controls).forEach(([key, control]) => {
|
||||||
// console.log(key, control);
|
// console.log(key, control);
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<div class="light-bottomsheet-mask" (click)="onMaskClick()"></div>
|
||||||
|
|
||||||
|
<section
|
||||||
|
class="light-bottomsheet-panel"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
[attr.aria-hidden]="!visible"
|
||||||
|
[ngStyle]="style || { 'max-height': mobileDrawerHeight, height: 'auto' }"
|
||||||
|
>
|
||||||
|
<div class="light-bottomsheet-content">
|
||||||
|
@if (header || closable) {
|
||||||
|
<header class="light-bottomsheet-header">
|
||||||
|
<h3 class="light-bottomsheet-title">{{ header }}</h3>
|
||||||
|
@if (closable) {
|
||||||
|
<button type="button" class="light-bottomsheet-close" (click)="onVisibilityChange(false)" aria-label="Close">
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</header>
|
||||||
|
}
|
||||||
|
<div class="p-4">
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
import { NgStyle } from '@angular/common';
|
||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'shared-light-bottomsheet',
|
||||||
|
templateUrl: './light-bottomsheet.component.html',
|
||||||
|
imports: [NgStyle],
|
||||||
|
styles: [
|
||||||
|
`
|
||||||
|
:host {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 11020;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-bottomsheet-mask {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(15, 23, 42, 0.22);
|
||||||
|
will-change: opacity;
|
||||||
|
animation: sheetFadeIn var(--sheet-transition, 130ms cubic-bezier(0.2, 0, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-bottomsheet-panel {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
max-height: 80svh;
|
||||||
|
background: var(--surface-card, #fff);
|
||||||
|
border-radius: 12px 12px 0 0;
|
||||||
|
box-shadow: none;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
will-change: transform;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
animation: sheetSlideUp var(--sheet-transition, 130ms cubic-bezier(0.2, 0, 0, 1));
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-bottomsheet-content {
|
||||||
|
max-height: 80svh;
|
||||||
|
overflow: auto;
|
||||||
|
padding-bottom: calc(0.75rem + env(safe-area-inset-bottom));
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-bottomsheet-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-bottomsheet-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-bottomsheet-close {
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
padding: 0.25rem;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sheetSlideUp {
|
||||||
|
from {
|
||||||
|
transform: translate3d(0, 100%, 0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sheetFadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
host: {
|
||||||
|
'[style.display]': 'visible ? "block" : "none"',
|
||||||
|
'[style.--sheet-transition]': 'transitionOptions',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export class SharedLightBottomsheetComponent {
|
||||||
|
@Input() header = '';
|
||||||
|
@Input() visible = false;
|
||||||
|
@Output() visibleChange = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@Input() modal = true;
|
||||||
|
@Input() closable = true;
|
||||||
|
@Input() style: Record<string, string> | undefined;
|
||||||
|
@Input() mobileDrawerHeight = '80svh';
|
||||||
|
@Input() transitionOptions = '130ms cubic-bezier(0.2, 0, 0, 1)';
|
||||||
|
|
||||||
|
@Output() onHide = new EventEmitter<any>();
|
||||||
|
|
||||||
|
onVisibilityChange(nextValue: boolean) {
|
||||||
|
this.visible = nextValue;
|
||||||
|
this.visibleChange.emit(nextValue);
|
||||||
|
if (!nextValue) {
|
||||||
|
this.onHide.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMaskClick() {
|
||||||
|
if (this.modal && this.closable) {
|
||||||
|
this.onVisibilityChange(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user