Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Projeto] Amigo Secreto

Minha solução não sei se é das melhores preciso assistir as aulas agora. Dei uma atualizada no código depois dos desafios mas preferi fazer do meu jeito ao invés da implementação do instrutor para praticar melhor a manipulação do DOM quebrei um pouco a cabeça mais deu certo.

let friends = [];
const clearInput = (id) => { document.getElementById(id).value = '';} 

function add() {
    let friendName = document.getElementById('nome-amigo').value;
    if(friendName === '') {
        alert('Digite um nome');
        clearInput('nome-amigo');
        return;
    }
    if(friends.includes(friendName)){
        alert('Esse nome já foi adicionado');
        clearInput('nome-amigo');
        return;
    }
    friends.push(friendName)

    // Update the DOM with the list of names
    updateFriendList(friendName);

    // Clear the input field after adding friend name
    clearInput('nome-amigo');
}

function draw() {
    clearInput('nome-amigo');
    // Get the div where i need to populate the pairs that are draw
    let drawFriends = document.querySelector('.prizeDraw__container');
    // Clear any previous elements inside it
    drawFriends.textContent = '';
    // Check if we have at least 3 people so we can make a pair
     if (friends.length < 3) {
        alert('Precisa adicionar ao menos três nomes!');
        return;
    }

    let shuffledFriends = shuffle(friends); // Shuffle the array
    // Create a new air to pair people
    let pairs = [];
    // Loop to go from start 0 to array.lenght-1
    for(let i = 0; i < shuffledFriends.length; i++) {
        // Pair the current index to the next one and check with modulo if you are at the end so you can pair the last with the first
        let pairIndex = (i + 1) % shuffledFriends.length;
        // push the pair to the array
        pairs.push(`${shuffledFriends[i]} -> ${shuffledFriends[pairIndex]}`);
        // Create a new <p> to start manipulating the DOM to display each pair
        let pairElement = document.createElement('p');
        pairElement.textContent = pairs[i];
        drawFriends.appendChild(pairElement);
    }
}

function reset() {
    friends = [];
    document.querySelector('.friends__container').textContent = "";
    document.querySelector('.prizeDraw__container').textContent = '';
    clearInput('nome-amigo');
}

// Fisher-Yates Shuffle swapping i starting at the end of the array with a random j index generated by math.random
function shuffle(array) {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
}

function updateFriendList(friendName) {
    const friendsList = document.getElementById('lista-amigos');

        const friendElement = document.createElement('span');
        friendElement.textContent = friendName;
        // Add the 'friend-item' class to apply the new styles created
        friendElement.classList.add('friend-item');     
        // Add a click event to remove the name that was clicked
        friendElement.addEventListener('click', () => {
            removeFriend(friendName);
        });           
        // Append the span to the paragraph with id 'lista-amigos'
        console.log(friendsList,friendElement);
        friendsList.appendChild(friendElement);       

}

function removeFriend(friend) {
    // Remove the friend from the array
    friends = friends.filter(friend => friend !== friend);

    // Now, remove the span element from the DOM
    const friendsList = document.getElementById('lista-amigos');
    const friendElements = friendsList.getElementsByTagName('span');

    // Loop through all span elements and remove the one matching the friend to remove
    for (let i = 0; i < friendElements.length; i++) {
        if (friendElements[i].textContent === friend) {
            friendElements[i].remove();
            break; // Once we find and remove the element, stop the loop
        }
    }
}
2 respostas

Olá Israel!

Que legal que você está praticando a manipulação do DOM e criando sua própria versão do projeto de Amigo Secreto! Seu código parece bem estruturado e você está utilizando várias funções para manter tudo organizado. Vou te dar algumas dicas para melhorar ainda mais:

  1. Função removeFriend: Parece que há um pequeno erro na função removeFriend. No filtro, você está usando a mesma variável friend para o parâmetro e a comparação, o que pode causar um comportamento inesperado. Tente renomear o parâmetro da função para evitar a confusão, por exemplo:

    function removeFriend(friendToRemove) {
        friends = friends.filter(friend => friend !== friendToRemove);
        // Resto do código...
    }
    
  2. Validação de Entrada: No seu código, você verifica se o campo de entrada está vazio antes de adicionar um amigo. Isso é ótimo! Você também pode considerar adicionar uma verificação para remover espaços extras no início ou no fim do nome usando trim():

    let friendName = document.getElementById('nome-amigo').value.trim();
    
  3. Comentários: Seus comentários são claros e ajudam a entender o que cada parte do código faz. Isso é uma boa prática, continue assim!

  4. Interface do Usuário: Se você quiser melhorar a experiência do usuário, pode adicionar um feedback visual quando um amigo é adicionado ou removido. Por exemplo, mudar a cor do texto ou adicionar uma animação.

  5. Testes: Teste seu código com diferentes cenários, como adicionar nomes repetidos ou tentar sortear com menos de três amigos, para garantir que todas as validações estão funcionando corretamente.

Espero ter ajudado e bons estudos!

solução!

Não sei quase nada sobre CSS mas tentei seguir as suas sugestões se não for um incomodo poderia avaliar fiz um deploy no vercel https://secret-santa-one-theta.vercel.app/ obrigado.

  1. Função realmente não me atentei que o parametro recebido friend ficava com o mesmo nome obrigado por pontuar, modificação realizada.

  2. Validação de Entrada obrigado pela dica isso elimina a necessidade de condicionais diferentes se o input fosse algo como uma string com varios espaços eliminando também qualquer espaço adicionais nos nomes.

  3. Apesar de entender quase nada sobre estilos .CSS tentei seguir suas sugestões eu até adicionei um fade-out e uma cor vermelha para quando remover, porém como também tem um hover mouse que muda a cor para um azul escuro se não tirar o mouse a cor não ficará vísivel mas pelo menos o efeito fadeout fica.

  4. Testes: Adicionei conforme as aulas e o seu comentário usei .toLowerCase para eliminar a questão do case sensitive no nome digitado na tela e usei o some que retorna um boolean também usando os valores do array para lower case.

Aqui estão os trechos alterados e o css adicionado

function removeFriend(friendToRemove) {
    // Remove the friend from the array
    friends = friends.filter(friend => friend !== friendToRemove);
    
    // código omitido 
    
    if (friendElements[i].textContent === friendToRemove) {

            // When a friend is removed uses CSS class with different color and fade-out animation
            friendElements[i].classList.add('removed');

            // Need to wait so added EventListener to wait for the fade-out animation to end before actually removing the element
            friendElements[i].addEventListener('animationend', () => {
                friendElements[i].remove();
            });
function updateFriendList(friendName) {
    //código omitido
    
         // Add the 'friend-item' class to apply the new styles created
        friendElement.classList.add('friend-item');   
        
    //código omitido
    
         // When a friend is added uses CSS class with different color and fade-in animation
        friendElement.classList.add('added');
function add() {
    let friendName = document.getElementById('nome-amigo').value.trim();
    
    //código omitido
    
     // Convert input name to lowercase for case-insensitive comparison
    let lowerCaseFriendName = friendName.toLowerCase();
    //Use some which returns true or false converting to Lower case to avoid dublicates due to case sensitive and compare the input also converted to lower case
    if(friends.some(friend => friend.toLowerCase() === lowerCaseFriendName)) {

CSS:

/* Add styles for adding/removing friends */
.friend-item {
  margin: 5px;
  padding: 5px;
  display: inline-block;
  background-color: #100773;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.3s ease;
}

/* When the item is hovered */
.friend-item:hover {
  background-color: #0a0447;
  transform: scale(1.1);
}

/* Adding and removing a friend with animation */
.added {
  background-color: #80e0a7;
  animation: fadeIn 0.5s ease-out;
}

.removed {
  background-color: #e33b3b;
  animation: fadeOut 0.5s ease-out;
}

/* Fade-in animation for adding */
@keyframes fadeIn {
  from {
      opacity: 0;
  }
  to {
      opacity: 1;
  }
}

/* Fade-out animation for removing */
@keyframes fadeOut {
  from {
      opacity: 1;
  }
  to {
      opacity: 0;
  }
}

.friend-item:not(:last-child)::after {
  content: ', ';
}