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:
@@ -37,14 +37,14 @@ export abstract class AbstractForm<
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.form.reset(this.initialValues ?? this.defaultValues);
|
||||
this.form.patchValue(this.initialValues ?? this.defaultValues);
|
||||
// Object.entries(this.form.controls).forEach(([key, control]) => {
|
||||
// console.log(key, control);
|
||||
// });
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.form.reset(this.initialValues ?? this.defaultValues);
|
||||
this.form.patchValue(this.initialValues ?? this.defaultValues);
|
||||
}
|
||||
|
||||
onSuccess(response: Response): void {}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
[formControl]="control"
|
||||
[showClear]="showClear"
|
||||
[name]="name || type"
|
||||
[overlayOptions]="overlayOptions()"
|
||||
appendTo="body"
|
||||
/>
|
||||
</uikit-field>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UikitFieldComponent } from '@/uikit';
|
||||
import { Component, computed, inject, Input } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Component, Inject, computed, inject, Input } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { Select } from 'primeng/select';
|
||||
import { Observable } from 'rxjs';
|
||||
@@ -19,6 +20,9 @@ export class EnumSelectComponent extends AbstractSelectComponent<string, IApiEnu
|
||||
@Input() customLabel?: string;
|
||||
|
||||
private readonly service = inject(EnumsService);
|
||||
constructor(@Inject(DOCUMENT) private readonly document: Document) {
|
||||
super();
|
||||
}
|
||||
|
||||
label = computed(() => this.customLabel ?? apiEnumTranslates[this.type]);
|
||||
|
||||
@@ -29,4 +33,20 @@ export class EnumSelectComponent extends AbstractSelectComponent<string, IApiEnu
|
||||
ngOnInit() {
|
||||
this.getData();
|
||||
}
|
||||
|
||||
overlayOptions() {
|
||||
return {
|
||||
autoZIndex: true,
|
||||
baseZIndex: this.overlayBaseZIndex(),
|
||||
};
|
||||
}
|
||||
|
||||
overlayBaseZIndex() {
|
||||
const drawers = Array.from(this.document.body.querySelectorAll('.p-drawer,[data-pc-name="drawer"]')) as HTMLElement[];
|
||||
const zIndexes = drawers
|
||||
.map((drawer) => Number.parseInt(drawer.style.zIndex || '0', 10))
|
||||
.filter((zIndex) => Number.isFinite(zIndex) && zIndex > 0);
|
||||
|
||||
return zIndexes.length ? Math.max(...zIndexes) + 2 : 1000;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -24,8 +24,8 @@
|
||||
[attr.name]="name"
|
||||
[attr.placeholder]="placeholder"
|
||||
[attr.autocomplete]="autocomplete"
|
||||
[class]="` w-full hasSuffix text-left ${size === 'large' ? 'p-inputtext-lg' : size === 'small' ? 'p-inputtext-sm' : ''}`"
|
||||
dir="ltr"
|
||||
[inputStyle]="{ direction: 'ltr' }"
|
||||
[inputStyleClass]="` w-full hasSuffix text-left ${size === 'large' ? 'p-inputtext-lg' : size === 'small' ? 'p-inputtext-sm' : ''}`"
|
||||
[required]="required"
|
||||
[invalid]="amountControl.invalid && (amountControl.touched || amountControl.dirty)"
|
||||
(onInput)="onPriceInput($event)"
|
||||
@@ -58,9 +58,10 @@
|
||||
<p-select
|
||||
[formControl]="selectedType"
|
||||
[options]="typeSelectOptions"
|
||||
tabindex="-1"
|
||||
optionValue="value"
|
||||
size="small"
|
||||
class="border-0!"
|
||||
class="border-none! shadow-none! w-full!"
|
||||
/>
|
||||
</p-inputgroup-addon>
|
||||
</p-inputgroup>
|
||||
|
||||
@@ -180,11 +180,16 @@ export class AmountPercentageInputComponent {
|
||||
const amountValue = Number(this.amountControl.value || 0);
|
||||
const percentageValue = Number(this.percentageControl.value || 0);
|
||||
const isPercentageType = percentageValue > 0 && amountValue <= 0;
|
||||
|
||||
console.log(amountValue, percentageValue, isPercentageType);
|
||||
|
||||
this.preparedLabel.set(this.prepareLabel(isPercentageType));
|
||||
|
||||
this.selectedType.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((value) => {
|
||||
this.preparedLabel.set(this.prepareLabel(value === 'percentage'));
|
||||
});
|
||||
|
||||
this.selectedType.setValue(isPercentageType ? 'percentage' : 'amount');
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-center gap-3">
|
||||
<p-checkBox [formControl]="control" [name]="name" [id]="name" binary class="shrink-0"> </p-checkBox>
|
||||
<p-checkBox [formControl]="control" [name]="name" [inputId]="name" binary class="shrink-0"> </p-checkBox>
|
||||
<uikit-label [name]="name"> {{ label }} </uikit-label>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
<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' }"
|
||||
>
|
||||
<section class="light-bottomsheet-panel" [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>
|
||||
<span class="text-xl font-bold">{{ header }}</span>
|
||||
@if (closable) {
|
||||
<button type="button" class="light-bottomsheet-close" (click)="onVisibilityChange(false)" aria-label="Close">
|
||||
×
|
||||
</button>
|
||||
<p-button
|
||||
type="button"
|
||||
icon="pi pi-times"
|
||||
text
|
||||
size="small"
|
||||
class="light-bottomsheet-close"
|
||||
(click)="onVisibilityChange(false)"
|
||||
aria-label="Close"
|
||||
>
|
||||
</p-button>
|
||||
}
|
||||
</header>
|
||||
}
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
import { NgStyle } from '@angular/common';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { DOCUMENT, NgStyle } from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
Renderer2,
|
||||
SimpleChanges,
|
||||
} from '@angular/core';
|
||||
import { Button } from 'primeng/button';
|
||||
|
||||
@Component({
|
||||
selector: 'shared-light-bottomsheet',
|
||||
templateUrl: './light-bottomsheet.component.html',
|
||||
imports: [NgStyle],
|
||||
imports: [NgStyle, Button],
|
||||
styles: [
|
||||
`
|
||||
:host {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 11020;
|
||||
z-index: 1210;
|
||||
}
|
||||
|
||||
.light-bottomsheet-mask {
|
||||
@@ -66,8 +68,6 @@ import {
|
||||
|
||||
.light-bottomsheet-title {
|
||||
margin: 0;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.light-bottomsheet-close {
|
||||
@@ -98,11 +98,17 @@ import {
|
||||
`,
|
||||
],
|
||||
host: {
|
||||
'[attr.role]': '"complementary"',
|
||||
'[attr.aria-modal]': 'true',
|
||||
'[attr.pfocustrap]': 'true',
|
||||
'[attr.data-pc-name]': "'drawer'",
|
||||
'[attr.data-pc-section]': "'root'",
|
||||
'[attr.aria-hidden]': '!visible',
|
||||
'[style.display]': 'visible ? "block" : "none"',
|
||||
'[style.--sheet-transition]': 'transitionOptions',
|
||||
},
|
||||
})
|
||||
export class SharedLightBottomsheetComponent implements OnInit, OnDestroy {
|
||||
export class SharedLightBottomsheetComponent implements OnInit, OnDestroy, OnChanges {
|
||||
@Input() header = '';
|
||||
@Input() visible = false;
|
||||
@Output() visibleChange = new EventEmitter<boolean>();
|
||||
@@ -116,6 +122,7 @@ export class SharedLightBottomsheetComponent implements OnInit, OnDestroy {
|
||||
@Output() onHide = new EventEmitter<any>();
|
||||
|
||||
private originalParent: Node | null = null;
|
||||
private readonly defaultDrawerZIndex = 1102;
|
||||
|
||||
constructor(
|
||||
private readonly elementRef: ElementRef<HTMLElement>,
|
||||
@@ -127,9 +134,20 @@ export class SharedLightBottomsheetComponent implements OnInit, OnDestroy {
|
||||
const host = this.elementRef.nativeElement;
|
||||
this.originalParent = host.parentNode;
|
||||
this.renderer.appendChild(this.document.body, host);
|
||||
this.syncZIndex();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['visible'] && this.visible) {
|
||||
this.syncZIndex();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.removeDrawer();
|
||||
}
|
||||
|
||||
private removeDrawer() {
|
||||
const host = this.elementRef.nativeElement;
|
||||
if (this.originalParent) {
|
||||
this.renderer.appendChild(this.originalParent, host);
|
||||
@@ -139,6 +157,9 @@ export class SharedLightBottomsheetComponent implements OnInit, OnDestroy {
|
||||
onVisibilityChange(nextValue: boolean) {
|
||||
this.visible = nextValue;
|
||||
this.visibleChange.emit(nextValue);
|
||||
if (nextValue) {
|
||||
this.syncZIndex();
|
||||
}
|
||||
if (!nextValue) {
|
||||
this.onHide.emit();
|
||||
}
|
||||
@@ -149,4 +170,19 @@ export class SharedLightBottomsheetComponent implements OnInit, OnDestroy {
|
||||
this.onVisibilityChange(false);
|
||||
}
|
||||
}
|
||||
|
||||
private syncZIndex() {
|
||||
const host = this.elementRef.nativeElement;
|
||||
const siblingDrawers = Array.from(
|
||||
this.document.body.querySelectorAll('.p-drawer'),
|
||||
) as HTMLElement[];
|
||||
const drawerZIndexes = siblingDrawers
|
||||
.map((drawer) => Number.parseInt(drawer.style.zIndex || '0', 10))
|
||||
.filter((zIndex) => Number.isFinite(zIndex) && zIndex > 0);
|
||||
|
||||
const maxDrawerZIndex = drawerZIndexes.length
|
||||
? Math.max(...drawerZIndexes)
|
||||
: this.defaultDrawerZIndex;
|
||||
this.renderer.setStyle(host, 'z-index', `${maxDrawerZIndex + 1}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
[formControl]="control"
|
||||
[showClear]="showClear"
|
||||
[filter]="true"
|
||||
[overlayOptions]="overlayOptions()"
|
||||
appendTo="body"
|
||||
/>
|
||||
</uikit-field>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UikitFieldComponent } from '@/uikit';
|
||||
import { Component, computed, Input } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Component, Inject, computed, Input } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { Select } from 'primeng/select';
|
||||
import { Observable } from 'rxjs';
|
||||
@@ -16,6 +17,10 @@ export class EnumSelectComponent extends AbstractSelectComponent<ISelectItem, IS
|
||||
@Input() type!: TLocalEnum;
|
||||
@Input() customLabel?: string;
|
||||
|
||||
constructor(@Inject(DOCUMENT) private readonly document: Document) {
|
||||
super();
|
||||
}
|
||||
|
||||
label = computed(() => this.customLabel ?? LOCAL_ENUMS[this.type].label);
|
||||
|
||||
override getDataService() {
|
||||
@@ -27,4 +32,20 @@ export class EnumSelectComponent extends AbstractSelectComponent<ISelectItem, IS
|
||||
ngOnInit() {
|
||||
this.getData();
|
||||
}
|
||||
|
||||
overlayOptions() {
|
||||
return {
|
||||
autoZIndex: true,
|
||||
baseZIndex: this.overlayBaseZIndex(),
|
||||
};
|
||||
}
|
||||
|
||||
overlayBaseZIndex() {
|
||||
const drawers = Array.from(this.document.body.querySelectorAll('.p-drawer,[data-pc-name="drawer"]')) as HTMLElement[];
|
||||
const zIndexes = drawers
|
||||
.map((drawer) => Number.parseInt(drawer.style.zIndex || '0', 10))
|
||||
.filter((zIndex) => Number.isFinite(zIndex) && zIndex > 0);
|
||||
|
||||
return zIndexes.length ? Math.max(...zIndexes) + 2 : 1000;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user