Consultas: pesquisar, filtrar e ordenar
Com muitos clientes, encontrar um deles é difícil. Hoje crias uma barra de pesquisa, um filtro por estado e a ordenação por nome: as mesmas operações que uma base de dados faz com SQL.
🎯 No fim desta aula vais conseguir
- Explicar o que é uma consulta: filtrar e ordenar os dados para responder a uma pergunta.
- Pesquisar texto sem ligar a maiúsculas e minúsculas (
toLowerCase,includes). - Filtrar registos por estado, combinando condições com
&&e||. - Ordenar uma lista com
sortelocaleCompare. - Reconhecer o equivalente em SQL:
WHEREeORDER BY.
🧰 Antes de começar
- Abre a pasta
meu-crmno VS Code e oindex.htmlcom o Live Server. - Confirma que os botões ✏️ e 🗑️ da aula 9 funcionam.
- Para testar bem as consultas precisas de pelo menos 6 clientes, com estados diferentes e dois com o mesmo apelido. Se não tiveres, cria estes (só precisas de nome e estado): Ana Silva (Lead), Carlos Silva (Cliente), Bruno Matos (Inativo), Rita Sousa (Cliente), Zé Pinto (Lead), Marta Costa (Cliente).
😕 Faltaste à aula 9 ou o teu projeto não funciona? Descarrega o ponto de controlo da aula 9, descompacta-o e trabalha a partir dele.
Parte A — A barra de pesquisa (≈ 10 min)
1 A barra de pesquisa e os filtros
Por cima da tabela vamos pôr três controlos: uma caixa de pesquisa (type="search"), uma lista para escolher o estado e outra para escolher a ordem.
Repara nos «avisos» que cada um dá ao JavaScript:
oninput="desenharTabela()"— corre sempre que escreves ou apagas uma letra na caixa de pesquisa;onchange="desenharTabela()"— corre quando escolhes outra opção numa lista.
Nos dois casos, a tabela volta a ser desenhada.
✅ Deves ver: a barra com a caixa «🔎 Pesquisar por nome...» e as duas listas, por cima da tabela. Se escreveres, ainda não acontece nada: falta ensinar o JavaScript a fazer a consulta.
Parte B — A consulta: filtrar e ordenar (≈ 35 min)
2 A função que faz a consulta
Uma consulta é uma pergunta que fazes aos dados, por exemplo: «Quais são os Leads, por ordem alfabética?». Responder tem dois passos, que já conheces do Excel:
- Filtrar — ficar só com os registos que interessam (como o Filtro automático do Excel). Em SQL chama-se
WHERE. - Ordenar — pôr os registos pela ordem pedida (como Ordenar de A a Z). Em SQL chama-se
ORDER BY.
A função clientesVisiveis() não mexe na lista clientes: cria uma lista nova, resultado, com «fotocópias» só dos clientes que passam. Lê com atenção:
.toLowerCase()põe o texto todo em minúsculas. Assim, «SILVA», «Silva» e «silva» ficam iguais antes de comparar..includes(texto)dátruese o nome contém o texto pesquisado (em qualquer sítio, não só no início).estado === '' || cliente.estado === estadolê-se: «não escolheste estado (opção Todos os estados, que vale'') ou o estado do cliente é o escolhido».- Um cliente só entra no
resultadose passar nas duas condições (nomePassa && estadoPassa). resultado.sort((a, b) => a.nome.localeCompare(b.nome))é uma receita para ordenar por nome: osortcompara os clientes dois a dois (aeb) e olocaleComparediz qual vem primeiro, respeitando os acentos (o «Á» fica ao pé do «A»). Para a ordem inversa, basta trocaracomb.
🤔 Prevê: se escreveres só a letra a na pesquisa, que clientes vão aparecer? Só os que começam por A?
3 A tabela passa a mostrar só os «visíveis»
Falta uma mudança pequena, mas importante: a função desenharTabela() desenhava todos os clientes. Agora vai desenhar só os que a consulta devolve.
⚠️ Atenção: aqui só substituis uma linha. Dentro da função desenharTabela(), apaga só a linha for (const cliente of clientes) { e cola a nova no lugar dela. Não apagues a linha seguinte (html += linhaCliente(cliente);) nem a } que fecha o ciclo.
O ciclo deve ficar assim:
4 Testar
- Grava tudo e volta ao CRM.
- Escreve
silvana pesquisa, letra a letra. Depois apaga e escreveSILVA. - Apaga a pesquisa e escolhe o estado Lead. Depois Todos os estados.
- Muda a ordem para Nome (Z → A).
- Combina: pesquisa
a+ estado Cliente + ordem Z → A.
✅ Deves ver: a tabela muda enquanto escreves; «silva» e «SILVA» mostram os mesmos clientes; o filtro mostra só os clientes daquele estado; a ordem inverte. Ao apagar a pesquisa e escolher «Todos os estados», voltam todos.
😕 Não funciona?
- Abre a Consola (F12).
Cannot read properties of null (reading 'value')→ falta a barra do passo 1, ou umidestá diferente (têm de serpesquisa,filtro-estadoeordenacao). clientesVisiveis is not defined→ falta o passo 2 (ou não gravaste oapp.js).Unexpected token '}'ouUnexpected end of input→ no passo 3 apagaste ou duplicaste uma chaveta. Compara o teu ciclo com o exemplo do passo 3.- Escreves e nada muda, sem erros → falta o
oninput="desenharTabela()"na caixa, ou o passo 3 não foi feito (a tabela ainda desenhaclientes). - A tabela fica sempre vazia → confirma que a primeira opção do estado tem
value="".
Parte C — A ponte para o SQL (≈ 5 min)
5 A mesma consulta, em SQL
As empresas guardam os dados em bases de dados e fazem as consultas com uma linguagem chamada SQL. A consulta «os Leads, por ordem alfabética do nome» escreve-se assim:
Compara com o teu JavaScript:
| No teu JavaScript | Em SQL |
|---|---|
for (const cliente of clientes) | SELECT * FROM clientes |
cliente.estado === estado | WHERE estado = 'Lead' |
cliente.nome.toLowerCase().includes(texto) | WHERE nome LIKE '%silva%' |
sort((a, b) => a.nome.localeCompare(b.nome)) | ORDER BY nome |
sort((a, b) => b.nome.localeCompare(a.nome)) | ORDER BY nome DESC |
Na próxima aula vais escrever SQL a sério, numa base de dados dentro do browser.
🔎 Investiga
- Pesquisa
SILVAem maiúsculas. Porque é que encontra «Ana Silva», escrito com minúsculas? Que duas partes do código tornam isto possível? - Combina a pesquisa com o filtro de estado. Qual das duas condições tem de ser verdadeira para um cliente aparecer: uma delas ou as duas? Que operador decide isso?
- Na função
clientesVisiveis, apagaestado === '' ||e grava. O que acontece quando escolhes «Todos os estados»? Porquê? (Volta a pôr como estava!)
✍️ Exercícios (fazem parte do teu projeto)
Estes exercícios não têm o código pronto: usa o que aprendeste hoje.
E1 · Ordenar por data
Acrescenta à lista de ordenação duas opções: «Mais recentes primeiro» e «Mais antigos primeiro», que ordenam os clientes pela data de criação (criadoEm).
💡 Dica: cada <option> precisa de um value diferente (por exemplo recentes e antigos). Em clientesVisiveis, acrescenta mais dois casos como os do nome, mas com criadoEm. Como a data é um texto AAAA-MM-DD, o localeCompare também serve! Para os mais recentes primeiro, quem vem primeiro: a ou b?
💡 Para testar: os clientes criados hoje têm todos a mesma data. Muda a data de alguns na Consola, por exemplo: clientes[0].criadoEm = '2025-12-25'; guardar('clientes', clientes); desenharTabela(); (repete com clientes[1] e outra data).
E2 · Contagem por estado
Por baixo da barra de pesquisa, mostra uma linha como «Leads: 3 | Clientes: 5 | Inativos: 1», com os números certos de todos os clientes. Tem de se atualizar sempre que crias, editas ou apagas um cliente.
💡 Dica: cria um <p id="contagem-estados"></p>. Numa função nova, começa com três contadores a zero (let leads = 0;…), percorre a lista clientes com um ciclo e, com if / else if, soma 1 ao contador certo (leads++). No fim, escreve o texto com textContent. Onde deves chamar essa função para que se atualize sempre? (Lembra-te do E1 da aula 7.)
⭐ Desafio · Pesquisar também na empresa e no email
Faz com que a pesquisa encontre clientes também pelo nome da empresa e pelo email (por exemplo, escrever padaria encontra a cliente da «Padaria Silva»).
💡 Dica: é a linha const nomePassa = … que decide se a pesquisa passa. Junta mais condições com || («ou»), usando o mesmo .toLowerCase().includes(texto).
📦 O que mostrar ao professor
⏱️ Se sobrar tempo
- Faz o desafio ⭐ e muda o texto de ajuda da caixa para «🔎 Pesquisar...».
- Se fizeste o E2 da aula 7, pesquisa um nome que não existe: aparece «Ainda não há clientes.», o que não é verdade! Muda o código para mostrar «Nenhum cliente encontrado.» quando há clientes mas nenhum passa na pesquisa.
- Escreve no caderno a consulta SQL para «os clientes Inativos, por ordem de nome de Z a A».
🤖 Pedir ajuda à IA (opcional)
Se a ordenação com sort te parece magia, pede a uma IA gratuita que te explique como funciona, sem te dar código para o projeto:
📖 Palavras novas
- Consulta
- Pergunta feita aos dados, que devolve só os registos pedidos, pela ordem pedida.
- Filtrar
- Ficar só com os registos que cumprem uma condição (em SQL,
WHERE). - Ordenar
- Pôr os registos por uma ordem (em SQL,
ORDER BY). toLowerCase()- Devolve o texto todo em minúsculas.
includes(texto)- Diz se um texto contém outro (
trueoufalse). sortelocaleCompare- Ordenam uma lista; o
localeComparecompara textos respeitando os acentos. oninput/onchange- Avisos que correm código quando se escreve numa caixa / quando se escolhe outra opção.