update superAdmin users business

This commit is contained in:
2026-03-14 16:26:22 +03:30
parent 9bfbef6f64
commit 20be653499
126 changed files with 2891 additions and 169 deletions
@@ -1,42 +1,48 @@
<uikit-field [label]="label" [name]="name" [control]="control" [showLabel]="!!label" [showErrors]="showErrors">
@if (type === "switch") {
<p-toggleSwitch [formControl]="control" />
} @else if (type === "price") {
<p-inputgroup>
<p-inputnumber
[attr.id]="name"
[formControl]="control"
[attr.name]="name"
[attr.placeholder]="placeholder"
[attr.inputmode]="inputMode"
[attr.maxlength]="maxLength || null"
[attr.type]="htmlType"
[attr.autocomplete]="autocomplete"
[class]="` w-full ${size === 'large' ? 'p-inputtext-lg' : size === 'small' ? 'p-inputtext-sm' : ''}`"
[required]="isRequired"
[invalid]="control.invalid && (control.touched || control.dirty)"
(input)="onInput($event)"
(onBlur)="blur.emit()"
/>
<p-inputgroup-addon>ریال</p-inputgroup-addon>
</p-inputgroup>
} @else {
<input
pInputText
[attr.id]="name"
[formControl]="control"
[attr.name]="name"
[attr.placeholder]="placeholder"
[attr.inputmode]="inputMode"
[attr.maxlength]="maxLength || null"
[attr.type]="htmlType"
[attr.autocomplete]="autocomplete"
[class]="`${inputClass} w-full ${size === 'large' ? 'p-inputtext-lg' : size === 'small' ? 'p-inputtext-sm' : ''}`"
[required]="isRequired"
[invalid]="control.invalid && (control.touched || control.dirty)"
(input)="onInput($event)"
(onBlur)="blur.emit()"
/>
<p-inputgroup>
<!-- [minlength]="minlength || null" -->
@if (type === "price") {
<p-inputnumber
[attr.id]="name"
[formControl]="control"
[maxlength]="preparedMaxLength || null"
[attr.name]="name"
[attr.placeholder]="preparedPlaceholder"
[attr.type]="htmlType"
[attr.autocomplete]="autocomplete"
[class]="` w-full ${size === 'large' ? 'p-inputtext-lg' : size === 'small' ? 'p-inputtext-sm' : ''}`"
[required]="isRequired"
[invalid]="control.invalid && (control.touched || control.dirty)"
(onBlur)="blur.emit()"
/>
<!-- (input)="onInput($event)" -->
} @else {
<input
pInputText
[attr.id]="name"
[formControl]="control"
[attr.name]="name"
[attr.placeholder]="preparedPlaceholder"
[attr.inputmode]="inputMode"
[attr.maxlength]="preparedMaxLength || null"
[attr.type]="htmlType"
[attr.autocomplete]="autocomplete"
[class]="
`${inputClass} w-full ${size === 'large' ? 'p-inputtext-lg' : size === 'small' ? 'p-inputtext-sm' : ''}`
"
[required]="isRequired"
[invalid]="control.invalid && (control.touched || control.dirty)"
(onBlur)="blur.emit()"
(input)="onInput($event)"
/>
}
@if (preparedSuffix()) {
<p-inputgroup-addon>{{ preparedSuffix() }}</p-inputgroup-addon>
}
</p-inputgroup>
}
@if (hint) {
<small [attr.id]="name + '-help'">{{ hint }}</small>
@@ -1,12 +1,15 @@
import { Maybe } from '@/core';
import { ToastService } from '@/core/services/toast.service';
import { UikitFieldComponent } from '@/uikit/uikit-field.component';
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Component, computed, EventEmitter, inject, Input, Output } from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { InputGroupModule } from 'primeng/inputgroup';
import { InputGroupAddon } from 'primeng/inputgroupaddon';
import { InputMaskModule } from 'primeng/inputmask';
import { InputNumberModule } from 'primeng/inputnumber';
import { InputTextModule } from 'primeng/inputtext';
import { KeyFilterModule } from 'primeng/keyfilter';
import { ToggleSwitch } from 'primeng/toggleswitch';
@Component({
@@ -21,6 +24,8 @@ import { ToggleSwitch } from 'primeng/toggleswitch';
ToggleSwitch,
InputGroupAddon,
InputNumberModule,
KeyFilterModule,
InputMaskModule,
],
templateUrl: './input.component.html',
})
@@ -33,27 +38,43 @@ export class InputComponent {
| 'email'
| 'checkbox'
| 'switch'
| 'number'
| 'price' = 'simple';
@Input() control!: FormControl<Maybe<any>>;
@Input() name!: string;
@Input() label: string = '';
@Input() customPlaceholder?: string;
@Input() placeholder?: string;
@Input() required = false;
@Input() disabled = false;
@Input() size?: 'small' | 'large';
@Input() autocomplete?: string = 'off';
@Input() showErrors = false;
@Input() showErrors = true;
@Input() hint?: string;
@Input() isLtrInput = false;
@Input() suffix: string = '';
@Input() maxLength?: number;
@Input() min?: number;
@Input() max?: number;
@Output() valueChange = new EventEmitter<string | number>();
@Output() blur = new EventEmitter<void>();
onInput(ev: Event) {
const v = (ev.target as HTMLInputElement).value;
this.valueChange.emit(this.type === 'price' ? parseFloat(v) : v);
}
private readonly toastService = inject(ToastService);
get placeholder(): string | null {
if (this.customPlaceholder) return this.customPlaceholder;
// onInput(ev: Event) {
// const v = (ev.target as HTMLInputElement).value;
// const newLocal = v || v == '0';
// // this.valueChange.emit(this.type === 'price' && newLocal ? parseFloat(v) : v);
// }
preparedSuffix = computed(() => {
if (this.type === 'price') {
return 'ریال';
} else return this.suffix;
});
get preparedPlaceholder(): string | null {
if (this.placeholder) return this.placeholder;
switch (this.type) {
case 'mobile':
return '09xxxxxxxx';
@@ -76,13 +97,18 @@ export class InputComponent {
case 'phone':
case 'postalCode':
case 'price':
case 'number':
return 'numeric';
default:
return 'text';
}
}
get maxLength(): number | null {
get isNumeric(): boolean {
return this.inputMode === 'numeric';
}
get preparedMaxLength(): number | null {
switch (this.type) {
case 'mobile':
return 11;
@@ -91,28 +117,45 @@ export class InputComponent {
case 'phone':
return 11;
default:
return null;
return this.maxLength || null;
}
}
get inputClass(): string {
let inputClass = [];
switch (this.type) {
case 'mobile':
case 'phone':
case 'price':
return 'ltrInput';
case 'number':
inputClass.push('ltrInput');
break;
case 'email':
case 'postalCode':
return 'ltrInput rtlPlaceholder';
default:
return '';
inputClass.push('ltrInput', 'rtlPlaceholder');
break;
}
if (this.isLtrInput) {
inputClass.push('ltrInput', 'rtlPlaceholder');
}
return inputClass.join(' ');
}
get htmlType(): string {
switch (this.type) {
case 'email':
return 'email';
case 'mobile':
case 'phone':
case 'price':
case 'postalCode':
case 'number':
return 'number';
case 'checkbox':
return 'checkbox';
case 'switch':
return 'radio';
default:
return 'text';
}
@@ -121,4 +164,40 @@ export class InputComponent {
get isRequired(): boolean {
return this.required || this.control.hasValidator(Validators.required);
}
onInput($event: Event) {
// @ts-ignore
const value = $event.target.value as string;
if (this.type === 'number') {
let newValue = parseFloat(value);
const minValidator = (this.min || this.min === 0) && parseFloat(value) < this.min!;
const maxValidator = (this.max || this.max === 0) && parseFloat(value) > this.max;
if (minValidator || maxValidator) {
if (minValidator) {
this.toastService.warn({
text: `مقدار فیلد باید بیشتر از ${this.min} باشد.`,
});
}
if (maxValidator) {
this.toastService.warn({
text: `مقدار فیلد باید کمتر از ${this.max} باشد.`,
});
}
newValue = parseFloat(value.slice(0, value.length - 1));
// @ts-ignore
$event.target.value = newValue;
}
this.control.setValue(newValue);
}
if (this.preparedMaxLength && this.preparedMaxLength < value.length) {
let newValue = value.slice(0, value.length - 1);
// @ts-ignore
$event.target.value = newValue;
this.control.setValue(newValue);
}
}
}