Home API Notes

Video

The link to my Video

Write-up

Car Search and Add

3.a.i.

The purpose of my program is to allow users to add their car builds and search through the cars of others, in order to help people discover new cars and to develop a car community.

3.a.ii.

The program allows a user to input their car and give it a unique description. Some people may have the same cars or may have multiple of the same car, thus, the descriptions are unique in order to allow people to save their various car builds/configurations. A user can input the make, model, price, year, body style and engine of any car - along with a description and the name of the car’s owner. The addition of cars allows the search feature to shine, as it works as a filter. The search feature iterates through specific criteria such as a specific make, model, body style, or multiple attributes/criteria at the same time. The search creates a table that allows the user to easily view specific cars.

3.a.iii.

The user inputs a car to add to the database. At first, they add a car that is already in the database (a duplicate), which returns an error message. After, a new car is added and can be viewed in the table. The user also uses different criteria to filter through the database of cars, causing only a specific list of cars to appear on the table.

3.b.i.

A POST method is used to submit a new car to the database. "Data" is the variable that is used to represent the list of car data later on in the code.

         // Add an event listener to the form to submit car data
        const form = document.getElementById('carForm');
        form.addEventListener('submit', async function(event) {
            event.preventDefault();

            // Retrieve the input values from the form
            const make = document.getElementById('make').value;
            const model = document.getElementById('model').value;
            const price = document.getElementById('price').value;
            const year = document.getElementById('year').value;
            const desc = document.getElementById('desc').value;
            const bodyStyle = document.getElementById('body_style').value;
            const engine = document.getElementById('engine').value;
            const owner = document.getElementById('owner').value;

            try {
                // Use the Fetch API to submit car data to the server
                const response = await fetch('https://cars.nighthawkcodingsociety.com/api/cars/create', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    // Use JSON.stringify to convert the input values into a JSON string that can be sent to the server as the request body
                    body: JSON.stringify({
                        make: make,
                        model: model,
                        price: price,
                        year: year,
                        desc: desc,
                        body_style: bodyStyle,
                        engine: engine,
                        owner: owner
                    })
                });
                // Check if the response from the server is ok
                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }
                // Display a success message to the user
                alert("Car has been added successfully!");
            } catch (error) {
                // If an error occurs, log it to the console and display an error message to the user
                console.error('Error:', error);
                alert("Please enter all fields or check if the added car is a duplicate.")
            }
        });

3.b.ii.

            const resultContainer = document.getElementById("result");

            const url = "https://cars.nighthawkcodingsociety.com/api/cars/";
            const headers = {
              method: 'GET',
              mode: 'cors',
              cache: 'default',
              credentials: 'omit',
              headers: {
                'Content-Type': 'application/json'
              },
            };

            // Fetch data from the database
            fetch(url, headers)
              .then(response => {
                // If the response is not OK, log the error and display it on the webpage
                if (response.status != 200) {
                    const errorMsg = 'Database response error: ' + response.status;
                    console.log(errorMsg);
                    const tr = document.createElement("tr");
                    const td = document.createElement("td");
                    td.innerHTML = errorMsg;
                    tr.appendChild(td);
                    resultContainer.appendChild(tr);
                    return;
                }
                // Parse the json and add it to the webpage
                response.json().then(data => {
                    console.log(data);      

                    for (const row of data) {

                      // Create new table row and cells for each car attribute
                      const tr = document.createElement("tr");
                      const make = document.createElement("td");
                      const model = document.createElement("td");
                      const year = document.createElement("td");
                      const price = document.createElement("td");
                      const engine = document.createElement("td");
                      const body_style = document.createElement("td");
                      const desc = document.createElement("td");
                      const owner = document.createElement("td");


                      // Set the inner HTML of each cell to the corresponding car attribute value
                      make.innerHTML = row.make;
                      model.innerHTML = row.model;
                      year.innerHTML = row.year;
                      price.innerHTML = row.price;
                      engine.innerHTML = row.engine;
                      body_style.innerHTML = row.body_style;
                      desc.innerHTML = row.desc;
                      owner.innerHTML = row.owner

                      // Append each cell to the row
                      // Allows the data to be added to the newly made table
                      tr.appendChild(make);
                      tr.appendChild(model);
                      tr.appendChild(year);
                      tr.appendChild(price);
                      tr.appendChild(engine);
                      tr.appendChild(body_style);
                      tr.appendChild(desc);
                      tr.appendChild(owner);

                      // Append the row to the container element
                      resultContainer.appendChild(tr);
                    }
                })
            })

3.b.iii.

The variable that represents the list is “data.” "Data" is the data of the cars that the program fetches from our database using a GET request - the data is represented by JSON. This data is used to populate the table with various attributes including make, model, year, etc.

3.b.iv.

The data contained within the list is the make, model, price, year, engine, body style, and owner of each car from the database.

3.b.v.

Without using the json “data” the car search would cease to work. This is because the car search uses the data to build tables based on specific criteria from the data itself.

3.c.i.

        // Table creation after search button is pressed
        function makeTable(data){
          // Remove current carData - prepare for new search
          document.getElementById("carData").remove()
          const [desiredMake, desiredModel, desiredPrice, desiredYear, desiredEngine, desiredBodyStyle, desiredOwner] = getInput()
          const tbody = document.createElement("tbody")
          // Set tbody id to carData - ensure that carData is still on page
          tbody.id = "carData"
          // Iterate over each row from the data in the database
          for (const row of data) {

            // Filter
            // Check if each row value matches user input, skip to the next iteration if there is no match
            if (desiredMake && !(row.make.toUpperCase() === desiredMake.toUpperCase()))
              continue
            if (desiredModel && !(row.model.toUpperCase() === desiredModel.toUpperCase()))
              continue
            if (desiredPrice && !(row.price <= parseInt(desiredPrice)))
              continue
            if (desiredYear && !(row.year === parseInt(desiredYear)))
              continue          
            if (desiredEngine && !(row.engine.toUpperCase() === desiredEngine.toUpperCase()))
              continue
            if (desiredBodyStyle && !(row.body_style.toUpperCase() === desiredBodyStyle.toUpperCase()))
              continue    
            if (desiredOwner && !(row.owner.toUpperCase() === desiredOwner.toUpperCase()))
              continue        


            // If all values match, create table elements
            const tr = document.createElement("tr");
            const make = document.createElement("td");
            const model = document.createElement("td");
            const year = document.createElement("td");
            const price = document.createElement("td");
            const engine = document.createElement("td");
            const body_style = document.createElement("td");
            const owner = document.createElement("td");

            // Set innerHTML to values of make, model, year, etc. from the API
            make.innerHTML = row.make;
            model.innerHTML = row.model;
            year.innerHTML = row.year;
            price.innerHTML = row.price;
            engine.innerHTML = row.engine;
            body_style.innerHTML = row.body_style;
            owner.innerHTML = row.owner;


            // Add data for make, model, price, etc. to the table row
            tr.appendChild(make);
            tr.appendChild(model);
            tr.appendChild(year);
            tr.appendChild(price);
            tr.appendChild(engine);
            tr.appendChild(body_style);
            tr.appendChild(owner);


            // Add row to the table
            tbody.appendChild(tr);
          }
          // Add the data from tbody into the table
          document.getElementById("table").appendChild(tbody)
        }

3.c.ii.

   <h1>Car Search</h1>
      <table id="table">
        <thead>
        <tr>
            <th>Make</th>
            <th>Model</th>
            <th>Year</th>
            <th>Price</th>
            <th>Engine</th>
            <th>Body Style</th>
            <th>Owner</th>
        </tr>
        </thead>
        <tr id="result"></tr>
        <tbody id="carData"></tbody>
      </table>
          <!-- Set label and input ids - allows for use in getInput() function -->
          <label for="make">Make</label>
          <input name="make" id="make">
          <label for="model">Model</label>
          <input name="model" id="model">
          <label for="year">Year</label>
          <input name="year" id="year">
          <label for="price">Price</label>
          <input name="price" id="price">
          <label for="engine">Engine</label>
          <input name="engine" id="engine">
          <label for="body_style">Body Style</label>
          <input name="body_style" id="body_style">
          <label for="owner">Owner</label>
          <input name="owner" id="owner">
          <button onclick="makeTable(carData)" style="background-color: #ffff; color: black;">Search</button>
          <button onclick="clearTable(carData)" style="background-color: #f2f2f2; color: black">Clear</button>

3.c.iii.

The identified procedure “makeTable” iterates through the list of cars from the data in our database. Cars that match the specific criteria set via the user’s input are the only cars that populate the table - thus, allowing the cars to be filtered/searched. uses a for loop to iterate through the list of cars from the data in our database.

3.c.iv.

The function first gets the user input values for desired make, model, price, year, engine, body style, and owner by calling the "getInput" function.The function first gets the user input values for desired make, model, price, year, engine, body style, and owner by calling the "getInput" function. The function then removes any previous data by removing the table with id "carData". The function creates a new table body element using the "createElement" method and sets its id to "carData". This table body element will hold the rows of car data that match the user's search criteria. The function then loops through each row of data from the database using a for-of loop. For each row of data, the function checks if each value matches the user input values using if statements. If a value doesn't match, the loop moves on to the next row using the "continue" statement. This filters the data to only show rows that match the user's search criteria. If all values match, the function creates a new table row element using the "createElement" method and creates new table data elements (td) for each column (make, model, year, price, engine, body style, and owner) using the same method. Set innerHTML: The function then sets the innerHTML of each td element to the corresponding value from the current row of data. The function appends each td element to the table row using the "appendChild" method.The function appends each td element to the table row using the "appendChild" method. The function appends the table row to the table body using the "appendChild" method. After all rows have been processed, the function appends the table body to the table with id "table" using the "appendChild" method.

3.d.i.

  • Call One In call one, makes a search with no values - makeTable has no user input.

  • Call Two This call will execute the algorithm with user input that filters the rows of data based on certain criteria. For example, the input would be "Lexus" for the desired make and "Coupe" for the desired body style.

3.d.ii.

  • Condition(s) tested by Call One As there is no user input, all of the "continue" statements when iterating through the data will be skipped and all of the rows will pass through to the table creation section of the algorithm.

  • Condition(s) tested by Call Two When the algorithm loops through each row of data, it will only create a new table row if the make matches "Lexus" and the body style matches "Coupe". All other rows will be skipped due to the "continue" statements in the filtering section of the algorithm.

3.d.iii.

  • Results of Call One The resulting table will include all rows of data from the "data" array.

  • Results of Call Two The resulting table will only include rows that match the user's input criteria, and not all rows from the filtered list of data.