# Aula 2.2 - Condições e repetições

## Identificação

- **Duração:** 2 horas
- **Tipo:** teoria aplicada e laboratório
- **Entrega:** classificador interativo de tarefas
- **Laboratório:** [`../exemplos/aula-2.2/index.html`](../exemplos/aula-2.2/index.html)

## Introdução

### Por que um programa precisa tomar decisões?

Um programa raramente executa sempre exatamente o mesmo caminho. Ele precisa observar
os dados e decidir o que fazer:

- se o formulário estiver inválido, mostrar uma orientação;
- se o usuário estiver autenticado, liberar a área privada;
- se uma tarefa for urgente e importante, classificá-la como prioridade crítica;
- se não houver tarefas, apresentar um estado vazio.

Em JavaScript, representamos essas decisões principalmente com `if`, `else if`,
`else` e `switch`.

```js
const isFormValid = true;

if (isFormValid) {
  console.log("O formulário pode ser enviado.");
} else {
  console.log("Revise os campos.");
}
```

### O que é uma condição?

Uma condição é uma expressão analisada como verdadeira ou falsa. O resultado orienta
qual trecho do programa será executado.

```js
const remainingDays = 2;
const isUrgent = remainingDays <= 2;

if (isUrgent) {
  console.log("Prioridade alta");
}
```

Não confunda **condição** com **repetição**:

- uma condição escolhe um caminho;
- uma repetição executa uma ação várias vezes enquanto uma regra permitir.

### Por que repetir instruções?

Imagine que existam cinquenta tarefas. Escrever cinquenta comandos manualmente não
seria sustentável. Uma estrutura de repetição, também chamada de *loop* ou *laço*,
percorre os dados:

```js
const tasks = ["Estudar JavaScript", "Revisar HTML", "Publicar projeto"];

for (const task of tasks) {
  console.log(task);
}
```

O loop não cria dados sozinho. Ele define como o programa visita uma sequência ou
repete uma operação.

### Preciso decorar todos os tipos de loop?

Não. O mais importante é reconhecer a intenção:

- `for...of`: percorrer valores de uma coleção;
- `for`: controlar índice, início, limite e incremento;
- `while`: repetir enquanto uma condição for verdadeira;
- `do...while`: executar ao menos uma vez e depois verificar;
- métodos de arrays, estudados na Aula 2.4, expressam transformações comuns.

### Onde isso aparece no projeto?

Nesta aula construiremos um classificador de tarefas. Cada tarefa passará por
condições que determinam sua prioridade. Depois, um loop atualizará a lista e as
métricas exibidas na página.

## Objetivos

Ao final da aula, o aluno deverá conseguir:

1. explicar o que é fluxo de controle;
2. criar condições booleanas explícitas;
3. utilizar `if`, `else if` e `else`;
4. combinar condições com operadores lógicos;
5. aplicar o operador ternário em decisões pequenas;
6. utilizar `switch` para valores discretos;
7. diferenciar `for`, `for...of`, `while` e `do...while`;
8. evitar loops infinitos;
9. utilizar `break` e `continue` conscientemente;
10. classificar e percorrer tarefas em uma interface.

## Pré-requisitos

- Aula 2.1 concluída;
- conhecimento de valores, tipos, comparações e operadores lógicos;
- navegador, DevTools e editor de código;
- noções de eventos e manipulação do DOM vistas no Módulo 1.

## Pergunta orientadora

> Como fazer o programa escolher caminhos e processar vários itens sem duplicar código?

## Roteiro sugerido

| Etapa | Duração |
|---|---:|
| Introdução e fluxo de controle | 15 min |
| Condições com `if` e operadores lógicos | 30 min |
| `switch` e operador ternário | 15 min |
| Estruturas de repetição | 30 min |
| Laboratório | 25 min |
| Revisão | 5 min |

## 1. Fluxo de controle

O código é lido normalmente de cima para baixo. Estruturas de controle alteram esse
fluxo:

```js
const hasPermission = false;

console.log("Início");

if (hasPermission) {
  console.log("Área privada");
}

console.log("Fim");
```

Como `hasPermission` é `false`, a linha dentro do bloco não é executada.

Um bloco é delimitado por chaves:

```js
if (condition) {
  // bloco executado quando a condição for verdadeira
}
```

Mesmo quando existe apenas uma instrução, mantenha as chaves. Elas tornam o limite
da decisão visível e reduzem erros durante futuras alterações.

## 2. `if`, `else if` e `else`

### Uma decisão

```js
const taskIsLate = true;

if (taskIsLate) {
  console.log("Tarefa atrasada");
}
```

### Dois caminhos

```js
const isAuthenticated = false;

if (isAuthenticated) {
  console.log("Abrir painel");
} else {
  console.log("Solicitar login");
}
```

### Vários caminhos

```js
const score = 82;

if (score >= 90) {
  console.log("Excelente");
} else if (score >= 70) {
  console.log("Aprovado");
} else {
  console.log("Revisão necessária");
}
```

A ordem importa. O primeiro teste verdadeiro encerra a cadeia. Por isso, nesse caso
verificamos primeiro a maior nota.

## 3. Condições claras

Prefira nomes que revelem o significado da regra:

```js
const remainingDays = 1;
const isUrgent = remainingDays <= 2;
const hasDeadline = remainingDays >= 0;

if (hasDeadline && isUrgent) {
  console.log("Tratar com prioridade");
}
```

Isso costuma ser mais claro que concentrar tudo em uma expressão longa:

```js
if (remainingDays >= 0 && remainingDays <= 2) {
  console.log("Tratar com prioridade");
}
```

As duas versões funcionam. A primeira facilita explicar e testar a regra.

## 4. Operadores lógicos nas decisões

### E lógico: `&&`

Todas as condições precisam ser verdadeiras:

```js
if (isUrgent && isImportant) {
  console.log("Faça agora");
}
```

### OU lógico: `||`

Ao menos uma condição precisa ser verdadeira:

```js
if (isLate || isBlocked) {
  console.log("Requer atenção");
}
```

### Negação: `!`

Inverte o valor booleano:

```js
if (!hasTitle) {
  console.log("Informe um título");
}
```

Use parênteses quando eles tornarem a intenção mais evidente:

```js
if (isActive && (isAdmin || isOwner)) {
  console.log("Acesso permitido");
}
```

## 5. Truthy e falsy em condições

Uma condição não precisa receber literalmente `true` ou `false`. JavaScript converte
outros valores para booleano:

```js
const title = "";

if (title) {
  console.log("Existe um título");
}
```

Como string vazia é *falsy*, o bloco não é executado.

Para regras importantes, deixe a intenção explícita:

```js
const hasTitle = title.trim().length > 0;

if (!hasTitle) {
  console.log("O título é obrigatório");
}
```

Isso evita confundir valores válidos como `0` com ausência de valor.

## 6. Comparar não é atribuir

Observe os operadores:

```js
const status = "done"; // atribuição durante a declaração

if (status === "done") { // comparação estrita
  console.log("Concluída");
}
```

Dentro de condições, prefira `===` e `!==`. Um sinal de igual isolado atribui um
valor; não representa uma comparação.

## 7. Operador ternário

O ternário representa uma escolha curta que produz um valor:

```js
const label = isUrgent ? "Urgente" : "Normal";
```

Sua estrutura é:

```text
condição ? valor_se_verdadeira : valor_se_falsa
```

Use-o para decisões pequenas. Para regras com vários passos, prefira `if`:

```js
let priority;

if (isUrgent && isImportant) {
  priority = "critical";
} else if (isUrgent) {
  priority = "high";
} else {
  priority = "normal";
}
```

Ternários aninhados rapidamente ficam difíceis de ler.

## 8. `switch`

`switch` é útil quando uma mesma expressão pode ter valores discretos:

```js
const status = "doing";

switch (status) {
  case "todo":
    console.log("A fazer");
    break;
  case "doing":
    console.log("Em andamento");
    break;
  case "done":
    console.log("Concluída");
    break;
  default:
    console.log("Status desconhecido");
}
```

O `break` encerra o `switch`. Sem ele, a execução continua no próximo `case`,
comportamento chamado de *fall-through*.

Use:

- `if` quando as regras usam intervalos ou expressões diferentes;
- `switch` quando comparamos uma expressão a alternativas conhecidas.

## 9. Repetição com `for`

O `for` reúne inicialização, condição e atualização:

```js
for (let index = 0; index < 3; index += 1) {
  console.log(index);
}
```

Leitura:

1. `let index = 0`: começa em zero;
2. `index < 3`: repete enquanto for verdadeiro;
3. `index += 1`: aumenta o índice ao final de cada volta.

Saída:

```text
0
1
2
```

Arrays começam no índice zero:

```js
const tasks = ["Estudar", "Praticar", "Revisar"];

for (let index = 0; index < tasks.length; index += 1) {
  console.log(index, tasks[index]);
}
```

## 10. Repetição com `for...of`

Quando precisamos dos valores, e não do índice, `for...of` costuma ser mais simples:

```js
const tasks = ["Estudar", "Praticar", "Revisar"];

for (const task of tasks) {
  console.log(task);
}
```

Não confunda:

- `for...of` percorre valores de objetos iteráveis, como arrays e strings;
- `for...in` percorre nomes de propriedades enumeráveis e não é a escolha usual
  para percorrer valores de arrays.

## 11. Repetição com `while`

`while` repete enquanto a condição for verdadeira:

```js
let attempts = 0;

while (attempts < 3) {
  console.log(`Tentativa ${attempts + 1}`);
  attempts += 1;
}
```

Ele é útil quando não sabemos antecipadamente quantas repetições serão necessárias,
mas sabemos qual condição deve encerrar o processo.

### Risco de loop infinito

Este código nunca altera `attempts`:

```js
let attempts = 0;

while (attempts < 3) {
  console.log(attempts);
}
```

A condição permanece verdadeira indefinidamente. Antes de escrever um `while`,
responda:

> O que muda a cada volta e como a condição se tornará falsa?

## 12. Repetição com `do...while`

`do...while` executa o bloco pelo menos uma vez:

```js
let option;

do {
  option = "continue";
} while (option === "retry");
```

A condição é verificada depois do bloco. Em interfaces web, eventos frequentemente
substituem a necessidade desse tipo de loop, pois cada nova interação do usuário
dispara outra execução.

## 13. `break` e `continue`

### `break`

Encerra o loop:

```js
for (const task of tasks) {
  if (task.id === searchedId) {
    console.log("Tarefa encontrada");
    break;
  }
}
```

### `continue`

Pula apenas a volta atual:

```js
for (const task of tasks) {
  if (task.status === "done") {
    continue;
  }

  console.log(task.title);
}
```

Use ambos com moderação. Muitos desvios dentro do loop dificultam acompanhar o
fluxo.

## 14. Regra do classificador

O laboratório utiliza urgência e importância:

| Urgente | Importante | Classificação | Orientação |
|---|---|---|---|
| sim | sim | crítica | faça agora |
| sim | não | alta | resolva ou delegue |
| não | sim | planejada | reserve um horário |
| não | não | baixa | reavalie a necessidade |

Uma implementação direta:

```js
let priority;

if (isUrgent && isImportant) {
  priority = "critical";
} else if (isUrgent) {
  priority = "high";
} else if (isImportant) {
  priority = "planned";
} else {
  priority = "low";
}
```

O laboratório também utiliza `switch` para traduzir o status e `for...of` para
renderizar as tarefas e calcular métricas.

## 15. Laboratório guiado

Abra o [classificador de tarefas](../exemplos/aula-2.2/index.html).

### Etapa 1 — Observe a decisão

1. preencha um título;
2. marque urgência e importância;
3. selecione um status;
4. adicione a tarefa;
5. compare a classificação com a tabela de regras.

### Etapa 2 — Observe a repetição

Adicione mais tarefas. A cada mudança, o programa percorre a coleção para:

- criar os cartões visuais;
- contar o total;
- contar prioridades críticas;
- contar tarefas concluídas.

### Etapa 3 — Inspecione o código

Abra `assets/main.js` e localize:

1. a cadeia `if / else if / else`;
2. o `switch` que traduz o status;
3. os loops `for...of`;
4. a condição que mostra o estado vazio;
5. a validação do título.

### Etapa 4 — Faça uma alteração

Adicione uma regra visual para tarefas com duração maior que quatro horas. Antes de
editar, escreva a condição em português:

> Se a estimativa for maior que quatro horas, mostrar “Divida em partes menores”.

Depois transforme-a em JavaScript.

## 16. Erros comuns

### Usar atribuição no lugar de comparação

```js
if (status = "done") {
  // incorreto para comparar
}
```

Use:

```js
if (status === "done") {
}
```

### Criar condições impossíveis

```js
if (score < 0 && score > 100) {
}
```

Um mesmo número não pode ser simultaneamente menor que zero e maior que cem.

### Errar o limite do loop

```js
for (let index = 0; index <= tasks.length; index += 1) {
  console.log(tasks[index]);
}
```

O último índice válido é `length - 1`. Portanto:

```js
for (let index = 0; index < tasks.length; index += 1) {
}
```

### Alterar a coleção durante a repetição sem planejamento

Adicionar ou remover itens do mesmo array que está sendo percorrido pode mudar
índices e produzir resultados inesperados. Primeiro compreenda a regra; na Aula 2.4
veremos transformações imutáveis.

### Bloquear a página com um loop

JavaScript da interface normalmente executa na thread principal. Um loop infinito
impede cliques, desenho e outras interações. Se a aba travar durante um exercício,
interrompa a execução pelo DevTools e revise a condição de saída.

## 17. Boas práticas

- dê nomes claros às condições;
- prefira comparações estritas;
- ordene cadeias de decisão do caso específico para o geral;
- mantenha um `else` ou `default` quando existir um caso de fallback;
- deixe visível como o loop termina;
- evite duplicar a mesma regra em vários lugares;
- teste limites: zero, vazio, primeiro item, último item e valor máximo;
- não use loops longos para bloquear deliberadamente a interface.

## 18. Exercícios

### Exercício 1 — Faixa de estimativa

Classifique uma tarefa:

- até 1 hora: curta;
- acima de 1 e até 4 horas: média;
- acima de 4 horas: longa.

### Exercício 2 — Contagem

Crie um loop que conte quantas tarefas ainda não estão concluídas.

### Exercício 3 — Busca

Percorra uma lista e interrompa o loop com `break` quando encontrar uma tarefa pelo
identificador.

### Exercício 4 — Validação

Rejeite títulos vazios ou formados apenas por espaços.

### Exercício 5 — Regra combinada

Marque como “atenção” uma tarefa que esteja atrasada **ou** bloqueada, desde que
ela ainda não esteja concluída.

## 19. Desafio

Acrescente ao laboratório:

- filtro por prioridade;
- botão para concluir uma tarefa;
- mensagem específica para tarefas longas;
- contador de tarefas em andamento;
- teste manual documentado para cada combinação de urgência e importância.

Não utilize `innerHTML` para inserir dados do usuário. Crie elementos e atribua
conteúdo com `textContent`.

## 20. Lista de verificação de conclusão

- [ ] Sei explicar condição e repetição com minhas palavras.
- [ ] Consigo escolher entre `if` e `switch`.
- [ ] Entendo a ordem de uma cadeia `else if`.
- [ ] Consigo usar `&&`, `||` e `!` em regras.
- [ ] Sei quando um ternário fica complexo demais.
- [ ] Consigo percorrer valores com `for...of`.
- [ ] Sei identificar a condição de saída de um `while`.
- [ ] Entendo os efeitos de `break` e `continue`.
- [ ] Testei as quatro combinações do classificador.
- [ ] Inspecionei a interface pelo DevTools.

## 21. Critérios de avaliação

| Critério | Pontos |
|---|---:|
| Condições corretas e legíveis | 30 |
| Repetição e métricas | 25 |
| Validação e estados da interface | 20 |
| Acessibilidade e segurança do DOM | 15 |
| Explicação das escolhas | 10 |
| **Total** | **100** |

## Resumo

Nesta aula, aprendemos que:

- condições escolhem caminhos;
- loops repetem operações;
- a ordem das regras altera o resultado;
- `for...of` é uma opção clara para percorrer valores;
- todo `while` precisa de uma condição que possa se tornar falsa;
- interfaces devem comunicar validação, estado vazio e resultado;
- regras legíveis são mais fáceis de testar e manter.

## Próxima aula

Na Aula 2.3, organizaremos regras em funções, entenderemos parâmetros e retorno e
estudaremos como escopo e closures controlam o acesso aos valores.
