Skip to content

Instantly share code, notes, and snippets.

@thinkphp
Created July 20, 2025 14:22
Show Gist options
  • Save thinkphp/2c1b71aec92f1804d4e5ac1e652370dc to your computer and use it in GitHub Desktop.
Save thinkphp/2c1b71aec92f1804d4e5ac1e652370dc to your computer and use it in GitHub Desktop.
coffee-shop.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coffee Shop Cart</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
margin: 0;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: 2fr 1fr;
gap: 30px;
}
.header {
grid-column: 1 / -1;
text-align: center;
margin-bottom: 20px;
}
h1, h2, h3 {
color: #5d4037;
}
.products {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 20px;
}
.product-card {
background-color: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.product-image {
height: 180px;
background-color: #d7ccc8;
display: flex;
align-items: center;
justify-content: center;
color: #5d4037;
font-weight: bold;
}
.product-info {
padding: 15px;
}
.product-title {
margin: 0 0 10px 0;
font-size: 18px;
}
.product-price {
font-weight: bold;
margin-bottom: 10px;
color: #5d4037;
}
.product-description {
font-size: 14px;
color: #666;
margin-bottom: 15px;
}
button {
background-color: #795548;
color: white;
border: none;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #5d4037;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.cart {
background-color: white;
border-radius: 8px;
padding: 20px;
position: sticky;
top: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.cart-item {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
.item-info {
flex-grow: 1;
}
.item-title {
margin: 0 0 5px 0;
font-size: 16px;
}
.item-price {
font-size: 14px;
color: #666;
}
.item-controls {
display: flex;
align-items: center;
}
.item-quantity {
margin: 0 10px;
width: 30px;
text-align: center;
}
.cart-total {
margin-top: 20px;
font-weight: bold;
font-size: 18px;
text-align: right;
}
.checkout-button {
width: 100%;
padding: 12px;
font-size: 16px;
background-color: #4caf50;
margin-top: 20px;
}
.checkout-button:hover {
background-color: #388e3c;
}
.emptycart-button {
width: 100%;
padding: 8px;
font-size: 14px;
background-color: #f44336;
margin-top: 10px;
}
.emptycart-button:hover {
background-color: #d32f2f;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
background-color: #4caf50;
color: white;
padding: 15px 25px;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
transform: translateX(200%);
transition: transform 0.3s ease;
}
.notification.show {
transform: translateX(0);
}
.empty-cart-message {
text-align: center;
color: #666;
margin: 30px 0;
}
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
}
.cart {
position: static;
margin-top: 30px;
}
}
</style>
</head>
<body>
<div class="container">
<header class="header">
<h1>Coffee Shop</h1>
<p>Select your favorite coffee and add it to cart</p>
</header>
<main class="products" id="products-container">
<!-- Products will be added here by JavaScript -->
</main>
<aside class="cart" id="cart-container">
<h2>Your Cart</h2>
<div id="cart-items">
<!-- Cart items will be added here by JavaScript -->
<p class="empty-cart-message">Your cart is empty</p>
</div>
<div class="cart-total" id="cart-total">Total: $0.00</div>
<button class="checkout-button" id="checkout-button" disabled>Proceed to Checkout</button>
<button class="emptycart-button" id="emptycart-button" disabled>Empty Cart</button>
</aside>
</div>
<div class="notification" id="notification">Item added to cart!</div>
<script>
// Coffee products data
const coffeeProducts = [
{
id: 1,
name: "Espresso",
price: 2.99,
description: "Strong and concentrated coffee shot"
},
{
id: 2,
name: "Cappuccino",
price: 4.50,
description: "Espresso with steamed milk and foam"
},
{
id: 3,
name: "Latte",
price: 4.99,
description: "Espresso with a lot of steamed milk"
},
{
id: 4,
name: "Americano",
price: 3.50,
description: "Espresso diluted with hot water"
},
{
id: 5,
name: "Mocha",
price: 5.50,
description: "Espresso with chocolate and steamed milk"
},
{
id: 6,
name: "Macchiato",
price: 3.99,
description: "Espresso with a dollop of milk foam"
}
];
// Shopping cart array
let cart = [];
// DOM elements
const productsContainer = document.getElementById('products-container');
const cartItemsContainer = document.getElementById('cart-items');
const cartTotalElement = document.getElementById('cart-total');
const checkoutButton = document.getElementById('checkout-button');
const emptyCartButton = document.getElementById('emptycart-button');
const notification = document.getElementById('notification');
// Display products
function displayProducts() {
productsContainer.innerHTML = '';
coffeeProducts.forEach(product => {
const productCard = document.createElement('div');
productCard.className = 'product-card';
productCard.innerHTML = `
<div class="product-image">Coffee Image: ${product.name}</div>
<div class="product-info">
<h3 class="product-title">${product.name}</h3>
<div class="product-price">$${product.price.toFixed(2)}</div>
<div class="product-description">${product.description}</div>
<button class="add-to-cart-button" data-id="${product.id}">Add to Cart</button>
</div>
`;
productsContainer.appendChild(productCard);
});
// Add event listeners to all "Add to Cart" buttons
document.querySelectorAll('.add-to-cart-button').forEach(button => {
button.addEventListener('click', addToCart);
});
}
// Add to cart function
function addToCart(event) {
const productId = parseInt(event.target.getAttribute('data-id'));
const product = coffeeProducts.find(p => p.id === productId);
// Check if the product already exists in the cart
const existingItem = cart.find(item => item.id === productId);
if (existingItem) {
existingItem.quantity += 1;
} else {
cart.push({
id: product.id,
name: product.name,
price: product.price,
quantity: 1
});
}
// Show notification
showNotification(`Added ${product.name} to cart!`);
// Update cart display
updateCart();
}
// Update cart display
function updateCart() {
if (cart.length === 0) {
cartItemsContainer.innerHTML = '<p class="empty-cart-message">Your cart is empty</p>';
checkoutButton.disabled = true;
emptyCartButton.disabled = true;
} else {
cartItemsContainer.innerHTML = '';
cart.forEach(item => {
const cartItem = document.createElement('div');
cartItem.className = 'cart-item';
cartItem.innerHTML = `
<div class="item-info">
<h3 class="item-title">${item.name}</h3>
<div class="item-price">$${item.price.toFixed(2)} each</div>
</div>
<div class="item-controls">
<button class="decrease-quantity" data-id="${item.id}">-</button>
<span class="item-quantity">${item.quantity}</span>
<button class="increase-quantity" data-id="${item.id}">+</button>
<button class="remove-item" data-id="${item.id}" style="margin-left: 10px; background-color: #f44336;">×</button>
</div>
`;
cartItemsContainer.appendChild(cartItem);
});
checkoutButton.disabled = false;
emptyCartButton.disabled = false;
}
// Calculate and update the cart total
updateCartTotal();
// Add event listeners to quantity buttons
document.querySelectorAll('.decrease-quantity').forEach(button => {
button.addEventListener('click', decreaseQuantity);
});
document.querySelectorAll('.increase-quantity').forEach(button => {
button.addEventListener('click', increaseQuantity);
});
document.querySelectorAll('.remove-item').forEach(button => {
button.addEventListener('click', removeItem);
});
}
// Update cart total
function updateCartTotal() {
const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
cartTotalElement.textContent = `Total: $${total.toFixed(2)}`;
}
// Increase item quantity
function increaseQuantity(event) {
const productId = parseInt(event.target.getAttribute('data-id'));
const item = cart.find(item => item.id === productId);
if (item) {
item.quantity += 1;
updateCart();
}
}
// Decrease item quantity
function decreaseQuantity(event) {
const productId = parseInt(event.target.getAttribute('data-id'));
const item = cart.find(item => item.id === productId);
if (item) {
item.quantity -= 1;
if (item.quantity <= 0) {
removeItem(event);
} else {
updateCart();
}
}
}
// Remove item from cart
function removeItem(event) {
const productId = parseInt(event.target.getAttribute('data-id'));
cart = cart.filter(item => item.id !== productId);
updateCart();
}
// Empty the cart
function emptyCart() {
cart = [];
updateCart();
showNotification('Cart has been emptied');
}
// Show notification
function showNotification(message) {
notification.textContent = message;
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
}, 3000);
}
// Checkout function
function checkout() {
// In a real application, this would connect to a payment processor
alert(`Proceeding to checkout with ${cart.length} items. Total: $${calculateTotal().toFixed(2)}`);
cart = [];
updateCart();
showNotification('Thank you for your order!');
}
// Calculate total function (for checkout)
function calculateTotal() {
return cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
}
// Initialize the application
function init() {
// Display products
displayProducts();
// Initial cart update
updateCart();
// Add event listeners for checkout and empty cart buttons
checkoutButton.addEventListener('click', checkout);
emptyCartButton.addEventListener('click', emptyCart);
}
// Start the application when DOM is fully loaded
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment