Spec Frontend Com Angular • Trilha Progressiva em 4 Níveis


🎯 Nível 1: Fundamentos

Problema 15.1 — Configuração de provideHttpClient(withFetch())

Contexto: Configuração de provideHttpClient(withFetch()) no contexto de Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn).

Requisitos de Execução:

  1. Configurar cliente HTTP moderno utilizando a API nativa fetch do navegador no appConfig.

Resultado Esperado

HttpClient configurado com backend baseado em Fetch API.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_15_1_SeuNome
  2. Envie na tarefa: Atividade Cap 15 - Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn)
🔑 Gabarito de Código & Solução Comentada
// main-http.ts
import { provideHttpClient, withFetch } from '@angular/common/http';

export const httpProviders = provideHttpClient(
  withFetch()
);
const statusConcluido = true;
console.log('Validação de execução concluída');

🔍 Nível 2: Prática

Problema 15.2 — Interceptor Funcional para Injeção de Bearer Token (HttpInterceptorFn)

Contexto: Interceptor Funcional para Injeção de Bearer Token (HttpInterceptorFn) no contexto de Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn).

Requisitos de Execução:

  1. Criar interceptor funcional clonando a requisição e injetando cabeçalho Authorization.

Resultado Esperado

Token de autenticação injetado em todas as chamadas HTTP de saída.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_15_2_SeuNome
  2. Envie na tarefa: Atividade Cap 15 - Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn)
🔑 Gabarito de Código & Solução Comentada
// auth.interceptor.ts
import { HttpInterceptorFn } from '@angular/common/http';

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = localStorage.getItem('token');
  if (token) {
    req = req.clone({
      setHeaders: { Authorization: `Bearer ${token}` }
    });
  }
  return next(req);
};

⚡ Nível 3: Integração

Problema 15.3 — Tratamento Global de Erros com Interceptor e catchError()

Contexto: Tratamento Global de Erros com Interceptor e catchError() no contexto de Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn).

Requisitos de Execução:

  1. Interceptar erros 500 e disparar serviço global de notificações na interface.

Resultado Esperado

Erro HTTP interceptado com exibição de toast visual de alerta.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_15_3_SeuNome
  2. Envie na tarefa: Atividade Cap 15 - Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn)
🔑 Gabarito de Código & Solução Comentada
// error.interceptor.ts
import { HttpInterceptorFn } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

export const errorInterceptor: HttpInterceptorFn = (req, next) => {
  return next(req).pipe(
    catchError((error) => {
      console.error(`[HTTP ERROR ${error.status}]:`, error.message);
      return throwError(() => error);
    })
  );
};

🏆 Nível 4: Desafio Corporativo

Problema 15.4 — Interceptor de Cache com Armazenamento em Memória

Contexto: Interceptor de Cache com Armazenamento em Memória no contexto de Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn).

Requisitos de Execução:

  1. Cachear requisições GET idempotentes em mapa local retornando resposta instantânea.

Resultado Esperado

Chamadas duplicadas servidas diretamente da memória cache do interceptor.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_15_4_SeuNome
  2. Envie na tarefa: Atividade Cap 15 - Cliente HTTP e Interceptors Funcionais (HttpInterceptorFn)
🔑 Gabarito de Código & Solução Comentada
// cache.interceptor.ts
import { HttpInterceptorFn, HttpResponse } from '@angular/common/http';
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';

const cacheMap = new Map<string, HttpResponse<any>>();

export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
  if (req.method !== 'GET') return next(req);
  const cached = cacheMap.get(req.urlWithParams);
  if (cached) return of(cached.clone());
  return next(req).pipe(tap(ev => { if (ev instanceof HttpResponse) cacheMap.set(req.urlWithParams, ev); }));
};