Desafio JavaScript

Relatório de produtos com formatação

Enunciado

Dado um array de objetos produtos (cada um com nome, preco e quantidade), crie uma função gerarRelatorio(produtos) que retorna uma string formatada em múltiplas linhas usando template literals. Cada linha deve seguir o formato: [nome]: [quantidade] unidades - Total: R$ [preco * quantidade com 2 casas decimais] No final, adicione uma linha com o valor total geral. Use métodos de string para deixar o nome em maiúsculas e remover espaços extras.

Requisitos

  • Usar template literals com interpolação e múltiplas linhas.
  • Usar toUpperCase() e trim() nos nomes.
  • Calcular total por produto e total geral com toFixed(2).
  • Retornar uma única string com quebras de linha (\n).

Código inicial

function gerarRelatorio(produtos) {
  // Seu código aqui
}

const produtos = [
  { nome: "  caneta  ", preco: 2.5, quantidade: 10 },
  { nome: "Lápis", preco: 1.2, quantidade: 5 },
  { nome: "borracha", preco: 3.0, quantidade: 2 }
];

console.log(gerarRelatorio(produtos));

Saída esperada

CANETA: 10 unidades - Total: R$ 25.00
LÁPIS: 5 unidades - Total: R$ 6.00
BORRACHA: 2 unidades - Total: R$ 6.00
Total geral: R$ 37.00
Ver dica

Use map para gerar as linhas e join('\n') para uni-las. Acumule o total geral em uma variável.

Mostrar solução
function gerarRelatorio(produtos) {
  let totalGeral = 0;
  const linhas = produtos.map(produto => {
    const nome = produto.nome.trim().toUpperCase();
    const total = produto.preco * produto.quantidade;
    totalGeral += total;
    return `${nome}: ${produto.quantidade} unidades - Total: R$ ${total.toFixed(2)}`;
  });
  linhas.push(`Total geral: R$ ${totalGeral.toFixed(2)}`);
  return linhas.join('\n');
}

const produtos = [
  { nome: "  caneta  ", preco: 2.5, quantidade: 10 },
  { nome: "Lápis", preco: 1.2, quantidade: 5 },
  { nome: "borracha", preco: 3.0, quantidade: 2 }
];

console.log(gerarRelatorio(produtos));

Passo a passo

  1. Inicializamos totalGeral como 0 para acumular o valor de todos os produtos.
  2. Usamos produtos.map() para iterar e criar um array de strings formatadas.
  3. Para cada produto, nome.trim().toUpperCase() limpa e padroniza o nome.
  4. Calculamos total = preco * quantidade e adicionamos a totalGeral.
  5. O template literal monta a linha com os valores interpolados e toFixed(2) formata o preço.
  6. Após o map, adicionamos a linha do total geral com push.
  7. join('\n') une todas as linhas em uma única string com quebras de linha.

Por que funciona

A imutabilidade das strings garante que trim() e toUpperCase() não alterem os nomes originais. O template literal permite interpolar expressões complexas e criar múltiplas linhas sem concatenação. O acúmulo do total geral é feito com uma variável externa ao map.

Erros comuns

  • Esquecer de inicializar totalGeral antes do map.
  • Usar forEach em vez de map e tentar retornar (forEach não retorna array).
  • Não usar toFixed(2) e obter números com muitas casas decimais.
  • Modificar o array original com sort ou reverse sem necessidade.

Outra forma de resolver

Usar reduce para acumular as linhas e o total:

const { linhas, total } = produtos.reduce((acc, p) => {
  const nome = p.nome.trim().toUpperCase();
  const totalProd = p.preco * p.quantidade;
  acc.linhas.push(`${nome}: ${p.quantidade} unidades - Total: R$ ${totalProd.toFixed(2)}`);
  acc.total += totalProd;
  return acc;
}, { linhas: [], total: 0 });
linhas.push(`Total geral: R$ ${total.toFixed(2)}`);
return linhas.join('\n');

Mas a versão com map é mais simples.

Saída esperada

CANETA: 10 unidades - Total: R$ 25.00
LÁPIS: 5 unidades - Total: R$ 6.00
BORRACHA: 2 unidades - Total: R$ 6.00
Total geral: R$ 37.00