Activity 31: Angular Ecommerce Product List

Features of the Application

  1. Responsive Design:

    • 2 columns on mobile (e.g., iPhone 14 Plus).

    • 3 columns on tablets (e.g., iPad Pro 11").

    • 5 columns on desktops (e.g., MacBook Pro 16").

  2. Dynamic Product List:

    • Showcases 18 products with consistent box sizes.

    • Includes product details like name, price, stock, and a "Add to Cart" button.

  3. CSS Layout:

    • Built using CSS Grid and Flexbox for responsiveness.

    • Implements BEM (Block Element Modifier) architecture for clean CSS.

  4. Deployed on Firebase Hosting for seamless access.

Here’s a sample documentation template you can use for your Hashnode blog post. Incorporate the screenshot (image you uploaded) into the blog as a visual example of the final output.


Title:

Responsive Angular Product List with Firebase Hosting


Introduction

In this tutorial, I’ll walk you through how I created a fully responsive Product List Application in Angular. The layout dynamically adjusts to display 2 columns on mobile, 3 on tablets, and 5 on desktops. The app is deployed on Firebase Hosting for fast and reliable access.

Check out the live demo and GitHub repository linked below!


Features of the Application

  1. Responsive Design:

    • 2 columns on mobile (e.g., iPhone 14 Plus).

    • 3 columns on tablets (e.g., iPad Pro 11").

    • 5 columns on desktops (e.g., MacBook Pro 16").

  2. Dynamic Product List:

    • Showcases 18 products with consistent box sizes.

    • Includes product details like name, price, stock, and a "Add to Cart" button.

  3. CSS Layout:

    • Built using CSS Grid and Flexbox for responsiveness.

    • Implements BEM (Block Element Modifier) architecture for clean CSS.

  4. Deployed on Firebase Hosting for seamless access.


Preview of the Application

Here’s how the product list looks across devices:

(Upload your screenshot to Hashnode or a reliable image hosting service like Imgur.)


Code Implementation

1. Angular Component Structure

Here’s the structure of the app:

  • app.component.ts (Handles product logic).

  • app.component.html (Defines the layout and binds data).

  • app.component.scss (Applies styling).


2. Responsive CSS

Here’s how I used CSS Grid and Flexbox to achieve a responsive layout:

product-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

.product-card {
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  padding: 16px;
  text-align: center;
}

button.add-to-cart {
  margin-top: auto;
  padding: 8px 12px;
  background-color: #4CAF50;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
button.add-to-cart:hover {
  background-color: #45a049;
}

3. Product Data Example

Here’s how the product data is structured in app.component.ts:

import { Component } from '@angular/core';
import { Product } from './models/product.model';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'Product List Application';

  products = [
    { id: 1, name: 'Laptop', price: 1000, imageUrl: 'img/laptop.jpg', description: 'High-performance laptop', stock: 10 },
    { id: 2, name: 'Phone', price: 500, imageUrl: 'img/phone.jpg', description: 'Latest smartphone', stock: 25 },
    { id: 3, name: 'Headphones', price: 200, imageUrl: 'img/headphones.jpg', description: 'Noise-cancelling headphones', stock: 15 },
    { id: 4, name: 'Smart Watch', price: 150, imageUrl: 'img/smartwatch.jpg', description: 'Fitness tracking smart watch', stock: 30 },
    { id: 5, name: 'Camera', price: 1200, imageUrl: 'img/camera.jpg', description: 'Digital camera with 4K video', stock: 8 },
    { id: 6, name: 'Keyboard', price: 80, imageUrl: 'img/keyboard.jpg', description: 'Mechanical keyboard with RGB lights', stock: 50 },
    { id: 7, name: 'Mouse', price: 40, imageUrl: 'img/mouse.jpg', description: 'Wireless mouse with ergonomic design', stock: 100 },
    { id: 8, name: 'Bluetooth Speaker', price: 60, imageUrl: 'img/speaker.jpg', description: 'Portable Bluetooth speaker with great sound', stock: 20 },
    { id: 9, name: 'Monitor', price: 300, imageUrl: 'img/monitor.jpg', description: '24-inch Full HD monitor', stock: 12 },
    { id: 10, name: 'Tablet', price: 400, imageUrl: 'img/tablet.jpg', description: '10-inch tablet with fast performance', stock: 18 },
    { id: 11, name: 'Printer', price: 150, imageUrl: 'img/printer.jpg', description: 'Wireless color printer', stock: 14 },
    { id: 12, name: 'Projector', price: 500, imageUrl: 'img/projector.jpg', description: 'Portable HD projector', stock: 7 },
    { id: 13, name: 'Smart TV', price: 800, imageUrl: 'img/smarttv.jpg', description: '55-inch 4K Smart TV', stock: 5 },
    { id: 14, name: 'External Hard Drive', price: 100, imageUrl: 'img/harddrive.jpg', description: '1TB external hard drive', stock: 30 },
    { id: 15, name: 'Smart Thermostat', price: 120, imageUrl: 'img/thermostat.jpg', description: 'WiFi-enabled smart thermostat', stock: 40 },
    { id: 16, name: 'Smart Light Bulb', price: 30, imageUrl: 'img/lightbulb.jpg', description: 'Energy-efficient smart LED bulb', stock: 60 },
    { id: 17, name: 'Drone', price: 350, imageUrl: 'img/drone.jpg', description: 'Quadcopter drone with HD camera', stock: 12 },
    { id: 18, name: 'Game Console', price: 400, imageUrl: 'img/console.jpg', description: 'Next-gen gaming console', stock: 20 }
  ];
  cart: Product[] = [];

  constructor() {

    this.loadCartFromStorage();
  }


  addToCart(product: Product) {

    const productInCart = this.cart.find(item => item.id === product.id);

    if (productInCart) {
      console.log(`${product.name} is already in the cart.`);
    } else {

      this.cart.push(product);
      console.log(`${product.name} added to cart.`);
    }


    this.saveCartToStorage();
  }


  saveCartToStorage() {
    localStorage.setItem('cart', JSON.stringify(this.cart));
  }


  loadCartFromStorage() {
    const savedCart = localStorage.getItem('cart');
    if (savedCart) {
      this.cart = JSON.parse(savedCart);
    }
  }


  clearCart() {
    this.cart = [];
    localStorage.removeItem('cart');
    console.log('Cart has been cleared');
  }
}

output:

firebase link: https://act-c62a1.web.app

github link: https://github.com/RodelCalda/ACTIVITY31.git