@flusys/ng-auth 9.1.0 → 9.1.2

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.
Files changed (37) hide show
  1. package/README.md +2 -0
  2. package/fesm2022/flusys-ng-auth-administration-page.component-DmN4KqiR.mjs +146 -0
  3. package/fesm2022/flusys-ng-auth-administration-page.component-DmN4KqiR.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-auth-branch-form.component-Df_sMC2G.mjs +743 -0
  5. package/fesm2022/flusys-ng-auth-branch-form.component-Df_sMC2G.mjs.map +1 -0
  6. package/fesm2022/flusys-ng-auth-branch-list.component-CWat6QWN.mjs +775 -0
  7. package/fesm2022/flusys-ng-auth-branch-list.component-CWat6QWN.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-auth-company-form.component-BvZ4Pn8j.mjs +198 -0
  9. package/fesm2022/flusys-ng-auth-company-form.component-BvZ4Pn8j.mjs.map +1 -0
  10. package/fesm2022/flusys-ng-auth-company-list.component-Corh9AIh.mjs +241 -0
  11. package/fesm2022/flusys-ng-auth-company-list.component-Corh9AIh.mjs.map +1 -0
  12. package/fesm2022/flusys-ng-auth-extension-order.util-2XWSLqii.mjs +6 -0
  13. package/fesm2022/flusys-ng-auth-extension-order.util-2XWSLqii.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-auth-forgot-password-page.component-BRTVZPX6.mjs +384 -0
  15. package/fesm2022/flusys-ng-auth-forgot-password-page.component-BRTVZPX6.mjs.map +1 -0
  16. package/fesm2022/flusys-ng-auth-login-page.component-DQl52Qau.mjs +1074 -0
  17. package/fesm2022/flusys-ng-auth-login-page.component-DQl52Qau.mjs.map +1 -0
  18. package/fesm2022/flusys-ng-auth-profile-page.component-b-8rPEXQ.mjs +1792 -0
  19. package/fesm2022/flusys-ng-auth-profile-page.component-b-8rPEXQ.mjs.map +1 -0
  20. package/fesm2022/flusys-ng-auth-register-page.component-D99y1jiA.mjs +1513 -0
  21. package/fesm2022/flusys-ng-auth-register-page.component-D99y1jiA.mjs.map +1 -0
  22. package/fesm2022/flusys-ng-auth-reset-password-page.component-C0tN_AW1.mjs +538 -0
  23. package/fesm2022/flusys-ng-auth-reset-password-page.component-C0tN_AW1.mjs.map +1 -0
  24. package/fesm2022/flusys-ng-auth-social-callback-page.component-gTD7_LJY.mjs +217 -0
  25. package/fesm2022/flusys-ng-auth-social-callback-page.component-gTD7_LJY.mjs.map +1 -0
  26. package/fesm2022/flusys-ng-auth-social-config-page.component-DpGmcb9n.mjs +541 -0
  27. package/fesm2022/flusys-ng-auth-social-config-page.component-DpGmcb9n.mjs.map +1 -0
  28. package/fesm2022/flusys-ng-auth-user-form.component-CM9UYc0q.mjs +1171 -0
  29. package/fesm2022/flusys-ng-auth-user-form.component-CM9UYc0q.mjs.map +1 -0
  30. package/fesm2022/flusys-ng-auth-user-list.component-Bew7gz-H.mjs +1046 -0
  31. package/fesm2022/flusys-ng-auth-user-list.component-Bew7gz-H.mjs.map +1 -0
  32. package/fesm2022/flusys-ng-auth-verify-email-page.component-DB9iKvt3.mjs +545 -0
  33. package/fesm2022/flusys-ng-auth-verify-email-page.component-DB9iKvt3.mjs.map +1 -0
  34. package/fesm2022/flusys-ng-auth.mjs +3030 -10735
  35. package/fesm2022/flusys-ng-auth.mjs.map +1 -1
  36. package/package.json +5 -5
  37. package/types/flusys-ng-auth.d.ts +978 -1558
@@ -0,0 +1,1171 @@
1
+ import { AUTH_USER_FORM_EXTENSION, AuthStateService, PasswordPolicyService, USER_FORM_FIELD_CONTEXT, UserApiService, UserPermissionApiService } from "./flusys-ng-auth.mjs";
2
+ import { t as sortByOrder } from "./flusys-ng-auth-extension-order.util-2XWSLqii.mjs";
3
+ import * as i0 from "@angular/core";
4
+ import { Component, DestroyRef, Injector, computed, effect, inject, signal } from "@angular/core";
5
+ import { APP_CONFIG, isCompanyFeatureEnabled } from "@flusys/ng-core";
6
+ import { finalize, firstValueFrom } from "rxjs";
7
+ import { ActivatedRoute, Router } from "@angular/router";
8
+ import { TranslatePipe, TranslateService } from "@flusys/ng-shared";
9
+ import { NgComponentOutlet, NgTemplateOutlet } from "@angular/common";
10
+ import { CardComponent, CheckboxComponent, FButtonDirective, InputTextDirective, MessageService, PasswordComponent, SelectComponent, SkeletonComponent, TextareaDirective, UiIconComponent } from "@flusys/ng-ui";
11
+ import { takeUntilDestroyed, toSignal } from "@angular/core/rxjs-interop";
12
+ import * as i1 from "@angular/forms";
13
+ import { FormsModule } from "@angular/forms";
14
+ import { FormField, email, form, required } from "@angular/forms/signals";
15
+ var UserFormComponent = class UserFormComponent {
16
+ destroyRef = inject(DestroyRef);
17
+ router = inject(Router);
18
+ route = inject(ActivatedRoute);
19
+ appConfig = inject(APP_CONFIG);
20
+ messageService = inject(MessageService);
21
+ userService = inject(UserApiService);
22
+ permissionService = inject(UserPermissionApiService);
23
+ authState = inject(AuthStateService);
24
+ passwordPolicy = inject(PasswordPolicyService);
25
+ translateAdapter = inject(TranslateService, { optional: true });
26
+ userFormExtension = inject(AUTH_USER_FORM_EXTENSION, { optional: true });
27
+ parentInjector = inject(Injector);
28
+ translate(key, vars) {
29
+ return this.translateAdapter?.translate(key, vars) ?? key;
30
+ }
31
+ routeParams = toSignal(this.route.paramMap);
32
+ userLoadTriggered = false;
33
+ isLoading = signal(false, ...ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []);
34
+ existingUser = signal(null, ...ngDevMode ? [{ debugName: "existingUser" }] : /* istanbul ignore next */ []);
35
+ isEditMode = computed(() => !!this.existingUser(), ...ngDevMode ? [{ debugName: "isEditMode" }] : /* istanbul ignore next */ []);
36
+ companyFeatureEnabled = computed(() => isCompanyFeatureEnabled(this.appConfig), ...ngDevMode ? [{ debugName: "companyFeatureEnabled" }] : /* istanbul ignore next */ []);
37
+ currentCompanyName = computed(() => this.authState.companyName(), ...ngDevMode ? [{ debugName: "currentCompanyName" }] : /* istanbul ignore next */ []);
38
+ currentBranchName = computed(() => this.authState.branchName(), ...ngDevMode ? [{ debugName: "currentBranchName" }] : /* istanbul ignore next */ []);
39
+ formModel = signal({
40
+ name: "",
41
+ email: "",
42
+ password: "",
43
+ phone: "",
44
+ isActive: true,
45
+ emailVerified: false
46
+ }, ...ngDevMode ? [{ debugName: "formModel" }] : /* istanbul ignore next */ []);
47
+ formTree = form(this.formModel, (f) => {
48
+ required(f.name, { message: this.translate("shared.name.required") });
49
+ required(f.email, { message: this.translate("auth.validation.email.required") });
50
+ email(f.email, { message: this.translate("shared.invalid.email") });
51
+ });
52
+ isLoadingExtraFields = signal(false, ...ngDevMode ? [{ debugName: "isLoadingExtraFields" }] : /* istanbul ignore next */ []);
53
+ extraFieldsModel = signal({}, ...ngDevMode ? [{ debugName: "extraFieldsModel" }] : /* istanbul ignore next */ []);
54
+ originalExtraFieldsModel = signal({}, ...ngDevMode ? [{ debugName: "originalExtraFieldsModel" }] : /* istanbul ignore next */ []);
55
+ extraFields = computed(() => {
56
+ if (!this.userFormExtension?.getExtraFields) return [];
57
+ return sortByOrder(this.userFormExtension.getExtraFields());
58
+ }, ...ngDevMode ? [{ debugName: "extraFields" }] : /* istanbul ignore next */ []);
59
+ hasExtraFields = computed(() => this.extraFields().length > 0, ...ngDevMode ? [{ debugName: "hasExtraFields" }] : /* istanbul ignore next */ []);
60
+ extraFieldsValidationError = computed(() => {
61
+ if (!this.userFormExtension?.validateExtraFields) return null;
62
+ return this.userFormExtension.validateExtraFields(this.extraFieldsModel());
63
+ }, ...ngDevMode ? [{ debugName: "extraFieldsValidationError" }] : /* istanbul ignore next */ []);
64
+ isExtraFieldsDirty = computed(() => {
65
+ const current = this.extraFieldsModel();
66
+ const original = this.originalExtraFieldsModel();
67
+ return JSON.stringify(current) !== JSON.stringify(original);
68
+ }, ...ngDevMode ? [{ debugName: "isExtraFieldsDirty" }] : /* istanbul ignore next */ []);
69
+ updateExtraField(key, value) {
70
+ this.extraFieldsModel.update((model) => ({
71
+ ...model,
72
+ [key]: value
73
+ }));
74
+ }
75
+ getExtraFieldValue(key) {
76
+ return this.extraFieldsModel()[key];
77
+ }
78
+ getFieldTemplateContext(field) {
79
+ return {
80
+ field,
81
+ value: this.extraFieldsModel()[field.key],
82
+ updateValue: (value) => this.updateExtraField(field.key, value)
83
+ };
84
+ }
85
+ fieldInjectors = /* @__PURE__ */ new Map();
86
+ getFieldInjector(field) {
87
+ const cached = this.fieldInjectors.get(field.key);
88
+ if (cached) {
89
+ cached.setField(field);
90
+ return cached.injector;
91
+ }
92
+ let currentField = field;
93
+ const extraFieldsModel = this.extraFieldsModel;
94
+ const injector = Injector.create({
95
+ providers: [{
96
+ provide: USER_FORM_FIELD_CONTEXT,
97
+ useValue: {
98
+ get field() {
99
+ return currentField;
100
+ },
101
+ get value() {
102
+ return extraFieldsModel()[currentField.key];
103
+ },
104
+ updateValue: (value) => this.updateExtraField(currentField.key, value)
105
+ }
106
+ }],
107
+ parent: field.injector ?? this.parentInjector
108
+ });
109
+ this.fieldInjectors.set(field.key, {
110
+ injector,
111
+ setField: (next) => currentField = next
112
+ });
113
+ return injector;
114
+ }
115
+ passwordError = computed(() => this.passwordPolicy.validate(this.formModel().password), ...ngDevMode ? [{ debugName: "passwordError" }] : /* istanbul ignore next */ []);
116
+ isFormValid = computed(() => {
117
+ const model = this.formModel();
118
+ const isEdit = this.isEditMode();
119
+ const nameValid = model.name.trim().length > 0;
120
+ const emailValid = model.email.includes("@");
121
+ const passwordValid = model.password ? !this.passwordError() : isEdit;
122
+ return nameValid && emailValid && passwordValid;
123
+ }, ...ngDevMode ? [{ debugName: "isFormValid" }] : /* istanbul ignore next */ []);
124
+ constructor() {
125
+ effect(() => {
126
+ const params = this.routeParams();
127
+ if (!params || this.userLoadTriggered) return;
128
+ this.userLoadTriggered = true;
129
+ const id = params.get("id");
130
+ if (id && id !== "new") this.loadUser(id);
131
+ });
132
+ }
133
+ async loadUser(id) {
134
+ this.isLoading.set(true);
135
+ try {
136
+ const response = await this.userService.findById(id);
137
+ if (response.success && response.data) {
138
+ this.existingUser.set(response.data);
139
+ this.formModel.set(this.toFormModel(response.data));
140
+ this.loadExtraFields(id);
141
+ }
142
+ } catch {
143
+ this.router.navigate(["/administration/users"]);
144
+ } finally {
145
+ this.isLoading.set(false);
146
+ }
147
+ }
148
+ loadExtraFields(userId) {
149
+ if (!this.userFormExtension?.getExtraFieldValues) return;
150
+ this.isLoadingExtraFields.set(true);
151
+ this.userFormExtension.getExtraFieldValues(userId).pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isLoadingExtraFields.set(false))).subscribe({
152
+ next: (values) => {
153
+ this.extraFieldsModel.set(values);
154
+ this.originalExtraFieldsModel.set(values);
155
+ },
156
+ error: () => {
157
+ const defaults = {};
158
+ for (const field of this.extraFields()) if (field.key) defaults[field.key] = void 0;
159
+ this.extraFieldsModel.set(defaults);
160
+ this.originalExtraFieldsModel.set(defaults);
161
+ }
162
+ });
163
+ }
164
+ toFormModel(user) {
165
+ return {
166
+ name: user.name,
167
+ email: user.email,
168
+ password: "",
169
+ phone: user.phone || "",
170
+ isActive: user.isActive,
171
+ emailVerified: user.emailVerified
172
+ };
173
+ }
174
+ onSubmit() {
175
+ if (!this.isFormValid()) {
176
+ this.messageService.add({
177
+ severity: "error",
178
+ summary: this.translate("shared.validation.error"),
179
+ detail: this.translate("shared.fill.required.fields")
180
+ });
181
+ return;
182
+ }
183
+ this.isLoading.set(true);
184
+ if (this.isEditMode() && this.existingUser()) this.updateUser();
185
+ else this.createUser();
186
+ }
187
+ async updateUser() {
188
+ const model = this.formModel();
189
+ const userId = this.existingUser().id;
190
+ const updateData = {
191
+ id: userId,
192
+ name: model.name,
193
+ email: model.email,
194
+ phone: model.phone || void 0,
195
+ isActive: model.isActive,
196
+ emailVerified: model.emailVerified
197
+ };
198
+ if (model.password) updateData.password = model.password;
199
+ try {
200
+ const [userResponse] = await Promise.all([this.userService.update(updateData), this.isExtraFieldsDirty() && this.userFormExtension?.saveExtraFieldValues ? firstValueFrom(this.userFormExtension.saveExtraFieldValues(userId, this.extraFieldsModel())) : Promise.resolve(void 0)]);
201
+ this.onSaveSuccess(userResponse.messageKey ? this.translate(userResponse.messageKey, userResponse.messageVariables) : userResponse.message);
202
+ } finally {
203
+ this.isLoading.set(false);
204
+ }
205
+ }
206
+ async createUser() {
207
+ const model = this.formModel();
208
+ const createData = {
209
+ name: model.name,
210
+ email: model.email,
211
+ password: model.password,
212
+ phone: model.phone || void 0,
213
+ isActive: model.isActive,
214
+ emailVerified: model.emailVerified
215
+ };
216
+ try {
217
+ const response = await this.userService.insert(createData);
218
+ if (response.success && response.data) {
219
+ const userId = response.data.id;
220
+ if (this.companyFeatureEnabled()) this.assignUserToCompanyAndBranch(userId);
221
+ this.saveExtraFieldsForNewUser(userId);
222
+ }
223
+ this.onSaveSuccess(response.messageKey ? this.translate(response.messageKey, response.messageVariables) : response.message);
224
+ } finally {
225
+ this.isLoading.set(false);
226
+ }
227
+ }
228
+ saveExtraFieldsForNewUser(userId) {
229
+ const extraFields = this.extraFieldsModel();
230
+ if (!(Object.keys(extraFields).length > 0 && Object.values(extraFields).some((v) => v !== void 0 && v !== "")) || !this.userFormExtension?.saveExtraFieldValues) return;
231
+ this.userFormExtension.saveExtraFieldValues(userId, extraFields).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({ error: () => {} });
232
+ }
233
+ onSaveSuccess(message) {
234
+ this.messageService.add({
235
+ severity: "success",
236
+ summary: this.translate("shared.success"),
237
+ detail: message
238
+ });
239
+ this.router.navigate(["/administration/users"]);
240
+ }
241
+ assignUserToCompanyAndBranch(userId) {
242
+ const company = this.authState.company();
243
+ const branch = this.authState.branch();
244
+ if (!company) return;
245
+ this.permissionService.assignUserToCompany(userId, company.id).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
246
+ next: () => {
247
+ if (branch) this.permissionService.assignUserToBranch(userId, branch.id).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({ error: () => {} });
248
+ },
249
+ error: () => {}
250
+ });
251
+ }
252
+ onCancel() {
253
+ this.router.navigate(["/administration/users"]);
254
+ }
255
+ static ɵfac = i0.ɵɵngDeclareFactory({
256
+ minVersion: "12.0.0",
257
+ version: "22.2.1",
258
+ ngImport: i0,
259
+ type: UserFormComponent,
260
+ deps: [],
261
+ target: i0.ɵɵFactoryTarget.Component
262
+ });
263
+ static ɵcmp = i0.ɵɵngDeclareComponent({
264
+ minVersion: "17.0.0",
265
+ version: "22.2.1",
266
+ type: UserFormComponent,
267
+ isStandalone: true,
268
+ selector: "lib-user-form",
269
+ ngImport: i0,
270
+ template: `
271
+ <f-card>
272
+ <ng-template #header>
273
+ <div class="flex justify-between items-center p-4">
274
+ <h2 class="text-xl font-semibold m-0">
275
+ {{
276
+ isEditMode()
277
+ ? ('administrative.user.edit' | translate)
278
+ : ('administrative.user.new' | translate)
279
+ }}
280
+ </h2>
281
+ </div>
282
+ </ng-template>
283
+
284
+ <form
285
+ (ngSubmit)="onSubmit()"
286
+ class="grid grid-cols-1 md:grid-cols-2 gap-4"
287
+ >
288
+ <div class="flex flex-col gap-2">
289
+ <label for="name" class="font-medium"
290
+ >{{ 'administrative.user.name' | translate }} *</label
291
+ >
292
+ <input
293
+ fInputText
294
+ id="name"
295
+ [formField]="formTree.name"
296
+ [placeholder]="'administrative.user.name.placeholder' | translate"
297
+ />
298
+ </div>
299
+
300
+ <div class="flex flex-col gap-2">
301
+ <label for="email" class="font-medium"
302
+ >{{ 'administrative.email.label' | translate }} *</label
303
+ >
304
+ <input
305
+ fInputText
306
+ id="email"
307
+ type="email"
308
+ [formField]="formTree.email"
309
+ [placeholder]="'auth.email.placeholder' | translate"
310
+ />
311
+ </div>
312
+
313
+ <div class="flex flex-col gap-2">
314
+ <label for="password" class="font-medium">
315
+ {{ 'administrative.user.password' | translate }}
316
+ {{
317
+ isEditMode()
318
+ ? ('administrative.user.password.optional' | translate)
319
+ : '*'
320
+ }}
321
+ </label>
322
+ <f-password
323
+ [inputId]="'password'"
324
+ [formField]="formTree.password"
325
+ [placeholder]="
326
+ 'administrative.user.password.placeholder' | translate
327
+ "
328
+ autocomplete="new-password"
329
+ />
330
+ @if (passwordError()) {
331
+ <small class="text-danger">{{ passwordError() }}</small>
332
+ }
333
+ </div>
334
+
335
+ <div class="flex flex-col gap-2">
336
+ <label for="phone" class="font-medium">{{
337
+ 'administrative.phone.label' | translate
338
+ }}</label>
339
+ <input
340
+ fInputText
341
+ id="phone"
342
+ [formField]="formTree.phone"
343
+ [placeholder]="'auth.phone.placeholder' | translate"
344
+ />
345
+ </div>
346
+
347
+ @if (hasExtraFields()) {
348
+ <div class="md:col-span-2 border-t border-surface pt-4 mt-2">
349
+ <div class="text-sm font-medium text-muted-color mb-4">
350
+ <ui-icon name="sliders-h" class="mr-2"></ui-icon
351
+ >{{ 'profile.additional.info' | translate }}
352
+ </div>
353
+ @if (isLoadingExtraFields()) {
354
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
355
+ <f-skeleton height="2.5rem" />
356
+ <f-skeleton height="2.5rem" />
357
+ </div>
358
+ } @else {
359
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
360
+ @for (field of extraFields(); track field.key) {
361
+ <div class="flex flex-col gap-2">
362
+ <label [for]="field.key" class="font-medium text-color">
363
+ {{ field.labelKey | translate: null : field.label
364
+ }}{{ field.required ? ' *' : '' }}
365
+ </label>
366
+ @if (field.component) {
367
+ <ng-container
368
+ [ngComponentOutlet]="field.component"
369
+ [ngComponentOutletInjector]="getFieldInjector(field)"
370
+ />
371
+ } @else if (field.template) {
372
+ <ng-container
373
+ [ngTemplateOutlet]="field.template"
374
+ [ngTemplateOutletContext]="
375
+ getFieldTemplateContext(field)
376
+ "
377
+ />
378
+ } @else {
379
+ @switch (field.type) {
380
+ @case ('text') {
381
+ <input
382
+ fInputText
383
+ [id]="field.key"
384
+ [placeholder]="
385
+ field.placeholderKey
386
+ | translate: null : field.placeholder ?? ''
387
+ "
388
+ [value]="getExtraFieldValue(field.key) ?? ''"
389
+ (input)="
390
+ updateExtraField(
391
+ field.key,
392
+ $any($event.target).value
393
+ )
394
+ "
395
+ class="w-full"
396
+ />
397
+ }
398
+ @case ('number') {
399
+ <input
400
+ fInputText
401
+ type="number"
402
+ [id]="field.key"
403
+ [placeholder]="
404
+ field.placeholderKey
405
+ | translate: null : field.placeholder ?? ''
406
+ "
407
+ [value]="getExtraFieldValue(field.key) ?? ''"
408
+ (input)="
409
+ updateExtraField(
410
+ field.key,
411
+ $any($event.target).valueAsNumber
412
+ )
413
+ "
414
+ class="w-full"
415
+ />
416
+ }
417
+ @case ('textarea') {
418
+ <textarea
419
+ fTextarea
420
+ [id]="field.key"
421
+ [placeholder]="
422
+ field.placeholderKey
423
+ | translate: null : field.placeholder ?? ''
424
+ "
425
+ [value]="getExtraFieldValue(field.key) ?? ''"
426
+ (input)="
427
+ updateExtraField(
428
+ field.key,
429
+ $any($event.target).value
430
+ )
431
+ "
432
+ class="w-full"
433
+ rows="3"
434
+ ></textarea>
435
+ }
436
+ @case ('select') {
437
+ <f-select
438
+ [id]="field.key"
439
+ class="w-full"
440
+ [options]="field.options ?? []"
441
+ optionValue="value"
442
+ [ngModel]="getExtraFieldValue(field.key) ?? ''"
443
+ [ngModelOptions]="{ standalone: true }"
444
+ (ngModelChange)="
445
+ updateExtraField(field.key, $event)
446
+ "
447
+ [placeholder]="
448
+ field.placeholderKey
449
+ | translate
450
+ : null
451
+ : field.placeholder ??
452
+ ('shared.select' | translate)
453
+ "
454
+ >
455
+ <ng-template #item let-opt>{{
456
+ opt.labelKey | translate: null : opt.label
457
+ }}</ng-template>
458
+ <ng-template #selectedItem let-opt>{{
459
+ opt.labelKey | translate: null : opt.label
460
+ }}</ng-template>
461
+ </f-select>
462
+ }
463
+ @case ('checkbox') {
464
+ <f-checkbox
465
+ [inputId]="field.key"
466
+ [checked]="
467
+ $any(getExtraFieldValue(field.key) ?? false)
468
+ "
469
+ (onChange)="
470
+ updateExtraField(field.key, $event.checked)
471
+ "
472
+ [label]="
473
+ field.placeholderKey
474
+ | translate
475
+ : null
476
+ : field.placeholder ??
477
+ (field.labelKey
478
+ | translate: null : field.label)
479
+ "
480
+ />
481
+ }
482
+ @case ('date') {
483
+ <input
484
+ fInputText
485
+ type="date"
486
+ [id]="field.key"
487
+ [value]="getExtraFieldValue(field.key) ?? ''"
488
+ (input)="
489
+ updateExtraField(
490
+ field.key,
491
+ $any($event.target).value
492
+ )
493
+ "
494
+ class="w-full"
495
+ />
496
+ }
497
+ }
498
+ }
499
+ </div>
500
+ }
501
+ </div>
502
+ @if (extraFieldsValidationError()) {
503
+ <small class="text-danger block mt-2">{{
504
+ extraFieldsValidationError()
505
+ }}</small>
506
+ }
507
+ }
508
+ </div>
509
+ }
510
+
511
+ <div class="flex items-center gap-6 md:col-span-2 pt-4">
512
+ <f-checkbox
513
+ [formField]="formTree.isActive"
514
+ [label]="'shared.active' | translate"
515
+ />
516
+ <f-checkbox
517
+ [formField]="formTree.emailVerified"
518
+ [label]="'administrative.user.email.verified' | translate"
519
+ />
520
+ </div>
521
+
522
+ @if (companyFeatureEnabled() && !isEditMode()) {
523
+ <div
524
+ class="md:col-span-2 p-3 bg-primary/10 rounded-lg border border-primary/20"
525
+ >
526
+ <div class="flex items-center gap-2 text-primary">
527
+ <ui-icon name="info-circle"></ui-icon>
528
+ <span class="text-sm">
529
+ {{ 'administrative.user.auto.assign.to' | translate }}
530
+ <strong>{{ currentCompanyName() }}</strong>
531
+ @if (currentBranchName()) {
532
+ / <strong>{{ currentBranchName() }}</strong>
533
+ }
534
+ </span>
535
+ </div>
536
+ </div>
537
+ }
538
+
539
+ <div class="flex justify-end gap-4 md:col-span-2 pt-4">
540
+ <button
541
+ fButton
542
+ type="button"
543
+ severity="secondary"
544
+ [outlined]="true"
545
+ (click)="onCancel()"
546
+ >
547
+ <span pButtonLabel>{{ 'shared.cancel' | translate }}</span>
548
+ </button>
549
+ <button
550
+ fButton
551
+ type="submit"
552
+ [disabled]="!isFormValid() || isLoading()"
553
+ >
554
+ @if (isLoading()) {
555
+ <ui-icon pButtonIcon name="spinner" [spin]="true"></ui-icon>
556
+ }
557
+ <span pButtonLabel>{{
558
+ isEditMode()
559
+ ? ('shared.update' | translate)
560
+ : ('shared.create' | translate)
561
+ }}</span>
562
+ </button>
563
+ </div>
564
+ </form>
565
+ </f-card>
566
+ `,
567
+ isInline: true,
568
+ dependencies: [
569
+ {
570
+ kind: "component",
571
+ type: CardComponent,
572
+ selector: "f-card",
573
+ inputs: [
574
+ "header",
575
+ "subheader",
576
+ "styleClass",
577
+ "style"
578
+ ]
579
+ },
580
+ {
581
+ kind: "component",
582
+ type: CheckboxComponent,
583
+ selector: "f-checkbox",
584
+ inputs: [
585
+ "label",
586
+ "binary",
587
+ "disabled",
588
+ "readonly",
589
+ "inputId",
590
+ "invalid",
591
+ "indeterminate",
592
+ "variant",
593
+ "size",
594
+ "touched",
595
+ "styleClass",
596
+ "style",
597
+ "checked"
598
+ ],
599
+ outputs: [
600
+ "onChange",
601
+ "onBlur",
602
+ "touch",
603
+ "checkedChange"
604
+ ]
605
+ },
606
+ {
607
+ kind: "directive",
608
+ type: FButtonDirective,
609
+ selector: "[fButton]",
610
+ inputs: [
611
+ "severity",
612
+ "text",
613
+ "outlined",
614
+ "link",
615
+ "variant",
616
+ "rounded",
617
+ "raised",
618
+ "fluid",
619
+ "disabled",
620
+ "loading",
621
+ "loadingIcon",
622
+ "size",
623
+ "label",
624
+ "icon",
625
+ "iconPos",
626
+ "ariaLabel",
627
+ "plain"
628
+ ]
629
+ },
630
+ {
631
+ kind: "directive",
632
+ type: InputTextDirective,
633
+ selector: "[fInputText]",
634
+ inputs: [
635
+ "invalid",
636
+ "touched",
637
+ "variant",
638
+ "size",
639
+ "fluid"
640
+ ]
641
+ },
642
+ {
643
+ kind: "component",
644
+ type: PasswordComponent,
645
+ selector: "f-password",
646
+ inputs: [
647
+ "toggleMask",
648
+ "feedback",
649
+ "disabled",
650
+ "placeholder",
651
+ "inputId",
652
+ "invalid",
653
+ "touched",
654
+ "inputStyleClass",
655
+ "styleClass",
656
+ "style",
657
+ "ariaDescribedby",
658
+ "autocomplete",
659
+ "variant",
660
+ "size",
661
+ "fluid",
662
+ "appendTo",
663
+ "promptLabel",
664
+ "weakLabel",
665
+ "mediumLabel",
666
+ "strongLabel",
667
+ "mediumRegex",
668
+ "strongRegex"
669
+ ],
670
+ outputs: ["onBlur", "onFocus"]
671
+ },
672
+ {
673
+ kind: "component",
674
+ type: SelectComponent,
675
+ selector: "f-select",
676
+ inputs: [
677
+ "options",
678
+ "optionLabel",
679
+ "optionValue",
680
+ "placeholder",
681
+ "disabled",
682
+ "filter",
683
+ "filterBy",
684
+ "filterMatchMode",
685
+ "filterLocale",
686
+ "filterPlaceholder",
687
+ "resetFilterOnHide",
688
+ "autofocusFilter",
689
+ "emptyMessage",
690
+ "emptyFilterMessage",
691
+ "showClear",
692
+ "loading",
693
+ "loadingIcon",
694
+ "dropdownIcon",
695
+ "clearIcon",
696
+ "inputId",
697
+ "invalid",
698
+ "touched",
699
+ "styleClass",
700
+ "style",
701
+ "appendTo",
702
+ "editable",
703
+ "readonly",
704
+ "autofocus",
705
+ "checkmark",
706
+ "group",
707
+ "optionGroupLabel",
708
+ "optionGroupChildren",
709
+ "virtualScroll",
710
+ "virtualScrollItemSize",
711
+ "lazy",
712
+ "selectedObject"
713
+ ],
714
+ outputs: [
715
+ "onFilter",
716
+ "onChange",
717
+ "onShow",
718
+ "onHide",
719
+ "onBlur",
720
+ "onFocus",
721
+ "onClear",
722
+ "onLazyLoad"
723
+ ]
724
+ },
725
+ {
726
+ kind: "component",
727
+ type: SkeletonComponent,
728
+ selector: "f-skeleton",
729
+ inputs: [
730
+ "width",
731
+ "height",
732
+ "size",
733
+ "borderRadius",
734
+ "shape",
735
+ "animation",
736
+ "styleClass"
737
+ ]
738
+ },
739
+ {
740
+ kind: "directive",
741
+ type: TextareaDirective,
742
+ selector: "[fTextarea]",
743
+ inputs: [
744
+ "invalid",
745
+ "touched",
746
+ "variant",
747
+ "fluid",
748
+ "autoResize"
749
+ ],
750
+ outputs: ["onResize"]
751
+ },
752
+ {
753
+ kind: "component",
754
+ type: UiIconComponent,
755
+ selector: "ui-icon",
756
+ inputs: [
757
+ "name",
758
+ "size",
759
+ "spin",
760
+ "fill",
761
+ "severity"
762
+ ]
763
+ },
764
+ {
765
+ kind: "ngmodule",
766
+ type: FormsModule
767
+ },
768
+ {
769
+ kind: "directive",
770
+ type: i1.ɵNgNoValidate,
771
+ selector: "form:not([ngNoForm]):not([ngNativeValidate])"
772
+ },
773
+ {
774
+ kind: "directive",
775
+ type: i1.NgControlStatus,
776
+ selector: "[formControlName],[ngModel],[formControl]"
777
+ },
778
+ {
779
+ kind: "directive",
780
+ type: i1.NgControlStatusGroup,
781
+ selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]"
782
+ },
783
+ {
784
+ kind: "directive",
785
+ type: i1.NgModel,
786
+ selector: "[ngModel]:not([formControlName]):not([formControl])",
787
+ inputs: [
788
+ "name",
789
+ "disabled",
790
+ "ngModel",
791
+ "ngModelOptions"
792
+ ],
793
+ outputs: ["ngModelChange"],
794
+ exportAs: ["ngModel"]
795
+ },
796
+ {
797
+ kind: "directive",
798
+ type: i1.NgForm,
799
+ selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]",
800
+ inputs: ["ngFormOptions"],
801
+ outputs: ["ngSubmit"],
802
+ exportAs: ["ngForm"]
803
+ },
804
+ {
805
+ kind: "directive",
806
+ type: NgComponentOutlet,
807
+ selector: "[ngComponentOutlet]",
808
+ inputs: [
809
+ "ngComponentOutlet",
810
+ "ngComponentOutletInputs",
811
+ "ngComponentOutletInjector",
812
+ "ngComponentOutletEnvironmentInjector",
813
+ "ngComponentOutletContent",
814
+ "ngComponentOutletNgModule"
815
+ ],
816
+ exportAs: ["ngComponentOutlet"]
817
+ },
818
+ {
819
+ kind: "directive",
820
+ type: NgTemplateOutlet,
821
+ selector: "[ngTemplateOutlet]",
822
+ inputs: [
823
+ "ngTemplateOutletContext",
824
+ "ngTemplateOutlet",
825
+ "ngTemplateOutletInjector"
826
+ ]
827
+ },
828
+ {
829
+ kind: "directive",
830
+ type: FormField,
831
+ selector: "[formField]",
832
+ inputs: ["formField"],
833
+ exportAs: ["formField"]
834
+ },
835
+ {
836
+ kind: "pipe",
837
+ type: TranslatePipe,
838
+ name: "translate"
839
+ }
840
+ ]
841
+ });
842
+ };
843
+ i0.ɵɵngDeclareClassMetadata({
844
+ minVersion: "12.0.0",
845
+ version: "22.2.1",
846
+ ngImport: i0,
847
+ type: UserFormComponent,
848
+ decorators: [{
849
+ type: Component,
850
+ args: [{
851
+ selector: "lib-user-form",
852
+ imports: [
853
+ CardComponent,
854
+ CheckboxComponent,
855
+ FButtonDirective,
856
+ InputTextDirective,
857
+ PasswordComponent,
858
+ SelectComponent,
859
+ SkeletonComponent,
860
+ TextareaDirective,
861
+ UiIconComponent,
862
+ FormsModule,
863
+ NgComponentOutlet,
864
+ NgTemplateOutlet,
865
+ FormField,
866
+ TranslatePipe
867
+ ],
868
+ template: `
869
+ <f-card>
870
+ <ng-template #header>
871
+ <div class="flex justify-between items-center p-4">
872
+ <h2 class="text-xl font-semibold m-0">
873
+ {{
874
+ isEditMode()
875
+ ? ('administrative.user.edit' | translate)
876
+ : ('administrative.user.new' | translate)
877
+ }}
878
+ </h2>
879
+ </div>
880
+ </ng-template>
881
+
882
+ <form
883
+ (ngSubmit)="onSubmit()"
884
+ class="grid grid-cols-1 md:grid-cols-2 gap-4"
885
+ >
886
+ <div class="flex flex-col gap-2">
887
+ <label for="name" class="font-medium"
888
+ >{{ 'administrative.user.name' | translate }} *</label
889
+ >
890
+ <input
891
+ fInputText
892
+ id="name"
893
+ [formField]="formTree.name"
894
+ [placeholder]="'administrative.user.name.placeholder' | translate"
895
+ />
896
+ </div>
897
+
898
+ <div class="flex flex-col gap-2">
899
+ <label for="email" class="font-medium"
900
+ >{{ 'administrative.email.label' | translate }} *</label
901
+ >
902
+ <input
903
+ fInputText
904
+ id="email"
905
+ type="email"
906
+ [formField]="formTree.email"
907
+ [placeholder]="'auth.email.placeholder' | translate"
908
+ />
909
+ </div>
910
+
911
+ <div class="flex flex-col gap-2">
912
+ <label for="password" class="font-medium">
913
+ {{ 'administrative.user.password' | translate }}
914
+ {{
915
+ isEditMode()
916
+ ? ('administrative.user.password.optional' | translate)
917
+ : '*'
918
+ }}
919
+ </label>
920
+ <f-password
921
+ [inputId]="'password'"
922
+ [formField]="formTree.password"
923
+ [placeholder]="
924
+ 'administrative.user.password.placeholder' | translate
925
+ "
926
+ autocomplete="new-password"
927
+ />
928
+ @if (passwordError()) {
929
+ <small class="text-danger">{{ passwordError() }}</small>
930
+ }
931
+ </div>
932
+
933
+ <div class="flex flex-col gap-2">
934
+ <label for="phone" class="font-medium">{{
935
+ 'administrative.phone.label' | translate
936
+ }}</label>
937
+ <input
938
+ fInputText
939
+ id="phone"
940
+ [formField]="formTree.phone"
941
+ [placeholder]="'auth.phone.placeholder' | translate"
942
+ />
943
+ </div>
944
+
945
+ @if (hasExtraFields()) {
946
+ <div class="md:col-span-2 border-t border-surface pt-4 mt-2">
947
+ <div class="text-sm font-medium text-muted-color mb-4">
948
+ <ui-icon name="sliders-h" class="mr-2"></ui-icon
949
+ >{{ 'profile.additional.info' | translate }}
950
+ </div>
951
+ @if (isLoadingExtraFields()) {
952
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
953
+ <f-skeleton height="2.5rem" />
954
+ <f-skeleton height="2.5rem" />
955
+ </div>
956
+ } @else {
957
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
958
+ @for (field of extraFields(); track field.key) {
959
+ <div class="flex flex-col gap-2">
960
+ <label [for]="field.key" class="font-medium text-color">
961
+ {{ field.labelKey | translate: null : field.label
962
+ }}{{ field.required ? ' *' : '' }}
963
+ </label>
964
+ @if (field.component) {
965
+ <ng-container
966
+ [ngComponentOutlet]="field.component"
967
+ [ngComponentOutletInjector]="getFieldInjector(field)"
968
+ />
969
+ } @else if (field.template) {
970
+ <ng-container
971
+ [ngTemplateOutlet]="field.template"
972
+ [ngTemplateOutletContext]="
973
+ getFieldTemplateContext(field)
974
+ "
975
+ />
976
+ } @else {
977
+ @switch (field.type) {
978
+ @case ('text') {
979
+ <input
980
+ fInputText
981
+ [id]="field.key"
982
+ [placeholder]="
983
+ field.placeholderKey
984
+ | translate: null : field.placeholder ?? ''
985
+ "
986
+ [value]="getExtraFieldValue(field.key) ?? ''"
987
+ (input)="
988
+ updateExtraField(
989
+ field.key,
990
+ $any($event.target).value
991
+ )
992
+ "
993
+ class="w-full"
994
+ />
995
+ }
996
+ @case ('number') {
997
+ <input
998
+ fInputText
999
+ type="number"
1000
+ [id]="field.key"
1001
+ [placeholder]="
1002
+ field.placeholderKey
1003
+ | translate: null : field.placeholder ?? ''
1004
+ "
1005
+ [value]="getExtraFieldValue(field.key) ?? ''"
1006
+ (input)="
1007
+ updateExtraField(
1008
+ field.key,
1009
+ $any($event.target).valueAsNumber
1010
+ )
1011
+ "
1012
+ class="w-full"
1013
+ />
1014
+ }
1015
+ @case ('textarea') {
1016
+ <textarea
1017
+ fTextarea
1018
+ [id]="field.key"
1019
+ [placeholder]="
1020
+ field.placeholderKey
1021
+ | translate: null : field.placeholder ?? ''
1022
+ "
1023
+ [value]="getExtraFieldValue(field.key) ?? ''"
1024
+ (input)="
1025
+ updateExtraField(
1026
+ field.key,
1027
+ $any($event.target).value
1028
+ )
1029
+ "
1030
+ class="w-full"
1031
+ rows="3"
1032
+ ></textarea>
1033
+ }
1034
+ @case ('select') {
1035
+ <f-select
1036
+ [id]="field.key"
1037
+ class="w-full"
1038
+ [options]="field.options ?? []"
1039
+ optionValue="value"
1040
+ [ngModel]="getExtraFieldValue(field.key) ?? ''"
1041
+ [ngModelOptions]="{ standalone: true }"
1042
+ (ngModelChange)="
1043
+ updateExtraField(field.key, $event)
1044
+ "
1045
+ [placeholder]="
1046
+ field.placeholderKey
1047
+ | translate
1048
+ : null
1049
+ : field.placeholder ??
1050
+ ('shared.select' | translate)
1051
+ "
1052
+ >
1053
+ <ng-template #item let-opt>{{
1054
+ opt.labelKey | translate: null : opt.label
1055
+ }}</ng-template>
1056
+ <ng-template #selectedItem let-opt>{{
1057
+ opt.labelKey | translate: null : opt.label
1058
+ }}</ng-template>
1059
+ </f-select>
1060
+ }
1061
+ @case ('checkbox') {
1062
+ <f-checkbox
1063
+ [inputId]="field.key"
1064
+ [checked]="
1065
+ $any(getExtraFieldValue(field.key) ?? false)
1066
+ "
1067
+ (onChange)="
1068
+ updateExtraField(field.key, $event.checked)
1069
+ "
1070
+ [label]="
1071
+ field.placeholderKey
1072
+ | translate
1073
+ : null
1074
+ : field.placeholder ??
1075
+ (field.labelKey
1076
+ | translate: null : field.label)
1077
+ "
1078
+ />
1079
+ }
1080
+ @case ('date') {
1081
+ <input
1082
+ fInputText
1083
+ type="date"
1084
+ [id]="field.key"
1085
+ [value]="getExtraFieldValue(field.key) ?? ''"
1086
+ (input)="
1087
+ updateExtraField(
1088
+ field.key,
1089
+ $any($event.target).value
1090
+ )
1091
+ "
1092
+ class="w-full"
1093
+ />
1094
+ }
1095
+ }
1096
+ }
1097
+ </div>
1098
+ }
1099
+ </div>
1100
+ @if (extraFieldsValidationError()) {
1101
+ <small class="text-danger block mt-2">{{
1102
+ extraFieldsValidationError()
1103
+ }}</small>
1104
+ }
1105
+ }
1106
+ </div>
1107
+ }
1108
+
1109
+ <div class="flex items-center gap-6 md:col-span-2 pt-4">
1110
+ <f-checkbox
1111
+ [formField]="formTree.isActive"
1112
+ [label]="'shared.active' | translate"
1113
+ />
1114
+ <f-checkbox
1115
+ [formField]="formTree.emailVerified"
1116
+ [label]="'administrative.user.email.verified' | translate"
1117
+ />
1118
+ </div>
1119
+
1120
+ @if (companyFeatureEnabled() && !isEditMode()) {
1121
+ <div
1122
+ class="md:col-span-2 p-3 bg-primary/10 rounded-lg border border-primary/20"
1123
+ >
1124
+ <div class="flex items-center gap-2 text-primary">
1125
+ <ui-icon name="info-circle"></ui-icon>
1126
+ <span class="text-sm">
1127
+ {{ 'administrative.user.auto.assign.to' | translate }}
1128
+ <strong>{{ currentCompanyName() }}</strong>
1129
+ @if (currentBranchName()) {
1130
+ / <strong>{{ currentBranchName() }}</strong>
1131
+ }
1132
+ </span>
1133
+ </div>
1134
+ </div>
1135
+ }
1136
+
1137
+ <div class="flex justify-end gap-4 md:col-span-2 pt-4">
1138
+ <button
1139
+ fButton
1140
+ type="button"
1141
+ severity="secondary"
1142
+ [outlined]="true"
1143
+ (click)="onCancel()"
1144
+ >
1145
+ <span pButtonLabel>{{ 'shared.cancel' | translate }}</span>
1146
+ </button>
1147
+ <button
1148
+ fButton
1149
+ type="submit"
1150
+ [disabled]="!isFormValid() || isLoading()"
1151
+ >
1152
+ @if (isLoading()) {
1153
+ <ui-icon pButtonIcon name="spinner" [spin]="true"></ui-icon>
1154
+ }
1155
+ <span pButtonLabel>{{
1156
+ isEditMode()
1157
+ ? ('shared.update' | translate)
1158
+ : ('shared.create' | translate)
1159
+ }}</span>
1160
+ </button>
1161
+ </div>
1162
+ </form>
1163
+ </f-card>
1164
+ `
1165
+ }]
1166
+ }],
1167
+ ctorParameters: () => []
1168
+ });
1169
+ export { UserFormComponent };
1170
+
1171
+ //# sourceMappingURL=flusys-ng-auth-user-form.component-CM9UYc0q.mjs.map