708 lines
21 KiB
TypeScript
708 lines
21 KiB
TypeScript
import { Component, HostListener, Inject, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
|
|
import { RouterLink, Router, NavigationEnd } from '@angular/router';
|
|
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
import { PLATFORM_ID } from '@angular/core';
|
|
import { filter } from 'rxjs/operators';
|
|
import { AuthService } from '../../services/auth.service';
|
|
import { NotificationsService, NotificationDto } from '../../services/notifications.service';
|
|
import { UsersService, CreateUserPayload, ApiFieldError } from '../../services/users.service';
|
|
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators, AbstractControl, ValidationErrors, FormsModule } from '@angular/forms';
|
|
import { HttpErrorResponse } from '@angular/common/http';
|
|
import { CustomSelectComponent } from '../custom-select/custom-select';
|
|
|
|
@Component({
|
|
selector: 'app-header',
|
|
standalone: true,
|
|
imports: [RouterLink, CommonModule, ReactiveFormsModule, FormsModule, CustomSelectComponent],
|
|
templateUrl: './header.html',
|
|
styleUrls: ['./header.scss'],
|
|
})
|
|
export class Header implements AfterViewInit {
|
|
isScrolled = false;
|
|
|
|
menuOpen = false;
|
|
optionsOpen = false;
|
|
notificationsOpen = false;
|
|
createUserOpen = false;
|
|
manageUsersOpen = false;
|
|
isLoggedHeader = false;
|
|
isHome = false;
|
|
isAdmin = false;
|
|
notifications: NotificationDto[] = [];
|
|
notificationsLoading = false;
|
|
notificationsError = false;
|
|
private notificationsLoaded = false;
|
|
private pendingToastCheck = false;
|
|
private lastNotificationsLoadAt = 0;
|
|
private readonly notificationsRefreshMs = 60_000;
|
|
readonly notificationsPreviewLimit = 40;
|
|
@ViewChild('notifToast') notifToast?: ElementRef;
|
|
|
|
createUserForm: FormGroup;
|
|
createUserSubmitting = false;
|
|
createUserErrors: ApiFieldError[] = [];
|
|
createUserForbidden = false;
|
|
createUserSuccess = '';
|
|
readonly permissionOptions = [
|
|
{ value: 'admin', label: 'Administrador' },
|
|
{ value: 'gestor', label: 'Gestor' },
|
|
];
|
|
|
|
manageUsersLoading = false;
|
|
manageUsersErrors: ApiFieldError[] = [];
|
|
manageUsersSuccess = '';
|
|
manageUsers: any[] = [];
|
|
manageSearch = '';
|
|
managePage = 1;
|
|
managePageSize = 10;
|
|
manageTotal = 0;
|
|
|
|
editUserForm: FormGroup;
|
|
editUserSubmitting = false;
|
|
editUserErrors: ApiFieldError[] = [];
|
|
editUserSuccess = '';
|
|
editUserTarget: any | null = null;
|
|
|
|
private readonly loggedPrefixes = [
|
|
'/geral',
|
|
'/mureg',
|
|
'/faturamento',
|
|
'/dadosusuarios',
|
|
'/vigencia',
|
|
'/trocanumero',
|
|
'/dashboard',
|
|
'/notificacoes',
|
|
'/chips-controle-recebidos',
|
|
'/resumo',
|
|
'/parcelamentos',
|
|
'/historico',
|
|
'/perfil',
|
|
];
|
|
|
|
constructor(
|
|
private router: Router,
|
|
private authService: AuthService,
|
|
private notificationsService: NotificationsService,
|
|
private usersService: UsersService,
|
|
private fb: FormBuilder,
|
|
@Inject(PLATFORM_ID) private platformId: object
|
|
) {
|
|
this.createUserForm = this.fb.group(
|
|
{
|
|
nome: ['', [Validators.required, Validators.minLength(2)]],
|
|
email: ['', [Validators.required, Validators.email]],
|
|
senha: ['', [Validators.required, Validators.minLength(6)]],
|
|
confirmarSenha: ['', [Validators.required, Validators.minLength(6)]],
|
|
permissao: ['', [Validators.required]],
|
|
},
|
|
{ validators: this.passwordsMatchValidator }
|
|
);
|
|
|
|
this.editUserForm = this.fb.group({
|
|
nome: [''],
|
|
email: [''],
|
|
senha: [''],
|
|
confirmarSenha: [''],
|
|
permissao: [''],
|
|
ativo: [true],
|
|
});
|
|
|
|
this.syncHeaderState(this.router.url);
|
|
this.syncPermissions();
|
|
|
|
this.router.events
|
|
.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd))
|
|
.subscribe((event) => {
|
|
const rawUrl = event.urlAfterRedirects || event.url;
|
|
this.syncHeaderState(rawUrl);
|
|
this.syncPermissions();
|
|
this.menuOpen = false;
|
|
this.optionsOpen = false;
|
|
this.notificationsOpen = false;
|
|
if (this.isLoggedHeader) {
|
|
this.ensureNotificationsLoaded();
|
|
}
|
|
});
|
|
if (this.isLoggedHeader) {
|
|
this.ensureNotificationsLoaded();
|
|
}
|
|
}
|
|
|
|
private syncHeaderState(rawUrl: string) {
|
|
let url = (rawUrl || '').split('?')[0].split('#')[0];
|
|
if (url && !url.startsWith('/')) url = `/${url}`;
|
|
url = url.replace(/\/+$/, '');
|
|
|
|
this.isHome = (url === '/' || url === '');
|
|
|
|
this.isLoggedHeader = this.loggedPrefixes.some((p) =>
|
|
url === p || url.startsWith(p + '/')
|
|
);
|
|
}
|
|
|
|
private syncPermissions() {
|
|
if (!isPlatformBrowser(this.platformId)) {
|
|
this.isAdmin = false;
|
|
return;
|
|
}
|
|
this.isAdmin = this.authService.hasRole('admin');
|
|
}
|
|
|
|
toggleMenu() {
|
|
this.menuOpen = !this.menuOpen;
|
|
}
|
|
|
|
closeMenu() {
|
|
this.menuOpen = false;
|
|
}
|
|
|
|
toggleOptions() {
|
|
this.optionsOpen = !this.optionsOpen;
|
|
if (this.optionsOpen) this.notificationsOpen = false;
|
|
}
|
|
|
|
closeOptions() {
|
|
this.optionsOpen = false;
|
|
}
|
|
|
|
goToProfile() {
|
|
this.closeOptions();
|
|
this.router.navigate(['/perfil']);
|
|
}
|
|
|
|
openCreateUserModal() {
|
|
if (!this.isAdmin) return;
|
|
this.createUserOpen = true;
|
|
this.closeOptions();
|
|
this.resetCreateUserState();
|
|
}
|
|
|
|
closeCreateUserModal() {
|
|
this.createUserOpen = false;
|
|
this.resetCreateUserState();
|
|
}
|
|
|
|
openManageUsersModal() {
|
|
if (!this.isAdmin) return;
|
|
this.manageUsersOpen = true;
|
|
this.closeOptions();
|
|
this.resetManageUsersState();
|
|
this.fetchManageUsers(1);
|
|
}
|
|
|
|
closeManageUsersModal() {
|
|
this.manageUsersOpen = false;
|
|
this.resetManageUsersState();
|
|
}
|
|
|
|
toggleNotifications() {
|
|
this.notificationsOpen = !this.notificationsOpen;
|
|
if (this.notificationsOpen) {
|
|
this.optionsOpen = false;
|
|
if (!this.notificationsLoaded) {
|
|
this.loadNotifications(false);
|
|
return;
|
|
}
|
|
|
|
if (Date.now() - this.lastNotificationsLoadAt > this.notificationsRefreshMs) {
|
|
// Atualiza em background para não bloquear a abertura visual do dropdown.
|
|
setTimeout(() => this.loadNotifications(false), 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
closeNotifications() {
|
|
this.notificationsOpen = false;
|
|
}
|
|
|
|
markNotificationRead(notification: NotificationDto) {
|
|
if (notification.lida) return;
|
|
this.notificationsService.markAsRead(notification.id).subscribe({
|
|
next: () => {
|
|
notification.lida = true;
|
|
notification.lidaEm = new Date().toISOString();
|
|
},
|
|
});
|
|
}
|
|
|
|
getVigenciaLabel(notification: NotificationDto): string {
|
|
return this.getNotificationTipo(notification) === 'Vencido' ? 'Venceu em' : 'Vence em';
|
|
}
|
|
|
|
getVigenciaDate(notification: NotificationDto): string {
|
|
const raw =
|
|
notification.dtTerminoFidelizacao ??
|
|
notification.referenciaData ??
|
|
notification.data;
|
|
if (!raw) return '-';
|
|
const parsed = this.parseDateOnly(raw);
|
|
if (!parsed) return '-';
|
|
return parsed.toLocaleDateString('pt-BR');
|
|
}
|
|
|
|
getNotificationTipo(notification: NotificationDto): 'Vencido' | 'AVencer' {
|
|
const reference = notification.dtTerminoFidelizacao ?? notification.referenciaData;
|
|
const parsed = this.parseDateOnly(reference);
|
|
if (!parsed) return notification.tipo;
|
|
|
|
const today = this.startOfDay(new Date());
|
|
return parsed < today ? 'Vencido' : 'AVencer';
|
|
}
|
|
|
|
getNotificationDaysToExpire(notification: NotificationDto): number | null {
|
|
const reference = notification.dtTerminoFidelizacao ?? notification.referenciaData;
|
|
const parsed = this.parseDateOnly(reference);
|
|
if (!parsed) {
|
|
return notification.diasParaVencer ?? null;
|
|
}
|
|
|
|
const today = this.startOfDay(new Date());
|
|
const msPerDay = 24 * 60 * 60 * 1000;
|
|
return Math.round((parsed.getTime() - today.getTime()) / msPerDay);
|
|
}
|
|
|
|
abbreviateName(value?: string | null): string {
|
|
const name = (value ?? '').trim();
|
|
if (!name) return '-';
|
|
const parts = name.split(/\s+/).filter(Boolean);
|
|
if (parts.length === 1) return parts[0];
|
|
|
|
const maxLen = 18;
|
|
const full = parts.join(' ');
|
|
if (full.length <= maxLen) return full;
|
|
|
|
if (parts.length >= 3) {
|
|
const candidate = `${parts[0]} ${parts[1]} ${parts[2][0]}.`;
|
|
if (candidate.length <= maxLen) return candidate;
|
|
return `${parts[0]} ${parts[1][0]}.`;
|
|
}
|
|
|
|
const two = `${parts[0]} ${parts[1]}`;
|
|
if (two.length <= maxLen) return two;
|
|
return `${parts[0]} ${parts[1][0]}.`;
|
|
}
|
|
|
|
get unreadCount() {
|
|
return this.notifications.filter(n => !n.lida).length;
|
|
}
|
|
|
|
get notificationsPreview() {
|
|
return this.notifications.slice(0, this.notificationsPreviewLimit);
|
|
}
|
|
|
|
get hasNotificationsTruncated() {
|
|
return this.notifications.length > this.notificationsPreviewLimit;
|
|
}
|
|
|
|
trackByNotificationId(_: number, notification: NotificationDto) {
|
|
return notification.id;
|
|
}
|
|
|
|
logout() {
|
|
this.authService.logout();
|
|
this.optionsOpen = false;
|
|
this.notificationsOpen = false;
|
|
this.isAdmin = false;
|
|
this.router.navigate(['/']);
|
|
}
|
|
|
|
@HostListener('window:scroll', [])
|
|
onWindowScroll() {
|
|
if (!isPlatformBrowser(this.platformId)) return;
|
|
this.isScrolled = window.scrollY > 10;
|
|
}
|
|
|
|
@HostListener('document:click', [])
|
|
onDocumentClick() {
|
|
this.optionsOpen = false;
|
|
this.notificationsOpen = false;
|
|
}
|
|
|
|
@HostListener('document:keydown.escape', [])
|
|
onEsc() {
|
|
if (!isPlatformBrowser(this.platformId)) return;
|
|
this.closeMenu();
|
|
this.closeOptions();
|
|
this.closeNotifications();
|
|
this.closeCreateUserModal();
|
|
this.closeManageUsersModal();
|
|
}
|
|
|
|
acknowledgeNotification(notification: NotificationDto) {
|
|
if (!isPlatformBrowser(this.platformId)) return;
|
|
const acknowledged = this.getAcknowledgedIds();
|
|
acknowledged.add(notification.id);
|
|
localStorage.setItem('vigenciaAcknowledgedIds', JSON.stringify(Array.from(acknowledged)));
|
|
}
|
|
|
|
acknowledgeCurrentToast() {
|
|
const current = this.toastNotification;
|
|
if (!current) return;
|
|
this.acknowledgeNotification(current);
|
|
}
|
|
|
|
ngAfterViewInit() {
|
|
if (this.pendingToastCheck) {
|
|
this.pendingToastCheck = false;
|
|
void this.maybeShowVigenciaToast();
|
|
}
|
|
}
|
|
|
|
private ensureNotificationsLoaded() {
|
|
if (this.notificationsLoaded || this.notificationsLoading) return;
|
|
this.loadNotifications(true);
|
|
}
|
|
|
|
private loadNotifications(showToast = true) {
|
|
if (!isPlatformBrowser(this.platformId)) return;
|
|
if (this.notificationsLoading) return;
|
|
this.notificationsLoading = true;
|
|
this.notificationsError = false;
|
|
this.notificationsService.list().subscribe({
|
|
next: (data) => {
|
|
this.notifications = data || [];
|
|
this.notificationsLoaded = true;
|
|
this.notificationsLoading = false;
|
|
this.lastNotificationsLoadAt = Date.now();
|
|
if (showToast) {
|
|
void this.maybeShowVigenciaToast();
|
|
}
|
|
},
|
|
error: () => {
|
|
this.notificationsError = true;
|
|
this.notificationsLoading = false;
|
|
},
|
|
});
|
|
}
|
|
|
|
private async maybeShowVigenciaToast() {
|
|
if (!isPlatformBrowser(this.platformId)) return;
|
|
if (!this.notifToast) {
|
|
this.pendingToastCheck = true;
|
|
return;
|
|
}
|
|
|
|
const pending = this.getPendingVigenciaToast();
|
|
if (!pending) return;
|
|
|
|
const bs = await import('bootstrap');
|
|
const toast = bs.Toast.getOrCreateInstance(this.notifToast.nativeElement, { autohide: false });
|
|
toast.show();
|
|
}
|
|
|
|
get toastNotification() {
|
|
return this.getPendingVigenciaToast();
|
|
}
|
|
|
|
private getPendingVigenciaToast() {
|
|
const acknowledged = this.getAcknowledgedIds();
|
|
return this.notifications.find(
|
|
n =>
|
|
this.getNotificationTipo(n) === 'AVencer' &&
|
|
this.getNotificationDaysToExpire(n) === 5 &&
|
|
!acknowledged.has(n.id)
|
|
);
|
|
}
|
|
|
|
private parseDateOnly(raw?: string | null): Date | null {
|
|
if (!raw) return null;
|
|
const datePart = raw.split('T')[0];
|
|
const parts = datePart.split('-');
|
|
if (parts.length === 3) {
|
|
const year = Number(parts[0]);
|
|
const month = Number(parts[1]);
|
|
const day = Number(parts[2]);
|
|
if (Number.isFinite(year) && Number.isFinite(month) && Number.isFinite(day)) {
|
|
return new Date(year, month - 1, day);
|
|
}
|
|
}
|
|
|
|
const fallback = new Date(raw);
|
|
if (Number.isNaN(fallback.getTime())) return null;
|
|
return this.startOfDay(fallback);
|
|
}
|
|
|
|
private startOfDay(date: Date): Date {
|
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
}
|
|
|
|
private getAcknowledgedIds() {
|
|
if (!isPlatformBrowser(this.platformId)) return new Set<string>();
|
|
try {
|
|
const raw = localStorage.getItem('vigenciaAcknowledgedIds');
|
|
const ids = raw ? (JSON.parse(raw) as string[]) : [];
|
|
return new Set(ids);
|
|
} catch {
|
|
return new Set<string>();
|
|
}
|
|
}
|
|
|
|
submitCreateUser() {
|
|
if (this.createUserSubmitting) return;
|
|
if (this.createUserForm.invalid) {
|
|
this.createUserForm.markAllAsTouched();
|
|
return;
|
|
}
|
|
if (!this.isAdmin) {
|
|
this.createUserForbidden = true;
|
|
return;
|
|
}
|
|
|
|
this.createUserSubmitting = true;
|
|
this.setCreateFormDisabled(true);
|
|
this.createUserErrors = [];
|
|
this.createUserForbidden = false;
|
|
this.createUserSuccess = '';
|
|
|
|
const payload = this.createUserForm.value as CreateUserPayload;
|
|
this.usersService.create(payload).subscribe({
|
|
next: (created) => {
|
|
this.createUserSubmitting = false;
|
|
this.setCreateFormDisabled(false);
|
|
this.createUserSuccess = `Usuario ${created.nome} criado com sucesso.`;
|
|
this.createUserForm.reset({ permissao: '' });
|
|
},
|
|
error: (err: HttpErrorResponse) => {
|
|
this.createUserSubmitting = false;
|
|
this.setCreateFormDisabled(false);
|
|
if (err.status === 401 || err.status === 403) {
|
|
this.createUserForbidden = true;
|
|
return;
|
|
}
|
|
const apiErrors = err?.error?.errors;
|
|
if (Array.isArray(apiErrors)) {
|
|
this.createUserErrors = apiErrors.map((e: any) => ({
|
|
field: e?.field,
|
|
message: e?.message || 'Erro ao criar usuario.',
|
|
}));
|
|
} else {
|
|
this.createUserErrors = [{ message: 'Erro ao criar usuario.' }];
|
|
}
|
|
},
|
|
});
|
|
}
|
|
|
|
fetchManageUsers(goToPage?: number) {
|
|
if (goToPage) this.managePage = goToPage;
|
|
this.manageUsersLoading = true;
|
|
this.manageUsersErrors = [];
|
|
this.manageUsersSuccess = '';
|
|
|
|
this.usersService
|
|
.list({
|
|
search: this.manageSearch?.trim() || undefined,
|
|
page: this.managePage,
|
|
pageSize: this.managePageSize,
|
|
})
|
|
.subscribe({
|
|
next: (res) => {
|
|
this.manageUsers = res.items || [];
|
|
this.manageTotal = res.total || 0;
|
|
this.manageUsersLoading = false;
|
|
},
|
|
error: () => {
|
|
this.manageUsers = [];
|
|
this.manageTotal = 0;
|
|
this.manageUsersLoading = false;
|
|
},
|
|
});
|
|
}
|
|
|
|
onManageSearch() {
|
|
this.managePage = 1;
|
|
this.fetchManageUsers();
|
|
}
|
|
|
|
clearManageSearch() {
|
|
this.manageSearch = '';
|
|
this.managePage = 1;
|
|
this.fetchManageUsers();
|
|
}
|
|
|
|
manageGoToPage(p: number) {
|
|
this.managePage = p;
|
|
this.fetchManageUsers();
|
|
}
|
|
|
|
get manageTotalPages(): number {
|
|
return Math.max(1, Math.ceil((this.manageTotal || 0) / (this.managePageSize || 10)));
|
|
}
|
|
|
|
get managePageNumbers(): number[] {
|
|
const total = this.manageTotalPages;
|
|
const current = this.managePage;
|
|
const max = 5;
|
|
let start = Math.max(1, current - 2);
|
|
let end = Math.min(total, start + (max - 1));
|
|
start = Math.max(1, end - (max - 1));
|
|
const pages: number[] = [];
|
|
for (let i = start; i <= end; i++) pages.push(i);
|
|
return pages;
|
|
}
|
|
|
|
openEditUser(user: any) {
|
|
this.editUserTarget = null;
|
|
this.editUserErrors = [];
|
|
this.editUserSuccess = '';
|
|
this.editUserSubmitting = false;
|
|
this.setEditFormDisabled(false);
|
|
this.editUserForm.reset({ nome: '', email: '', senha: '', confirmarSenha: '', permissao: '', ativo: true });
|
|
|
|
this.usersService.getById(user.id).subscribe({
|
|
next: (full) => {
|
|
this.editUserTarget = full;
|
|
this.editUserForm.reset({
|
|
nome: full.nome ?? '',
|
|
email: full.email ?? '',
|
|
senha: '',
|
|
confirmarSenha: '',
|
|
permissao: full.permissao ?? '',
|
|
ativo: full.ativo ?? true,
|
|
});
|
|
},
|
|
error: () => {
|
|
this.editUserErrors = [{ message: 'Erro ao carregar usuario.' }];
|
|
},
|
|
});
|
|
}
|
|
|
|
cancelEditUser() {
|
|
this.editUserTarget = null;
|
|
this.editUserErrors = [];
|
|
this.editUserSuccess = '';
|
|
this.editUserSubmitting = false;
|
|
this.setEditFormDisabled(false);
|
|
this.editUserForm.reset({ nome: '', email: '', senha: '', confirmarSenha: '', permissao: '', ativo: true });
|
|
}
|
|
|
|
submitEditUser() {
|
|
if (this.editUserSubmitting || !this.editUserTarget) return;
|
|
|
|
const payload: any = {};
|
|
const nome = (this.editUserForm.get('nome')?.value || '').toString().trim();
|
|
const email = (this.editUserForm.get('email')?.value || '').toString().trim();
|
|
const permissao = (this.editUserForm.get('permissao')?.value || '').toString().trim();
|
|
const ativo = !!this.editUserForm.get('ativo')?.value;
|
|
|
|
if (nome && nome !== (this.editUserTarget.nome || '').trim()) payload.nome = nome;
|
|
if (email && email !== (this.editUserTarget.email || '').trim()) payload.email = email;
|
|
if (permissao && permissao !== (this.editUserTarget.permissao || '').trim()) payload.permissao = permissao;
|
|
if ((this.editUserTarget.ativo ?? true) !== ativo) payload.ativo = ativo;
|
|
|
|
const senha = (this.editUserForm.get('senha')?.value || '').toString();
|
|
const confirmar = (this.editUserForm.get('confirmarSenha')?.value || '').toString();
|
|
if (senha || confirmar) {
|
|
if (!senha || !confirmar) {
|
|
this.editUserErrors = [{ message: 'Para alterar a senha, preencha senha e confirmacao.' }];
|
|
return;
|
|
}
|
|
if (senha.length < 6) {
|
|
this.editUserErrors = [{ message: 'Senha deve ter no minimo 6 caracteres.' }];
|
|
return;
|
|
}
|
|
if (senha !== confirmar) {
|
|
this.editUserErrors = [{ message: 'As senhas nao conferem.' }];
|
|
return;
|
|
}
|
|
payload.senha = senha;
|
|
payload.confirmarSenha = confirmar;
|
|
}
|
|
|
|
if (Object.keys(payload).length === 0) {
|
|
this.editUserErrors = [{ message: 'Nenhuma alteracao detectada.' }];
|
|
return;
|
|
}
|
|
|
|
this.editUserSubmitting = true;
|
|
this.setEditFormDisabled(true);
|
|
this.editUserErrors = [];
|
|
this.editUserSuccess = '';
|
|
|
|
this.usersService.update(this.editUserTarget.id, payload).subscribe({
|
|
next: (updated) => {
|
|
this.editUserSubmitting = false;
|
|
this.setEditFormDisabled(false);
|
|
this.editUserSuccess = `Usuario ${updated.nome} atualizado.`;
|
|
this.editUserTarget = updated;
|
|
this.fetchManageUsers(this.managePage);
|
|
},
|
|
error: (err: HttpErrorResponse) => {
|
|
this.editUserSubmitting = false;
|
|
this.setEditFormDisabled(false);
|
|
const apiErrors = err?.error?.errors;
|
|
if (Array.isArray(apiErrors)) {
|
|
this.editUserErrors = apiErrors.map((e: any) => ({
|
|
field: e?.field,
|
|
message: e?.message || 'Erro ao atualizar usuario.',
|
|
}));
|
|
} else {
|
|
this.editUserErrors = [{ message: err?.error?.message || 'Erro ao atualizar usuario.' }];
|
|
}
|
|
},
|
|
});
|
|
}
|
|
|
|
confirmDeleteUser(user: any) {
|
|
if (!confirm(`Excluir usuario ${user.nome}?`)) return;
|
|
this.usersService.update(user.id, { ativo: false }).subscribe({
|
|
next: () => this.fetchManageUsers(this.managePage),
|
|
});
|
|
}
|
|
|
|
hasFieldError(field: string): boolean {
|
|
return this.getFieldErrors(field).length > 0;
|
|
}
|
|
|
|
getFieldErrors(field: string): string[] {
|
|
const key = this.normalizeField(field);
|
|
return this.createUserErrors
|
|
.filter((e) => this.normalizeField(e.field) === key)
|
|
.map((e) => e.message);
|
|
}
|
|
|
|
get passwordMismatch(): boolean {
|
|
return !!this.createUserForm.errors?.['passwordsMismatch'];
|
|
}
|
|
|
|
private resetCreateUserState() {
|
|
this.createUserErrors = [];
|
|
this.createUserForbidden = false;
|
|
this.createUserSuccess = '';
|
|
this.createUserSubmitting = false;
|
|
this.setCreateFormDisabled(false);
|
|
this.createUserForm.reset({ permissao: '' });
|
|
}
|
|
|
|
private resetManageUsersState() {
|
|
this.manageUsersErrors = [];
|
|
this.manageUsersSuccess = '';
|
|
this.manageUsersLoading = false;
|
|
this.manageUsers = [];
|
|
this.manageSearch = '';
|
|
this.managePage = 1;
|
|
this.manageTotal = 0;
|
|
this.cancelEditUser();
|
|
}
|
|
|
|
private normalizeField(field?: string | null): string {
|
|
return (field || '').trim().toLowerCase();
|
|
}
|
|
|
|
private setCreateFormDisabled(disabled: boolean) {
|
|
if (disabled) this.createUserForm.disable({ emitEvent: false });
|
|
else this.createUserForm.enable({ emitEvent: false });
|
|
}
|
|
|
|
private setEditFormDisabled(disabled: boolean) {
|
|
if (disabled) this.editUserForm.disable({ emitEvent: false });
|
|
else this.editUserForm.enable({ emitEvent: false });
|
|
}
|
|
|
|
private passwordsMatchValidator(group: AbstractControl): ValidationErrors | null {
|
|
const senha = group.get('senha')?.value;
|
|
const confirmar = group.get('confirmarSenha')?.value;
|
|
if (!senha || !confirmar) return null;
|
|
return senha === confirmar ? null : { passwordsMismatch: true };
|
|
}
|
|
}
|