Improving the Guide Page

Introduction: Why Improve the Guide Page?

Welcome back! So far, you have built a step-by-step cooking guide page that lets users follow recipes one step at a time. You have already added basic navigation, some interactivity, and styling. In this lesson, we will focus on making the guide page even more helpful and enjoyable for users.

Why do these improvements matter? When someone is cooking, they want the process to be smooth and easy. Features like keyboard shortcuts, and recipe ratings can make a big difference. They help users stay on track, move through steps quickly, and share feedback on recipes. By the end of this lesson, you will know how to add these features to your guide page.

Quick Recap: What the Guide Page Can Already Do

Before we dive into the new features, let’s quickly remind ourselves of what you have already built:

  • The guide page loads recipe steps from the server.
  • Users can move between steps using "Prev" and "Next" buttons.
  • The page uses JavaScript to update the step text and handle navigation.
  • There is some basic styling to make the page look nice.

All of these features are already in place. In this lesson, we will build on top of them, so you do not need to change anything that is already working.

Making Navigation Easier with Keyboard Shortcuts

First, let’s make it easier for users to move through the recipe steps and play instructions using their keyboard. This is especially helpful if their hands are messy from cooking!

Listening for Key Presses

We add an event listener for keyboard events:

document.addEventListener('keydown', (e) => {
  if (e.code === 'Space') {
    e.preventDefault();
    playTTS();
  } else if (e.code === 'ArrowRight') {
    e.preventDefault();
    if (!nextBtn.disabled) nextBtn.click();
  } else if (e.code === 'ArrowLeft') {
    e.preventDefault();
    if (!prevBtn.disabled) prevBtn.click();
  }
});
  • When the user presses the Space bar, the current step is read aloud.
  • Right Arrow moves to the next step (if possible).
  • Left Arrow moves to the previous step (if possible).

Explanation:

  • e.preventDefault(); stops the browser from performing its default action (like scrolling).
  • playTTS(); plays the text-to-speech for the current step.
  • nextBtn.click(); and prevBtn.click(); simulate clicking the navigation buttons.

Letting Users Rate Recipes

Finally, let’s add a way for users to rate the recipe after they finish all the steps. This helps collect feedback and makes the app more interactive.

To include the rating form in your guide page, update your HTML and CSS as follows:

Step 1: Update the HTML

Add the following block inside your main guide page template, just after the step navigation and timer elements:

<!-- New additions to the file: Rating -->
<div id="rating-form" class="rating-form" style="display: none;">
  <h2>Rate this Recipe</h2>
  <div id="star-rating" class="stars">
    <span data-value="1">★</span>
    <span data-value="2">★</span>
    <span data-value="3">★</span>
    <span data-value="4">★</span>
    <span data-value="5">★</span>
  </div>
  <p id="rating-feedback" class="success"></p>
</div>

This block creates a hidden rating form that will only appear when the user finishes the recipe. It includes a heading, five clickable stars for rating, and a feedback message area. The style="display: none;" ensures the form is hidden by default.

Step 2: Showing the Rating Form in JavaScript

When the user finishes the last step, the rating form appears:

if (currentIndex < steps.length - 1) {
  currentIndex++;
  updateStep();
} else {
  // End of recipe
  stepText.textContent = 'Recipe completed!';
  prevBtn.disabled = true;
  nextBtn.disabled = true;
  playTtsBtn.disabled = true;
  ratingForm.style.display = 'block';
}
  • When the last step is done, the navigation buttons are disabled.
  • The rating form is shown by setting ratingForm.style.display = 'block';.

Step 3: Handling Star Ratings

The rating form uses stars that the user can click to select a rating:

// Select all the star elements inside the star container
const stars = starContainer.querySelectorAll('span');

// Loop through each star and add event listeners for interactivity
stars.forEach(star => {
  // Highlight stars on mouseover (hover)
  star.addEventListener('mouseover', () => {
    const val = parseInt(star.dataset.value, 10); // Get the value of the hovered star
    stars.forEach(s => {
      // Highlight all stars up to the hovered one
      s.classList.toggle('hovered', parseInt(s.dataset.value) <= val);
    });
  });

  // Remove highlight when mouse leaves the star area
  star.addEventListener('mouseout', () => {
    stars.forEach(s => s.classList.remove('hovered'));
  });

  // Handle click event to select a rating and submit it
  star.addEventListener('click', async () => {
    selectedRating = parseInt(star.dataset.value, 10); // Store the selected rating
    stars.forEach(s => {
      // Visually mark all stars up to the selected one as chosen
      s.classList.toggle('selected', parseInt(s.dataset.value) <= selectedRating);
    });

    try {
      // Send the rating to the server using a POST request
      const res = await fetch('/api/reviews', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ recipe_id: RECIPE_ID, rating: selectedRating }),
      });

      // Parse the server response
      const data = await res.json();
      // Show a thank you message or server response
      ratingFeedback.textContent = data.message || 'Thank you!';
      // Disable further interaction with the stars after submission
      starContainer.style.pointerEvents = 'none';
    } catch (err) {
      // Handle errors (e.g., network issues)
      console.error('Rating error:', err);
      ratingFeedback.textContent = 'Failed to submit rating.';
    }
  });
});
  • The code first selects all the <span> elements (the stars) inside the rating container.
  • For each star:
    • Mouseover: When the user hovers over a star, all stars up to and including that one are given the hovered class, which changes their color. This gives instant visual feedback about the potential rating.
    • Mouseout: When the mouse leaves a star, the hovered class is removed from all stars, resetting their appearance.
    • Click: When a star is clicked:
      • The code records which star was clicked (the rating).
      • All stars up to and including the clicked one are given the selected class, visually marking the chosen rating.
      • An asynchronous POST request is sent to /api/reviews with the recipe ID and the selected rating.
      • If the request succeeds, a thank you message (or the server’s message) is shown, and the stars are disabled so the user cannot rate again.
      • If there’s an error (like a network problem), an error message is shown instead.

This approach provides a smooth, interactive experience for users rating the recipe, with immediate visual feedback and server communication.

Output Example:
After finishing the recipe, five stars appear. Hovering highlights them, and clicking submits your rating and shows a thank you message.

Step 4: CSS Changes

Add the following CSS to your guide.css file to style the rating form and stars:

.rating-form {
  margin-top: 2rem;
  border-top: 1px solid #eee;
  padding-top: 1rem;
}

.stars {
  font-size: 2rem;
  color: #ccc;
  cursor: pointer;
  user-select: none;
}

.stars span {
  padding: 0 0.2rem;
}

.stars span:hover,
.stars span.hovered,
.stars span.selected {
  color: #f39c12;
}

.success {
  color: green;
  margin-top: 1rem;
}

Explanation:

  • .rating-form adds spacing and a border to separate the rating section from the rest of the page.
  • .stars sets the size and default color of the stars, and makes them clickable.
  • .stars span adds spacing between each star.
  • The .hovered and .selected classes change the star color to gold when hovered or selected.
  • .success styles the feedback message after submitting a rating.

Summary And Practice Preview

In this lesson, you learned how to make your cooking guide page even more helpful by:

  • Making it easier to move through steps and play instructions using keyboard shortcuts.
  • Letting users rate the recipe at the end with a simple star system.

These improvements make the guide more user-friendly and interactive. Up next, you will get a chance to practice adding and using these features yourself. This hands-on practice will help you understand how each part works and how to use them in your own projects. Great job making it this far — let’s keep going!

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal