I’m doing a uni project on an online course website like Udemy using VueJs. When I remove a course from the checkout page, the course.spaces are not being updated on the main page. I’m encountering an error where my find() and findIndex() functions are returning undefined when I console.log the variables they’re stored in. Any help would be appreciated!
main.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/reset.css">
<link rel="stylesheet" href="styles/header.css">
<link rel="stylesheet" href="styles/afk_academy.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<title></title>
</head>
<body>
<!-- Header -->
<div id="app">
<header id="header">
<div id="logo-container" v-on:click="goToHome">
<img id="logo" src="images/afk-academy-high-resolution-logo-transparent.png">
</div>
<div id="searchbar-container">
<input id="search-bar" type="text" placeholder="Search...">
<i class="search-icon fa-solid fa-magnifying-glass"></i>
</div>
<div id="cart-icon-container">
<a
v-if="cartItemCount > 0"
id="cart-link"
v-on:click="toggle_page"
>
<p id="cart-count"> {{ calculateCartQuantity }}</p>
<i class="cart-icon fa-solid fa-cart-shopping"></i>
</a>
<a v-else id="cart-link-disabled" href="javascript:void(0);">
<i class="cart-icon fa-solid fa-cart-shopping"></i>
</a>
</div>
</header>
<main id="main-container">
<!-- Main Page -->
<div v-if="!checkoutPage" id="index">
<h1 id="courses-title">Online courses:</h1>
<section id="courses-section">
<div id="course-container" v-for="(course, index) in coursesCopy" :key="course.id">
<div id="course-thumbnail-container">
<img id="course-thumbnail" v-bind:src="course.thumbnail" alt="Algorithms course image"></img>
</div>
<div id="course-description">
<p id="course-subject" v-text="course.subject"></p>
<p id="course-location" v-text="course.location"></p>
<p id="course-price" v-text="course.price"></p>
<p id="available-spaces" v-text="course.spaces"></p>
<button
id="add-button"
v-on:click="addToCart(course.id)"
:disabled="!canAddToCart(course)"
>
+
</button>
</div>
</div>
</section>
</div>
<!-- Checkout Page -->
<div v-else id="checkout">
<section id="courses-added">
<div v-for="(course, index) in cart" :key="course.id" class="course-container">
<figure>
<img v-bind:src="course.thumbnail" class="course-thumbnail">
</figure>
<div class="course-description">
<p class="course-subject" v-text="course.subject"></p>
<p class="course-price" v-text="course.price"></p>
<p class="course-quantity" v-text="course.quantity"></p>
</div>
<button v-on:click="removeFromCart(course.id)">Remove</button>
</div>
</section>
</div>
</main>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="scripts/courses.js"></script>
<script src="scripts/afk_academy.js" type="text/javascript"></script>
</body>
</html>
checkout.js:
let webstore = new Vue({
el: "#app",
data: {
checkoutPage: false,
cart: JSON.parse(localStorage.getItem('cart')) || [],
courses: courses,
coursesCopy: JSON.parse(localStorage.getItem('coursesCopy')) || [...courses],
},
methods: {
addToCart: function(courseId) {
let course = this.findCourse(courseId, this.coursesCopy);
if (course && course.spaces > 0) {
let matchingItem = this.findCourse(courseId, this.cart);
if (matchingItem) {
matchingItem.quantity++;
} else {
this.cart.push({course, quantity: 1 });
}
course.spaces--;
console.log(this.coursesCopy);
this.saveToStorage();
}
},
removeFromCart(courseId) {
const index = this.findCourseId(courseId, this.cart);
if (index !== -1) {
const quantity = this.cart[index].quantity;
const originalCourse = this.findCourse(courseId, this.coursesCopy);
this.cart.splice(index, 1);
if (originalCourse) {
originalCourse.spaces += quantity;
}
}
console.log(index);
console.log(this.coursesCopy);
this.saveToStorage();
},
findCourse(courseId, array) {
const course = array.find(item => item.id === courseId);
return course;
},
findCourseId(courseId, array) {
const index = array.findIndex(item => item.id === courseId);
return index;
},
saveToStorage() {
try {
localStorage.setItem('cart', JSON.stringify(this.cart));
localStorage.setItem('coursesCopy', JSON.stringify(this.coursesCopy));
} catch (error) {
console.error("Error saving to localStorage:", error);
}
},
goToCheckout: function() {
this.checkoutPage = true;
},
goToHome: function() {
this.checkoutPage = false;
},
toggle_page: function() {
if (!this.checkoutPage) {
this.goToCheckout();
return;
}
if (this.checkoutPage) {
this.goToHome();
return;
}
}
},
computed: {
cartItemCount: function() {
return this.cart.length;
},
calculateCartQuantity: function() {
let cartQuantity = 0;
this.cart.forEach((cartItem) => {
cartQuantity += cartItem.quantity;
});
return cartQuantity;
},
canAddToCart: function() {
return (course) => course.spaces > 0;
},
checkCart: function() {
return !(this.cartItemCount > 0);
}
}
});
courses.js:
const courses = [
{
id: 1,
subject: "Algorithms",
location: "London",
price: 20,
spaces: 5,
thumbnail: "images/algorithms.png"
},
{
id: 2,
subject: "Maths",
location: "Toronto",
price: 25,
spaces: 5,
thumbnail: "images/algorithms.png"
},
{
id: 3,
subject: "Python",
location: "Riyadh",
price: 200,
spaces: 5,
thumbnail: "images/algorithms.png"
},
{
id: 4,
subject: "Java",
location: "Dubai",
price: 20,
spaces: 5,
thumbnail: "images/algorithms.png"
},
{
id: 5,
subject: "Chemistry",
location: "Dublin",
price: 350,
spaces: 5,
thumbnail: "images/algorithms.png"
},
{
id: 6,
subject: "Physics",
location: "Tokyo",
price: 230,
spaces: 5,
thumbnail: "images/algorithms.png"
},
];