Skip to the content.

🚀 Projeto Lista de Tarefas” (To-Do List)

v2.0

🗺️ Visão Geral da Arquitetura

Neste projeto, construiremos um sistema completo de “Lista de Tarefas” (To-Do List), demonstrando como diferentes aplicações cliente podem consumir uma única fonte de dados central (API). A arquitetura final será:

Diagrama da Arquitetura

graph TD
    subgraph "🎛️ Gerenciamento e Automação"
        Script["🛠️ Painel de Controle (listadetarefas-painel.ps1)"]
    end

    subgraph "📱 Clientes (Frontends)"
        Web["đź’» Frontend Web (Angular)"]
        Desktop["🖥️ Frontend Desktop (JavaFX)"]
        Mobile["📱 Frontend Mobile (Android)"]
    end

    subgraph "⚙️ Serviços (Backend)"
        API["🔌 Backend API (Spring Boot)"]
        DB[("🗄️ Banco de Dados Em Memória H2")]
    end

    %% Conexões de Dados
    Web -->|Requisições HTTP/JSON| API
    Desktop -->|Requisições HTTP/JSON| API
    Mobile -->|Requisições HTTP/JSON| API
    API --- DB

    %% Conexões de Gerenciamento
    Script -- Gerencia --> API
    Script -- Gerencia --> Web
    Script -- Gerencia --> Desktop
    Script -- Gerencia --> Mobile


⚙️ Módulo 1: A Fundação – Backend com Spring Boot (listadetarefas-api)

Objetivo: Criar o serviço central que irá gerenciar os dados das tarefas, servindo como a única fonte de verdade para todos os clientes.

🛠️ Ferramentas Necessárias

### 📂 Passo 1: Criação do Projeto

  1. Acesse o Spring Initializr (https://start.spring.io).
  2. Preencha os metadados do projeto:
    • Project: Maven
    • Language: Java
    • Spring Boot: VersĂŁo estável mais recente (ex: 3.x.x)
    • Group: br.com.curso
    • Artifact: listadetarefas-api
    • Package name: br.com.curso.listadetarefas.api
  3. Adicione as seguintes dependĂŞncias (Dependencies):
    • Spring Web, Spring Data JPA, H2 Database, Lombok.
  4. Clique em GENERATE, baixe o projeto, descompacte-o e abra na sua IDE.

Estrutura Inicial de Pastas

Após criar o projeto, sua estrutura de pastas principal será:

listadetarefas-api/
├── src/
│   └── main/
│       ├── java/
│       │   └── br/com/curso/listadetarefas/api/
│       │       └── ListadetarefasApiApplication.java
│       └── resources/
│           └── application.properties
└── pom.xml

### ⚙️ Passo 2: Configuração do Projeto

Abra o arquivo src/main/resources/application.properties e substitua seu conteĂşdo por este:

# Permite que o servidor aceite conexões de qualquer endereço de rede da máquina.
server.address=0.0.0.0

# Habilita o console web do H2
spring.h2.console.enabled=true
# Define o caminho para acessar o console
spring.h2.console.path=/h2-console

# Configurações do Datasource para H2
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

### 📝 Passo 3: Modelagem dos Dados

Vamos definir a estrutura da nossa tabela de tarefas.

Diagrama Entidade-Relacionamento (ER)

erDiagram
    TB_TAREFAS {
        BIGINT id PK "Auto-incremento"
        VARCHAR descricao
        BOOLEAN concluida
    }
  1. Dentro de src/main/java/br/com/curso/listadetarefas/api, crie um novo pacote chamado tarefa.
  2. Dentro do pacote tarefa, crie a classe Tarefa.java.
// src/main/java/br/com/curso/listadetarefas/api/tarefa/Tarefa.java
package br.com.curso.listadetarefas.api.tarefa;

import jakarta.persistence.*;
import lombok.Data;

@Data
@Entity
@Table(name = "tb_tarefas")
public class Tarefa {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String descricao;
    private boolean concluida;
}

Estrutura de Pastas Após a Criação do Modelo

api/
└── src/main/java/br/com/curso/listadetarefas/api/
    ├── tarefa/
    │   └── Tarefa.java  # <- Arquivo criado
    └── ListadetarefasApiApplication.java

### 🏗️ Passo 4: Construção das Camadas de Serviço

Agora, criaremos as classes que formam a arquitetura da nossa API: Repository (acesso a dados), Service (regras de negĂłcio) e Controller (endpoints HTTP).

Diagrama de Classes

classDiagram
    TarefaController ..> TarefaService : Usa
    TarefaService ..> TarefaRepository : Usa
    TarefaRepository ..> Tarefa : Gerencia
    class TarefaController {
        +List~Tarefa~ listarTarefas()
        +Tarefa criarTarefa(Tarefa)
        +ResponseEntity~Tarefa~ atualizarTarefa(Long, Tarefa)
        +ResponseEntity~Void~ deletarTarefa(Long)
    }
    class TarefaService {
        +List~Tarefa~ listarTodas()
        +Tarefa criar(Tarefa)
        +Tarefa atualizar(Long, Tarefa)
        +void deletar(Long)
    }
    class TarefaRepository {
        <<Interface>>
    }
    class Tarefa {
        -Long id
        -String descricao
        -boolean concluida
    }
  1. Dentro do pacote tarefa, crie as seguintes classes e interfaces:

TarefaRepository.java

package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TarefaRepository extends JpaRepository<Tarefa, Long> {
}

TarefaService.java

package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class TarefaService {
    @Autowired
    private TarefaRepository tarefaRepository;

    public List<Tarefa> listarTodas() { return tarefaRepository.findAll(); }
    public Tarefa criar(Tarefa tarefa) { return tarefaRepository.save(tarefa); }
    public Tarefa atualizar(Long id, Tarefa tarefaAtualizada) {
        return tarefaRepository.findById(id)
            .map(tarefaExistente -> {
                tarefaExistente.setDescricao(tarefaAtualizada.getDescricao());
                tarefaExistente.setConcluida(tarefaAtualizada.isConcluida());
                return tarefaRepository.save(tarefaExistente);
            }).orElseThrow(() -> new RuntimeException("Tarefa nĂŁo encontrada com o id: " + id));
    }
    public void deletar(Long id) {
        if (!tarefaRepository.existsById(id)) {
            throw new RuntimeException("Tarefa nĂŁo encontrada com o id: " + id);
        }
        tarefaRepository.deleteById(id);
    }
}

TarefaController.java

package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/api/tarefas")
@CrossOrigin(origins = "*")
public class TarefaController {
    @Autowired
    private TarefaService tarefaService;

    @GetMapping
    public List<Tarefa> listarTarefas() { return tarefaService.listarTodas(); }
    @PostMapping
    public Tarefa criarTarefa(@RequestBody Tarefa tarefa) { return tarefaService.criar(tarefa); }
    @PutMapping("/{id}")
    public ResponseEntity<Tarefa> atualizarTarefa(@PathVariable Long id, @RequestBody Tarefa tarefa) {
        try {
            Tarefa atualizada = tarefaService.atualizar(id, tarefa);
            return ResponseEntity.ok(atualizada);
        } catch (RuntimeException e) {
            return ResponseEntity.notFound().build();
        }
    }
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deletarTarefa(@PathVariable Long id) {
        try {
            tarefaService.deletar(id);
            return ResponseEntity.noContent().build();
        } catch (RuntimeException e) {
            return ResponseEntity.notFound().build();
        }
    }
}

Estrutura de Pastas Final do Backend

api/
└── src/main/java/br/com/curso/listadetarefas/api/
    ├── tarefa/
    │   ├── Tarefa.java
    │   ├── TarefaController.java
    │   ├── TarefaRepository.java
    │   └── TarefaService.java
    └── ListadetarefasApiApplication.java

### ✅ Passo 5: Execução e Teste da API

Diagrama de Casos de Uso da API

usecaseDiagram
    Usuário as "Usuário (via Cliente)"
    package "Sistema de Tarefas" {
        usecase "Listar todas as tarefas" as UC1
        usecase "Adicionar nova tarefa" as UC2
        usecase "Atualizar uma tarefa" as UC3
        usecase "Deletar uma tarefa" as UC4
    }
    Usuário --> UC1
    Usuário --> UC2
    Usuário --> UC3
    Usuário --> UC4
  1. Execute a Aplicação:

    • Na sua IDE, execute a classe ListadetarefasApiApplication.java.
    • Ou, via terminal na raiz do projeto: ./mvnw spring-boot:run
  2. Teste com Cliente REST (ex: Postman):

    • Use um cliente REST para fazer requisições para http://localhost:8080/api/tarefas e verifique todas as operações de CRUD (GET, POST, PUT, DELETE) como detalhado no guia anterior.
  3. Teste com o Console H2:

    • Com a API rodando, acesse http://localhost:8080/h2-console no navegador.
    • Use as seguintes credenciais para logar:
      • JDBC URL: jdbc:h2:mem:testdb
      • User Name: sa
      • Password: (em branco)
    • ApĂłs criar tarefas via API, execute o comando SQL SELECT * FROM TB_TAREFAS; para ver os dados diretamente no banco.

đź’» MĂłdulo 2: Cliente Web com Angular (listadetarefas-web)

Objetivo: Criar uma interface web moderna e reativa para interagir com a API.

🛠️ Ferramentas Necessárias

### 📂 Passo 1: Criação do Projeto

  1. No terminal, crie o projeto:
    ng new listadetarefas-web --standalone --style=css
    
  2. Navegue até a pasta cd listadetarefas-web.
  3. Gere os arquivos necessários:
    ng generate interface models/tarefa
    ng generate service services/tarefa
    ng generate component components/task-list
    

Estrutura de Pastas Após Geração

listadetarefas-web/
└── src/
    └── app/
        ├── components/
        │   └── task-list/
        │       ├── task-list.component.css
        │       ├── task-list.component.html
        │       └── task-list.component.ts
        ├── models/
        │   └── tarefa.ts
        └── services/
            └── tarefa.service.ts

### ✍️ Passo 2: Codificação do Cliente Web

Siga os passos e use os cĂłdigos fornecidos no guia anterior para os seguintes arquivos:

### 🔗 Passo 3: Integração Final

Para corrigir o erro 'app-task-list' is not a known element', integre o componente principal:

  1. Configure o HttpClient: Verifique se provideHttpClient(withFetch()) está em src/app/app.config.ts.
  2. Importe o Componente: Altere o src/app/app.component.ts para importar e usar o TaskListComponent:
// src/app/app.component.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { TaskListComponent } from './components/task-list/task-list.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ RouterOutlet, TaskListComponent ], // Importado aqui
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent { }
  1. Atualize o Template Principal: Limpe o src/app/app.component.html e adicione apenas:
<app-task-list></app-task-list>

### ✅ Passo 4: Execução e Teste

  1. Pré-requisito: A API backend deve estar rodando.
  2. Execute: No terminal (na pasta listadetarefas-web), rode ng serve --open.
  3. Teste: Abra as ferramentas de desenvolvedor do navegador (F12) e teste todas as funcionalidades: adicionar, editar com duplo clique, marcar como concluĂ­da e deletar.

🚀 ricardotecpro.github.io