Problemas em componente

typescript

import {
  AfterViewInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  OnDestroy,
  OnInit,
  ViewChild,
  ViewEncapsulation,
} from "@angular/core";
import {
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from "@angular/forms";
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { MatSort } from "@angular/material/sort";
import { Router } from "@angular/router";
import { fuseAnimations } from "@fuse/animations";
import { FuseConfirmationService } from "@fuse/services/confirmation";
import { FuseMediaWatcherService } from "@fuse/services/media-watcher";
import { NUMERO_INICIAL_PESQUISA } from "app/core/api/erp.api";
import { StateStorageService } from "app/core/auth/state-storage.service";
import { DefaultComponent } from "app/core/classes/default.component";
import { EnumService } from "app/modules/services/enum.service";
import {
  debounceTime,
  map,
  merge,
  Observable,
  Subject,
  switchMap,
  takeUntil,
} from "rxjs";
import { UsuarioService } from "../usuario.service";

@Component({
  selector: "usuario-list",
  templateUrl: "./usuario-list.component.html",
  styles: [
    `
      .usuario-grid {
        grid-template-columns: 48px auto 40px;

        @screen sm {
          grid-template-columns: 48px auto 112px 72px;
        }

        @screen md {
          grid-template-columns: 48px 112px auto 112px 72px;
        }

        @screen lg {
          grid-template-columns: 48px 112px auto 112px 96px 96px 72px;
        }
      }
    `,
  ],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  animations: fuseAnimations,
})
export class UsuarioListComponent
  extends DefaultComponent
  implements OnInit, AfterViewInit, OnDestroy
{
  @ViewChild(MatPaginator) private _paginator: MatPaginator;
  @ViewChild(MatSort) private _sort: MatSort;
  usuarios$: Observable<any[]>;
  isLoading: boolean = false;
  pagination: any;
  searchInputControl: FormControl = new FormControl();
  selectUsuario: any | null = null;
  selectedUsuarioForm: FormGroup;
  private _unsubscribeAll: Subject<any> = new Subject<any>();
  nomePagina = "Usuário";
  urlBase = "usuario";
  perfisUsuario: any[] = [];

  constructor(
    protected router: Router,
    protected stateStorageService: StateStorageService,
    private _changeDetectorRef: ChangeDetectorRef,
    private _fuseConfirmationService: FuseConfirmationService,
    private _fuseMediaWatcherService: FuseMediaWatcherService,
    private _formBuilder: FormBuilder,
    private usuarioService: UsuarioService,
    private enumService: EnumService
  ) {
    super(router, stateStorageService);
  }

  async ngOnInit(): Promise<void> {
    await super.ngOnInit();
    this.selectedUsuarioForm = this._formBuilder.group({
      idString: [],
      nome: [, [Validators.required]],
      email: [, [Validators.required]],
      telefone: [, [Validators.required]],
      celular: [, [Validators.required]],
      senha: [, [Validators.required]],
      confirmeSenha: [, [Validators.required]],
      grupoAcesso: [, [Validators.required]],
    });
    this.usuarioService.pagination$
      .pipe(takeUntil(this._unsubscribeAll))
      .subscribe((pagination: any) => {
        this.pagination = pagination;
        this._changeDetectorRef.markForCheck();
      });
    this.usuarios$ = this.usuarioService.usuarios$;
    this.searchInputControl.valueChanges
      .pipe(
        takeUntil(this._unsubscribeAll),
        debounceTime(300),
        switchMap((query) => {
          this.closeDetails();
          this.isLoading = true;
          return this.usuarioService.pesquisar(
            0,
            NUMERO_INICIAL_PESQUISA,
            "nome",
            "asc",
            query
          );
        }),
        map(() => (this.isLoading = false))
      )
      .subscribe();
    await this.perfilUsuario();
  }

  async paginacao(event: PageEvent): Promise<void> {
    this.paginar();
  }

  paginar() {
    merge(this._sort.sortChange, this._paginator.page)
      .pipe(
        switchMap(() => {
          this.closeDetails();
          this.isLoading = true;
          return this.usuarioService.pesquisar(
            this._paginator.pageIndex,
            this._paginator.pageSize,
            this._sort.active,
            this._sort.direction
          );
        }),
        map(() => (this.isLoading = false))
      )
      .subscribe();
  }

  ngAfterViewInit(): void {
    if (this._sort && this._paginator) {
      this._sort.sort({
        id: "nome",
        start: "asc",
        disableClear: true,
      });
      this._changeDetectorRef.markForCheck();
      this._sort.sortChange
        .pipe(takeUntil(this._unsubscribeAll))
        .subscribe(() => {
          this._paginator.pageIndex = 0;
          this.closeDetails();
        });
      merge(this._sort.sortChange, this._paginator.page)
        .pipe(
          switchMap(() => {
            this.closeDetails();
            this.isLoading = true;
            return this.usuarioService.pesquisar(
              this._paginator.pageIndex,
              this._paginator.pageSize,
              this._sort.active,
              this._sort.direction
            );
          }),
          map(() => (this.isLoading = false))
        )
        .subscribe();
    }
  }

  ngOnDestroy(): void {
    this._unsubscribeAll.next(null);
    this._unsubscribeAll.complete();
  }

  adicionarUsuario() {
    this.inserir = false;
    this.usuarioService.criaUsuario().subscribe(
      (usuario) => {
        this.inserir = true;
        this.selectUsuario = usuario;
        this.selectedUsuarioForm.patchValue(usuario);
        this._changeDetectorRef.markForCheck();
      },
      (err) => this.errorServiceS.error(err)
    );
  }

  salvar() {
    const usuario = this.selectedUsuarioForm.getRawValue();
    this.usuarioService.salvar(usuario).subscribe(
      (usuario) => {
        this.selectUsuario = usuario;
        this.selectedUsuarioForm.patchValue(usuario);
        this._changeDetectorRef.markForCheck();
        this.closeDetails();
      },
      (err) => this.errorServiceS.error(err)
    );
  }

  visualizarUsuario(usuarioId: string): void {
    this.inserir = false;
    this.editar = false;
    this.ver = false;
    this.excluido = false;
    if (this.selectUsuario && this.selectUsuario.idString === usuarioId) {
      this.closeDetails();
      return;
    }
    this.usuarioService.buscarUsuarioPorId(usuarioId).subscribe(
      async (usuario) => {
        this.ver = true;
        this.selectUsuario = usuario;
        this.selectedUsuarioForm.patchValue(usuario);
        await this.ajusteTela();
      },
      (err) => this.errorServiceS.error(err)
    );
  }

  async closeDetails(): Promise<void> {
    this.selectUsuario = null;
    this.inserir = false;
    this.paginar();
    await this.ajusteTela();
  }

  updateSelectedUsuario(): void {
    const product = this.selectedUsuarioForm.getRawValue();
    delete product.currentImageIndex;
    this.usuarioService.updateProduct(product.id, product).subscribe(() => {});
  }

  ativarUsuario(idString: string): void {
    const confirmation = this._fuseConfirmationService.open({
      title: "Ativar usuários",
      message: "Deseja ativar este usuário ?",
      actions: {
        confirm: {
          label: "Ativar",
        },
      },
    });
    confirmation.afterClosed().subscribe((result) => {
      if (result === "confirmed") {
        this.usuarioService.ativarUsuario(idString).subscribe(
          async () => await this.closeDetails(),
          (err) => this.errorServiceS.error(err)
        );
      }
    });
  }

  desativarUsuario(idString: string): void {
    const confirmation = this._fuseConfirmationService.open({
      title: "Desativar usuários",
      message: "Deseja desativar este usuário ?",
      actions: {
        confirm: {
          label: "Desativar",
        },
      },
    });
    confirmation.afterClosed().subscribe((result) => {
      if (result === "confirmed") {
        this.usuarioService.desativarUsuario(idString).subscribe(
          async () => await this.closeDetails(),
          (err) => this.errorServiceS.error(err)
        );
      }
    });
  }

  private async ajusteTela() {
    this._fuseMediaWatcherService.onMediaChange$
      .pipe(takeUntil(this._unsubscribeAll))
      .subscribe(({}) => this._changeDetectorRef.markForCheck());
  }

  private async perfilUsuario(): Promise<any> {
    this.perfisUsuario = [];
    await this.enumService
      .perfilUsuario()
      .then((perfisUsuario) => (this.perfisUsuario = perfisUsuario))
      .catch((erro) => this.errorServiceS.error(erro));
  }
}

html

<div
  class="sm:absolute sm:inset-0 flex flex-col flex-auto min-w-0 sm:overflow-hidden bg-card dark:bg-transparent"
>
  <div
    class="relative flex flex-col sm:flex-row flex-0 sm:items-center sm:justify-between py-8 px-6 md:px-8 border-b"
  >
    <div class="absolute inset-x-0 bottom-0" *ngIf="isLoading">
      <mat-progress-bar [mode]="'indeterminate'"></mat-progress-bar>
    </div>
    <div class="text-4xl font-extrabold tracking-tight">{{ nomePagina }}</div>
    <div class="flex flex-shrink-0 items-center mt-6 sm:mt-0 sm:ml-4">
      <mat-form-field
        *ngIf="podePesquisar"
        class="fuse-mat-dense fuse-mat-no-subscript fuse-mat-rounded min-w-64"
        pTooltip="Pesquisa {{ nomePagina }}"
      >
        <mat-icon
          class="icon-size-5"
          matPrefix
          [svgIcon]="'heroicons_solid:search'"
        ></mat-icon>
        <input
          matInput
          [formControl]="searchInputControl"
          [autocomplete]="'off'"
        />
      </mat-form-field>
      <button
        *ngIf="!inserir && podeIncluir"
        class="ml-4"
        mat-flat-button
        [color]="'primary'"
        (click)="adicionarUsuario()"
      >
        <mat-icon
          [svgIcon]="'heroicons_outline:plus'"
          pTooltip="Adicionar {{ nomePagina }}"
        ></mat-icon>
      </button>
    </div>
  </div>
  <div class="flex flex-auto overflow-hidden">
    <div
      class="flex flex-col flex-auto sm:mb-18 overflow-hidden sm:overflow-y-auto"
    >
      <ng-container *ngIf="usuarios$ | async as usuarios">
        <ng-container *ngIf="usuarios.length > 0; else noUsuarios">
          <div class="grid">
            <div
              class="usuario-grid z-10 sticky top-0 grid gap-4 py-4 px-6 md:px-8 shadow text-md font-semibold text-secondary bg-gray-50 dark:bg-black dark:bg-opacity-5"
              matSort
              matSortDisableClear
            >
              <div [mat-sort-header]="'nome'">Nome</div>
              <div
                [mat-sort-header]="'email'"
                style="padding-left: 500px !important"
                class="hidden lg:block"
              >
                E-mail
              </div>
              <div
                [mat-sort-header]="'telefone'"
                style="padding-left: 700px !important"
                class="hidden lg:block"
              >
                Telefone
              </div>
              <div [mat-sort-header]="'celular'" class="hidden lg:block">
                Celular
              </div>
              <div [mat-sort-header]="'grupoAcesso'" class="hidden lg:block">
                Grupo de acesso
              </div>
              <div
                [mat-sort-header]="'statusDoRegistro'"
                class="hidden lg:block"
              >
                Status do registro
              </div>
              <div class="hidden sm:block">Ações</div>
            </div>
            <ng-container *ngIf="usuarios$ | async as usuarios">
              <ng-container
                *ngFor="let usuario of usuarios; trackBy: trackByFn"
              >
                <div
                  class="usuario-grid grid items-center gap-4 py-3 px-6 md:px-8 border-b"
                  *ngIf="usuario.email !== null"
                >
                  <div class="min-w-100 lg:truncate">
                    {{ usuario.nome }}
                  </div>
                  <div
                    style="padding-left: 500px !important"
                    class="hidden lg:block min-w-100"
                  >
                    {{ usuario.email }}
                  </div>
                  <div
                    style="padding-left: 700px !important"
                    class="hidden lg:block min-w-100"
                  >
                    {{ usuario.telefone }}
                  </div>
                  <div class="hidden lg:block">
                    {{ usuario.celular }}
                  </div>
                  <div class="hidden lg:block">
                    {{ usuario.grupoAcessoDescricao }}
                  </div>
                  <div class="hidden lg:block">
                    <ng-container
                      *ngIf="usuario.statusDoRegistro.key === 'ATIVO'"
                    >
                      <mat-icon
                        class="text-green-400 icon-size-5"
                        [svgIcon]="'heroicons_solid:check'"
                        pTooltip="{{ usuario.statusDoRegistro.descricao }}"
                      ></mat-icon>
                    </ng-container>
                    <ng-container
                      *ngIf="usuario.statusDoRegistro.key !== 'ATIVO'"
                    >
                      <mat-icon
                        class="text-gray-400 icon-size-5"
                        [svgIcon]="'heroicons_solid:x'"
                        pTooltip="{{ usuario.statusDoRegistro.descricao }}"
                      ></mat-icon>
                    </ng-container>
                  </div>
                  <div *ngIf="usuario.idString !== undefined">
                    <button
                      *ngIf="podeVisualizar"
                      class="min-w-10 min-h-7 h-7 px-2 leading-6"
                      mat-stroked-button
                      (click)="visualizarUsuario(usuario.idString)"
                    >
                      <mat-icon
                        class="icon-size-5"
                        [pTooltip]="
                          selectUsuario?.idString === usuario.idString
                            ? 'Voltar para a tela de pesquisa'
                            : 'Visualizar usuário'
                        "
                        [svgIcon]="
                          selectUsuario?.idString === usuario.idString
                            ? 'heroicons_solid:chevron-up'
                            : 'heroicons_solid:chevron-down'
                        "
                      ></mat-icon>
                    </button>
                  </div>
                </div>
                <div class="grid">
                  <ng-container
                    *ngIf="selectUsuario?.idString === usuario.idString"
                  >
                    <ng-container
                      *ngTemplateOutlet="
                        rowDetailsTemplate;
                        context: { $implicit: usuario }
                      "
                    ></ng-container>
                  </ng-container>
                </div>
              </ng-container>
            </ng-container>
          </div>
          <mat-paginator
            class="sm:absolute sm:inset-x-0 sm:bottom-0 border-b sm:border-t sm:border-b-0 z-10 bg-gray-50 dark:bg-transparent"
            [ngClass]="{ 'pointer-events-none': isLoading }"
            [length]="pagination.totalElementos"
            [pageIndex]="0"
            [pageSize]="pagination.paginaTamanho"
            [pageSizeOptions]="[5, 15, 25, 50, 75, 100, 500]"
            [showFirstLastButtons]="true"
            (page)="paginacao($event)"
          ></mat-paginator>
        </ng-container>
      </ng-container>
      <ng-template #rowDetailsTemplate let-usuario>
        <div class="shadow-lg overflow-hidden">
          <div class="flex border-b">
            <form
              class="flex flex-col w-full"
              [formGroup]="selectedUsuarioForm"
            >
              <div class="flex items-center">
                <div style="padding-top: 10px; align-self: flex-end">
                  <button
                    class="ml-4"
                    mat-flat-button
                    [color]="'primary'"
                    (click)="closeDetails()"
                    pTooltip="Fechar tela"
                  >
                    <mat-icon
                      [svgIcon]="'heroicons_outline:arrow-down-tray'"
                    ></mat-icon>
                  </button>
                  <button
                    *ngIf="!inserir && ver && podeAlterar"
                    class="ml-4"
                    mat-flat-button
                    [color]="'primary'"
                    (click)="alterar(rotaAtual)"
                    pTooltip="Alterar {{ nomePagina }}"
                  >
                    <mat-icon [svgIcon]="'heroicons_outline:pencil'"></mat-icon>
                  </button>
                  <button
                    *ngIf="!inserir && editar && podeVisualizar"
                    class="ml-4"
                    mat-flat-button
                    [color]="'primary'"
                    (click)="visualizar(rotaAtual)"
                    pTooltip="Visualizar {{ nomePagina }}"
                  >
                    <mat-icon [svgIcon]="'heroicons_outline:eye'"></mat-icon>
                  </button>
                  <button
                    *ngIf="
                      !inserir &&
                      ver &&
                      podeAtivarInativar &&
                      selectUsuario.statusDoRegistro.key === 'ATIVO'
                    "
                    class="ml-4"
                    mat-flat-button
                    [color]="'warn'"
                    (click)="desativarUsuario(selectUsuario.idString)"
                    pTooltip="Inativar {{ nomePagina }}"
                  >
                    <mat-icon
                      [svgIcon]="'heroicons_outline:hand-thumb-down'"
                    ></mat-icon>
                  </button>
                  <button
                    *ngIf="
                      !inserir &&
                      ver &&
                      podeAtivarInativar &&
                      selectUsuario.statusDoRegistro.key !== 'ATIVO'
                    "
                    class="ml-4"
                    mat-flat-button
                    [color]="'accent'"
                    (click)="ativarUsuario(selectUsuario.idString)"
                    pTooltip="Ativar {{ nomePagina }}"
                  >
                    <mat-icon
                      [svgIcon]="'heroicons_outline:hand-thumb-up'"
                    ></mat-icon>
                  </button>
                  <button
                    *ngIf="podeAlterar || podeIncluir"
                    class="ml-4"
                    mat-flat-button
                    [color]="'primary'"
                    (click)="salvar()"
                    pTooltip="Salvar {{ nomePagina }}"
                  >
                    <mat-icon [svgIcon]="'heroicons_outline:check'"></mat-icon>
                  </button>
                </div>
              </div>
              <div class="flex flex-col p-8">
                <div class="flex flex-auto flex-wrap">
                  <mat-form-field class="w-full">
                    <mat-label>Nome</mat-label>
                    <input matInput [formControlName]="'nome'" />
                  </mat-form-field>
                </div>
                <mat-form-field class="w-full">
                  <mat-label>E-mail</mat-label>
                  <input matInput [formControlName]="'email'" />
                </mat-form-field>
                <mat-form-field class="w-full">
                  <mat-label>Telefone</mat-label>
                  <input
                    matInput
                    [formControlName]="'telefone'"
                    [textMask]="{ mask: telefone }"
                  />
                </mat-form-field>
                <mat-form-field class="w-full">
                  <mat-label>Celular</mat-label>
                  <input
                    matInput
                    [formControlName]="'celular'"
                    [textMask]="{ mask: MASKS.celular.textMask }"
                  />
                </mat-form-field>
                <mat-form-field class="w-full">
                  <mat-label>Grupo de acesso</mat-label>
                  <mat-select [formControlName]="'grupoAcesso'">
                    <mat-option
                      *ngFor="let entidade of perfisUsuario"
                      [value]="entidade.key"
                      >{{ entidade.descricao }}</mat-option
                    >
                  </mat-select>
                </mat-form-field>
                <mat-form-field class="w-full" *ngIf="inserir">
                  <mat-label>Senha</mat-label>
                  <input matInput [formControlName]="'senha'" />
                </mat-form-field>
                <mat-form-field class="w-full" *ngIf="inserir">
                  <mat-label>Confirme a senha</mat-label>
                  <input matInput [formControlName]="'confirmeSenha'" />
                </mat-form-field>
                <div
                  class="sm:col-span-4 font-bold text-red-500"
                  *ngIf="inserir"
                >
                  {{ informacaoSenha }}
                </div>
              </div>
            </form>
          </div>
        </div>
      </ng-template>
      <ng-template #noUsuarios>
        <div
          class="p-8 sm:p-16 border-t text-4xl font-semibold tracking-tight text-center"
        >
          Não existe usuários
        </div>
      </ng-template>
    </div>
  </div>
</div>

1º) Quando clico na paginação a primeira vez ele não no banco de dados, fazer a paginação. Somente da segunda vez. Não consegui identificar o erro.

  1. Após fazer a ação de ativarUsuario e desativarUsuario, não está fazendo atualização a grade de pesquisa. Não consegui identificar o erro.