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.
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é!