There are 10 bugs in this code, each one is labelled in the form: TODO: Bug n – xyz
Here’s the code
Readme
ShopNow – Colorful E-Commerce Website
A vibrant and responsive e-commerce product page built with HTML, CSS, and JavaScript. This project showcases a modern, colorful design with product filtering, shopping cart functionality, and a simulated checkout flow.
Features
- Stunning UI Design: Vibrant colors, gradients, and animations for an engaging shopping experience
- Product Listing: Display products in a responsive grid layout with hover effects
- Filtering System: Filter products by category, price range, and ratings
- Shopping Cart: Add products to cart, adjust quantities, and remove items
- Responsive Design: Optimized for all devices (mobile, tablet, desktop)
- Checkout Flow: Simulated checkout process with order confirmation
- Local Storage: Cart data persists between page refreshes
- Category Showcase: Visual category cards with hover animations
- Interactive Elements: Form validation, notifications, and feedback elements
Visual Design Elements
- Modern Color Scheme: Vibrant purples, pinks, and complementary accents
- Gradient Effects: Smooth color transitions for buttons, backgrounds, and headers
- Card Animations: Subtle animations on hover for product and category cards
- Interactive UI Elements: Visual feedback for user interactions
- Custom Icons: FontAwesome integration with consistent styling
- Typography: Google Fonts integration with Poppins for a clean, modern look
Technologies Used
- HTML5: Semantic markup structure
- CSS3:
- Flexbox and Grid for layouts
- CSS Variables for theming
- Custom animations and transitions
- Gradients and color effects
- Media queries for responsiveness
- JavaScript (Vanilla):
- DOM manipulation
- Event handling
- Local storage for cart persistence
- Filter functionality
Project Structure
e-commerce/
├── index.html # Main HTML file
├── css/
│ ├── reset.css # CSS reset and base styles
│ ├── styles.css # Main styles with color scheme
│ ├── product.css # Product-specific styles
│ ├── cart.css # Shopping cart styles
│ └── responsive.css # Responsive design rules
├── js/
│ ├── products.js # Product data
│ ├── app.js # Main application logic
│ └── cart.js # Shopping cart functionality
├── img/ # Product images and assets
│ ├── hero.jpg
│ ├── product1.jpg - product12.jpg
│ ├── category-electronics.jpg
│ ├── category-fashion.jpg
│ ├── category-home.jpg
│ ├── category-beauty.jpg
│ └── ...
└── README.md # Project documentation
Getting Started
- Clone or download this repository
- Open
index.html
in your web browser
- No build process or dependencies required
Usage
Product Filtering
- Use the category checkboxes to filter by product type
- Adjust the price slider to set maximum price
- Select star ratings to filter by minimum rating
- Click “Apply Filters” to see filtered results
- Click “Clear All” to reset filters
Shopping Cart
- Click “Add to Cart” on any product to add it to your cart
- Click the cart icon in the header to view your cart
- Adjust quantities using the + and – buttons
- Remove items using the trash icon
- Click “Proceed to Checkout” to continue
Checkout Process
- Fill in the shipping information form
- Enter payment details
- Review order summary
- Click “Complete Purchase” to place the order
- View order confirmation with reference number
Customization
Color Scheme
The website uses CSS variables for easy color customization:
:root {
--primary-color: #6c5ce7;
--primary-light: #a29bfe;
--secondary-color: #2d3436;
--accent-color: #fd79a8;
--accent-hover: #e84393;
/* Other color variables */
}
You can change these variables in styles.css
to completely transform the site’s appearance.
Adding New Products
To add new products, edit the products.js
file following the existing structure:
{
id: 13,
name: "New Product Name",
category: "category-name",
price: 99.99,
oldPrice: 129.99, // Set to null if no discount
rating: 4.5,
reviewCount: 200,
image: "img/product13.jpg",
isNew: true,
isSale: false,
description: "Product description here."
}
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Opera (latest)
Future Enhancements
- Product detail page
- User authentication
- Wishlist functionality
- Product reviews
- Related products
- Advanced filtering options
- Payment gateway integration
- Dark mode theme toggle
License
This project is licensed under the MIT License – see the LICENSE file for details.
Acknowledgments
- Font Awesome for icons
- Google Fonts for typography
- Unsplash for product and category images
**app.js **-
// DOM Elements
const productGrid = document.getElementById('product-grid');
const applyFiltersBtn = document.getElementById('apply-filters');
const clearFiltersBtn = document.getElementById('clear-filters');
const priceRange = document.getElementById('price-range');
const priceValue = document.getElementById('price-value');
const categoryFilters = document.querySelectorAll('.category-filter');
const ratingFilters = document.querySelectorAll('.rating-filter');
const hamburger = document.querySelector('.hamburger');
const navLinks = document.querySelector('.nav-links');
const overlay = document.getElementById('overlay');
// State
let filteredProducts = [...products];
let selectedCategories = ['all'];
let selectedRatings = [];
let maxPrice = 1000;
// Initialize the page
document.addEventListener('DOMContentLoaded', () => {
renderProducts(products);
setupEventListeners();
});
// Setup Event Listeners
function setupEventListeners() {
// Mobile menu toggle
hamburger.addEventListener('click', () => {
navLinks.classList.toggle('active');
});
// Price range input
priceRange.addEventListener('input', (e) => {
maxPrice = e.target.value;
priceValue.textContent = `$${maxPrice}`;
});
// Category filters
categoryFilters.forEach(filter => {
filter.addEventListener('change', (e) => {
if (e.target.value === 'all') {
// If 'All' is checked, uncheck other categories
if (e.target.checked) {
categoryFilters.forEach(cat => {
if (cat.value !== 'all') {
cat.checked = false;
}
});
selectedCategories = ['all'];
} else {
// If 'All' is unchecked, make sure at least one category is selected
e.target.checked = true;
}
} else {
// If another category is checked, uncheck 'All'
const allCategoryFilter = document.querySelector('.category-filter[value="all"]');
allCategoryFilter.checked = false;
// Update selected categories
selectedCategories = Array.from(categoryFilters)
.filter(cat => cat.checked && cat.value !== 'all')
.map(cat => cat.value);
// If no category is selected, check 'All'
if (selectedCategories.length === 0) {
allCategoryFilter.checked = true;
selectedCategories = ['all'];
}
}
});
});
// Rating filters
ratingFilters.forEach(filter => {
filter.addEventListener('change', (e) => {
if (e.target.checked) {
selectedRatings.push(Number(e.target.value));
} else {
selectedRatings = selectedRatings.filter(rating => rating !== Number(e.target.value));
}
});
});
// Apply filters
applyFiltersBtn.addEventListener('click', applyFilters);
// Clear filters
clearFiltersBtn.addEventListener('click', clearFilters);
}
// Filter products based on selected criteria
function applyFilters() {
// Start with all products
let filtered = [...products];
// Filter by price
filtered = filtered.filter(product => product.price <= maxPrice);
// Filter by category
if (!selectedCategories.includes('all')) {
filtered = filtered.filter(product => selectedCategories.includes(product.category));
}
// Filter by rating
if (selectedRatings.length > 0) {
const minRating = Math.min(...selectedRatings);
filtered = filtered.filter(product => product.rating >= minRating);
}
// Update the UI
filteredProducts = filtered;
renderProducts(filteredProducts);
}
// Clear all filters
function clearFilters() {
// Reset price filter
priceRange.value = 1000;
maxPrice = 1000;
priceValue.textContent = `$${maxPrice}`;
// Reset category filters
categoryFilters.forEach(filter => {
filter.checked = filter.value === 'all';
});
selectedCategories = ['all'];
// Reset rating filters
ratingFilters.forEach(filter => {
filter.checked = false;
});
selectedRatings = [];
// Show all products
filteredProducts = [...products];
renderProducts(filteredProducts);
}
// Render products in the grid
function renderProducts(productsToRender) {
productGrid.innerHTML = '';
if (productsToRender.length === 0) {
productGrid.innerHTML = `
<div class="product-not-found">
<h3>No products found</h3>
<p>Try adjusting your filters to find products.</p>
</div>
`;
return;
}
productsToRender.forEach(product => {
const productEl = createProductElement(product);
productGrid.appendChild(productEl);
});
}
// Create a product element
function createProductElement(product) {
const productEl = document.createElement('div');
productEl.className = 'product-card';
// Generate stars based on rating
const fullStars = Math.floor(product.rating);
const hasHalfStar = product.rating % 1 !== 0;
let starsHTML = '';
for (let i = 0; i < fullStars; i++) {
starsHTML += '<i class="fas fa-star"></i>';
}
if (hasHalfStar) {
starsHTML += '<i class="fas fa-star-half-alt"></i>';
}
const emptyStars = 5 - fullStars - (hasHalfStar ? 1 : 0);
for (let i = 0; i < emptyStars; i++) {
starsHTML += '<i class="far fa-star"></i>';
}
productEl.innerHTML = `
<div class="product-image">
<img src="${product.image}" alt="${product.name}">
${product.isNew ? '<span class="product-tag new">New</span>' : ''}
${product.isSale ? '<span class="product-tag sale">Sale</span>' : ''}
<div class="product-actions">
<button class="action-btn" title="Add to Wishlist"><i class="far fa-heart"></i></button>
<button class="action-btn" title="Quick View"><i class="far fa-eye"></i></button>
<button class="action-btn" title="Compare"><i class="fas fa-sync-alt"></i></button>
</div>
</div>
<div class="product-info">
<div class="product-category">${product.category}</div>
<h3 class="product-title">${product.name}</h3>
<div class="product-price">
<span class="current-price">$${product.price.toFixed(2)}</span>
${product.oldPrice ? `<span class="original-price">$${product.oldPrice.toFixed(2)}</span>` : ''}
</div>
<div class="product-rating">
<div class="stars">${starsHTML}</div>
<span class="rating-count">(${product.reviewCount})</span>
</div>
<button class="add-to-cart" data-id="${product.id}">
<i class="fas fa-shopping-cart"></i> Add to Cart
</button>
</div>
`;
// Add event listener to the Add to Cart button
const addToCartBtn = productEl.querySelector('.add-to-cart');
addToCartBtn.addEventListener('click', () => {
addToCart(product.id);
});
return productEl;
}
// Trigger 'Add to Cart' with animations
function addToCart(productId) {
// Create a visual effect for adding to cart
const notification = document.createElement('div');
notification.className = 'add-to-cart-notification';
notification.textContent = `${productId} added to cart!`;
document.body.appendChild(notification);
// Trigger cart update
if (typeof updateCart === 'function') {
updateCart(productId);
}
// Remove notification after animation completes
setTimeout(() => {
notification.classList.add('fade-out');
setTimeout(() => {
document.body.removeChild(notification);
}, 300);
}, 2000);
}
// TODO: Bug 1 - Critical: Authentication bypass
function checkAuth() {
return localStorage.getItem('token'); // Bug: No token validation
}
// TODO: Bug 2 - Critical: XSS vulnerability
function renderProducts() {
const products = getProducts();
return products.map(p => `<div>${p.name}</div>`).join(''); // Bug: No HTML escaping
}
// TODO: Bug 3 - Critical: CSRF protection missing
function submitOrder(orderData) {
fetch('/api/orders', { // Bug: No CSRF token
method: 'POST',
body: JSON.stringify(orderData)
});
}
// TODO: Bug 4 - Critical: Price manipulation vulnerability
function updatePrice(item, price) {
item.price = price; // Bug: Client-side price modification possible
updateCart();
}
// TODO: Bug 5 - Critical: Event listener timing
document.querySelector('.products-container').innerHTML = renderProducts();
// TODO: Bug 6 - Critical: Local storage error
function loadCart() {
const cart = JSON.parse(localStorage.getItem('cart')); // Bug: No error handling
return cart || [];
}
// TODO: Bug 7 - Critical: Race condition in checkout
async function checkout() {
const items = getCartItems();
// Bug: Stock levels could change between check and purchase
if (checkStock(items)) {
await processPurchase(items);
}
}
// TODO: Bug 8 - Critical: SQL Injection in search
function searchProducts(query) {
return fetch(`/api/products/search?q=${query}`); // Bug: No parameter escaping
}
// TODO: Bug 9 - Critical: Infinite loop potential
function calculateDiscount(items) {
return items.reduce((acc, item) => {
return acc + calculateDiscount(item.subItems); // Bug: No base case
}, 0);
}
// TODO: Bug 10 - Critical: Cart persistence
window.addEventListener('unload', () => {
// Bug: Missing cart save to localStorage
console.log('Page unloading...');
});
let cart = [];
// Initialize store
function initializeStore() {
try {
const storedCart = localStorage.getItem('cart');
if (storedCart) {
cart = JSON.parse(storedCart);
}
} catch (error) {
console.error("Error parsing cart from localStorage:", error);
cart = [];
}
updateCart(cart);
}
// Update cart display
function updateCart(cart) {
const cartCountElem = document.querySelector('.cart-count');
if (cartCountElem) {
cartCountElem.textContent = cart.length;
} else {
console.warn("cart-count element not found");
}
}
// Add to cart function
function addToCart(productId) {
const product = products.find(p => p.id === productId);
if (!product) {
console.error("Product not found:", productId);
return;
}
cart.push(product);
localStorage.setItem('cart', JSON.stringify(cart));
updateCart(cart);
}
cart.js
// DOM Elements
const cartIcon = document.getElementById('cart-icon');
const cartSidebar = document.getElementById('cart-sidebar');
const closeCartBtn = document.getElementById('close-cart');
const cartItems = document.getElementById('cart-items');
const cartTotalPrice = document.getElementById('cart-total-price');
const checkoutBtn = document.getElementById('checkout-btn');
const checkoutModal = document.getElementById('checkout-modal');
const closeCheckoutBtn = document.getElementById('close-checkout');
const confirmationModal = document.getElementById('confirmation-modal');
const closeConfirmationBtn = document.getElementById('close-confirmation');
const continueShoppingBtn = document.getElementById('continue-shopping');
const checkoutForm = document.getElementById('checkout-form');
const summarySubtotal = document.getElementById('summary-subtotal');
const summaryTax = document.getElementById('summary-tax');
const summaryTotal = document.getElementById('summary-total');
const orderReference = document.getElementById('order-reference');
// Cart state
let cart = [];
let cartTotal = 0;
// Initialize cart
document.addEventListener('DOMContentLoaded', () => {
// Load cart from localStorage if available
const savedCart = localStorage.getItem('cart');
if (savedCart) {
cart = JSON.parse(savedCart);
updateCartCount();
renderCart();
}
setupCartEvents();
});
// Setup cart event listeners
function setupCartEvents() {
// Toggle cart sidebar
cartIcon.addEventListener('click', () => {
cartSidebar.classList.add('active');
overlay.classList.add('active');
});
// Close cart
closeCartBtn.addEventListener('click', () => {
cartSidebar.classList.remove('active');
overlay.classList.remove('active');
});
// Checkout button
checkoutBtn.addEventListener('click', () => {
if (cart.length === 0) {
alert('Your cart is empty. Add some products first!');
return;
}
openCheckoutModal();
});
// Close checkout modal
closeCheckoutBtn.addEventListener('click', () => {
checkoutModal.classList.remove('active');
overlay.classList.remove('active');
});
// Close confirmation modal
closeConfirmationBtn.addEventListener('click', () => {
confirmationModal.classList.remove('active');
overlay.classList.remove('active');
});
// Continue shopping button
continueShoppingBtn.addEventListener('click', () => {
confirmationModal.classList.remove('active');
overlay.classList.remove('active');
});
// Handle checkout form submission
checkoutForm.addEventListener('submit', (e) => {
e.preventDefault();
processOrder();
});
// Close modals when clicking on overlay
overlay.addEventListener('click', () => {
cartSidebar.classList.remove('active');
checkoutModal.classList.remove('active');
confirmationModal.classList.remove('active');
overlay.classList.remove('active');
});
}
// Add a product to cart
function updateCart(product) {
// Check if product already exists in cart
const existingItem = cart.find(item => item.id === product.id);
if (existingItem) {
existingItem.quantity += 1;
} else {
cart.push({
...product,
quantity: 1
});
}
// Save cart to localStorage
localStorage.setItem('cart', JSON.stringify(cart));
// Update UI
updateCartCount();
renderCart();
}
// Render cart items
function renderCart() {
if (cart.length === 0) {
cartItems.innerHTML = '<div class="empty-cart-message">Your cart is empty</div>';
cartTotalPrice.textContent = '$0.00';
cartTotal = 0;
return;
}
cartItems.innerHTML = '';
let total = 0;
cart.forEach(item => {
const itemTotal = item.price * item.quantity;
total += itemTotal;
const cartItem = document.createElement('div');
cartItem.className = 'cart-item';
cartItem.innerHTML = `
<div class="cart-item-image">
<img src="${item.image}" alt="${item.name}">
</div>
<div class="cart-item-details">
<h4 class="cart-item-title">${item.name}</h4>
<div class="cart-item-price">$${item.price.toFixed(2)}</div>
<div class="cart-item-quantity">
<button class="quantity-btn decrease" data-id="${item.id}">-</button>
<input type="text" class="quantity-input" value="${item.quantity}" readonly>
<button class="quantity-btn increase" data-id="${item.id}">+</button>
</div>
</div>
<button class="remove-item" data-id="${item.id}">
<i class="fas fa-trash-alt"></i>
</button>
`;
cartItems.appendChild(cartItem);
});
// Update cart total
cartTotal = total;
cartTotalPrice.textContent = `$${total.toFixed(2)}`;
// Add event listeners to quantity buttons and remove buttons
const decreaseButtons = document.querySelectorAll('.quantity-btn.decrease');
const increaseButtons = document.querySelectorAll('.quantity-btn.increase');
const removeButtons = document.querySelectorAll('.remove-item');
decreaseButtons.forEach(button => {
button.addEventListener('click', () => {
decreaseQuantity(Number(button.dataset.id));
});
});
increaseButtons.forEach(button => {
button.addEventListener('click', () => {
increaseQuantity(Number(button.dataset.id));
});
});
removeButtons.forEach(button => {
button.addEventListener('click', () => {
removeFromCart(Number(button.dataset.id));
});
});
}
// Update cart count badge
function updateCartCount() {
const cartCount = document.querySelector('.cart-count');
const count = cart.reduce((total, item) => total + item.quantity, 0);
cartCount.textContent = count;
}
// Decrease item quantity
function decreaseQuantity(productId) {
const item = cart.find(item => item.id === productId);
if (item.quantity > 1) {
item.quantity -= 1;
} else {
removeFromCart(productId);
return;
}
localStorage.setItem('cart', JSON.stringify(cart));
renderCart();
}
// Increase item quantity
function increaseQuantity(productId) {
const item = cart.find(item => item.id === productId);
item.quantity += 1;
localStorage.setItem('cart', JSON.stringify(cart));
renderCart();
}
// Remove item from cart
function removeFromCart(productId) {
cart = cart.filter(item => item.id !== productId);
localStorage.setItem('cart', JSON.stringify(cart));
updateCartCount();
renderCart();
}
// Open checkout modal
function openCheckoutModal() {
// Update summary values
const subtotal = cartTotal;
const tax = subtotal * 0.08; // Assuming 8% tax
const total = subtotal + tax + 10; // Adding $10 shipping
summarySubtotal.textContent = `$${subtotal.toFixed(2)}`;
summaryTax.textContent = `$${tax.toFixed(2)}`;
summaryTotal.textContent = `$${total.toFixed(2)}`;
// Show modal
checkoutModal.classList.add('active');
overlay.classList.add('active');
}
// Process the order
function processOrder() {
// Generate a random order number
const orderNumber = `ORD-${Math.floor(100000 + Math.random() * 900000)}`;
orderReference.textContent = orderNumber;
// Close checkout modal
checkoutModal.classList.remove('active');
// Show confirmation modal
confirmationModal.classList.add('active');
// Clear cart
cart = [];
localStorage.removeItem('cart');
updateCartCount();
renderCart();
}
function updateCartTotal() {
// TODO: Bug - Cart total calculation is incorrect (hint: floating point precision error in price calculations)
let total = 0;
const cartItems = document.querySelectorAll('.cart-item');
cartItems.forEach(item => {
const price = parseFloat(item.querySelector('.price').textContent);
const quantity = parseInt(item.querySelector('.quantity').value);
total += price * quantity;
});
// Bug: Direct floating point multiplication causes precision errors
document.querySelector('.cart-total').textContent = total;
}
// TODO: Bug 9 - Critical: Cart total calculation (hint: floating point precision error)
function calculateTotal() {
return cart.reduce((total, item) => {
return total + item.price * item.quantity;
}, 0);
}
// TODO: Bug 10 - Critical: Cart persistence (hint: cart not saved before page unload)
window.addEventListener('unload', () => {
// Bug: Missing cart save to localStorage
console.log('Page unloading...');
});
please give the answers fast and i need them one by one if possible
ai answers are allowed