Build an RPG Creature Search App Project - Build an RPG Creature Search App

Tell us what’s happening:

I’m already fullfill the rest of the criteria, but only fail at 21st criteria. it says when search button is clicked, the app should send a fetch request to the correct endpoint for the creature name or id, which is i already did. but still not passes the test

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RPG Creature Search App</title>
    <link rel="stylesheet" href="./styles.css">
</head>
<body>
    <h1 class="title">RPG Creature Search App</h1>
    <h2 class="author">by Widi Arsa</h2>
    <div class="container">
        <form action="" role="search" id="search-form">
            <label for="search-input">Search for Creature Name or ID:</label>
            <div class="input">
                <input type="text" id="search-input" required> 
                <button id="search-button">Search</button>
            </div>
        </form>
        <div class="output">
            <div class="left-container">
                <div class="name">
                    <span id="creature-name">creature-name</span>
                    <span id="creature-id">creature-id</span>
                </div>
                <div class="size">
                    <span id="weight">weight</span>
                    <span id="height">height</span>
                </div>
                <div id="types"></div>
                <div class="special">
                    <p id="special-name">special-name</p>
                    <p id="special-description">special-description</p>
                </div>
            </div>

            <table class="right-container">
                <tbody>
                    <tr>
                        <td>HP</td>
                        <td id="hp"></td>
                    </tr>
                    <tr>
                        <td>Attack</td>
                        <td id="attack"></td>
                    </tr>
                    <tr>
                        <td>Defense</td>
                        <td id="defense"></td>
                    </tr>
                    <tr>
                        <td>Sp. Attack</td>
                        <td id="special-attack"></td>
                    </tr>
                    <tr>
                        <td>Sp. Defense</td>
                        <td id="special-defense"></td>
                    </tr>
                    <tr>
                        <td>Speed</td>
                        <td id="speed"></td>
                    </tr>
                </tbody>
            </table>
        </div>
        <button id="expand">||</button>
    </div>
<script src="./script.js"></script>
</body>
</html>
/* file: styles.css */
:root {
    --base-color: red;
    --dark-bg: black;
    --light-bg: white;
    --sec-color: #1b1b32;
}

*,
::after,
::before {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background-color: var(--sec-color);

}

.inline {
    display: inline;
}

.title, .author {
    display: block;
    color: var(--light-bg);
    text-align: center;
    margin: 20px auto;
}

.container {
    width: 500px;
    margin: 0 auto;
    position: relative;
}

#expand {
    display: none;
    z-index: 3;
    padding: 20px 3px;
    color: var(--dark-bg);
    border: 0;
    position: absolute;
    top: 180px;
    left: 97%;
    border-radius: 5px;
    transition: all 0.2s ease;
}

#expand:hover {
    cursor: pointer;
    padding: 20px 5px;
}

#search-form {
    width: 500px;
    height: 200px;
    background-color: var(--light-bg);
    color: var(--dark-bg);
    border-radius: 20px;
    text-align: center;
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-shadow: 10px 10px 0px 0px rgba(223, 220, 220, 0.75);
}

#search-form.no-border {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}

label {
    display: block;
    padding-bottom: 20px;
    text-align: center;
}

#search-input {
    margin: 0 auto;
    height: 40px;
    width: 300px;
    padding: 0 10px;
    vertical-align: middle;
    border-radius: 10px;
    border: 1px solid rgb(147, 147, 147);
}

#search-button {
    background: linear-gradient(to right, var(--sec-color) 0%, var(--sec-color) 50%, #b30000 50%, #b30000 100%);
    background-size: 200% 100%;
    background-position: right center;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 6px;
    font-weight: bold;
    cursor: pointer;
    transition: background-position 0.3s ease-in-out, color 0.3s ease;
}

#search-button:hover {
    background-position: left center;
}

.left-container {
    display: flex;
    flex-direction: column;
    padding: 20px;
}

#types {
    margin: 20px 0;
}

.type {
    background-color: green;
    padding: 5px 20px;
    text-transform: uppercase;
    border-radius: 10px;
    margin-right: 10px;
}

.fire {
    background-color: #ff6f52;
}

.water {
    background-color: #42a1ff;
}

.electric {
    background-color: #fecc33;
}

.grass {
    background-color: #78cc55;
}

.ice {
  background-color: #66ccfe;
}

.fighting {
  background-color: #d3887e;
}

.poison {
  background-color: #c68bb7;
}

.ground {
  background-color: #dfba52;
}

.flying {
  background-color: #8899ff;
}

.psychic {
  background-color: #ff66a3;
}

.bug {
  background-color: #aabb23;
}

.rock {
  background-color: #baaa66;
}

.ghost {
  background-color: #9995d0;
}

.dragon {
  background-color: #9e93f1;
}

.dark {
  background-color: #b59682;
}

.steel {
  background-color: #abaabb;
}

.fairy {
  background-color: #ed99ed;
}

.name {
    margin-bottom: 10px;
}

#creature-name {
    font-size: 2em;
    font-weight: bold;
    margin-right: 10px;
}

#creature-id {
    font-size: 2em;
}

#special-name {
    font-size: 1.5em;
    font-weight: bold;
    margin-bottom: 10px;
}

.left-container {
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;
    box-shadow: 10px 10px 0px 0px rgba(223, 220, 220, 0.75);
    background-color: var(--light-bg);
    display: block;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    z-index: -1;
    transition: all 0.5s ease-out;
}

.left-container.show {
    max-height: 500px; /* sesuaikan tinggi maksimum kontennya */
    opacity: 1;
}

.right-container {
    opacity: 0;
    position: absolute;
    top: 0px;
    left: 495px;
    gap: 20px;
    font-size: 1.5em;
    transform: translateX(-30px);
    transition: all 0.5s ease;
}

.right-container.show {
    opacity: 1;
    transform: translateX(0);
}

table {
    width: auto;
    table-layout: auto;
    border-radius: 20px;
    background-color: white;
    border-collapse: separate;
    border-spacing: 10px 10px;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

td {
    padding: 15px;
    white-space: nowrap;
}

tr {
    text-align: center;
}

tr:first-child td:first-child {
  border-top-left-radius: 10px;
}
tr:first-child td:last-child {
  border-top-right-radius: 10px;
}
tr:last-child td:first-child {
  border-bottom-left-radius: 10px;
}
tr:last-child td:last-child {
  border-bottom-right-radius: 10px;
}



/* file: script.js */
const searchInput = document.getElementById('search-input');
const searchBtn = document.getElementById('search-button');
const creatureName = document.getElementById('creature-name');
const creatureId = document.getElementById('creature-id');
const weight = document.getElementById('weight');
const height = document.getElementById('height');
const types = document.getElementById('types');
const specialName = document.getElementById('special-name');
const specialDesc = document.getElementById('special-description');
const leftContainer = document.querySelector('.left-container');
const form = document.getElementById('search-form');
const expand = document.getElementById('expand');
const rightContainer = document.querySelector('.right-container');
const tr = document.querySelectorAll('tr');

const hp = document.getElementById('hp');
const attack = document.getElementById('attack');
const defense = document.getElementById('defense');
const spAttack = document.getElementById('special-attack');
const spDefense = document.getElementById('special-defense');
const speed = document.getElementById('speed');

let timeOutId = null;
let theme = 'fire';

const listUrl = 'https://rpg-creature-api.freecodecamp.rocks/api/creatures';
const detailUrl = 'https://rpg-creature-api.freecodecamp.rocks/api/creature';

const fetchData = async (url) => {
    try {
        const res = await fetch(url);
        const data = await res.json();
        return data;
    } catch (err) {
        console.log('Error: ',err);
    }
}

const checkCreature = async () => {
    const input  = searchInput.value.trim();
    const isNumber = !isNaN(Number(input));

    if (input) {
        const data = await fetchData(listUrl);

        const search = data.find(item => 
            isNumber 
            ? item.id === Number(input) 
            : item.name === input
        );
        
        
        if (search) {
            const creatureUrl = isNumber ? `${detailUrl}/${search.id}` : `${detailUrl}/${search.name}`;
            const dataSearch = await fetchData(creatureUrl);
    
            theme = showCreature(dataSearch);
            leftContainer.classList.add('show');
            expand.classList.add(theme);
            form.classList.add('no-border');
            setTimeout(() => {
                expand.style.display = 'block';
            }, 500);
        } else {
            alert(`Creature Not Found`)
        }
    } else {
        alert('enter input')
    }
        
}

const showCreature = (data) => {
    const creatureTypesArr = data.types;
    let creatureTypes = ``
    creatureTypesArr.forEach((type) => {
        creatureTypes += `<span class='type ${type.name}'>${type.name}</span>`
    });

    types.innerHTML = creatureTypes;
    creatureName.textContent = data.name;
    creatureId.textContent = `#${data.id}`;
    weight.textContent = `weight: ${data.weight}`;
    height.textContent = `height: ${data.height}`;
    specialName.textContent = data.special.name;
    specialDesc.textContent = data.special.description;

    hp.textContent = data.stats.find((item) => item.name === "hp").base_stat;
    attack.textContent = data.stats.find((item) => item.name === "attack").base_stat;
    defense.textContent = data.stats.find((item) => item.name === "defense").base_stat;
    spAttack.textContent = data.stats.find((item) => item.name === "special-attack").base_stat;
    spDefense.textContent = data.stats.find((item) => item.name === "special-defense").base_stat;
    speed.textContent = data.stats.find((item) => item.name === "speed").base_stat;
    return creatureTypesArr[0].name;
}

searchBtn.addEventListener('click', (e) => {
    e.preventDefault();
    clearTimeout(timeOutId);
    
    if (leftContainer.classList.contains('show')) {
        expand.style.display = 'none';
        setTimeout(() => {
            leftContainer.classList.remove('show');
            form.classList.remove('no-border'); 
        }, 200);
    }

    timeOutId = setTimeout(() => {
        checkCreature();
    }, 300);
});

expand.addEventListener('click', () => {
    rightContainer.classList.toggle('show');

    if (rightContainer.classList.contains('show')) {
        form.style.borderTopRightRadius = '0';
    } else {
        form.style.borderTopRightRadius = '20px';
    }
    tr.forEach((el) => {
        el.classList.toggle(theme);
    })
})

Your browser information:

User Agent is: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36

Challenge Information:

Build an RPG Creature Search App Project - Build an RPG Creature Search App

Please post your code. Thanks

I wouldn’t do this. You’re requesting all data on every user interaction, which is wasteful. I would just try to request the creature the user wants and see if it works