@elite.framework/ng.core 1.0.63 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,991 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, Output, Input, ChangeDetectionStrategy, Component, inject, Injectable, Directive } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import * as i2$1 from '@angular/forms';
6
- import { ReactiveFormsModule, FormsModule, FormGroup } from '@angular/forms';
7
- import { FormlyPrimeNGModule } from '@ngx-formly/primeng';
8
- import * as i2 from 'primeng/button';
9
- import { ButtonModule } from 'primeng/button';
10
- import { Subject, takeUntil } from 'rxjs';
11
- import { ProgressSpinnerModule } from 'primeng/progressspinner';
12
- import { MessageModule } from 'primeng/message';
13
- import * as i3 from 'primeng/splitbutton';
14
- import { SplitButtonModule } from 'primeng/splitbutton';
15
- import { FormlyForm, FieldType, FormlyAttributes } from '@ngx-formly/core';
16
- import * as i3$1 from '@ngx-translate/core';
17
- import { TranslateService, TranslateModule } from '@ngx-translate/core';
18
- import * as i1$1 from 'primeng/dynamicdialog';
19
- import Swal from 'sweetalert2';
20
- import { Router, ActivatedRoute } from '@angular/router';
2
+ import { Component } from '@angular/core';
21
3
 
22
- class GenericButton {
23
- // permissionChecker = inject(PermissionCheckerService);
24
- // لو وُجدت هذه المصفوفة، نُستخدم splitButton
25
- model;
26
- type = 'button';
27
- icon = '';
28
- label = '';
29
- variant = 'raised';
30
- severity = 'primary';
31
- size = 'normal';
32
- iconPosition = 'left';
33
- disabled = false;
34
- loading = false;
35
- ariaLabel;
36
- extraClasses = ''; // لأي Tailwind إضافي
37
- permission;
38
- clicked = new EventEmitter();
39
- itemClick = new EventEmitter();
40
- // خريطة أحجام
41
- sizeMap = {
42
- small: 'px-2 py-1 text-sm',
43
- normal: 'px-4 py-2 text-base',
44
- large: 'px-6 py-3 text-lg',
45
- };
46
- // خريطة ألوان للـ raised و rounded
47
- colorMap = {
48
- primary: 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 text-white',
49
- secondary: 'bg-gray-600 hover:bg-gray-700 focus:ring-gray-500 text-white',
50
- success: 'bg-green-600 hover:bg-green-700 focus:ring-green-500 text-white',
51
- info: 'bg-teal-600 hover:bg-teal-700 focus:ring-teal-500 text-white',
52
- warning: 'bg-yellow-500 hover:bg-yellow-600 focus:ring-yellow-400 text-white',
53
- danger: 'bg-red-600 hover:bg-red-700 focus:ring-red-500 text-white',
54
- };
55
- // خريطة حدوده للـ outlined
56
- outlinedMap = {
57
- primary: 'border border-blue-600 text-blue-600 hover:bg-blue-50 focus:ring-blue-500',
58
- secondary: 'border border-gray-600 text-gray-600 hover:bg-gray-50 focus:ring-gray-500',
59
- success: 'border border-green-600 text-green-600 hover:bg-green-50 focus:ring-green-500',
60
- info: 'border border-teal-600 text-teal-600 hover:bg-teal-50 focus:ring-teal-500',
61
- warning: 'border border-yellow-500 text-yellow-500 hover:bg-yellow-50 focus:ring-yellow-400',
62
- danger: 'border border-red-600 text-red-600 hover:bg-red-50 focus:ring-red-500',
63
- };
64
- get twClasses() {
65
- const base = [
66
- 'inline-flex items-center justify-center font-medium',
67
- 'focus:outline-none focus:ring-2 focus:ring-offset-2 transition',
68
- this.sizeMap[this.size]
69
- ];
70
- // variant-specific
71
- if (this.variant === 'outlined') {
72
- base.push(this.outlinedMap[this.severity]);
73
- }
74
- else {
75
- base.push(this.colorMap[this.severity]);
76
- }
77
- if (this.variant === 'text') {
78
- base.push('bg-transparent hover:bg-gray-100 focus:ring-gray-200 text-gray-700');
79
- }
80
- if (this.variant === 'rounded') {
81
- base.push('rounded-full');
82
- }
83
- else {
84
- base.push('rounded-md');
85
- }
86
- if (this.disabled || this.loading) {
87
- base.push('opacity-50 cursor-not-allowed');
88
- }
89
- if (this.extraClasses) {
90
- base.push(this.extraClasses);
91
- }
92
- return base.join(' ');
93
- }
94
- onClick() {
95
- if (!this.disabled && !this.loading) {
96
- this.clicked.emit();
97
- }
98
- }
99
- onItemClick(evt) {
100
- this.itemClick.emit(evt);
101
- }
102
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
103
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: GenericButton, isStandalone: true, selector: "lib-generic-button", inputs: { model: "model", type: "type", icon: "icon", label: "label", variant: "variant", severity: "severity", size: "size", iconPosition: "iconPosition", disabled: "disabled", loading: "loading", ariaLabel: "ariaLabel", extraClasses: "extraClasses", permission: "permission" }, outputs: { clicked: "clicked", itemClick: "itemClick" }, ngImport: i0, template: "\n<!-- generic-button.component.html -->\n <!-- *hasPermission=\"permission\" -->\n<ng-container >\n <ng-container *ngIf=\"model?.length; else simpleBtn\">\n <!-- \u062D\u0627\u0644\u0629 \u0627\u0644\u0640 splitButton -->\n <p-splitButton\n [model]=\"model\"\n [icon]=\"icon\"\n [label]=\"label\"\n [styleClass]=\"twClasses\"\n [disabled]=\"disabled || loading\" (onClick)=\"onClick()\"\n (onClick)=\"onClick()\"\n (onItemClick)=\"onItemClick($event)\"\n ></p-splitButton>\n </ng-container>\n\n <ng-template #simpleBtn>\n <!-- \u062D\u0627\u0644\u0629 \u0627\u0644\u0632\u0631\u0651 \u0627\u0644\u0639\u0627\u062F\u064A -->\n <button\n [attr.type]=\"type\"\n pButton\n [icon]=\"loading ? 'pi pi-spin pi-spinner' : icon\"\n [label]=\"label\"\n [ngClass]=\"twClasses\"\n [attr.aria-label]=\"ariaLabel || label\"\n [disabled]=\"disabled || loading\" (onClick)=\"onClick()\"\n (click)=\"onClick()\"\n >\n\n <!-- \u0645\u062D\u062A\u0648\u0649 \u0645\u062E\u0635\u0651\u0635 -->\n <ng-content *ngIf=\"!label && !icon && !loading\"></ng-content>\n </button>\n </ng-template>\n </ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: SplitButtonModule }, { kind: "component", type: i3.SplitButton, selector: "p-splitbutton, p-splitButton, p-split-button", inputs: ["model", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "icon", "iconPos", "label", "tooltip", "tooltipOptions", "styleClass", "menuStyle", "menuStyleClass", "dropdownIcon", "appendTo", "dir", "expandAriaLabel", "showTransitionOptions", "hideTransitionOptions", "buttonProps", "menuButtonProps", "autofocus", "disabled", "tabindex", "menuButtonDisabled", "buttonDisabled"], outputs: ["onClick", "onMenuHide", "onMenuShow", "onDropdownClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4
+ class NgCore {
5
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgCore, deps: [], target: i0.ɵɵFactoryTarget.Component });
6
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: NgCore, isStandalone: true, selector: "lib-ng-core", ngImport: i0, template: "<p>NgCore works!</p>\n", styles: [""] });
104
7
  }
105
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericButton, decorators: [{
8
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgCore, decorators: [{
106
9
  type: Component,
107
- args: [{ selector: 'lib-generic-button', standalone: true, imports: [CommonModule, ButtonModule, SplitButtonModule, /* HasPermissionDirective */], changeDetection: ChangeDetectionStrategy.OnPush, template: "\n<!-- generic-button.component.html -->\n <!-- *hasPermission=\"permission\" -->\n<ng-container >\n <ng-container *ngIf=\"model?.length; else simpleBtn\">\n <!-- \u062D\u0627\u0644\u0629 \u0627\u0644\u0640 splitButton -->\n <p-splitButton\n [model]=\"model\"\n [icon]=\"icon\"\n [label]=\"label\"\n [styleClass]=\"twClasses\"\n [disabled]=\"disabled || loading\" (onClick)=\"onClick()\"\n (onClick)=\"onClick()\"\n (onItemClick)=\"onItemClick($event)\"\n ></p-splitButton>\n </ng-container>\n\n <ng-template #simpleBtn>\n <!-- \u062D\u0627\u0644\u0629 \u0627\u0644\u0632\u0631\u0651 \u0627\u0644\u0639\u0627\u062F\u064A -->\n <button\n [attr.type]=\"type\"\n pButton\n [icon]=\"loading ? 'pi pi-spin pi-spinner' : icon\"\n [label]=\"label\"\n [ngClass]=\"twClasses\"\n [attr.aria-label]=\"ariaLabel || label\"\n [disabled]=\"disabled || loading\" (onClick)=\"onClick()\"\n (click)=\"onClick()\"\n >\n\n <!-- \u0645\u062D\u062A\u0648\u0649 \u0645\u062E\u0635\u0651\u0635 -->\n <ng-content *ngIf=\"!label && !icon && !loading\"></ng-content>\n </button>\n </ng-template>\n </ng-container>\n" }]
108
- }], propDecorators: { model: [{
109
- type: Input
110
- }], type: [{
111
- type: Input
112
- }], icon: [{
113
- type: Input
114
- }], label: [{
115
- type: Input
116
- }], variant: [{
117
- type: Input
118
- }], severity: [{
119
- type: Input
120
- }], size: [{
121
- type: Input
122
- }], iconPosition: [{
123
- type: Input
124
- }], disabled: [{
125
- type: Input
126
- }], loading: [{
127
- type: Input
128
- }], ariaLabel: [{
129
- type: Input
130
- }], extraClasses: [{
131
- type: Input
132
- }], permission: [{
133
- type: Input
134
- }], clicked: [{
135
- type: Output
136
- }], itemClick: [{
137
- type: Output
138
- }] } });
139
-
140
- class GenericFormlyFields {
141
- /** الـ FormGroup الذي يُدار خارجيًا */
142
- form;
143
- /** حقول Formly */
144
- fields = [];
145
- /** النموذج (object) الذي سيُربط بالحقول */
146
- model = {};
147
- /** خيارات Formly (validation, hideExpression, ...) */
148
- options = {};
149
- ngOnInit() {
150
- // ما من حاجة هنا: يفترض أن form مُهيّأ في الخارج
151
- }
152
- ngOnChanges(changes) {
153
- // لو احتجت تتعامل مع تغيّر الحقول أو الموديل، هنا المكان
154
- }
155
- // دالة مساعدة للوصول الآمن لخصائص الحقل
156
- getFieldIcon(field) {
157
- return field.templateOptions?.['icon'] || null;
158
- }
159
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericFormlyFields, deps: [], target: i0.ɵɵFactoryTarget.Component });
160
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: GenericFormlyFields, isStandalone: true, selector: "lib-generic-formly-fields", inputs: { form: "form", fields: "fields", model: "model", options: "options" }, usesOnChanges: true, ngImport: i0, template: "<!-- \u064A\u0631\u0633\u0645 \u062D\u0642\u0648\u0644 Formly \u062F\u0627\u062E\u0644 \u0627\u0644\u0640 form \u0627\u0644\u0645\u0648\u062C\u0648\u062F -->\n<formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\">\n</formly-form>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }] });
161
- }
162
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericFormlyFields, decorators: [{
163
- type: Component,
164
- args: [{ selector: 'lib-generic-formly-fields', standalone: true, imports: [
165
- CommonModule,
166
- ReactiveFormsModule,
167
- FormsModule,
168
- FormlyForm,
169
- // FormlyPrimeNGModule,
170
- ], template: "<!-- \u064A\u0631\u0633\u0645 \u062D\u0642\u0648\u0644 Formly \u062F\u0627\u062E\u0644 \u0627\u0644\u0640 form \u0627\u0644\u0645\u0648\u062C\u0648\u062F -->\n<formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\">\n</formly-form>\n" }]
171
- }], propDecorators: { form: [{
172
- type: Input
173
- }], fields: [{
174
- type: Input
175
- }], model: [{
176
- type: Input
177
- }], options: [{
178
- type: Input
179
- }] } });
180
-
181
- class GenericErrormessage {
182
- /** نص رسالة الخطأ */
183
- text = '';
184
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericErrormessage, deps: [], target: i0.ɵɵFactoryTarget.Component });
185
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: GenericErrormessage, isStandalone: true, selector: "lib-generic-errormessage", inputs: { text: "text" }, ngImport: i0, template: " \n@if (text) {\n<div class=\"bg-red-100 border border-red-300 text-red-800 px-4 py-3 rounded my-4\"> {{ text }} </div>\n}", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
186
- }
187
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericErrormessage, decorators: [{
188
- type: Component,
189
- args: [{ selector: 'lib-generic-errormessage', imports: [CommonModule], template: " \n@if (text) {\n<div class=\"bg-red-100 border border-red-300 text-red-800 px-4 py-3 rounded my-4\"> {{ text }} </div>\n}" }]
190
- }], propDecorators: { text: [{
191
- type: Input
192
- }] } });
193
-
194
- class GenericCrudDialog {
195
- ref;
196
- config;
197
- form = new FormGroup({});
198
- model = {};
199
- fields = [];
200
- options = {};
201
- loading = false;
202
- id = null;
203
- errorMessage = null;
204
- translate = inject(TranslateService);
205
- destroy$ = new Subject();
206
- idField;
207
- constructor(ref, config) {
208
- this.ref = ref;
209
- this.config = config;
210
- // استقبال البيانات من المكون الأب
211
- this.fields = this.config.data.fields;
212
- this.idField = this.config.data.idField;
213
- this.model = this.config.data.item ? { ...this.config.data.item } : {};
214
- // تحديد وضع العملية (تعديل أو إضافة)
215
- // this.isEditMode = !!this.config.data.item;
216
- try {
217
- const id = this.model[this.idField];
218
- this.id = id != undefined;
219
- }
220
- catch (error) {
221
- }
222
- }
223
- onSubmit() {
224
- if (this.form.invalid)
225
- return;
226
- this.loading = true;
227
- this.errorMessage = null;
228
- const service = this.config.data.service;
229
- console.log('service:', service);
230
- try {
231
- this.id = this.model[this.idField];
232
- }
233
- catch (error) {
234
- }
235
- console.log('isEditMode:', this.id);
236
- debugger;
237
- const isEditMode = !!this.config.data.item;
238
- const operation$ = isEditMode
239
- ? service.update(this.id, this.model)
240
- : service.create(this.model);
241
- operation$.pipe(takeUntil(this.destroy$)).subscribe({
242
- next: () => {
243
- this.ref.close(true); // نجاح العملية
244
- },
245
- error: (err) => {
246
- this.loading = false;
247
- this.errorMessage = err.error?.message ||
248
- err.message ||
249
- 'حدث خطأ أثناء الحفظ. يرجى المحاولة مرة أخرى.';
250
- }
251
- });
252
- }
253
- ngOnDestroy() {
254
- this.destroy$.next();
255
- this.destroy$.complete();
256
- }
257
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericCrudDialog, deps: [{ token: i1$1.DynamicDialogRef }, { token: i1$1.DynamicDialogConfig }], target: i0.ɵɵFactoryTarget.Component });
258
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: GenericCrudDialog, isStandalone: true, selector: "app-generic-crud-dialog", ngImport: i0, template: " <div class=\"p-4\">\n @if (errorMessage) {\n <lib-generic-errormessage [text]=\"errorMessage\"></lib-generic-errormessage>\n }\n\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <!-- \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0645\u0643\u0648\u0646 \u0627\u0644\u0639\u0627\u0645 \u0644\u0644\u062D\u0642\u0648\u0644 -->\n <lib-generic-formly-fields\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\">\n </lib-generic-formly-fields>\n\n <div class=\"flex justify-end gap-2 mt-4\">\n\n <!-- \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0645\u0643\u0648\u0646 \u0627\u0644\u0639\u0627\u0645 \u0644\u0644\u0623\u0632\u0631\u0627\u0631 - \u0632\u0631 \u0627\u0644\u062D\u0641\u0638 -->\n <lib-generic-button\n variant=\"raised\"\n severity=\"primary\"\n type=\"submit\"\n [loading]=\"loading\"\n [disabled]=\"loading || form.invalid\"\n [label]=\"(id ? 'COMMON.UPDATE' : 'COMMON.SAVE') | translate\">\n </lib-generic-button>\n <!-- \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0645\u0643\u0648\u0646 \u0627\u0644\u0639\u0627\u0645 \u0644\u0644\u0623\u0632\u0631\u0627\u0631 - \u0632\u0631 \u0627\u0644\u0625\u0644\u063A\u0627\u0621 -->\n <lib-generic-button\n variant=\"text\"\n severity=\"secondary\"\n [disabled]=\"loading\"\n [label]=\"'COMMON.CANCEL' | translate\"\n (clicked)=\"ref.close(false)\">\n </lib-generic-button>\n\n </div>\n </form>\n </div>\n", styles: [":host{display:block}button{min-width:120px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormlyPrimeNGModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: GenericButton, selector: "lib-generic-button", inputs: ["model", "type", "icon", "label", "variant", "severity", "size", "iconPosition", "disabled", "loading", "ariaLabel", "extraClasses", "permission"], outputs: ["clicked", "itemClick"] }, { kind: "component", type: // إضافة المكون العام للأزرار
259
- GenericFormlyFields, selector: "lib-generic-formly-fields", inputs: ["form", "fields", "model", "options"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: GenericErrormessage, selector: "lib-generic-errormessage", inputs: ["text"] }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
260
- }
261
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: GenericCrudDialog, decorators: [{
262
- type: Component,
263
- args: [{ selector: 'app-generic-crud-dialog', standalone: true, imports: [
264
- CommonModule,
265
- ReactiveFormsModule,
266
- FormlyPrimeNGModule,
267
- ButtonModule,
268
- ProgressSpinnerModule,
269
- MessageModule,
270
- GenericButton, // إضافة المكون العام للأزرار
271
- GenericFormlyFields,
272
- TranslateModule,
273
- GenericErrormessage
274
- ], template: " <div class=\"p-4\">\n @if (errorMessage) {\n <lib-generic-errormessage [text]=\"errorMessage\"></lib-generic-errormessage>\n }\n\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <!-- \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0645\u0643\u0648\u0646 \u0627\u0644\u0639\u0627\u0645 \u0644\u0644\u062D\u0642\u0648\u0644 -->\n <lib-generic-formly-fields\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\">\n </lib-generic-formly-fields>\n\n <div class=\"flex justify-end gap-2 mt-4\">\n\n <!-- \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0645\u0643\u0648\u0646 \u0627\u0644\u0639\u0627\u0645 \u0644\u0644\u0623\u0632\u0631\u0627\u0631 - \u0632\u0631 \u0627\u0644\u062D\u0641\u0638 -->\n <lib-generic-button\n variant=\"raised\"\n severity=\"primary\"\n type=\"submit\"\n [loading]=\"loading\"\n [disabled]=\"loading || form.invalid\"\n [label]=\"(id ? 'COMMON.UPDATE' : 'COMMON.SAVE') | translate\">\n </lib-generic-button>\n <!-- \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0645\u0643\u0648\u0646 \u0627\u0644\u0639\u0627\u0645 \u0644\u0644\u0623\u0632\u0631\u0627\u0631 - \u0632\u0631 \u0627\u0644\u0625\u0644\u063A\u0627\u0621 -->\n <lib-generic-button\n variant=\"text\"\n severity=\"secondary\"\n [disabled]=\"loading\"\n [label]=\"'COMMON.CANCEL' | translate\"\n (clicked)=\"ref.close(false)\">\n </lib-generic-button>\n\n </div>\n </form>\n </div>\n", styles: [":host{display:block}button{min-width:120px}\n"] }]
275
- }], ctorParameters: () => [{ type: i1$1.DynamicDialogRef }, { type: i1$1.DynamicDialogConfig }] });
276
-
277
- class DeactivationReasonFormComponent {
278
- ref;
279
- config;
280
- form = new FormGroup({});
281
- model = {};
282
- fields;
283
- loading = false;
284
- errorMessage = null;
285
- destroy$ = new Subject();
286
- idField;
287
- constructor(ref, config) {
288
- this.ref = ref;
289
- this.config = config;
290
- this.model = config.data?.model || {};
291
- this.idField = this.config.data.idField;
292
- this.fields = [
293
- {
294
- key: 'deactivationReason',
295
- type: 'textarea',
296
- props: {
297
- label: 'DeactivationReason',
298
- placeholder: 'DeactivationReason',
299
- rows: 5,
300
- required: true,
301
- },
302
- },
303
- ];
304
- }
305
- onSubmit() {
306
- if (this.form.invalid)
307
- return;
308
- // this.loading = true;
309
- // this.errorMessage = null;
310
- const service = this.config.data.service;
311
- const id = this.model[this.idField];
312
- this.model.isActive = false;
313
- const operation$ = service.update(id, this.model);
314
- operation$.pipe(takeUntil(this.destroy$)).subscribe({
315
- next: () => {
316
- this.ref.close(this.model); // نجاح العملية
317
- },
318
- error: (err) => {
319
- this.loading = false;
320
- this.errorMessage = err.error?.message ||
321
- err.message ||
322
- 'حدث خطأ أثناء الحفظ. يرجى المحاولة مرة أخرى.';
323
- }
324
- });
325
- }
326
- ngOnDestroy() {
327
- this.destroy$.next();
328
- this.destroy$.complete();
329
- }
330
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DeactivationReasonFormComponent, deps: [{ token: i1$1.DynamicDialogRef }, { token: i1$1.DynamicDialogConfig }], target: i0.ɵɵFactoryTarget.Component });
331
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: DeactivationReasonFormComponent, isStandalone: true, selector: "app-deactivation-reason-form", ngImport: i0, template: `
332
- <form [formGroup]="form" (ngSubmit)="onSubmit()" class="p-4 space-y-4">
333
- <formly-form [form]="form" [fields]="fields" [model]="model"></formly-form>
334
-
335
-
336
- <div class="bottom-0 left-0 right-0 bg-gray-200 border-t border-gray-400 px-4 py-3 flex justify-end gap-2">
337
-
338
- <p-button
339
- [label]="( 'SAVE') | translate"
340
- size="small"
341
- [disabled]="form.invalid"
342
- [type]="'submit'">
343
- </p-button>
344
-
345
- <p-button
346
- [label]="'CANCEL' | translate "
347
- severity="danger"
348
- size="small"
349
- (onClick)="ref.close(false)">
350
- </p-button>
351
-
352
- </div>
353
- </form>
354
- `, isInline: true, dependencies: [{ kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
355
- }
356
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DeactivationReasonFormComponent, decorators: [{
357
- type: Component,
358
- args: [{
359
- selector: 'app-deactivation-reason-form',
360
- template: `
361
- <form [formGroup]="form" (ngSubmit)="onSubmit()" class="p-4 space-y-4">
362
- <formly-form [form]="form" [fields]="fields" [model]="model"></formly-form>
363
-
364
-
365
- <div class="bottom-0 left-0 right-0 bg-gray-200 border-t border-gray-400 px-4 py-3 flex justify-end gap-2">
366
-
367
- <p-button
368
- [label]="( 'SAVE') | translate"
369
- size="small"
370
- [disabled]="form.invalid"
371
- [type]="'submit'">
372
- </p-button>
373
-
374
- <p-button
375
- [label]="'CANCEL' | translate "
376
- severity="danger"
377
- size="small"
378
- (onClick)="ref.close(false)">
379
- </p-button>
380
-
381
- </div>
382
- </form>
383
- `,
384
- imports: [FormlyForm, CommonModule, ReactiveFormsModule, FormsModule, TranslateModule, ButtonModule]
385
- }]
386
- }], ctorParameters: () => [{ type: i1$1.DynamicDialogRef }, { type: i1$1.DynamicDialogConfig }] });
387
-
388
- // app/shared/services/swal.service.ts
389
- class SwalService {
390
- /** رسالة تأكيد قبل تنفيذ إجراء */
391
- confirm(title = 'هل أنت متأكد؟', text = 'لن يمكنك التراجع عن هذا الإجراء', confirmButtonText = 'نعم', cancelButtonText = 'إلغاء') {
392
- return Swal.fire({
393
- icon: 'warning',
394
- title,
395
- text,
396
- showCancelButton: true,
397
- confirmButtonText,
398
- cancelButtonText,
399
- // reverseButtons: true,
400
- customClass: {
401
- container: 'swal2-container' // ✅ أضف هذه الفئة
402
- }
403
- });
404
- }
405
- /** رسالة نجاح */
406
- success(title, text, timer = 2000) {
407
- return Swal.fire({
408
- icon: 'success',
409
- title,
410
- text,
411
- timer,
412
- showConfirmButton: false,
413
- customClass: {
414
- container: 'swal2-container' // ✅ أضف هذه الفئة
415
- }
416
- });
417
- }
418
- /** رسالة خطأ */
419
- error(title, text, footer) {
420
- return Swal.fire({
421
- icon: 'error',
422
- title,
423
- text,
424
- footer,
425
- customClass: {
426
- container: 'swal2-container' // ✅ أضف هذه الفئة
427
- }
428
- });
429
- }
430
- /** رسالة معلومات */
431
- info(title, text) {
432
- return Swal.fire({
433
- icon: 'info',
434
- title,
435
- text,
436
- });
437
- }
438
- /** عرض نافذة SweetAlert2 بأي خيارات تريد */
439
- alert(options) {
440
- return Swal.fire(options);
441
- }
442
- /** Toast بسيط قابل لإعادة الاستخدام */
443
- toast(title, icon = 'info', position = 'top-end', timer = 3000) {
444
- const Toast = Swal.mixin({
445
- toast: true,
446
- position,
447
- timer,
448
- showConfirmButton: false,
449
- });
450
- Toast.fire({ icon, title });
451
- }
452
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: SwalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
453
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: SwalService, providedIn: 'root' });
454
- }
455
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: SwalService, decorators: [{
456
- type: Injectable,
457
- args: [{ providedIn: 'root' }]
458
- }] });
459
-
460
- // src/app/shared/components/base-crud.component.ts
461
- class BaseCrud {
462
- list = [];
463
- paginator = true;
464
- canLoad = true;
465
- loading = false;
466
- errorMsg = '';
467
- first = 0;
468
- rows = 10;
469
- totalRecords = 0;
470
- searchGlobal = '';
471
- sort;
472
- pageFilters = {};
473
- currentFilters = {};
474
- mode = '';
475
- scrollHeight = '400px';
476
- swalService = inject(SwalService);
477
- dialogRef;
478
- dialogVisible = false;
479
- drawerVisible = false;
480
- selectedItem = null;
481
- defaultModel = null;
482
- // selectedItem: T | any = {};
483
- isViewMode = false;
484
- isEditMode = false;
485
- displayMode = 'drawer';
486
- router = inject(Router);
487
- route = inject(ActivatedRoute);
488
- loadPage(pageIndex, pageSize) {
489
- if (this.canLoad) {
490
- this.loading = true;
491
- var filters = {
492
- maxResultCount: pageSize,
493
- skipCount: pageIndex,
494
- sorting: this.sort,
495
- ...this.currentFilters,
496
- ...this.pageFilters,
497
- ...(this.searchGlobal ? { filter: this.searchGlobal } : {}),
498
- };
499
- //
500
- this.service.getList(filters)
501
- .subscribe({
502
- next: (res) => {
503
- //
504
- this.list = res.items;
505
- this.totalRecords = res.totalCount;
506
- this.loading = false;
507
- },
508
- error: err => {
509
- this.errorMsg = err.error?.message || err.message || 'خطأ في التحميل';
510
- this.loading = false;
511
- }
512
- });
513
- }
514
- }
515
- onSearch(filters) {
516
- //
517
- if (filters && typeof filters === 'object' && !Array.isArray(filters)) {
518
- this.pageFilters = filters;
519
- }
520
- else {
521
- this.searchGlobal = filters;
522
- }
523
- this.loadPage(0, 10);
524
- }
525
- onPageChange(event) {
526
- // فك المتغيّرات مع قيمة افتراضية لفلاتر
527
- const { first = this.first, rows = this.rows, sort = this.sort, filters = {} } = event;
528
- this.first = first;
529
- this.rows = rows;
530
- this.sort = sort;
531
- // const pageIndex = Math.floor(first / rows);
532
- const skipCount = first;
533
- const pageIndex = skipCount;
534
- // الوصول للفلتر العام عبر الصيغة المربعة
535
- const globalValue = filters['global'];
536
- this.searchGlobal = typeof globalValue === 'string' ? globalValue : '';
537
- // فلترة خاصة بحقل واحد
538
- // const fieldFilters = { ...filters };
539
- // delete fieldFilters['global'];
540
- // this.currentFilters = fieldFilters as Partial<F>;
541
- this.loadPage(pageIndex, rows);
542
- }
543
- openEditor(item, mode) {
544
- this.mode = mode;
545
- this.selectedItem = item ?? this.defaultModel ?? {};
546
- this.isEditMode = mode === 'edit';
547
- this.isViewMode = mode === 'view';
548
- // resolve displayMode (string or map)
549
- const modeConfig = typeof this.displayMode === 'string'
550
- ? this.displayMode
551
- : this.displayMode[mode] ?? 'drawer';
552
- switch (modeConfig) {
553
- case 'drawer':
554
- this.drawerVisible = true;
555
- break;
556
- case 'dialog':
557
- this.dialogVisible = true;
558
- break;
559
- case 'route':
560
- const id = item ? item[this.idField] : 'new';
561
- if (mode === 'add') {
562
- this.router.navigate([mode], { relativeTo: this.route });
563
- }
564
- else {
565
- this.router.navigate([id, mode], { relativeTo: this.route });
566
- }
567
- break;
568
- }
569
- }
570
- visibleChange(value) {
571
- const modeConfig = typeof this.displayMode === 'string'
572
- ? this.displayMode
573
- : this.displayMode[this.mode] ?? 'drawer';
574
- if (modeConfig === 'dialog') {
575
- this.dialogVisible = value;
576
- }
577
- else if (modeConfig === 'drawer') {
578
- this.drawerVisible = value;
579
- }
580
- else {
581
- // route mode does not use drawer/dialog
582
- }
583
- }
584
- // onTableAction(event: { name: string; row: T | null }): void {
585
- // switch (event.name) {
586
- // case 'add': this.openDrawer(null,event.name); break;
587
- // case 'view': this.openDrawer(event.row!,event.name); break;
588
- // case 'edit': this.openDrawer(event.row!,event.name); break;
589
- // case 'delete': this.onDelete(event.row!);break;
590
- // case 'state': this.openDeactivationReason(event.row!);break;
591
- // }
592
- // }
593
- onTableAction(event) {
594
- switch (event.name) {
595
- case 'add':
596
- case 'edit':
597
- case 'view':
598
- this.openEditor(event.row, event.name);
599
- break;
600
- case 'delete':
601
- this.onDelete(event.row);
602
- break;
603
- case 'state':
604
- this.openDeactivationReason(event.row);
605
- break;
606
- }
607
- }
608
- openDrawer(item, mode) {
609
- this.mode = mode;
610
- // this.drawerVisible = !this.drawerVisible;
611
- if (item == null) {
612
- this.selectedItem = this.defaultModel || {};
613
- }
614
- else {
615
- this.selectedItem = item;
616
- }
617
- if (mode == 'edit') {
618
- this.drawerVisible = true;
619
- this.isEditMode = true;
620
- this.isViewMode = false;
621
- // this.isEditMode = item !=null ;
622
- }
623
- if (mode == 'add') {
624
- this.drawerVisible = true;
625
- this.isViewMode = false;
626
- this.isEditMode = false;
627
- }
628
- if (mode == 'view') {
629
- // this.drawerVisible = true;
630
- this.dialogVisible = true;
631
- this.isViewMode = true;
632
- this.isEditMode = false;
633
- }
634
- }
635
- openDialog(item) {
636
- this.dialogRef = this.dialogService.open((GenericCrudDialog), {
637
- header: item ? 'تعديل' : 'اضافه',
638
- styleClass: 'w-1/2',
639
- modal: true,
640
- data: {
641
- item,
642
- fields: this.formFields,
643
- service: this.service,
644
- idField: this.idField
645
- }
646
- });
647
- //
648
- this.dialogRef.onClose.subscribe((reload) => {
649
- if (reload)
650
- this.loadPage(0, this.rows);
651
- });
652
- }
653
- openDeactivationReason(model) {
654
- this.selectedItem = model;
655
- if (this.selectedItem.isActive == true) {
656
- const ref = this.dialogService.open(DeactivationReasonFormComponent, {
657
- header: 'السبب (في حال تم إيقافه)',
658
- width: '30vw',
659
- data: { model: { ...model },
660
- fields: this.formFields,
661
- service: this.service,
662
- idField: this.idField },
663
- });
664
- ref.onClose.subscribe((result) => {
665
- if (result) {
666
- this.selectedItem.isActive = false;
667
- this.selectedItem.deactivationReason = result.deactivationReason;
668
- // Optionally: save model via API
669
- }
670
- });
671
- }
672
- else {
673
- this.selectedItem.isActive = true;
674
- this.selectedItem.deactivationReason = "";
675
- const id = this.selectedItem[this.idField];
676
- this.service.update(id, this.selectedItem).subscribe({
677
- next: () => {
678
- },
679
- error: (err) => {
680
- this.loading = false;
681
- }
682
- });
683
- }
684
- }
685
- // onDelete(item: any): void {
686
- // if (!confirm('هل تريد الحذف فعلاً؟')) return;
687
- // const id = (item as any)[this.idField];
688
- // this.service.delete(id).subscribe(() => {
689
- // this.loadPage(0, this.rows);
690
- // });
691
- // }
692
- onDelete(item) {
693
- const id = item[this.idField];
694
- this.swalService.confirm('تأكيد الحذف', 'هل تريد حذف هذا السجل فعلاً؟', 'نعم، احذف', 'إلغاء').then((result) => {
695
- if (result.isConfirmed) {
696
- this.service.delete(id).subscribe({
697
- next: () => {
698
- this.loadPage(0, this.rows);
699
- this.swalService.success('تم الحذف بنجاح');
700
- },
701
- error: (err) => {
702
- this.loading = false;
703
- const msg = err.error?.title ||
704
- err.message ||
705
- 'حدث خطأ أثناء الحفظ. يرجى المحاولة مرة أخرى.';
706
- // this.errorMessage = msg;
707
- // ❌ رسالة خطأ
708
- this.swalService.error('فشل الحذف', msg);
709
- }
710
- });
711
- }
712
- });
713
- }
714
- get columns() {
715
- const flattenFields = (fields) => {
716
- return fields.flatMap(field => {
717
- // Check for nested group/panel
718
- if (field.fieldGroup?.length) {
719
- return flattenFields(field.fieldGroup);
720
- }
721
- // Skip fields with no props or table.hidden === true
722
- if (!field.props || field.props['table']?.hidden === true) {
723
- return [];
724
- }
725
- // Determine the column type: table.type > field.type > 'label-type'
726
- // const tableType = field.props['table']?.type || field.type || 'label-type';
727
- const tableType = field.props['table']?.type || 'label-type';
728
- //
729
- return [{
730
- type: tableType,
731
- key: field['key'], // always set key for table rendering
732
- props: {
733
- ...field.props, // base props
734
- ...field.props['table']?.props // table-specific overrides
735
- },
736
- expressions: field.props['table']?.expressions
737
- }];
738
- });
739
- };
740
- return flattenFields(this.formFields);
741
- }
742
- get filters() {
743
- const flattenForFilter = (fields) => {
744
- return fields.flatMap(field => {
745
- if (field.fieldGroup?.length) {
746
- // Recursively handle nested panels/groups
747
- return flattenForFilter(field.fieldGroup);
748
- }
749
- // Skip fields with no props or filter.hidden === true
750
- if (!field.props || field.props['filter']?.hidden === true) {
751
- return [];
752
- }
753
- return [field];
754
- });
755
- };
756
- return flattenForFilter(this.formFields);
757
- }
758
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: BaseCrud, deps: [], target: i0.ɵɵFactoryTarget.Directive });
759
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.4", type: BaseCrud, isStandalone: true, ngImport: i0 });
760
- }
761
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: BaseCrud, decorators: [{
762
- type: Directive
763
- }] });
764
-
765
- class InputWithIconType extends FieldType {
766
- get type() {
767
- return this.to.type || 'text';
768
- }
769
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: InputWithIconType, deps: null, target: i0.ɵɵFactoryTarget.Component });
770
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: InputWithIconType, isStandalone: true, selector: "formly-field-input-with-icon", usesInheritance: true, ngImport: i0, template: `
771
- <div class="relative">
772
- <!-- [formControl]="formControl" -->
773
- <input
774
- [type]="type"
775
-
776
- [formlyAttributes]="field"
777
- class="w-full rounded-xl border border-gray-200 bg-gray-50 pl-12 pr-4 py-3 text-sm focus:border-primary focus:ring-2 focus:ring-blue-100 transition-all"
778
- [placeholder]="to.placeholder"
779
- [disabled]="to.disabled ? true : false"
780
- />
781
- <i class="{{ to['icon'] }} absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 text-base"></i>
782
- </div>
783
- `, isInline: true, dependencies: [{ kind: "directive", type: FormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }] });
784
- }
785
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: InputWithIconType, decorators: [{
786
- type: Component,
787
- args: [{
788
- selector: 'formly-field-input-with-icon',
789
- imports: [FormlyAttributes, ReactiveFormsModule, CommonModule, FormsModule],
790
- template: `
791
- <div class="relative">
792
- <!-- [formControl]="formControl" -->
793
- <input
794
- [type]="type"
795
-
796
- [formlyAttributes]="field"
797
- class="w-full rounded-xl border border-gray-200 bg-gray-50 pl-12 pr-4 py-3 text-sm focus:border-primary focus:ring-2 focus:ring-blue-100 transition-all"
798
- [placeholder]="to.placeholder"
799
- [disabled]="to.disabled ? true : false"
800
- />
801
- <i class="{{ to['icon'] }} absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 text-base"></i>
802
- </div>
803
- `,
804
- }]
10
+ args: [{ selector: 'lib-ng-core', imports: [], template: "<p>NgCore works!</p>\n" }]
805
11
  }] });
806
12
 
807
- const DEFAULT_CONTROL_CLASS = [
808
- 'w-full',
809
- 'border',
810
- 'border-gray-300',
811
- 'rounded',
812
- 'focus:outline-none',
813
- 'focus:ring-2',
814
- 'focus:ring-green-400',
815
- ].join(' ');
816
- function numberField(key, label, required = false, className = 'col-span-1') {
817
- return {
818
- key,
819
- type: 'input',
820
- className,
821
- wrappers: ['form-field'],
822
- templateOptions: {
823
- type: "number",
824
- label,
825
- required,
826
- attributes: { class: DEFAULT_CONTROL_CLASS },
827
- },
828
- };
829
- }
830
- function textField(key, label, required = false, className = 'col-span-1',
831
- // ✅ تم تغيير هذا البراميتر ليقبل خصائص إضافية لـ templateOptions
832
- extraTemplateOptions) {
833
- return {
834
- key,
835
- type: 'advanced-input',
836
- className,
837
- wrappers: ['form-field'],
838
- props: {
839
- label,
840
- required,
841
- attributes: {
842
- class: DEFAULT_CONTROL_CLASS,
843
- },
844
- // ✅ دمج الخصائص الإضافية هنا
845
- ...extraTemplateOptions,
846
- },
847
- };
848
- }
849
- function textField2(key, label, required = false, className = 'col-span-1', expressions) {
850
- return {
851
- key,
852
- type: 'input',
853
- className,
854
- wrappers: ['form-field'],
855
- templateOptions: {
856
- label,
857
- required,
858
- attributes: {
859
- class: DEFAULT_CONTROL_CLASS,
860
- },
861
- // ✅ اضف disabled ليتضبب الحقل إذا كان readonly
862
- },
863
- expressions,
864
- };
865
- }
866
- function textareaField(key, label, rows = 3, className = 'col-span-1') {
867
- return {
868
- key,
869
- type: 'textarea',
870
- className,
871
- wrappers: ['form-field'],
872
- templateOptions: {
873
- label,
874
- rows,
875
- attributes: { class: DEFAULT_CONTROL_CLASS },
876
- },
877
- };
878
- }
879
- function selectField({ key, label, options = [], className, defaultValue, fullWidth = false, required = false, }) {
880
- const config = {
881
- key,
882
- type: 'select',
883
- className: className ?? (fullWidth ? 'col-span-2' : 'col-span-1'),
884
- wrappers: ['form-field'],
885
- templateOptions: {
886
- label,
887
- options,
888
- required,
889
- placeholder: `اختر ${label}`,
890
- showClear: true,
891
- filter: true,
892
- appendTo: 'body',
893
- optionLabel: 'label',
894
- optionValue: 'value',
895
- attributes: { class: DEFAULT_CONTROL_CLASS },
896
- },
897
- };
898
- if (options !== undefined) {
899
- config.templateOptions.options = options;
900
- }
901
- if (defaultValue !== undefined) {
902
- config.defaultValue = defaultValue;
903
- }
904
- return config;
905
- }
906
- // export function checkboxField(
907
- // key: string,
908
- // label: string,
909
- // required = false,
910
- // className = 'col-span-1',
911
- // useNumberMapping = false
912
- // ): FormlyFieldConfig {
913
- // const field: FormlyFieldConfig = {
914
- // key,
915
- // type: 'checkbox',
916
- // className,
917
- // wrappers: ['form-field'],
918
- // templateOptions: {
919
- // label,
920
- // required,
921
- // attributes: {
922
- // class: 'flex items-center gap-2',
923
- // },
924
- // },
925
- // };
926
- // if (useNumberMapping) {
927
- // field.hooks = {
928
- // onInit: (field) => {
929
- // // ✅ تهيئة القيمة داخل الفورم كنترول
930
- // const initialValue = field.model?.[key];
931
- // if (initialValue === 1 || initialValue === 2) {
932
- // field.formControl?.setValue(initialValue === 1, { emitEvent: false });
933
- // }
934
- // // ✅ تحويل عند تغيّر القيمة من الـ checkbox
935
- // field.formControl?.valueChanges.subscribe(val => {
936
- // const newValue = val ? 1 : 2;
937
- // if (field.model) {
938
- // field.model[key] = newValue;
939
- // }
940
- // });
941
- // }
942
- // };
943
- // }
944
- // return field;
945
- // }
946
- function checkboxField(key, label, required = false, className = 'col-span-1') {
947
- return {
948
- key,
949
- type: 'checkbox',
950
- className,
951
- wrappers: ['form-field'],
952
- templateOptions: {
953
- label,
954
- required,
955
- attributes: {
956
- class: 'flex items-center gap-2',
957
- },
958
- },
959
- hooks: {
960
- onInit: (field) => {
961
- const val = field.model?.[key];
962
- if (val === 1) {
963
- field.formControl?.setValue(true, { emitEvent: false });
964
- }
965
- else if (val === 2) {
966
- field.formControl?.setValue(false, { emitEvent: false });
967
- }
968
- else if (val === undefined) {
969
- field.model[key] = 2; // تعيين القيمة الافتراضية في الموديل
970
- field.formControl?.setValue(false, { emitEvent: false });
971
- }
972
- else {
973
- field.formControl?.setValue(false, { emitEvent: false });
974
- }
975
- field.formControl?.valueChanges.subscribe(val => {
976
- const newVal = val ? 1 : 2;
977
- if (field.model && field.model[key] !== newVal) {
978
- field.model[key] = newVal;
979
- }
980
- });
981
- }
982
- }
983
- };
984
- }
985
-
986
13
  /**
987
14
  * Generated bundle index. Do not edit.
988
15
  */
989
16
 
990
- export { BaseCrud, DEFAULT_CONTROL_CLASS, InputWithIconType, checkboxField, numberField, selectField, textField, textField2, textareaField };
17
+ export { NgCore };
991
18
  //# sourceMappingURL=elite.framework-ng.core.mjs.map