Data

23 nov, 2018

Criação de um aplicativo utilizando dados abertos do governo com Angular 7 – Parte 03

Publicidade

Trabalhando na View

Finalmente vamos preparar nossa interface para o usuário informar a data e visualizar as licitações.

Nossa aplicação ficará assim:

Faremos uso dos componentes do Material Angular. No terminal de comando, no diretório projeto, informe:

> ng add @angular/material

Após o fim do download será solicitado algumas configurações adicionais.

A primeira delas é a escolha do tema. Na frente de cada um há um link para ver a composição das cores. Eu escolhi o primeiro:

Os próximos passos são a escolha da biblioteca HammerJS, responsável pelo reconhecimento de gestos, e em seguida, a definição de animações, utilizadas por componentes do Angular Material.

Finalizados esses passos já podemos importar os módulos de cada componente que serão utilizados no projeto.

Entre as linhas 9 a 15, definimos os módulos dos componentes. Entre eles, destaco o MatDatepickerModule e o MatCardModule.

Nas linhas 19 a 24 estão as definições necessárias para configurar e exibir a data de acordo com o padrão dd/MM/yyyy. Registro o provider desses componentes na linha 43.

E finalmente, no array do import estão as definições dos módulos. Abaixo, o código completo do app.module.ts.

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";

import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { HttpClientModule } from "@angular/common/http";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
// Componentes do Material Angular
import { MatDatepickerModule } from "@angular/material/datepicker";
import { MatNativeDateModule } from "@angular/material";
import {MatCardModule} from '@angular/material/card';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {MatBadgeModule} from '@angular/material/badge';
import {MatIconModule} from '@angular/material/icon';
import {MatButtonModule} from '@angular/material/button';



import { LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import localePt from '@angular/common/locales/pt';
import {MatExpansionModule} from '@angular/material/expansion';

registerLocaleData(localePt, 'pt-BR');


@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
    MatDatepickerModule,
    MatNativeDateModule,
    MatCardModule,
    MatProgressSpinnerModule,
    MatBadgeModule,
    MatIconModule,
    MatButtonModule,
    MatExpansionModule
  ],
  providers: [ { provide: LOCALE_ID, useValue: 'pt-BR' }  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Na classe app.component.ts vamos escrever um método para busca e dois atributos para receber o resultado e exibir um spinner até a efetivação da requisição.

Na linha 13 injetamos o serviço para requisição da API. O método busca tem um parâmetro para recuperar a data que o usuário informou, porém a API somente no formato dd/MM/yyyy.

Dessa forma, as linhas 18 e 19 justamente formatam a data no padrão.

No método getLicitacoes() invocamos um subscribe que retorna um objeto do tipo RetornoLicitacao (linha 21), e como o método foi finalizado, encerramos a visualização do spinner (linha 22).

import { Component, OnInit } from "@angular/core";
import { LicitacaoService, RetornoLicitacao } from "./licitacao.service";
import { DatePipe } from "@angular/common";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
  licitacoes: RetornoLicitacao;
  showSpinner: boolean;
  constructor(private licitacaoService: LicitacaoService) { }

  ngOnInit() { }
  busca($event) {
    this.showSpinner = true;
    let datePipe = new DatePipe("pt-BR");
    let data = datePipe.transform(new Date($event.value), "dd/MM/yyyy");
    this.licitacaoService.getLicitacoes(data).subscribe(dados => {
      this.licitacoes = dados;
      this.showSpinner = false;
    })
  }
}

O próximo passo é modificar nosso template html. Limpe o arquivo app.component.html e deixe-o assim:

<div class="container">

  <!-- PESQUISA -->
  <div class="pesquisa">
    <mat-card>
      <mat-card-header>
        <h2>Pesquisa </h2>
      </mat-card-header>
      <input matInput (dateInput)="busca($event)" [matDatepicker]="picker" placeholder="Selecione uma data">
      <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker></mat-datepicker>
    </mat-card>
  </div>

  <!-- Resultados -->
  <h2>({{licitacoes?.quantidade}}) Resultados</h2>
  <mat-spinner *ngIf="showSpinner"></mat-spinner>

  <div class="resultados">
    <mat-card *ngFor="let licitacao of licitacoes?.listaLicitacoes">
      <mat-card-content>
        <h3>{{licitacao.modalidade}} - Nº{{licitacao.num_ano_edital}} </h3>
        <p class="sublinhado">{{licitacao.orgao_responsavel}}</p>
        <p> Valor Máximo: <b style="color: red">{{licitacao.valor_maximo_inicial}}</b> </p>
        <p> Abertura: <b style="color: blue">{{licitacao.data_abertura}}</b> </p>
        <p> Critério: <b>{{licitacao.criterio_julgamento}}</b> </p>
        <p class="sublinhado">Objetivo</p>
        <p style="text-align: justify">{{licitacao.objetivo}}</p>
        <mat-accordion>
          <mat-expansion-panel *ngFor="let lote of licitacao?.composicao_processo">
            <mat-expansion-panel-header>
              LOTE {{lote.numero_lote}}
            </mat-expansion-panel-header>
            <p>{{lote.caracteristica_lote}}</p>
            <p> R$ Maximo Inicial: <b style="color: red">{{lote.valor_maximo_inicial_lote}}</b> </p>
          </mat-expansion-panel>
        </mat-accordion>
        <mat-card-actions class="icons-action">
          <a [href]="licitacao.local_disputa" target="_blank">
            <mat-icon>important_devices</mat-icon>
          </a>
        </mat-card-actions>
      </mat-card-content>
    </mat-card>
  </div>
</div>

Comentando o código

Definimos uma tag de spinner do material (linha 17) com a diretiva *ngIf para contralar a exibição do componente.

Na linha 20 fazemos um loop usando a diretiva *ngFor para exibir os cards para cada licitação. Note que acessamos o atributo listaLicitacoes do objeto licitacoes.

Fazemos o mesmo processo na linha 30 para recuperar os lotes de cada licitacao.

Já é possível executar para ver como ficou. No terminal, digite:

> ng serve -o

É possível que você tenha problemas com o CORS. Para contornar essa situação, instale esse plugin do Chrome.

CORS

Para ficar exatamente como a figura inicial você deve copiar os estilos para app.component.css.

Todo o código do projeto está no GIT.

Em caso de dúvidas, entre em contato.

Até!