Help needed for Error 14 on the Creature Search app!

Tell us what’s happening:

Hi, I cannot seems to find the problem with the way I handle things here., well at least concerning the only error preventing me from finishing this project!

I have the error 14 poppin up even though it doesn’t when I test it myself.

(14. When the #search-input element contains the value Red and the #search-button element is clicked, an alert should appear with the text “Creature not found”.)

this, albeit weirdly, should do the trick no ?

monster = monsterList.find(monster => monster.name === input);
if (!monster) {
alert(“Creature not found”);
}

Your code so far

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=0">
    <title>Creature Search App</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <div class="title"><h1>Creature Search App</h1></div>
    <div class="container">
      <div class="top">
        <input id="search-input" placeholder="type a creature name or id here" required></input>
        <button id="search-button" type="button">Search</button>
      </div>
      <div class="middle">
        <div class="middle-top" id="creature-name"></div>
        <div class="middle-bottom" id="creature-special">
          <div id="special-name"></div>
          <div id="special-function"></div>
        </div>
      </div>
      <div class="bottom">
        <div class="column">
          <div class="left stats">HP:<span id="hp"></span></div>
          <div class="left stats">Attack:<span id="attack"></span></div>
          <div class="left stats">Defense:<span id="defense"></span></div>
          <div class="left stats">Special-Attack:<span id="special-attack"></span></div>
          <div class="left stats">Special-Defense:<span id="special-defense"></span></div>
          <div class="left stats">Speed:<span id="speed"></span></div>
        </div>
        <div class="column">
          <div class="right stats">Creature-Id:<span id="creature-id"></span></div>
          <div class="right stats">Weight:<span id="weight"></span></div>
          <div class="right stats">Height:<span id="height"></span></div>
          <div class="right stats">Type:<span id="types"></span></div>
        </div>
      </div>
    </div>
  </body>
  <script src="script.js"></script>
</html>

/* file: styles.css */
:root {
  --dark: #191716;
  --yellow: #DCC48E;
  --blue: #B3C0A4;
  --white: #EAEFD3;
}
*,
*::after,
*::before {
  box-sizing: border-box; 
  margin: 0;
  padding: 0;
}
body {
  background-color: var(--dark);
  color: var(--white);
  padding: 80px;
  min-width: 500px
}
input {
  width : 80%;
  height: 20px;
  border-radius: 10px;
  border: none;
  padding-left: 8px;
}
button {
  border: none;
  width: 60px;
  height: 20px;
  border-radius: 10px;
}
button:hover {
  cursor: pointer;
}
.title {
  margin: auto;
  text-align: center;
  padding-bottom: 20px;
  font-size : 25px;
}
.container  {
  display: flex;
  align-items: center;
  flex-direction: column; 
  margin-top: 150px;
  border-radius: 15px;
  border: 5px solid var(--blue);
  height: 500px;
  width : 500px;
  margin : auto;
}
.top {
  background-color: var(--blue);
  width: 100%;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  border-radius: 5px 5px 0 0;
}
.middle {
  width: 100%;
  height: 120px;
  display: flex;
  align-items: center;
  flex-direction: column;
  background-color: var(--blue); 
}
.middle-top {
  width : 100%;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  font-weight: 900;
  color: var(--dark);
}
.middle-bottom {
  width : 80%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  font-size: 18px;
  font-weight: 900;
  color: var(--dark);
  background-color: var(--white);
  border-radius: 5px;
}
.special-function {
  font-size: 16px;
  width : 100%;
  height: 100%;
  word-wrap: break-word;
}
.bottom {
  width: 100%;
  height: 330px;
  display: flex;
  align-items: center;
  flex-direction: row;
  justify-content: space-evenly;
  background-color: var(--blue); 
  gap: 10px;
}
.column {
  height : 100%;
  width: 50%;
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: space-evenly;
  gap : 10px;
  
}
.left{
  height: 55px;
}
.right {
 height: 25%;
}
.left, .right {
  background-color: var(--yellow);
  color: var(--dark);
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  border: 2px solid var(--yellow);
}
/* file: script.js */

const latestMonster = "https://rpg-creature-api.freecodecamp.rocks/api/creatures"
const searchBtn = document.getElementById("search-button");
const creatureName = document.getElementById("creature-name");
const specialName = document.getElementById("special-name");
const specialFunction = document.getElementById("special-function");
const hp = document.getElementById("hp");
const attack = document.getElementById("attack");
const defense = document.getElementById("defense");
const specialAttack = document.getElementById("special-attack");
const specialDefense = document.getElementById("special-defense");
const speedDiv = document.getElementById("speed");
const creatureId = document.getElementById("creature-id");
const weight = document.getElementById("weight");
const height = document.getElementById("height");
const types = document.getElementById("types");

let monsterList = {};
let actualMonster = {};

const fetchData = async () => {
  try {
    const res = await fetch(latestMonster);
    const data = await res.json();
    monsterList = data;
  } catch (err) {
    console.log(err);
  }
}
fetchData();

const clearForm = () => {
  creatureName.innerHTML = ``;
  specialName.innerHTML = ``; 
  specialFunction.innerHTML = ``;
  weight.innerHTML = ``;
  height.innerHTML = ``;
  creatureId.innerHTML = ``;
  hp.innerHTML = ``;
  attack.innerHTML = ``;
  defense.innerHTML = ``;
  specialAttack.innerHTML = ``;
  specialDefense.innerHTML = ``;
  speedDiv.innerHTML = ``;
  types.innerHTML = ``;
}
const updateData = async (input) => {
   const thisMonster = `https://rpg-creature-api.freecodecamp.rocks/api/creature/${input}`
    try {
      const res = await fetch(thisMonster);
      const data = await res.json();
      actualMonster = data;
      //console.log(actualMonster)
    } catch (err) { 
      alert("Creature not found");
    }
  const attackStat = actualMonster.stats.find(stat => stat.name === 'attack').base_stat;
  const hpStat = actualMonster.stats.find(stat => stat.name === 'hp').base_stat;
  const defenseStat = actualMonster.stats.find(stat => stat.name === 'defense').base_stat;
  const speAttackStat = actualMonster.stats.find(stat => stat.name === 'special-attack').base_stat;
  const speDefenseStat = actualMonster.stats.find(stat => stat.name === 'special-defense').base_stat;
  const speedStat = actualMonster.stats.find(stat => stat.name === 'speed').base_stat;
  creatureName.innerHTML = `${actualMonster.name}`;
  specialName.innerHTML = `${actualMonster.special.name}`; 
  specialFunction.innerHTML = `${actualMonster.special.description}`;
  weight.innerHTML = `${actualMonster.weight}`;
  height.innerHTML = `${actualMonster.height}`;
  creatureId.innerHTML = `${actualMonster.id}`;
  hp.innerHTML = `${hpStat}`;
  attack.innerHTML = `${attackStat}`;
  defense.innerHTML = `${defenseStat}`;
  specialAttack.innerHTML = `${speAttackStat}`;
  specialDefense.innerHTML = `${speDefenseStat}`;
  speedDiv.innerHTML = `${speedStat}`;
  const typeName = actualMonster.types.map(tp => tp.name.toUpperCase());
  if (typeName.length >1 ) {
    types.innerHTML = "";
    typeName.forEach((el) => {
      types.innerHTML += `
      <span>${el}</span>
      `;})
  
  } else {
    types.innerHTML = `<p>${typeName}</p>`;
  }

}

const monsterData = () => {
  clearForm();
  let selectedMonster = {};
  const input = document.getElementById("search-input").value;
  if (isNaN(input)) {
    selectedMonster = monsterList.find(monster => monster.name === input);
    console.log(selectedMonster)
    if (!selectedMonster) {
      alert("Creature not found");
    }
    updateData(selectedMonster.id);
    return;
  } else {
    let inputNbr = parseInt(input);
    selectedMonster = monsterList.find(monster => monster.id === inputNbr);
    console.log(selectedMonster)
    if (!selectedMonster) {
      clearForm();
      alert("Creature not found");
      return;
    }
    updateData(selectedMonster.name);
    return;
  } 
}
searchBtn.addEventListener("click", monsterData) 

### Your browser information:

User Agent is: <code>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36</code>

### Challenge Information:
Build an RPG Creature Search App Project - Build an RPG Creature Search App
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures-v8/build-an-rpg-creature-search-app-project/build-an-rpg-creature-search-app

Hi. Can you please link to the challenge you are doing.

Sure! It’s the last Java challenge for the certification!
Here is the link, hope it will works

it’s JavaScript, not Java, be sure to remember that they are different challenges!

It may be weird, but maybe it’s taking too much time, and the tests are completing earlier

could you try to use fetch even on invalid inputs? if they do not exist the API returns 404, you can try to use that as a way to say if the creature exists or not

  • You should let your handler kick off the fetch.
  • There is really no reason for fetching all creatures and using find,
    and then later using the single creature endpoint.
  • The single creature endpoint accepts both a name or an id. You do not
    need any logic to figure out what it is.

I think a logical order would be:

  1. The handler clears the DOM, gets the input and passes that to a data fetch function, then stores the data returned so it can pass it to the DOM update function.

  2. The data fetch function uses the input it is passed, gets the data and returns it, or throws an error.

  3. The DOM update function is passed the data that was fetched and uses it for the DOM updates.

Yeah it was a bit of a mess, sorry about that! I did ended up doing what you said and it worked just great!
I did complicated the whole project for no reason haha
Thanks a lot by the way!